summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:24:47 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:24:47 +0000
commitdb25e5ca8d5b55c1e2940cceab38f4c019e59d54 (patch)
tree8637c0c3300f6a1324bac0b35e2f0b2e69803e08
parent8fc7d872bc04a50bfce52d5a93f33867832e4268 (diff)
parentaf8f6cf3aba3398b36117dd3acce6f5a3c0610c6 (diff)
downloadnative-db25e5ca8d5b55c1e2940cceab38f4c019e59d54.tar.gz
Snap for 6439596 from af8f6cf3aba3398b36117dd3acce6f5a3c0610c6 to qt-aml-tzdata-releaseandroid-mainline-10.0.0_r11
Change-Id: I853bc427c872c044202800e8bb558018278291ed
-rw-r--r--Android.bp23
-rw-r--r--PREUPLOAD.cfg3
-rw-r--r--cmds/atrace/Android.bp2
-rw-r--r--cmds/atrace/atrace.cpp5
-rw-r--r--cmds/bugreport/bugreport.cpp2
-rw-r--r--cmds/bugreportz/main.cpp2
-rw-r--r--cmds/dumpstate/Android.bp13
-rw-r--r--cmds/dumpstate/DumpstateInternal.cpp8
-rw-r--r--cmds/dumpstate/DumpstateSectionReporter.cpp42
-rw-r--r--cmds/dumpstate/DumpstateSectionReporter.h65
-rw-r--r--cmds/dumpstate/DumpstateService.cpp13
-rw-r--r--cmds/dumpstate/DumpstateUtil.cpp28
-rw-r--r--cmds/dumpstate/DumpstateUtil.h6
-rw-r--r--cmds/dumpstate/TEST_MAPPING7
-rw-r--r--cmds/dumpstate/binder/android/os/IDumpstate.aidl2
-rw-r--r--cmds/dumpstate/binder/android/os/IDumpstateListener.aidl17
-rw-r--r--cmds/dumpstate/dumpstate.cpp1165
-rw-r--r--cmds/dumpstate/dumpstate.h21
-rw-r--r--cmds/dumpstate/dumpstate_test.xml29
-rw-r--r--cmds/dumpstate/tests/dumpstate_smoke_test.cpp199
-rw-r--r--cmds/dumpstate/tests/dumpstate_test.cpp106
-rw-r--r--cmds/dumpstate/utils.cpp1012
-rw-r--r--cmds/dumpsys/TEST_MAPPING13
-rw-r--r--cmds/dumpsys/dumpsys.cpp56
-rw-r--r--cmds/dumpsys/dumpsys.h8
-rw-r--r--cmds/dumpsys/tests/dumpsys_test.cpp28
-rw-r--r--cmds/idlcli/Android.bp53
-rw-r--r--cmds/idlcli/CommandVibrator.cpp40
-rw-r--r--cmds/idlcli/IdlCli.h41
-rw-r--r--cmds/idlcli/main.cpp23
-rw-r--r--cmds/idlcli/utils.h270
-rw-r--r--cmds/idlcli/vibrator.h86
-rw-r--r--cmds/idlcli/vibrator/CommandOff.cpp61
-rw-r--r--cmds/idlcli/vibrator/CommandOn.cpp71
-rw-r--r--cmds/idlcli/vibrator/CommandPerform.cpp107
-rw-r--r--cmds/idlcli/vibrator/CommandSetAmplitude.cpp72
-rw-r--r--cmds/idlcli/vibrator/CommandSetExternalControl.cpp70
-rw-r--r--cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp63
-rw-r--r--cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp63
-rw-r--r--cmds/installd/Android.bp11
-rw-r--r--cmds/installd/InstalldNativeService.cpp31
-rw-r--r--cmds/installd/InstalldNativeService.h1
-rw-r--r--cmds/installd/OWNERS2
-rw-r--r--cmds/installd/art_helper/Android.bp12
-rw-r--r--cmds/installd/art_helper/art_image_values.cpp37
-rw-r--r--cmds/installd/art_helper/art_image_values.h (renamed from services/inputflinger/dispatcher/InputDispatcherFactory.cpp)23
-rw-r--r--cmds/installd/binder/android/os/IInstalld.aidl1
-rw-r--r--cmds/installd/dexopt.cpp54
-rw-r--r--cmds/installd/dexopt.h16
-rw-r--r--cmds/installd/installd.cpp2
-rw-r--r--cmds/installd/migrate_legacy_obb_data.sh10
-rw-r--r--cmds/installd/otapreopt.cpp14
-rw-r--r--cmds/installd/otapreopt_chroot.cpp24
-rw-r--r--cmds/installd/tests/Android.bp2
-rw-r--r--cmds/installd/tests/installd_cache_test.cpp22
-rw-r--r--cmds/installd/tests/installd_dexopt_test.cpp66
-rw-r--r--cmds/lshal/Android.bp18
-rw-r--r--cmds/lshal/Command.h5
-rw-r--r--cmds/lshal/DebugCommand.cpp3
-rw-r--r--cmds/lshal/DebugCommand.h5
-rw-r--r--cmds/lshal/HelpCommand.h5
-rw-r--r--cmds/lshal/ListCommand.cpp19
-rw-r--r--cmds/lshal/ListCommand.h5
-rw-r--r--cmds/lshal/Lshal.cpp3
-rw-r--r--cmds/lshal/Lshal.h6
-rw-r--r--cmds/lshal/NullableOStream.h5
-rw-r--r--cmds/lshal/PipeRelay.h7
-rw-r--r--cmds/lshal/TEST_MAPPING8
-rw-r--r--cmds/lshal/TableEntry.h5
-rw-r--r--cmds/lshal/TextTable.h5
-rw-r--r--cmds/lshal/Timeout.h2
-rw-r--r--cmds/lshal/WaitCommand.cpp87
-rw-r--r--cmds/lshal/WaitCommand.h49
-rw-r--r--cmds/lshal/libprocpartition/include/procpartition/procpartition.h5
-rw-r--r--cmds/lshal/test.cpp20
-rw-r--r--cmds/lshal/utils.h5
-rw-r--r--cmds/service/Android.bp2
-rw-r--r--cmds/service/service.cpp194
-rw-r--r--cmds/servicemanager/Access.cpp150
-rw-r--r--cmds/servicemanager/Access.h56
-rw-r--r--cmds/servicemanager/Android.bp61
-rw-r--r--cmds/servicemanager/ServiceManager.cpp336
-rw-r--r--cmds/servicemanager/ServiceManager.h73
-rw-r--r--cmds/servicemanager/TEST_MAPPING12
-rw-r--r--cmds/servicemanager/bctest.c107
-rw-r--r--cmds/servicemanager/binder.c682
-rw-r--r--cmds/servicemanager/binder.h94
-rw-r--r--cmds/servicemanager/main.cpp56
-rw-r--r--cmds/servicemanager/service_manager.c442
-rw-r--r--cmds/servicemanager/test_sm.cpp429
-rw-r--r--data/etc/android.hardware.se.omapi.ese.xml21
-rw-r--r--data/etc/android.hardware.se.omapi.sd.xml21
-rw-r--r--data/etc/android.hardware.se.omapi.uicc.xml21
-rw-r--r--headers/media_plugin/media/cas/CasAPI.h14
-rw-r--r--headers/media_plugin/media/openmax/OMX_Video.h1
-rw-r--r--include/android/choreographer.h6
-rw-r--r--include/android/configuration.h18
-rw-r--r--include/android/font.h20
-rw-r--r--include/android/font_matcher.h16
-rw-r--r--include/android/hardware_buffer_jni.h4
-rw-r--r--include/android/input.h16
-rw-r--r--include/android/multinetwork.h11
-rw-r--r--include/android/native_window_jni.h2
-rw-r--r--include/android/sensor.h43
-rw-r--r--include/android/surface_control.h59
-rw-r--r--include/android/surface_texture.h15
-rw-r--r--include/android/surface_texture_jni.h8
-rw-r--r--include/android/system_fonts.h8
-rw-r--r--include/android/trace.h8
-rw-r--r--include/audiomanager/OWNERS2
-rw-r--r--include/input/IInputFlinger.h4
-rw-r--r--libs/adbd_auth/Android.bp44
-rw-r--r--libs/adbd_auth/adbd_auth.cpp443
-rw-r--r--libs/adbd_auth/include/adbd_auth.h65
-rw-r--r--libs/adbd_auth/libadbd_auth.map.txt13
-rw-r--r--libs/android_runtime_lazy/Android.bp5
-rw-r--r--libs/arect/Android.bp7
-rw-r--r--libs/binder/ActivityManager.cpp2
-rw-r--r--libs/binder/Android.bp102
-rw-r--r--libs/binder/AppOpsManager.cpp2
-rw-r--r--libs/binder/Binder.cpp71
-rw-r--r--libs/binder/BpBinder.cpp66
-rw-r--r--libs/binder/BufferedTextOutput.cpp9
-rw-r--r--libs/binder/Debug.cpp2
-rw-r--r--libs/binder/IActivityManager.cpp2
-rw-r--r--libs/binder/IAppOpsCallback.cpp4
-rw-r--r--libs/binder/IAppOpsService.cpp4
-rw-r--r--libs/binder/IBatteryStats.cpp4
-rw-r--r--libs/binder/IInterface.cpp2
-rw-r--r--libs/binder/IMediaResourceMonitor.cpp2
-rw-r--r--libs/binder/IMemory.cpp6
-rw-r--r--libs/binder/IPCThreadState.cpp56
-rw-r--r--libs/binder/IPermissionController.cpp4
-rw-r--r--libs/binder/IProcessInfoService.cpp2
-rw-r--r--libs/binder/IResultReceiver.cpp4
-rw-r--r--libs/binder/IServiceManager.cpp274
-rw-r--r--libs/binder/IShellCallback.cpp4
-rw-r--r--libs/binder/IUidObserver.cpp2
-rw-r--r--libs/binder/IpPrefix.cpp1
-rw-r--r--libs/binder/MemoryBase.cpp2
-rw-r--r--libs/binder/MemoryDealer.cpp2
-rw-r--r--libs/binder/MemoryHeapBase.cpp2
-rw-r--r--libs/binder/Parcel.cpp492
-rw-r--r--libs/binder/PermissionCache.cpp2
-rw-r--r--libs/binder/PermissionController.cpp2
-rw-r--r--libs/binder/PersistableBundle.cpp3
-rw-r--r--libs/binder/ProcessInfoService.cpp2
-rw-r--r--libs/binder/ProcessState.cpp172
-rw-r--r--libs/binder/Stability.cpp124
-rw-r--r--libs/binder/Static.cpp15
-rw-r--r--libs/binder/TEST_MAPPING25
-rw-r--r--libs/binder/TextOutput.cpp2
-rw-r--r--libs/binder/Value.cpp420
-rw-r--r--libs/binder/aidl/android/os/IServiceCallback.aidl30
-rw-r--r--libs/binder/aidl/android/os/IServiceManager.aidl99
-rw-r--r--libs/binder/include/binder/ActivityManager.h2
-rw-r--r--libs/binder/include/binder/AppOpsManager.h2
-rw-r--r--libs/binder/include/binder/Binder.h16
-rw-r--r--libs/binder/include/binder/BinderService.h2
-rw-r--r--libs/binder/include/binder/BpBinder.h13
-rw-r--r--libs/binder/include/binder/BufferedTextOutput.h2
-rw-r--r--libs/binder/include/binder/Debug.h2
-rw-r--r--libs/binder/include/binder/IActivityManager.h2
-rw-r--r--libs/binder/include/binder/IAppOpsCallback.h2
-rw-r--r--libs/binder/include/binder/IAppOpsService.h2
-rw-r--r--libs/binder/include/binder/IBatteryStats.h2
-rw-r--r--libs/binder/include/binder/IBinder.h63
-rw-r--r--libs/binder/include/binder/IInterface.h8
-rw-r--r--libs/binder/include/binder/IMediaResourceMonitor.h2
-rw-r--r--libs/binder/include/binder/IMemory.h4
-rw-r--r--libs/binder/include/binder/IPCThreadState.h4
-rw-r--r--libs/binder/include/binder/IPermissionController.h2
-rw-r--r--libs/binder/include/binder/IProcessInfoService.h2
-rw-r--r--libs/binder/include/binder/IResultReceiver.h2
-rw-r--r--libs/binder/include/binder/IServiceManager.h70
-rw-r--r--libs/binder/include/binder/IShellCallback.h2
-rw-r--r--libs/binder/include/binder/IUidObserver.h2
-rw-r--r--libs/binder/include/binder/Map.h (renamed from services/inputflinger/dispatcher/InputDispatcherThread.cpp)28
-rw-r--r--libs/binder/include/binder/MemoryBase.h2
-rw-r--r--libs/binder/include/binder/MemoryDealer.h2
-rw-r--r--libs/binder/include/binder/MemoryHeapBase.h2
-rw-r--r--libs/binder/include/binder/Parcel.h220
-rw-r--r--libs/binder/include/binder/ParcelFileDescriptor.h18
-rw-r--r--libs/binder/include/binder/PermissionCache.h2
-rw-r--r--libs/binder/include/binder/PermissionController.h2
-rw-r--r--libs/binder/include/binder/ProcessInfoService.h2
-rw-r--r--libs/binder/include/binder/ProcessState.h25
-rw-r--r--libs/binder/include/binder/Stability.h105
-rw-r--r--libs/binder/include/binder/TextOutput.h2
-rw-r--r--libs/binder/include/binder/Value.h186
-rw-r--r--libs/binder/include/private/binder/ParcelValTypes.h (renamed from libs/binder/ParcelValTypes.h)0
-rw-r--r--libs/binder/include/private/binder/Static.h (renamed from libs/binder/Static.h)12
-rw-r--r--libs/binder/include/private/binder/binder_module.h10
-rw-r--r--libs/binder/ndk/Android.bp44
-rw-r--r--libs/binder/ndk/ibinder.cpp41
-rw-r--r--libs/binder/ndk/include_apex/android/binder_manager.h (renamed from libs/binder/ndk/include_platform/android/binder_manager.h)0
-rw-r--r--libs/binder/ndk/include_apex/android/binder_process.h (renamed from libs/binder/ndk/include_platform/android/binder_process.h)2
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_auto_utils.h54
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_ibinder.h134
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h8
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_parcel.h112
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_status.h28
-rw-r--r--libs/binder/ndk/include_platform/android/binder_stability.h73
-rw-r--r--libs/binder/ndk/libbinder_ndk.map.txt24
-rw-r--r--libs/binder/ndk/parcel.cpp2
-rwxr-xr-xlibs/binder/ndk/scripts/format.sh22
-rwxr-xr-xlibs/binder/ndk/scripts/init_map.sh19
-rw-r--r--libs/binder/ndk/stability.cpp45
-rw-r--r--libs/binder/ndk/test/Android.bp31
-rw-r--r--libs/binder/ndk/test/AndroidTest.xml32
-rw-r--r--libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl19
-rw-r--r--libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp168
-rwxr-xr-xlibs/binder/ndk/update.sh23
-rw-r--r--libs/binder/tests/Android.bp74
-rw-r--r--libs/binder/tests/IBinderStabilityTest.aidl46
-rw-r--r--libs/binder/tests/binderDriverInterfaceTest.cpp1
-rw-r--r--libs/binder/tests/binderLibTest.cpp124
-rw-r--r--libs/binder/tests/binderSafeInterfaceTest.cpp3
-rw-r--r--libs/binder/tests/binderStabilityTest.cpp328
-rw-r--r--libs/binder/tests/binderValueTypeTest.cpp110
-rw-r--r--libs/binder/tests/schd-dbg.cpp1
-rw-r--r--libs/binderthreadstate/Android.bp2
-rw-r--r--libs/dumputils/Android.bp2
-rw-r--r--libs/dumputils/dump_utils.cpp36
-rw-r--r--libs/graphicsenv/GraphicsEnv.cpp8
-rw-r--r--libs/graphicsenv/OWNERS6
-rw-r--r--libs/graphicsenv/include/graphicsenv/GraphicsEnv.h11
-rw-r--r--libs/gui/Android.bp14
-rw-r--r--libs/gui/BufferQueueConsumer.cpp10
-rw-r--r--libs/gui/BufferQueueCore.cpp7
-rw-r--r--libs/gui/BufferQueueProducer.cpp5
-rw-r--r--libs/gui/IProducerListener.cpp26
-rw-r--r--libs/gui/ISurfaceComposer.cpp4
-rw-r--r--libs/gui/LayerState.cpp4
-rw-r--r--libs/gui/Surface.cpp49
-rw-r--r--libs/gui/include/gui/BufferQueueCore.h6
-rw-r--r--libs/gui/include/gui/IProducerListener.h6
-rw-r--r--libs/gui/include/gui/Surface.h44
-rw-r--r--libs/gui/tests/Android.bp1
-rw-r--r--libs/gui/tests/BufferQueue_test.cpp28
-rw-r--r--libs/gui/tests/EndToEndNativeInputTest.cpp63
-rw-r--r--libs/gui/tests/Surface_test.cpp126
-rw-r--r--libs/input/IInputFlinger.cpp17
-rw-r--r--libs/input/InputWindow.cpp4
-rw-r--r--libs/input/TouchVideoFrame.cpp4
-rw-r--r--libs/input/tests/TouchVideoFrame_test.cpp8
-rw-r--r--libs/math/include/math/quat.h2
-rw-r--r--libs/math/include/math/vec2.h2
-rw-r--r--libs/math/include/math/vec3.h6
-rw-r--r--libs/nativewindow/AHardwareBuffer.cpp8
-rw-r--r--libs/nativewindow/include/android/hardware_buffer.h22
-rw-r--r--libs/nativewindow/include/android/native_window.h7
-rw-r--r--libs/sensor/Android.bp17
-rw-r--r--libs/sensor/OWNERS2
-rw-r--r--libs/sensor/SensorManager.cpp2
-rw-r--r--libs/sensorprivacy/Android.bp12
-rw-r--r--libs/ui/Android.bp25
-rw-r--r--libs/ui/ColorSpace.cpp6
-rw-r--r--libs/ui/GraphicBufferAllocator.cpp4
-rw-r--r--libs/ui/Region.cpp8
-rw-r--r--libs/ui/include/ui/Size.h2
-rw-r--r--libs/ui/tests/Android.bp2
-rw-r--r--libs/vr/libbufferhub/Android.bp2
-rw-r--r--libs/vr/libbufferhubqueue/Android.bp2
-rw-r--r--libs/vr/libdisplay/vsync_service.cpp4
-rw-r--r--libs/vr/libvrflinger/Android.bp1
-rw-r--r--opengl/OWNERS9
-rw-r--r--opengl/libagl/Android.bp5
-rw-r--r--opengl/libagl/context.h2
-rw-r--r--opengl/libs/Android.bp5
-rw-r--r--opengl/libs/EGL/eglApi.cpp19
-rw-r--r--opengl/libs/EGL/egl_layers.cpp2
-rw-r--r--opengl/libs/ETC1/etc1.cpp52
-rw-r--r--opengl/libs/hooks.h2
-rw-r--r--opengl/tests/EGLTest/Android.bp5
-rw-r--r--opengl/tests/gl_perf/fill_common.cpp8
-rw-r--r--services/bufferhub/Android.bp4
-rw-r--r--services/displayservice/Android.bp1
-rw-r--r--services/gpuservice/Android.bp3
-rw-r--r--services/gpuservice/OWNERS3
-rw-r--r--services/inputflinger/Android.bp66
-rw-r--r--services/inputflinger/EventHub.cpp (renamed from services/inputflinger/reader/EventHub.cpp)459
-rw-r--r--services/inputflinger/EventHub.h (renamed from services/inputflinger/reader/include/EventHub.h)106
-rw-r--r--services/inputflinger/InputClassifier.cpp159
-rw-r--r--services/inputflinger/InputClassifier.h92
-rw-r--r--services/inputflinger/InputDispatcher.cpp (renamed from services/inputflinger/dispatcher/InputDispatcher.cpp)2944
-rw-r--r--services/inputflinger/InputDispatcher.h1305
-rw-r--r--services/inputflinger/InputManager.cpp12
-rw-r--r--services/inputflinger/InputManager.h13
-rw-r--r--services/inputflinger/InputReader.cpp7534
-rw-r--r--services/inputflinger/InputReader.h1809
-rw-r--r--services/inputflinger/InputReaderFactory.cpp (renamed from services/inputflinger/reader/InputReaderFactory.cpp)6
-rw-r--r--services/inputflinger/InputReporter.cpp (renamed from services/inputflinger/reporter/InputReporter.cpp)6
-rw-r--r--services/inputflinger/TouchVideoDevice.cpp (renamed from services/inputflinger/reader/TouchVideoDevice.cpp)50
-rw-r--r--services/inputflinger/TouchVideoDevice.h (renamed from services/inputflinger/reader/include/TouchVideoDevice.h)18
-rw-r--r--services/inputflinger/dispatcher/Android.bp42
-rw-r--r--services/inputflinger/dispatcher/CancelationOptions.h53
-rw-r--r--services/inputflinger/dispatcher/Connection.cpp64
-rw-r--r--services/inputflinger/dispatcher/Connection.h74
-rw-r--r--services/inputflinger/dispatcher/Entry.cpp255
-rw-r--r--services/inputflinger/dispatcher/Entry.h223
-rw-r--r--services/inputflinger/dispatcher/InjectionState.cpp42
-rw-r--r--services/inputflinger/dispatcher/InjectionState.h60
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.h464
-rw-r--r--services/inputflinger/dispatcher/InputState.cpp370
-rw-r--r--services/inputflinger/dispatcher/InputState.h123
-rw-r--r--services/inputflinger/dispatcher/InputTarget.cpp45
-rw-r--r--services/inputflinger/dispatcher/InputTarget.h117
-rw-r--r--services/inputflinger/dispatcher/Monitor.cpp28
-rw-r--r--services/inputflinger/dispatcher/Monitor.h41
-rw-r--r--services/inputflinger/dispatcher/Queue.h88
-rw-r--r--services/inputflinger/dispatcher/TouchState.cpp159
-rw-r--r--services/inputflinger/dispatcher/TouchState.h63
-rw-r--r--services/inputflinger/dispatcher/TouchedWindow.h36
-rw-r--r--services/inputflinger/dispatcher/include/InputDispatcherConfiguration.h44
-rw-r--r--services/inputflinger/dispatcher/include/InputDispatcherFactory.h33
-rw-r--r--services/inputflinger/dispatcher/include/InputDispatcherInterface.h158
-rw-r--r--services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h123
-rw-r--r--services/inputflinger/dispatcher/include/InputDispatcherThread.h41
-rw-r--r--services/inputflinger/host/InputDriver.cpp6
-rw-r--r--services/inputflinger/host/InputFlinger.h1
-rw-r--r--services/inputflinger/include/InputReporterInterface.h (renamed from services/inputflinger/reporter/InputReporterInterface.h)2
-rw-r--r--services/inputflinger/reader/Android.bp72
-rw-r--r--services/inputflinger/reader/InputDevice.cpp338
-rw-r--r--services/inputflinger/reader/InputReader.cpp767
-rw-r--r--services/inputflinger/reader/Macros.h84
-rw-r--r--services/inputflinger/reader/include/InputDevice.h142
-rw-r--r--services/inputflinger/reader/include/InputReader.h177
-rw-r--r--services/inputflinger/reader/include/InputReaderContext.h65
-rw-r--r--services/inputflinger/reader/include/StylusState.h53
-rw-r--r--services/inputflinger/reader/mapper/CursorInputMapper.cpp480
-rw-r--r--services/inputflinger/reader/mapper/CursorInputMapper.h123
-rw-r--r--services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp92
-rw-r--r--services/inputflinger/reader/mapper/ExternalStylusInputMapper.h51
-rw-r--r--services/inputflinger/reader/mapper/InputMapper.cpp101
-rw-r--r--services/inputflinger/reader/mapper/InputMapper.h92
-rw-r--r--services/inputflinger/reader/mapper/JoystickInputMapper.cpp408
-rw-r--r--services/inputflinger/reader/mapper/JoystickInputMapper.h111
-rw-r--r--services/inputflinger/reader/mapper/KeyboardInputMapper.cpp412
-rw-r--r--services/inputflinger/reader/mapper/KeyboardInputMapper.h99
-rw-r--r--services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp361
-rw-r--r--services/inputflinger/reader/mapper/MultiTouchInputMapper.h117
-rw-r--r--services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp134
-rw-r--r--services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h49
-rw-r--r--services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp85
-rw-r--r--services/inputflinger/reader/mapper/SingleTouchInputMapper.h44
-rw-r--r--services/inputflinger/reader/mapper/SwitchInputMapper.cpp76
-rw-r--r--services/inputflinger/reader/mapper/SwitchInputMapper.h45
-rw-r--r--services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h88
-rw-r--r--services/inputflinger/reader/mapper/TouchInputMapper.cpp3909
-rw-r--r--services/inputflinger/reader/mapper/TouchInputMapper.h838
-rw-r--r--services/inputflinger/reader/mapper/VibratorInputMapper.cpp131
-rw-r--r--services/inputflinger/reader/mapper/VibratorInputMapper.h53
-rw-r--r--services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp101
-rw-r--r--services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h52
-rw-r--r--services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp59
-rw-r--r--services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h60
-rw-r--r--services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp76
-rw-r--r--services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h57
-rw-r--r--services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp162
-rw-r--r--services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h66
-rw-r--r--services/inputflinger/tests/Android.bp3
-rw-r--r--services/inputflinger/tests/InputClassifier_test.cpp55
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp8
-rw-r--r--services/inputflinger/tests/InputReader_test.cpp12
-rw-r--r--services/nativeperms/.clang-format13
-rw-r--r--services/nativeperms/Android.bp (renamed from services/inputflinger/reporter/Android.bp)37
-rw-r--r--services/nativeperms/android/os/IPermissionController.aidl25
-rw-r--r--services/nativeperms/android/os/README4
-rw-r--r--services/nativeperms/nativeperms.cpp87
-rw-r--r--services/nativeperms/nativeperms.rc4
-rw-r--r--services/schedulerservice/Android.bp2
-rw-r--r--services/sensorservice/Android.bp2
-rw-r--r--services/sensorservice/OWNERS2
-rw-r--r--services/sensorservice/SensorService.cpp11
-rw-r--r--services/sensorservice/hidl/Android.bp2
-rw-r--r--services/surfaceflinger/Android.bp16
-rw-r--r--services/surfaceflinger/BufferQueueLayer.cpp5
-rw-r--r--services/surfaceflinger/CompositionEngine/Android.bp9
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp10
-rw-r--r--services/surfaceflinger/Layer.cpp153
-rw-r--r--services/surfaceflinger/Layer.h32
-rw-r--r--services/surfaceflinger/RegionSamplingThread.cpp7
-rw-r--r--services/surfaceflinger/Scheduler/PhaseOffsets.cpp1
-rw-r--r--services/surfaceflinger/Scheduler/RefreshRateConfigs.h184
-rw-r--r--services/surfaceflinger/Scheduler/RefreshRateStats.h71
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.cpp112
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.h33
-rw-r--r--services/surfaceflinger/Scheduler/SchedulerUtils.h6
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp277
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h17
-rw-r--r--services/surfaceflinger/SurfaceFlingerProperties.cpp8
-rw-r--r--services/surfaceflinger/SurfaceFlingerProperties.h2
-rw-r--r--services/surfaceflinger/SurfaceTracing.cpp2
-rw-r--r--services/surfaceflinger/TimeStats/OWNERS3
-rw-r--r--services/surfaceflinger/layerproto/Android.bp2
-rw-r--r--services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop68
-rw-r--r--services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt138
-rw-r--r--services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt138
-rw-r--r--services/surfaceflinger/sysprop/api/current.txt1
-rw-r--r--services/surfaceflinger/sysprop/api/removed.txt1
-rw-r--r--services/surfaceflinger/sysprop/api/system-current.txt46
-rw-r--r--services/surfaceflinger/sysprop/api/system-removed.txt1
-rw-r--r--services/surfaceflinger/sysprop/api/test-current.txt1
-rw-r--r--services/surfaceflinger/sysprop/api/test-removed.txt1
-rw-r--r--services/surfaceflinger/tests/fakehwc/Android.bp2
-rw-r--r--services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp3
-rw-r--r--services/surfaceflinger/tests/unittests/CompositionTest.cpp12
-rw-r--r--services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp12
-rw-r--r--services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp112
-rw-r--r--services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp139
-rw-r--r--services/surfaceflinger/tests/unittests/SchedulerTest.cpp19
-rw-r--r--services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h4
-rw-r--r--services/surfaceflinger/version-script32.txt12
-rw-r--r--services/surfaceflinger/version-script64.txt11
-rw-r--r--services/vr/hardware_composer/Android.bp307
-rw-r--r--services/vr/hardware_composer/aidl/Android.bp27
-rw-r--r--services/vr/virtual_touchpad/Android.bp10
-rw-r--r--vulkan/libvulkan/Android.bp7
-rw-r--r--vulkan/libvulkan/api.cpp11
-rw-r--r--vulkan/libvulkan/code-generator.tmpl52
-rw-r--r--vulkan/libvulkan/driver.cpp80
-rw-r--r--vulkan/libvulkan/driver.h9
-rw-r--r--vulkan/libvulkan/driver_gen.cpp49
-rw-r--r--vulkan/libvulkan/driver_gen.h3
-rw-r--r--vulkan/libvulkan/layers_extensions.cpp57
-rw-r--r--vulkan/libvulkan/swapchain.cpp6
-rw-r--r--vulkan/nulldrv/Android.bp9
-rw-r--r--vulkan/tools/Android.bp10
-rw-r--r--vulkan/tools/vkinfo.cpp8
430 files changed, 19793 insertions, 23593 deletions
diff --git a/Android.bp b/Android.bp
index 9829c7fbad..de9ea86f1d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -7,7 +7,6 @@ ndk_headers {
}
subdirs = [
- "adbd_auth",
"cmds/*",
"headers",
"libs/*",
@@ -21,25 +20,3 @@ cc_library_headers {
vendor: true,
export_include_dirs: ["include_sensor"],
}
-
-filegroup {
- name: "framework_native_aidl_binder",
- srcs: ["aidl/binder/**/*.aidl"],
- path: "aidl/binder",
- visibility: ["//frameworks/native"],
-}
-
-filegroup {
- name: "framework_native_aidl_gui",
- srcs: ["aidl/gui/**/*.aidl"],
- path: "aidl/gui",
- visibility: ["//frameworks/native"],
-}
-
-filegroup {
- name: "framework_native_aidl",
- srcs: [
- ":framework_native_aidl_binder",
- ":framework_native_aidl_gui",
- ],
-}
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 4f7cdf3e5e..1a932c3d04 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,16 +4,13 @@ clang_format = true
[Builtin Hooks Options]
# Only turn on clang-format check for the following subfolders.
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
- include/input/
libs/binder/ndk/
libs/graphicsenv/
libs/gui/
- libs/input/
libs/renderengine/
libs/ui/
libs/vr/
services/bufferhub/
- services/inputflinger/
services/surfaceflinger/
services/vr/
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index e7d0ad0549..cc2a6f7e31 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -10,7 +10,9 @@ cc_binary {
shared_libs: [
"libbinder",
+ "libhwbinder",
"libhidlbase",
+ "libhidltransport",
"liblog",
"libutils",
"libcutils",
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 5186ad3a1f..1429bc8b07 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -1468,11 +1468,10 @@ int main(int argc, char **argv)
// Reset the trace buffer size to 1.
if (traceStop) {
+ cleanUpVendorTracing();
cleanUpUserspaceTracing();
- if (!onlyUserspace) {
- cleanUpVendorTracing();
+ if (!onlyUserspace)
cleanUpKernelTracing();
- }
}
return g_traceAborted ? 1 : 0;
diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp
index 840ae473bc..917c8132b7 100644
--- a/cmds/bugreport/bugreport.cpp
+++ b/cmds/bugreport/bugreport.cpp
@@ -37,7 +37,7 @@ int main() {
property_set("ctl.start", "dumpstate");
// Socket will not be available until service starts.
- int s = -1;
+ int s;
for (int i = 0; i < 20; i++) {
s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM);
diff --git a/cmds/bugreportz/main.cpp b/cmds/bugreportz/main.cpp
index 40346bee1f..74a95b0b57 100644
--- a/cmds/bugreportz/main.cpp
+++ b/cmds/bugreportz/main.cpp
@@ -72,7 +72,7 @@ int main(int argc, char* argv[]) {
property_set("ctl.start", "dumpstatez");
// Socket will not be available until service starts.
- int s = -1;
+ int s;
for (int i = 0; i < 20; i++) {
s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
if (s >= 0) break;
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 09aee89e1b..ee32cb4495 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -86,13 +86,15 @@ cc_defaults {
"libdumpstateaidl",
"libdumpstateutil",
"libdumputils",
- "libhardware_legacy",
"libhidlbase",
+ "libhidltransport",
"liblog",
"libutils",
],
srcs: [
+ "DumpstateSectionReporter.cpp",
"DumpstateService.cpp",
+ "utils.cpp",
],
static_libs: [
"libincidentcompanion",
@@ -118,11 +120,10 @@ cc_binary {
"kill",
"librank",
"logcat",
- "lpdump",
- "lpdumpd",
"lsmod",
"lsof",
"netstat",
+ "parse_radio_log",
"printenv",
"procrank",
"screencap",
@@ -145,12 +146,6 @@ cc_test {
"tests/dumpstate_test.cpp",
],
static_libs: ["libgmock"],
- test_config: "dumpstate_test.xml",
- data: [
- ":dumpstate_test_fixture",
- "tests/testdata/**/*",
- ],
- test_suites: ["device-tests"],
}
cc_test {
diff --git a/cmds/dumpstate/DumpstateInternal.cpp b/cmds/dumpstate/DumpstateInternal.cpp
index bbc724c4c0..33e35f7274 100644
--- a/cmds/dumpstate/DumpstateInternal.cpp
+++ b/cmds/dumpstate/DumpstateInternal.cpp
@@ -68,8 +68,7 @@ bool DropRootUser() {
}
static const std::vector<std::string> group_names{
- "log", "sdcard_r", "sdcard_rw", "mount", "inet", "net_bw_stats",
- "readproc", "bluetooth", "wakelock"};
+ "log", "sdcard_r", "sdcard_rw", "mount", "inet", "net_bw_stats", "readproc", "bluetooth"};
std::vector<gid_t> groups(group_names.size(), 0);
for (size_t i = 0; i < group_names.size(); ++i) {
grp = getgrnam(group_names[i].c_str());
@@ -117,11 +116,6 @@ bool DropRootUser() {
capdata[cap_syslog_index].effective |= cap_syslog_mask;
}
- const uint32_t cap_block_suspend_mask = CAP_TO_MASK(CAP_BLOCK_SUSPEND);
- const uint32_t cap_block_suspend_index = CAP_TO_INDEX(CAP_BLOCK_SUSPEND);
- capdata[cap_block_suspend_index].permitted |= cap_block_suspend_mask;
- capdata[cap_block_suspend_index].effective |= cap_block_suspend_mask;
-
if (capset(&capheader, &capdata[0]) != 0) {
MYLOGE("capset({%#x, %#x}) failed: %s\n", capdata[0].effective,
capdata[1].effective, strerror(errno));
diff --git a/cmds/dumpstate/DumpstateSectionReporter.cpp b/cmds/dumpstate/DumpstateSectionReporter.cpp
new file mode 100644
index 0000000000..f814bde26d
--- /dev/null
+++ b/cmds/dumpstate/DumpstateSectionReporter.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "dumpstate"
+
+#include "DumpstateSectionReporter.h"
+
+namespace android {
+namespace os {
+namespace dumpstate {
+
+DumpstateSectionReporter::DumpstateSectionReporter(const std::string& title,
+ sp<android::os::IDumpstateListener> listener,
+ bool sendReport)
+ : title_(title), listener_(listener), sendReport_(sendReport), status_(OK), size_(-1) {
+ started_ = std::chrono::steady_clock::now();
+}
+
+DumpstateSectionReporter::~DumpstateSectionReporter() {
+ if ((listener_ != nullptr) && (sendReport_)) {
+ auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now() - started_);
+ listener_->onSectionComplete(title_, status_, size_, (int32_t)elapsed.count());
+ }
+}
+
+} // namespace dumpstate
+} // namespace os
+} // namespace android
diff --git a/cmds/dumpstate/DumpstateSectionReporter.h b/cmds/dumpstate/DumpstateSectionReporter.h
new file mode 100644
index 0000000000..e971de84c5
--- /dev/null
+++ b/cmds/dumpstate/DumpstateSectionReporter.h
@@ -0,0 +1,65 @@
+/*
+ * 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 ANDROID_OS_DUMPSTATESECTIONREPORTER_H_
+#define ANDROID_OS_DUMPSTATESECTIONREPORTER_H_
+
+#include <android/os/IDumpstateListener.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace os {
+namespace dumpstate {
+
+
+/*
+ * Helper class used to report per section details to a listener.
+ *
+ * Typical usage:
+ *
+ * DumpstateSectionReporter sectionReporter(title, listener, sendReport);
+ * sectionReporter.setSize(5000);
+ *
+ */
+class DumpstateSectionReporter {
+ public:
+ DumpstateSectionReporter(const std::string& title, sp<android::os::IDumpstateListener> listener,
+ bool sendReport);
+
+ ~DumpstateSectionReporter();
+
+ void setStatus(status_t status) {
+ status_ = status;
+ }
+
+ void setSize(int size) {
+ size_ = size;
+ }
+
+ private:
+ std::string title_;
+ android::sp<android::os::IDumpstateListener> listener_;
+ bool sendReport_;
+ status_t status_;
+ int size_;
+ std::chrono::time_point<std::chrono::steady_clock> started_;
+};
+
+} // namespace dumpstate
+} // namespace os
+} // namespace android
+
+#endif // ANDROID_OS_DUMPSTATESECTIONREPORTER_H_
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index f98df99534..ddae9ea8f6 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -151,15 +151,15 @@ binder::Status DumpstateService::startBugreport(int32_t calling_uid,
signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
}
- std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
- options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
- screenshot_fd);
-
- if (bugreport_fd.get() == -1 || (options->do_fb && screenshot_fd.get() == -1)) {
+ if (bugreport_fd.get() == -1 || screenshot_fd.get() == -1) {
+ // TODO(b/111441001): screenshot fd should be optional
MYLOGE("Invalid filedescriptor");
signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
}
+ std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
+ options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
+ screenshot_fd);
ds_ = &(Dumpstate::GetInstance());
ds_->SetOptions(std::move(options));
@@ -200,7 +200,8 @@ status_t DumpstateService::dump(int fd, const Vector<String16>&) {
dprintf(fd, "id: %d\n", ds_->id_);
dprintf(fd, "pid: %d\n", ds_->pid_);
dprintf(fd, "update_progress: %s\n", ds_->options_->do_progress_updates ? "true" : "false");
- dprintf(fd, "last_percent_progress: %d\n", ds_->last_reported_percent_progress_);
+ dprintf(fd, "update_progress_threshold: %d\n", ds_->update_progress_threshold_);
+ dprintf(fd, "last_updated_progress: %d\n", ds_->last_updated_progress_);
dprintf(fd, "progress:\n");
ds_->progress_->Dump(fd, " ");
dprintf(fd, "args: %s\n", ds_->options_->args.c_str());
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 4b69607156..97c8ae2045 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -378,6 +378,34 @@ int RunCommandToFd(int fd, const std::string& title, const std::vector<std::stri
return status;
}
+int GetPidByName(const std::string& ps_name) {
+ DIR* proc_dir;
+ struct dirent* ps;
+ unsigned int pid;
+ std::string cmdline;
+
+ if (!(proc_dir = opendir("/proc"))) {
+ MYLOGE("Can't open /proc\n");
+ return -1;
+ }
+
+ while ((ps = readdir(proc_dir))) {
+ if (!(pid = atoi(ps->d_name))) {
+ continue;
+ }
+ android::base::ReadFileToString("/proc/" + std::string(ps->d_name) + "/cmdline", &cmdline);
+ if (cmdline.find(ps_name) == std::string::npos) {
+ continue;
+ } else {
+ closedir(proc_dir);
+ return pid;
+ }
+ }
+ MYLOGE("can't find the pid\n");
+ closedir(proc_dir);
+ return -1;
+}
+
} // namespace dumpstate
} // namespace os
} // namespace android
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index b7ac25c81e..d75b08c046 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -205,6 +205,12 @@ int RunCommandToFd(int fd, const std::string& title, const std::vector<std::stri
*/
int DumpFileToFd(int fd, const std::string& title, const std::string& path);
+/*
+ * Finds the process id by process name.
+ * |ps_name| the process name we want to search for
+ */
+int GetPidByName(const std::string& ps_name);
+
} // namespace dumpstate
} // namespace os
} // namespace android
diff --git a/cmds/dumpstate/TEST_MAPPING b/cmds/dumpstate/TEST_MAPPING
deleted file mode 100644
index 083944f729..0000000000
--- a/cmds/dumpstate/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "presubmit": [
- {
- "name": "dumpstate_test"
- }
- ]
-} \ No newline at end of file
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index cb2d8b8d2c..347856ddcb 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -73,7 +73,7 @@ interface IDumpstate {
* @param callingUid UID of the original application that requested the report.
* @param callingPackage package of the original application that requested the report.
* @param bugreportFd the file to which the zipped bugreport should be written
- * @param screenshotFd the file to which screenshot should be written
+ * @param screenshotFd the file to which screenshot should be written; optional
* @param bugreportMode the mode that specifies other run time options; must be one of above
* @param listener callback for updates; optional
*/
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index e486460753..ea1e467dca 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -61,4 +61,21 @@ interface IDumpstateListener {
* Called when taking bugreport finishes successfully.
*/
void onFinished();
+
+ // TODO(b/111441001): Remove old methods when not used anymore.
+ void onProgressUpdated(int progress);
+ void onMaxProgressUpdated(int maxProgress);
+
+ /**
+ * Called after every section is complete.
+ *
+ * @param name section name
+ * @param status values from status_t
+ * {@code OK} section completed successfully
+ * {@code TIMEOUT} dump timed out
+ * {@code != OK} error
+ * @param size size in bytes, may be invalid if status != OK
+ * @param durationMs duration in ms
+ */
+ void onSectionComplete(@utf8InCpp String name, int status, int size, int durationMs);
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index c5bfb42bde..5de40776b9 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -22,8 +22,6 @@
#include <inttypes.h>
#include <libgen.h>
#include <limits.h>
-#include <math.h>
-#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -34,22 +32,13 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <string.h>
-#include <sys/capability.h>
-#include <sys/inotify.h>
-#include <sys/klog.h>
-#include <time.h>
#include <unistd.h>
#include <chrono>
-#include <cmath>
#include <fstream>
#include <functional>
#include <future>
#include <memory>
-#include <numeric>
#include <regex>
#include <set>
#include <string>
@@ -69,19 +58,17 @@
#include <binder/IServiceManager.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
-#include <cutils/sockets.h>
#include <debuggerd/client.h>
#include <dumpsys.h>
#include <dumputils/dump_utils.h>
-#include <hardware_legacy/power.h>
#include <hidl/ServiceManagement.h>
-#include <log/log.h>
#include <openssl/sha.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
#include <serviceutils/PriorityDumper.h>
#include <utils/StrongPointer.h>
#include "DumpstateInternal.h"
+#include "DumpstateSectionReporter.h"
#include "DumpstateService.h"
#include "dumpstate.h"
@@ -106,29 +93,10 @@ using android::base::StringPrintf;
using android::os::IDumpstateListener;
using android::os::dumpstate::CommandOptions;
using android::os::dumpstate::DumpFileToFd;
+using android::os::dumpstate::DumpstateSectionReporter;
+using android::os::dumpstate::GetPidByName;
using android::os::dumpstate::PropertiesHelper;
-// Keep in sync with
-// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
-static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
-
-/* Most simple commands have 10 as timeout, so 5 is a good estimate */
-static const int32_t WEIGHT_FILE = 5;
-
-// TODO: temporary variables and functions used during C++ refactoring
-static Dumpstate& ds = Dumpstate::GetInstance();
-static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
- const CommandOptions& options = CommandOptions::DEFAULT,
- bool verbose_duration = false) {
- return ds.RunCommand(title, full_command, options, verbose_duration);
-}
-
-// Reasonable value for max stats.
-static const int STATS_MAX_N_RUNS = 1000;
-static const long STATS_MAX_AVERAGE = 100000;
-
-CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
-
typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
/* read before root is shed */
@@ -154,7 +122,6 @@ void add_mountinfo();
#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
#define WLUTIL "/vendor/xbin/wlutil"
#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
-#define OTA_METADATA_DIR "/metadata/ota"
// TODO(narayan): Since this information has to be kept in sync
// with tombstoned, we should just put it in a common header.
@@ -166,6 +133,7 @@ static const std::string ANR_DIR = "/data/anr/";
static const std::string ANR_FILE_PREFIX = "anr_";
// TODO: temporary variables and functions used during C++ refactoring
+static Dumpstate& ds = Dumpstate::GetInstance();
#define RETURN_IF_USER_DENIED_CONSENT() \
if (ds.IsUserConsentDenied()) { \
@@ -180,8 +148,6 @@ static const std::string ANR_FILE_PREFIX = "anr_";
func_ptr(__VA_ARGS__); \
RETURN_IF_USER_DENIED_CONSENT();
-static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
-
namespace android {
namespace os {
namespace {
@@ -254,7 +220,7 @@ int64_t GetModuleMetadataVersion() {
MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
return 0L;
}
- MYLOGD("Module metadata package name: %s\n", package_name.c_str());
+ MYLOGD("Module metadata package name: %s", package_name.c_str());
int64_t version_code;
status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
&version_code);
@@ -269,6 +235,10 @@ int64_t GetModuleMetadataVersion() {
} // namespace os
} // namespace android
+static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
+ const CommandOptions& options = CommandOptions::DEFAULT) {
+ return ds.RunCommand(title, fullCommand, options);
+}
static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
long dumpsysTimeoutMs = 0) {
@@ -301,10 +271,12 @@ static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot(
* Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
* The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
* is set, the vector only contains files that were written in the last 30 minutes.
+ * If |limit_by_count| is set, the vector only contains the ten latest files.
*/
static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
const std::string& file_prefix,
- bool limit_by_mtime) {
+ bool limit_by_mtime,
+ bool limit_by_count = true) {
const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
@@ -348,6 +320,15 @@ static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
}
+ // Sort in descending modification time so that we only keep the newest
+ // reports if |limit_by_count| is true.
+ std::sort(dump_data.begin(), dump_data.end(),
+ [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
+
+ if (limit_by_count && dump_data.size() > 10) {
+ dump_data.erase(dump_data.begin() + 10, dump_data.end());
+ }
+
return dump_data;
}
@@ -440,6 +421,108 @@ static void dump_dev_files(const char *title, const char *driverpath, const char
closedir(d);
}
+
+
+// dump anrd's trace and add to the zip file.
+// 1. check if anrd is running on this device.
+// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
+// 3. wait until the trace generation completes and add to the zip file.
+static bool dump_anrd_trace() {
+ unsigned int pid;
+ char buf[50], path[PATH_MAX];
+ struct dirent *trace;
+ struct stat st;
+ DIR *trace_dir;
+ int retry = 5;
+ long max_ctime = 0, old_mtime;
+ long long cur_size = 0;
+ const char *trace_path = "/data/misc/anrd/";
+
+ if (!ds.IsZipping()) {
+ MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
+ return false;
+ }
+
+ // find anrd's pid if it is running.
+ pid = GetPidByName("/system/bin/anrd");
+
+ if (pid > 0) {
+ if (stat(trace_path, &st) == 0) {
+ old_mtime = st.st_mtime;
+ } else {
+ MYLOGE("Failed to find: %s\n", trace_path);
+ return false;
+ }
+
+ // send SIGUSR1 to the anrd to generate a trace.
+ sprintf(buf, "%u", pid);
+ if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
+ CommandOptions::WithTimeout(1).Build())) {
+ MYLOGE("anrd signal timed out. Please manually collect trace\n");
+ return false;
+ }
+
+ while (retry-- > 0 && old_mtime == st.st_mtime) {
+ sleep(1);
+ stat(trace_path, &st);
+ }
+
+ if (retry < 0 && old_mtime == st.st_mtime) {
+ MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
+ return false;
+ }
+
+ // identify the trace file by its creation time.
+ if (!(trace_dir = opendir(trace_path))) {
+ MYLOGE("Can't open trace file under %s\n", trace_path);
+ }
+ while ((trace = readdir(trace_dir))) {
+ if (strcmp(trace->d_name, ".") == 0
+ || strcmp(trace->d_name, "..") == 0) {
+ continue;
+ }
+ sprintf(path, "%s%s", trace_path, trace->d_name);
+ if (stat(path, &st) == 0) {
+ if (st.st_ctime > max_ctime) {
+ max_ctime = st.st_ctime;
+ sprintf(buf, "%s", trace->d_name);
+ }
+ }
+ }
+ closedir(trace_dir);
+
+ // Wait until the dump completes by checking the size of the trace.
+ if (max_ctime > 0) {
+ sprintf(path, "%s%s", trace_path, buf);
+ while(true) {
+ sleep(1);
+ if (stat(path, &st) == 0) {
+ if (st.st_size == cur_size) {
+ break;
+ } else if (st.st_size > cur_size) {
+ cur_size = st.st_size;
+ } else {
+ return false;
+ }
+ } else {
+ MYLOGE("Cant stat() %s anymore\n", path);
+ return false;
+ }
+ }
+ // Add to the zip file.
+ if (!ds.AddZipEntry("anrd_trace.txt", path)) {
+ MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
+ } else {
+ android::os::UnlinkAndLogOnError(path);
+ return true;
+ }
+ } else {
+ MYLOGE("Can't stats any trace file under %s\n", trace_path);
+ }
+ }
+ return false;
+}
+
static bool skip_not_stat(const char *path) {
static const char stat[] = "/stat";
size_t len = strlen(path);
@@ -877,17 +960,6 @@ static void DoKernelLogcat() {
CommandOptions::WithTimeoutInMs(timeout_ms).Build());
}
-static void DoSystemLogcat(time_t since) {
- char since_str[80];
- strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
-
- unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
- RunCommand("SYSTEM LOG",
- {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
- since_str},
- CommandOptions::WithTimeoutInMs(timeout_ms).Build());
-}
-
static void DoLogcat() {
unsigned long timeout_ms;
// DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
@@ -900,17 +972,17 @@ static void DoLogcat() {
RunCommand(
"EVENT LOG",
{"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
- CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
+ CommandOptions::WithTimeoutInMs(timeout_ms).Build());
timeout_ms = logcat_timeout({"stats"});
RunCommand(
"STATS LOG",
{"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
- CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
+ CommandOptions::WithTimeoutInMs(timeout_ms).Build());
timeout_ms = logcat_timeout({"radio"});
RunCommand(
"RADIO LOG",
{"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
- CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
+ CommandOptions::WithTimeoutInMs(timeout_ms).Build());
RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
@@ -919,31 +991,6 @@ static void DoLogcat() {
"-v", "uid", "-d", "*:v"});
}
-static void DumpIncidentReport() {
- if (!ds.IsZipping()) {
- MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
- return;
- }
- DurationReporter duration_reporter("INCIDENT REPORT");
- const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
- auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
- O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
- if (fd < 0) {
- MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
- return;
- }
- RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
- bool empty = 0 == lseek(fd, 0, SEEK_END);
- if (!empty) {
- // Use a different name from "incident.proto"
- // /proto/incident.proto is reserved for incident service dump
- // i.e. metadata for debugging.
- ds.AddZipEntry(kProtoPath + "incident_report" + kProtoExt, path);
- }
- unlink(path.c_str());
-}
-
static void DumpIpTablesAsRoot() {
RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
@@ -955,15 +1002,6 @@ static void DumpIpTablesAsRoot() {
RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
}
-static void DumpDynamicPartitionInfo() {
- if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
- return;
- }
-
- RunCommand("LPDUMP", {"lpdump", "--all"});
- RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
-}
-
static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
anr_traces_dir.c_str());
@@ -1083,17 +1121,20 @@ static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, i
RETURN_IF_USER_DENIED_CONSENT();
std::string path(title);
path.append(" - ").append(String8(service).c_str());
+ DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
size_t bytes_written = 0;
- status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
+ status_t status = dumpsys.startDumpThread(service, args);
if (status == OK) {
dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
std::chrono::duration<double> elapsed_seconds;
status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
/* as_proto = */ false, elapsed_seconds, bytes_written);
+ section_reporter.setSize(bytes_written);
dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
bool dump_complete = (status == OK);
dumpsys.stopDumpThread(dump_complete);
}
+ section_reporter.setStatus(status);
auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - start);
@@ -1156,7 +1197,8 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori
path.append("_HIGH");
}
path.append(kProtoExt);
- status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
+ DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
+ status_t status = dumpsys.startDumpThread(service, args);
if (status == OK) {
status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
bool dumpTerminated = (status == OK);
@@ -1164,6 +1206,8 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori
}
ZipWriter::FileEntry file_entry;
ds.zip_writer_->GetLastEntry(&file_entry);
+ section_reporter.setSize(file_entry.compressed_size);
+ section_reporter.setStatus(status);
auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - start);
@@ -1270,45 +1314,6 @@ static void DumpHals() {
}
}
-static void DumpExternalFragmentationInfo() {
- struct stat st;
- if (stat("/proc/buddyinfo", &st) != 0) {
- MYLOGE("Unable to dump external fragmentation info\n");
- return;
- }
-
- printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
- std::ifstream ifs("/proc/buddyinfo");
- auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
- for (std::string line; std::getline(ifs, line);) {
- std::smatch match_results;
- if (std::regex_match(line, match_results, unusable_index_regex)) {
- std::stringstream free_pages(std::string{match_results[3]});
- std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
- std::istream_iterator<int>());
-
- int total_free_pages = 0;
- for (size_t i = 0; i < free_pages_per_order.size(); i++) {
- total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
- }
-
- printf("Node %s, zone %8s", match_results[1].str().c_str(),
- match_results[2].str().c_str());
-
- int usable_free_pages = total_free_pages;
- for (size_t i = 0; i < free_pages_per_order.size(); i++) {
- auto unusable_index = (total_free_pages - usable_free_pages) /
- static_cast<double>(total_free_pages);
- printf(" %5.3f", unusable_index);
- usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
- }
-
- printf("\n");
- }
- }
- printf("\n");
-}
-
// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
// via the consent they are shown. Ignores other errors that occur while running various
// commands. The consent checking is currently done around long running tasks, which happen to
@@ -1322,6 +1327,7 @@ static Dumpstate::RunStatus dumpstate() {
dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
RunCommand("UPTIME", {"uptime"});
DumpBlockStatFiles();
+ dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
DumpFile("MEMORY INFO", "/proc/meminfo");
RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
"pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
@@ -1334,10 +1340,11 @@ static Dumpstate::RunStatus dumpstate() {
DumpFile("ZONEINFO", "/proc/zoneinfo");
DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
DumpFile("BUDDYINFO", "/proc/buddyinfo");
- DumpExternalFragmentationInfo();
+ DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
+ DumpFile("KERNEL SYNC", "/d/sync");
RunCommand("PROCESSES AND THREADS",
{"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
@@ -1373,11 +1380,13 @@ static Dumpstate::RunStatus dumpstate() {
/* Dump Bluetooth HCI logs */
ds.AddDir("/data/misc/bluetooth/logs", true);
- if (ds.options_->do_fb && !ds.do_early_screenshot_) {
+ if (!ds.do_early_screenshot_) {
MYLOGI("taking late screenshot\n");
ds.TakeScreenshot();
}
+ DoLogcat();
+
AddAnrTraceFiles();
// NOTE: tombstones are always added as separate entries in the zip archive
@@ -1410,6 +1419,8 @@ static Dumpstate::RunStatus dumpstate() {
RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
+ RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
+
/* Binder state is expensive to look at as it uses a lot of memory. */
DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
@@ -1417,6 +1428,7 @@ static Dumpstate::RunStatus dumpstate() {
DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
+ RunDumpsys("WINSCOPE TRACE", {"window", "trace"});
/* Add window and surface trace files. */
if (!PropertiesHelper::IsUserBuild()) {
ds.AddDir(WMTRACE_DATA_DIR, false);
@@ -1515,9 +1527,6 @@ static Dumpstate::RunStatus dumpstate() {
printf("========================================================\n");
// This differs from the usual dumpsys stats, which is the stats report data.
RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
-
- RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpIncidentReport);
-
return Dumpstate::RunStatus::OK;
}
@@ -1530,16 +1539,13 @@ static Dumpstate::RunStatus dumpstate() {
* with the caller.
*/
static Dumpstate::RunStatus DumpstateDefault() {
+ // Try to dump anrd trace if the daemon is running.
+ dump_anrd_trace();
+
// Invoking the following dumpsys calls before DumpTraces() to try and
// keep the system stats as close to its initial state as possible.
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
- // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
- // buffer.
- DoLogcat();
- // Capture timestamp after first logcat to use in next logcat
- time_t logcat_ts = time(nullptr);
-
/* collect stack traces from Dalvik and native processes (needs root) */
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
@@ -1557,8 +1563,6 @@ static Dumpstate::RunStatus DumpstateDefault() {
}
add_mountinfo();
DumpIpTablesAsRoot();
- DumpDynamicPartitionInfo();
- ds.AddDir(OTA_METADATA_DIR, true);
// Capture any IPSec policies in play. No keys are exposed here.
RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
@@ -1578,19 +1582,12 @@ static Dumpstate::RunStatus DumpstateDefault() {
RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
}
- DumpFile("PSI cpu", "/proc/pressure/cpu");
- DumpFile("PSI memory", "/proc/pressure/memory");
- DumpFile("PSI io", "/proc/pressure/io");
-
if (!DropRootUser()) {
return Dumpstate::RunStatus::ERROR;
}
RETURN_IF_USER_DENIED_CONSENT();
- Dumpstate::RunStatus status = dumpstate();
- // Capture logcat since the last time we did it.
- DoSystemLogcat(logcat_ts);
- return status;
+ return dumpstate();
}
// This method collects common dumpsys for telephony and wifi
@@ -1907,21 +1904,22 @@ void Dumpstate::DumpstateBoard() {
static void ShowUsage() {
fprintf(stderr,
- "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] "
+ "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
"[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
" -h: display this help message\n"
" -b: play sound file instead of vibrate, at beginning of job\n"
" -e: play sound file instead of vibrate, at end of job\n"
- " -d: append date to filename\n"
- " -p: capture screenshot to filename.png\n"
- " -z: generate zipped file\n"
+ " -o: write to file (instead of stdout)\n"
+ " -d: append date to filename (requires -o)\n"
+ " -p: capture screenshot to filename.png (requires -o)\n"
+ " -z: generate zipped file (requires -o)\n"
" -s: write output to control socket (for init)\n"
- " -S: write file location to control socket (for init; requires -z)\n"
+ " -S: write file location to control socket (for init; requires -o and -z)\n"
" -q: disable vibrate\n"
- " -B: send broadcast when finished\n"
+ " -B: send broadcast when finished (requires -o)\n"
" -P: send broadcast when started and update system properties on "
- "progress (requires -B)\n"
- " -R: take bugreport in remote mode (requires -z, -d and -B, "
+ "progress (requires -o and -B)\n"
+ " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
"shouldn't be used with -P)\n"
" -w: start binder service and make it wait for a call to startBugreport\n"
" -v: prints the dumpstate header and exit\n");
@@ -2033,7 +2031,7 @@ static void SendBroadcast(const std::string& action, const std::vector<std::stri
static void Vibrate(int duration_ms) {
// clang-format off
- RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
+ RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
CommandOptions::WithTimeout(10)
.Log("Vibrate: '%s'\n")
.Always()
@@ -2405,6 +2403,7 @@ Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[])
}
}
+ // TODO: use helper function to convert argv into a string
for (int i = 0; i < argc; i++) {
args += argv[i];
if (i < argc - 1) {
@@ -2555,13 +2554,6 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
MYLOGI("begin\n");
- if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
- MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
- } else {
- // Wake lock will be released automatically on process death
- MYLOGD("Wake lock acquired.\n");
- }
-
register_sig_handler();
// TODO(b/111441001): maybe skip if already started?
@@ -2635,8 +2627,13 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
}
if (options_->do_fb && do_early_screenshot_) {
- MYLOGI("taking early screenshot\n");
- TakeScreenshot();
+ if (screenshot_path_.empty()) {
+ // should not have happened
+ MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
+ } else {
+ MYLOGI("taking early screenshot\n");
+ TakeScreenshot();
+ }
}
if (options_->do_zip_file && zip_file != nullptr) {
@@ -2692,7 +2689,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
// Dump state for the default case. This also drops root.
RunStatus s = DumpstateDefault();
if (s != RunStatus::OK) {
- if (s == RunStatus::USER_CONSENT_DENIED) {
+ if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
HandleUserConsentDenied();
}
return s;
@@ -2888,833 +2885,3 @@ int run_main(int argc, char* argv[]) {
exit(2);
}
}
-
-// TODO(111441001): Default DumpOptions to sensible values.
-Dumpstate::Dumpstate(const std::string& version)
- : pid_(getpid()),
- options_(new Dumpstate::DumpOptions()),
- last_reported_percent_progress_(0),
- version_(version),
- now_(time(nullptr)) {
-}
-
-Dumpstate& Dumpstate::GetInstance() {
- static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
- return singleton_;
-}
-
-DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose)
- : title_(title), logcat_only_(logcat_only), verbose_(verbose) {
- if (!title_.empty()) {
- started_ = Nanotime();
- }
-}
-
-DurationReporter::~DurationReporter() {
- if (!title_.empty()) {
- float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
- if (elapsed < .5f && !verbose_) {
- return;
- }
- MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
- if (logcat_only_) {
- return;
- }
- // Use "Yoda grammar" to make it easier to grep|sort sections.
- printf("------ %.3fs was the duration of '%s' ------\n", elapsed, title_.c_str());
- }
-}
-
-const int32_t Progress::kDefaultMax = 5000;
-
-Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
-}
-
-Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
- : Progress(initial_max, growth_factor, "") {
- progress_ = progress;
-}
-
-Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
- : initial_max_(initial_max),
- progress_(0),
- max_(initial_max),
- growth_factor_(growth_factor),
- n_runs_(0),
- average_max_(0),
- path_(path) {
- if (!path_.empty()) {
- Load();
- }
-}
-
-void Progress::Load() {
- MYLOGD("Loading stats from %s\n", path_.c_str());
- std::string content;
- if (!android::base::ReadFileToString(path_, &content)) {
- MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
- return;
- }
- if (content.empty()) {
- MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
- return;
- }
- std::vector<std::string> lines = android::base::Split(content, "\n");
-
- if (lines.size() < 1) {
- MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
- (int)lines.size(), max_);
- return;
- }
- char* ptr;
- n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
- average_max_ = strtol(ptr, nullptr, 10);
- if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
- average_max_ > STATS_MAX_AVERAGE) {
- MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
- initial_max_ = Progress::kDefaultMax;
- } else {
- initial_max_ = average_max_;
- }
- max_ = initial_max_;
-
- MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
-}
-
-void Progress::Save() {
- int32_t total = n_runs_ * average_max_ + progress_;
- int32_t runs = n_runs_ + 1;
- int32_t average = floor(((float)total) / runs);
- MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
- path_.c_str());
- if (path_.empty()) {
- return;
- }
-
- std::string content = android::base::StringPrintf("%d %d\n", runs, average);
- if (!android::base::WriteStringToFile(content, path_)) {
- MYLOGE("Could not save stats on %s\n", path_.c_str());
- }
-}
-
-int32_t Progress::Get() const {
- return progress_;
-}
-
-bool Progress::Inc(int32_t delta_sec) {
- bool changed = false;
- if (delta_sec >= 0) {
- progress_ += delta_sec;
- if (progress_ > max_) {
- int32_t old_max = max_;
- max_ = floor((float)progress_ * growth_factor_);
- MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
- changed = true;
- }
- }
- return changed;
-}
-
-int32_t Progress::GetMax() const {
- return max_;
-}
-
-int32_t Progress::GetInitialMax() const {
- return initial_max_;
-}
-
-void Progress::Dump(int fd, const std::string& prefix) const {
- const char* pr = prefix.c_str();
- dprintf(fd, "%sprogress: %d\n", pr, progress_);
- dprintf(fd, "%smax: %d\n", pr, max_);
- dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
- dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
- dprintf(fd, "%spath: %s\n", pr, path_.c_str());
- dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
- dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
-}
-
-bool Dumpstate::IsZipping() const {
- return zip_writer_ != nullptr;
-}
-
-std::string Dumpstate::GetPath(const std::string& suffix) const {
- return GetPath(bugreport_internal_dir_, suffix);
-}
-
-std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
- return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
- name_.c_str(), suffix.c_str());
-}
-
-void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
- progress_ = std::move(progress);
-}
-
-void for_each_userid(void (*func)(int), const char *header) {
- std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
- "for_each_userid(%s)", header);
- DurationReporter duration_reporter(title);
- if (PropertiesHelper::IsDryRun()) return;
-
- DIR *d;
- struct dirent *de;
-
- if (header) printf("\n------ %s ------\n", header);
- func(0);
-
- if (!(d = opendir("/data/system/users"))) {
- printf("Failed to open /data/system/users (%s)\n", strerror(errno));
- return;
- }
-
- while ((de = readdir(d))) {
- int userid;
- if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
- continue;
- }
- func(userid);
- }
-
- closedir(d);
-}
-
-static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
- DIR *d;
- struct dirent *de;
-
- if (!(d = opendir("/proc"))) {
- printf("Failed to open /proc (%s)\n", strerror(errno));
- return;
- }
-
- if (header) printf("\n------ %s ------\n", header);
- while ((de = readdir(d))) {
- if (ds.IsUserConsentDenied()) {
- MYLOGE(
- "Returning early because user denied consent to share bugreport with calling app.");
- closedir(d);
- return;
- }
- int pid;
- int fd;
- char cmdpath[255];
- char cmdline[255];
-
- if (!(pid = atoi(de->d_name))) {
- continue;
- }
-
- memset(cmdline, 0, sizeof(cmdline));
-
- snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
- if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
- TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
- close(fd);
- if (cmdline[0]) {
- helper(pid, cmdline, arg);
- continue;
- }
- }
-
- // if no cmdline, a kernel thread has comm
- snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
- if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
- TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
- close(fd);
- if (cmdline[1]) {
- cmdline[0] = '[';
- size_t len = strcspn(cmdline, "\f\b\r\n");
- cmdline[len] = ']';
- cmdline[len+1] = '\0';
- }
- }
- if (!cmdline[0]) {
- strcpy(cmdline, "N/A");
- }
- helper(pid, cmdline, arg);
- }
-
- closedir(d);
-}
-
-static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
- for_each_pid_func *func = (for_each_pid_func*) arg;
- func(pid, cmdline);
-}
-
-void for_each_pid(for_each_pid_func func, const char *header) {
- std::string title = header == nullptr ? "for_each_pid"
- : android::base::StringPrintf("for_each_pid(%s)", header);
- DurationReporter duration_reporter(title);
- if (PropertiesHelper::IsDryRun()) return;
-
- __for_each_pid(for_each_pid_helper, header, (void *) func);
-}
-
-static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
- DIR *d;
- struct dirent *de;
- char taskpath[255];
- for_each_tid_func *func = (for_each_tid_func *) arg;
-
- snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
-
- if (!(d = opendir(taskpath))) {
- printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
- return;
- }
-
- func(pid, pid, cmdline);
-
- while ((de = readdir(d))) {
- if (ds.IsUserConsentDenied()) {
- MYLOGE(
- "Returning early because user denied consent to share bugreport with calling app.");
- closedir(d);
- return;
- }
- int tid;
- int fd;
- char commpath[255];
- char comm[255];
-
- if (!(tid = atoi(de->d_name))) {
- continue;
- }
-
- if (tid == pid)
- continue;
-
- snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
- memset(comm, 0, sizeof(comm));
- if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
- strcpy(comm, "N/A");
- } else {
- char *c;
- TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
- close(fd);
-
- c = strrchr(comm, '\n');
- if (c) {
- *c = '\0';
- }
- }
- func(pid, tid, comm);
- }
-
- closedir(d);
-}
-
-void for_each_tid(for_each_tid_func func, const char *header) {
- std::string title = header == nullptr ? "for_each_tid"
- : android::base::StringPrintf("for_each_tid(%s)", header);
- DurationReporter duration_reporter(title);
-
- if (PropertiesHelper::IsDryRun()) return;
-
- __for_each_pid(for_each_tid_helper, header, (void *) func);
-}
-
-void show_wchan(int pid, int tid, const char *name) {
- if (PropertiesHelper::IsDryRun()) return;
-
- char path[255];
- char buffer[255];
- int fd, ret, save_errno;
- char name_buffer[255];
-
- memset(buffer, 0, sizeof(buffer));
-
- snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
- if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
- printf("Failed to open '%s' (%s)\n", path, strerror(errno));
- return;
- }
-
- ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
- save_errno = errno;
- close(fd);
-
- if (ret < 0) {
- printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
- return;
- }
-
- snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
- pid == tid ? 0 : 3, "", name);
-
- printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
-
- return;
-}
-
-// print time in centiseconds
-static void snprcent(char *buffer, size_t len, size_t spc,
- unsigned long long time) {
- static long hz; // cache discovered hz
-
- if (hz <= 0) {
- hz = sysconf(_SC_CLK_TCK);
- if (hz <= 0) {
- hz = 1000;
- }
- }
-
- // convert to centiseconds
- time = (time * 100 + (hz / 2)) / hz;
-
- char str[16];
-
- snprintf(str, sizeof(str), " %llu.%02u",
- time / 100, (unsigned)(time % 100));
- size_t offset = strlen(buffer);
- snprintf(buffer + offset, (len > offset) ? len - offset : 0,
- "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
-}
-
-// print permille as a percent
-static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
- char str[16];
-
- snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
- size_t offset = strlen(buffer);
- snprintf(buffer + offset, (len > offset) ? len - offset : 0,
- "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
-}
-
-void show_showtime(int pid, const char *name) {
- if (PropertiesHelper::IsDryRun()) return;
-
- char path[255];
- char buffer[1023];
- int fd, ret, save_errno;
-
- memset(buffer, 0, sizeof(buffer));
-
- snprintf(path, sizeof(path), "/proc/%d/stat", pid);
- if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
- printf("Failed to open '%s' (%s)\n", path, strerror(errno));
- return;
- }
-
- ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
- save_errno = errno;
- close(fd);
-
- if (ret < 0) {
- printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
- return;
- }
-
- // field 14 is utime
- // field 15 is stime
- // field 42 is iotime
- unsigned long long utime = 0, stime = 0, iotime = 0;
- if (sscanf(buffer,
- "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
- "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
- "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
- "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
- &utime, &stime, &iotime) != 3) {
- return;
- }
-
- unsigned long long total = utime + stime;
- if (!total) {
- return;
- }
-
- unsigned permille = (iotime * 1000 + (total / 2)) / total;
- if (permille > 1000) {
- permille = 1000;
- }
-
- // try to beautify and stabilize columns at <80 characters
- snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
- if ((name[0] != '[') || utime) {
- snprcent(buffer, sizeof(buffer), 57, utime);
- }
- snprcent(buffer, sizeof(buffer), 65, stime);
- if ((name[0] != '[') || iotime) {
- snprcent(buffer, sizeof(buffer), 73, iotime);
- }
- if (iotime) {
- snprdec(buffer, sizeof(buffer), 79, permille);
- }
- puts(buffer); // adds a trailing newline
-
- return;
-}
-
-void do_dmesg() {
- const char *title = "KERNEL LOG (dmesg)";
- DurationReporter duration_reporter(title);
- printf("------ %s ------\n", title);
-
- if (PropertiesHelper::IsDryRun()) return;
-
- /* Get size of kernel buffer */
- int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
- if (size <= 0) {
- printf("Unexpected klogctl return value: %d\n\n", size);
- return;
- }
- char *buf = (char *) malloc(size + 1);
- if (buf == nullptr) {
- printf("memory allocation failed\n\n");
- return;
- }
- int retval = klogctl(KLOG_READ_ALL, buf, size);
- if (retval < 0) {
- printf("klogctl failure\n\n");
- free(buf);
- return;
- }
- buf[retval] = '\0';
- printf("%s\n\n", buf);
- free(buf);
- return;
-}
-
-void do_showmap(int pid, const char *name) {
- char title[255];
- char arg[255];
-
- snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
- snprintf(arg, sizeof(arg), "%d", pid);
- RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
-}
-
-int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
- DurationReporter duration_reporter(title);
-
- int status = DumpFileToFd(STDOUT_FILENO, title, path);
-
- UpdateProgress(WEIGHT_FILE);
-
- return status;
-}
-
-int read_file_as_long(const char *path, long int *output) {
- int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
- if (fd < 0) {
- int err = errno;
- MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
- return -1;
- }
- char buffer[50];
- ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
- if (bytes_read == -1) {
- MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
- return -2;
- }
- if (bytes_read == 0) {
- MYLOGE("File %s is empty\n", path);
- return -3;
- }
- *output = atoi(buffer);
- return 0;
-}
-
-/* calls skip to gate calling dump_from_fd recursively
- * in the specified directory. dump_from_fd defaults to
- * dump_file_from_fd above when set to NULL. skip defaults
- * to false when set to NULL. dump_from_fd will always be
- * called with title NULL.
- */
-int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
- int (*dump_from_fd)(const char* title, const char* path, int fd)) {
- DurationReporter duration_reporter(title);
- DIR *dirp;
- struct dirent *d;
- char *newpath = nullptr;
- const char *slash = "/";
- int retval = 0;
-
- if (!title.empty()) {
- printf("------ %s (%s) ------\n", title.c_str(), dir);
- }
- if (PropertiesHelper::IsDryRun()) return 0;
-
- if (dir[strlen(dir) - 1] == '/') {
- ++slash;
- }
- dirp = opendir(dir);
- if (dirp == nullptr) {
- retval = -errno;
- MYLOGE("%s: %s\n", dir, strerror(errno));
- return retval;
- }
-
- if (!dump_from_fd) {
- dump_from_fd = dump_file_from_fd;
- }
- for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
- if ((d->d_name[0] == '.')
- && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
- || (d->d_name[1] == '\0'))) {
- continue;
- }
- asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
- (d->d_type == DT_DIR) ? "/" : "");
- if (!newpath) {
- retval = -errno;
- continue;
- }
- if (skip && (*skip)(newpath)) {
- continue;
- }
- if (d->d_type == DT_DIR) {
- int ret = dump_files("", newpath, skip, dump_from_fd);
- if (ret < 0) {
- retval = ret;
- }
- continue;
- }
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
- if (fd.get() < 0) {
- retval = -1;
- printf("*** %s: %s\n", newpath, strerror(errno));
- continue;
- }
- (*dump_from_fd)(nullptr, newpath, fd.get());
- }
- closedir(dirp);
- if (!title.empty()) {
- printf("\n");
- }
- return retval;
-}
-
-/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
- * it's possible to avoid issues where opening the file itself can get
- * stuck.
- */
-int dump_file_from_fd(const char *title, const char *path, int fd) {
- if (PropertiesHelper::IsDryRun()) return 0;
-
- int flags = fcntl(fd, F_GETFL);
- if (flags == -1) {
- printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
- return -1;
- } else if (!(flags & O_NONBLOCK)) {
- printf("*** %s: fd must have O_NONBLOCK set.\n", path);
- return -1;
- }
- return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
-}
-
-int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
- const CommandOptions& options, bool verbose_duration) {
- DurationReporter duration_reporter(title, false /* logcat_only */, verbose_duration);
-
- int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
-
- /* TODO: for now we're simplifying the progress calculation by using the
- * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
- * where its weight should be much higher proportionally to its timeout.
- * Ideally, it should use a options.EstimatedDuration() instead...*/
- UpdateProgress(options.Timeout());
-
- return status;
-}
-
-void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
- const CommandOptions& options, long dumpsysTimeoutMs) {
- long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
- std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
- dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
- RunCommand(title, dumpsys, options);
-}
-
-int open_socket(const char *service) {
- int s = android_get_control_socket(service);
- if (s < 0) {
- MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
- return -1;
- }
- fcntl(s, F_SETFD, FD_CLOEXEC);
-
- // Set backlog to 0 to make sure that queue size will be minimum.
- // In Linux, because the minimum queue will be 1, connect() will be blocked
- // if the other clients already called connect() and the connection request was not accepted.
- if (listen(s, 0) < 0) {
- MYLOGE("listen(control socket): %s\n", strerror(errno));
- return -1;
- }
-
- struct sockaddr addr;
- socklen_t alen = sizeof(addr);
- int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
-
- // Close socket just after accept(), to make sure that connect() by client will get error
- // when the socket is used by the other services.
- // There is still a race condition possibility between accept and close, but there is no way
- // to close-on-accept atomically.
- // See detail; b/123306389#comment25
- close(s);
-
- if (fd < 0) {
- MYLOGE("accept(control socket): %s\n", strerror(errno));
- return -1;
- }
-
- return fd;
-}
-
-/* redirect output to a service control socket */
-bool redirect_to_socket(FILE* redirect, const char* service) {
- int fd = open_socket(service);
- if (fd == -1) {
- return false;
- }
- fflush(redirect);
- // TODO: handle dup2 failure
- TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
- close(fd);
- return true;
-}
-
-// TODO: should call is_valid_output_file and/or be merged into it.
-void create_parent_dirs(const char *path) {
- char *chp = const_cast<char *> (path);
-
- /* skip initial slash */
- if (chp[0] == '/')
- chp++;
-
- /* create leading directories, if necessary */
- struct stat dir_stat;
- while (chp && chp[0]) {
- chp = strchr(chp, '/');
- if (chp) {
- *chp = 0;
- if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
- MYLOGI("Creating directory %s\n", path);
- if (mkdir(path, 0770)) { /* drwxrwx--- */
- MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
- } else if (chown(path, AID_SHELL, AID_SHELL)) {
- MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
- }
- }
- *chp++ = '/';
- }
- }
-}
-
-bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
- create_parent_dirs(path);
-
- int fd = TEMP_FAILURE_RETRY(open(path,
- O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
- if (fd < 0) {
- MYLOGE("%s: %s\n", path, strerror(errno));
- return false;
- }
-
- TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
- close(fd);
- return true;
-}
-
-bool redirect_to_file(FILE* redirect, char* path) {
- return _redirect_to_file(redirect, path, O_TRUNC);
-}
-
-bool redirect_to_existing_file(FILE* redirect, char* path) {
- return _redirect_to_file(redirect, path, O_APPEND);
-}
-
-void dump_route_tables() {
- DurationReporter duration_reporter("DUMP ROUTE TABLES");
- if (PropertiesHelper::IsDryRun()) return;
- const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
- ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
- FILE* fp = fopen(RT_TABLES_PATH, "re");
- if (!fp) {
- printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
- return;
- }
- char table[16];
- // Each line has an integer (the table number), a space, and a string (the table name). We only
- // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
- // Add a fixed max limit so this doesn't go awry.
- for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
- RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
- RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
- }
- fclose(fp);
-}
-
-// TODO: make this function thread safe if sections are generated in parallel.
-void Dumpstate::UpdateProgress(int32_t delta_sec) {
- if (progress_ == nullptr) {
- MYLOGE("UpdateProgress: progress_ not set\n");
- return;
- }
-
- // Always update progess so stats can be tuned...
- progress_->Inc(delta_sec);
-
- // ...but only notifiy listeners when necessary.
- if (!options_->do_progress_updates) return;
-
- int progress = progress_->Get();
- int max = progress_->GetMax();
- int percent = 100 * progress / max;
-
- if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
- return;
- }
- last_reported_percent_progress_ = percent;
-
- if (control_socket_fd_ >= 0) {
- dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
- fsync(control_socket_fd_);
- }
-
- if (listener_ != nullptr) {
- if (percent % 5 == 0) {
- // We don't want to spam logcat, so only log multiples of 5.
- MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max,
- percent);
- } else {
- // stderr is ignored on normal invocations, but useful when calling
- // /system/bin/dumpstate directly for debuggging.
- fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
- progress, max, percent);
- }
-
- listener_->onProgress(percent);
- }
-}
-
-void Dumpstate::TakeScreenshot(const std::string& path) {
- const std::string& real_path = path.empty() ? screenshot_path_ : path;
- int status =
- RunCommand("", {"/system/bin/screencap", "-p", real_path},
- CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
- if (status == 0) {
- MYLOGD("Screenshot saved on %s\n", real_path.c_str());
- } else {
- MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
- }
-}
-
-bool is_dir(const char* pathname) {
- struct stat info;
- if (stat(pathname, &info) == -1) {
- return false;
- }
- return S_ISDIR(info.st_mode);
-}
-
-time_t get_mtime(int fd, time_t default_mtime) {
- struct stat info;
- if (fstat(fd, &info) == -1) {
- return default_mtime;
- }
- return info.st_mtime;
-}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 82bf8219a2..d02ec759a7 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -73,15 +73,13 @@ extern "C" {
*/
class DurationReporter {
public:
- explicit DurationReporter(const std::string& title, bool logcat_only = false,
- bool verbose = false);
+ explicit DurationReporter(const std::string& title, bool logcat_only = false);
~DurationReporter();
private:
std::string title_;
bool logcat_only_;
- bool verbose_;
uint64_t started_;
DISALLOW_COPY_AND_ASSIGN(DurationReporter);
@@ -226,8 +224,7 @@ class Dumpstate {
*/
int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
const android::os::dumpstate::CommandOptions& options =
- android::os::dumpstate::CommandOptions::DEFAULT,
- bool verbose_duration = false);
+ android::os::dumpstate::CommandOptions::DEFAULT);
/*
* Runs `dumpsys` with the given arguments, automatically setting its timeout
@@ -403,8 +400,12 @@ class Dumpstate {
// Runtime options.
std::unique_ptr<DumpOptions> options_;
- // Last progress that was sent to the listener [0-100].
- int last_reported_percent_progress_ = 0;
+ // How frequently the progess should be updated;the listener will only be notificated when the
+ // delta from the previous update is more than the threshold.
+ int32_t update_progress_threshold_ = 100;
+
+ // Last progress that triggered a listener updated
+ int32_t last_updated_progress_;
// Whether it should take an screenshot earlier in the process.
bool do_early_screenshot_ = false;
@@ -440,7 +441,8 @@ class Dumpstate {
// Full path of the bugreport file, be it zip or text, inside bugreport_internal_dir_.
std::string path_;
- // Full path of the file containing the screenshot (when requested).
+ // TODO: If temporary this should be removed at the end.
+ // Full path of the temporary file containing the screenshot (when requested).
std::string screenshot_path_;
// Pointer to the zipped file.
@@ -584,6 +586,9 @@ bool is_dir(const char* pathname);
/** Gets the last modification time of a file, or default time if file is not found. */
time_t get_mtime(int fd, time_t default_mtime);
+/* Dumps eMMC Extended CSD data. */
+void dump_emmc_ecsd(const char *ext_csd_path);
+
/** Gets command-line arguments. */
void format_args(int argc, const char *argv[], std::string *args);
diff --git a/cmds/dumpstate/dumpstate_test.xml b/cmds/dumpstate/dumpstate_test.xml
deleted file mode 100644
index e4e4a30a1e..0000000000
--- a/cmds/dumpstate/dumpstate_test.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Config for dumpstate_test">
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="push" value="dumpstate_test->/data/local/tmp/dumpstate_test" />
- </target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
- <option name="test-suite-tag" value="apct" />
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
- <option name="file-exclusion-filter-regex" value=".*/dumpstate_test_fixture" />
- <option name="file-exclusion-filter-regex" value=".*/tests/.*" />
- <option name="module-name" value="dumpstate_test" />
- </test>
-</configuration>
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 7e6f6f53e5..fc3642c912 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -14,21 +14,20 @@
* limitations under the License.
*/
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <fcntl.h>
+#include <libgen.h>
+
#include <android-base/file.h>
#include <android/os/BnDumpstate.h>
#include <android/os/BnDumpstateListener.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
-#include <fcntl.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <libgen.h>
#include <ziparchive/zip_archive.h>
-#include <fstream>
-#include <regex>
-
#include "dumpstate.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
@@ -45,11 +44,6 @@ class DumpstateListener;
namespace {
-struct SectionInfo {
- std::string name;
- int32_t size_bytes;
-};
-
sp<IDumpstate> GetDumpstateService() {
return android::interface_cast<IDumpstate>(
android::defaultServiceManager()->getService(String16("dumpstate")));
@@ -61,80 +55,15 @@ int OpenForWrite(const std::string& filename) {
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
}
-void GetEntry(const ZipArchiveHandle archive, const std::string_view entry_name, ZipEntry* data) {
- int32_t e = FindEntry(archive, entry_name, data);
- EXPECT_EQ(e, 0) << ErrorCodeString(e) << " entry name: " << entry_name;
-}
-
-// Extracts the main bugreport txt from the given archive and writes into output_fd.
-void ExtractBugreport(const ZipArchiveHandle* handle, int output_fd) {
- // Read contents of main_entry.txt which is a single line indicating the name of the zip entry
- // that contains the main bugreport txt.
- ZipEntry main_entry;
- GetEntry(*handle, "main_entry.txt", &main_entry);
- std::string bugreport_txt_name;
- bugreport_txt_name.resize(main_entry.uncompressed_length);
- ExtractToMemory(*handle, &main_entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
- main_entry.uncompressed_length);
-
- // Read the main bugreport txt and extract to output_fd.
- ZipEntry entry;
- GetEntry(*handle, bugreport_txt_name, &entry);
- ExtractEntryToFile(*handle, &entry, output_fd);
-}
-
-bool IsSectionStart(const std::string& line, std::string* section_name) {
- static const std::regex kSectionStart = std::regex{"DUMP OF SERVICE (.*):"};
- std::smatch match;
- if (std::regex_match(line, match, kSectionStart)) {
- *section_name = match.str(1);
- return true;
- }
- return false;
-}
-
-bool IsSectionEnd(const std::string& line) {
- // Not all lines that contain "was the duration of" is a section end, but all section ends do
- // contain "was the duration of". The disambiguation can be done by the caller.
- return (line.find("was the duration of") != std::string::npos);
-}
-
-// Extracts the zipped bugreport and identifies the sections.
-void ParseSections(const std::string& zip_path, std::vector<SectionInfo>* sections) {
- // Open the archive
- ZipArchiveHandle handle;
- ASSERT_EQ(OpenArchive(zip_path.c_str(), &handle), 0);
-
- // Extract the main entry to a temp file
- TemporaryFile tmp_binary;
- ASSERT_NE(-1, tmp_binary.fd);
- ExtractBugreport(&handle, tmp_binary.fd);
-
- // Read line by line and identify sections
- std::ifstream ifs(tmp_binary.path, std::ifstream::in);
- std::string line;
- int section_bytes = 0;
- std::string current_section_name;
- while (std::getline(ifs, line)) {
- std::string section_name;
- if (IsSectionStart(line, &section_name)) {
- section_bytes = 0;
- current_section_name = section_name;
- } else if (IsSectionEnd(line)) {
- if (!current_section_name.empty()) {
- sections->push_back({current_section_name, section_bytes});
- }
- current_section_name = "";
- } else if (!current_section_name.empty()) {
- section_bytes += line.length();
- }
- }
-
- CloseArchive(handle);
-}
-
} // namespace
+struct SectionInfo {
+ std::string name;
+ status_t status;
+ int32_t size_bytes;
+ int32_t duration_ms;
+};
+
/**
* Listens to bugreport progress and updates the user by writing the progress to STDOUT. All the
* section details generated by dumpstate are added to a vector to be used by Tests later.
@@ -167,6 +96,26 @@ class DumpstateListener : public BnDumpstateListener {
return binder::Status::ok();
}
+ binder::Status onProgressUpdated(int32_t progress) override {
+ dprintf(out_fd_, "\rIn progress %d/%d", progress, max_progress_);
+ return binder::Status::ok();
+ }
+
+ binder::Status onMaxProgressUpdated(int32_t max_progress) override {
+ std::lock_guard<std::mutex> lock(lock_);
+ max_progress_ = max_progress;
+ return binder::Status::ok();
+ }
+
+ binder::Status onSectionComplete(const ::std::string& name, int32_t status, int32_t size_bytes,
+ int32_t duration_ms) override {
+ std::lock_guard<std::mutex> lock(lock_);
+ if (sections_.get() != nullptr) {
+ sections_->push_back({name, status, size_bytes, duration_ms});
+ }
+ return binder::Status::ok();
+ }
+
bool getIsFinished() {
std::lock_guard<std::mutex> lock(lock_);
return is_finished_;
@@ -179,6 +128,7 @@ class DumpstateListener : public BnDumpstateListener {
private:
int out_fd_;
+ int max_progress_ = 5000;
int error_code_ = -1;
bool is_finished_ = false;
std::shared_ptr<std::vector<SectionInfo>> sections_;
@@ -216,8 +166,8 @@ class ZippedBugreportGenerationTest : public Test {
duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
}
- static const std::string getZipFilePath() {
- return ds.GetPath(".zip");
+ static const char* getZipFilePath() {
+ return ds.GetPath(".zip").c_str();
}
};
std::shared_ptr<std::vector<SectionInfo>> ZippedBugreportGenerationTest::sections =
@@ -226,12 +176,12 @@ Dumpstate& ZippedBugreportGenerationTest::ds = Dumpstate::GetInstance();
std::chrono::milliseconds ZippedBugreportGenerationTest::duration = 0s;
TEST_F(ZippedBugreportGenerationTest, IsGeneratedWithoutErrors) {
- EXPECT_EQ(access(getZipFilePath().c_str(), F_OK), 0);
+ EXPECT_EQ(access(getZipFilePath(), F_OK), 0);
}
TEST_F(ZippedBugreportGenerationTest, Is3MBto30MBinSize) {
struct stat st;
- EXPECT_EQ(stat(getZipFilePath().c_str(), &st), 0);
+ EXPECT_EQ(stat(getZipFilePath(), &st), 0);
EXPECT_GE(st.st_size, 3000000 /* 3MB */);
EXPECT_LE(st.st_size, 30000000 /* 30MB */);
}
@@ -250,7 +200,7 @@ class ZippedBugReportContentsTest : public Test {
public:
ZipArchiveHandle handle;
void SetUp() {
- ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath().c_str(), &handle), 0);
+ ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath(), &handle), 0);
}
void TearDown() {
CloseArchive(handle);
@@ -258,30 +208,29 @@ class ZippedBugReportContentsTest : public Test {
void FileExists(const char* filename, uint32_t minsize, uint32_t maxsize) {
ZipEntry entry;
- GetEntry(handle, filename, &entry);
+ EXPECT_EQ(FindEntry(handle, ZipString(filename), &entry), 0);
EXPECT_GT(entry.uncompressed_length, minsize);
EXPECT_LT(entry.uncompressed_length, maxsize);
}
};
TEST_F(ZippedBugReportContentsTest, ContainsMainEntry) {
- ZipEntry main_entry;
+ ZipEntry mainEntryLoc;
// contains main entry name file
- GetEntry(handle, "main_entry.txt", &main_entry);
+ EXPECT_EQ(FindEntry(handle, ZipString("main_entry.txt"), &mainEntryLoc), 0);
- std::string bugreport_txt_name;
- bugreport_txt_name.resize(main_entry.uncompressed_length);
- ExtractToMemory(handle, &main_entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
- main_entry.uncompressed_length);
+ char* buf = new char[mainEntryLoc.uncompressed_length];
+ ExtractToMemory(handle, &mainEntryLoc, (uint8_t*)buf, mainEntryLoc.uncompressed_length);
+ delete[] buf;
// contains main entry file
- FileExists(bugreport_txt_name.c_str(), 1000000U, 50000000U);
+ FileExists(buf, 1000000U, 50000000U);
}
TEST_F(ZippedBugReportContentsTest, ContainsVersion) {
ZipEntry entry;
// contains main entry name file
- GetEntry(handle, "version.txt", &entry);
+ EXPECT_EQ(FindEntry(handle, ZipString("version.txt"), &entry), 0);
char* buf = new char[entry.uncompressed_length + 1];
ExtractToMemory(handle, &entry, (uint8_t*)buf, entry.uncompressed_length);
@@ -295,10 +244,6 @@ TEST_F(ZippedBugReportContentsTest, ContainsBoardSpecificFiles) {
FileExists("dumpstate_board.txt", 100000U, 1000000U);
}
-TEST_F(ZippedBugReportContentsTest, ContainsProtoFile) {
- FileExists("proto/activity.proto", 100000U, 1000000U);
-}
-
// Spot check on some files pulled from the file system
TEST_F(ZippedBugReportContentsTest, ContainsSomeFileSystemFiles) {
// FS/proc/*/mountinfo size > 0
@@ -313,11 +258,6 @@ TEST_F(ZippedBugReportContentsTest, ContainsSomeFileSystemFiles) {
*/
class BugreportSectionTest : public Test {
public:
- static void SetUpTestCase() {
- ParseSections(ZippedBugreportGenerationTest::getZipFilePath().c_str(),
- ZippedBugreportGenerationTest::sections.get());
- }
-
int numMatches(const std::string& substring) {
int matches = 0;
for (auto const& section : *ZippedBugreportGenerationTest::sections) {
@@ -327,11 +267,10 @@ class BugreportSectionTest : public Test {
}
return matches;
}
-
void SectionExists(const std::string& sectionName, int minsize) {
for (auto const& section : *ZippedBugreportGenerationTest::sections) {
if (sectionName == section.name) {
- EXPECT_GE(section.size_bytes, minsize) << " for section:" << sectionName;
+ EXPECT_GE(section.size_bytes, minsize);
return;
}
}
@@ -339,59 +278,71 @@ class BugreportSectionTest : public Test {
}
};
+// Test all sections are generated without timeouts or errors
+TEST_F(BugreportSectionTest, GeneratedWithoutErrors) {
+ for (auto const& section : *ZippedBugreportGenerationTest::sections) {
+ EXPECT_EQ(section.status, 0) << section.name << " failed with status " << section.status;
+ }
+}
+
TEST_F(BugreportSectionTest, Atleast3CriticalDumpsysSectionsGenerated) {
- int numSections = numMatches("CRITICAL");
+ int numSections = numMatches("DUMPSYS CRITICAL");
EXPECT_GE(numSections, 3);
}
TEST_F(BugreportSectionTest, Atleast2HighDumpsysSectionsGenerated) {
- int numSections = numMatches("HIGH");
+ int numSections = numMatches("DUMPSYS HIGH");
EXPECT_GE(numSections, 2);
}
TEST_F(BugreportSectionTest, Atleast50NormalDumpsysSectionsGenerated) {
- int allSections = ZippedBugreportGenerationTest::sections->size();
- int criticalSections = numMatches("CRITICAL");
- int highSections = numMatches("HIGH");
+ int allSections = numMatches("DUMPSYS");
+ int criticalSections = numMatches("DUMPSYS CRITICAL");
+ int highSections = numMatches("DUMPSYS HIGH");
int normalSections = allSections - criticalSections - highSections;
EXPECT_GE(normalSections, 50) << "Total sections less than 50 (Critical:" << criticalSections
<< "High:" << highSections << "Normal:" << normalSections << ")";
}
+TEST_F(BugreportSectionTest, Atleast1ProtoDumpsysSectionGenerated) {
+ int numSections = numMatches("proto/");
+ EXPECT_GE(numSections, 1);
+}
+
// Test if some critical sections are being generated.
TEST_F(BugreportSectionTest, CriticalSurfaceFlingerSectionGenerated) {
- SectionExists("CRITICAL SurfaceFlinger", /* bytes= */ 10000);
+ SectionExists("DUMPSYS CRITICAL - SurfaceFlinger", /* bytes= */ 10000);
}
TEST_F(BugreportSectionTest, ActivitySectionsGenerated) {
- SectionExists("CRITICAL activity", /* bytes= */ 5000);
- SectionExists("activity", /* bytes= */ 10000);
+ SectionExists("DUMPSYS CRITICAL - activity", /* bytes= */ 5000);
+ SectionExists("DUMPSYS - activity", /* bytes= */ 10000);
}
TEST_F(BugreportSectionTest, CpuinfoSectionGenerated) {
- SectionExists("CRITICAL cpuinfo", /* bytes= */ 1000);
+ SectionExists("DUMPSYS CRITICAL - cpuinfo", /* bytes= */ 1000);
}
TEST_F(BugreportSectionTest, WindowSectionGenerated) {
- SectionExists("CRITICAL window", /* bytes= */ 20000);
+ SectionExists("DUMPSYS CRITICAL - window", /* bytes= */ 20000);
}
TEST_F(BugreportSectionTest, ConnectivitySectionsGenerated) {
- SectionExists("HIGH connectivity", /* bytes= */ 3000);
- SectionExists("connectivity", /* bytes= */ 5000);
+ SectionExists("DUMPSYS HIGH - connectivity", /* bytes= */ 5000);
+ SectionExists("DUMPSYS - connectivity", /* bytes= */ 5000);
}
TEST_F(BugreportSectionTest, MeminfoSectionGenerated) {
- SectionExists("HIGH meminfo", /* bytes= */ 100000);
+ SectionExists("DUMPSYS HIGH - meminfo", /* bytes= */ 100000);
}
TEST_F(BugreportSectionTest, BatteryStatsSectionGenerated) {
- SectionExists("batterystats", /* bytes= */ 1000);
+ SectionExists("DUMPSYS - batterystats", /* bytes= */ 1000);
}
TEST_F(BugreportSectionTest, WifiSectionGenerated) {
- SectionExists("wifi", /* bytes= */ 100000);
+ SectionExists("DUMPSYS - wifi", /* bytes= */ 100000);
}
class DumpstateBinderTest : public Test {
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index cff1d439d9..71d15f4761 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -62,6 +62,10 @@ class DumpstateListenerMock : public IDumpstateListener {
MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
MOCK_METHOD1(onError, binder::Status(int32_t error_code));
MOCK_METHOD0(onFinished, binder::Status());
+ MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
+ MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
+ MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
+ int32_t size, int32_t durationMs));
protected:
MOCK_METHOD0(onAsBinder, IBinder*());
@@ -101,8 +105,9 @@ class DumpstateBaseTest : public Test {
protected:
const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
- const std::string kTestDataPath = kTestPath + "/tests/testdata/";
- const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
+ const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/";
+ const std::string kTestDataPath = kFixturesPath + "tests/testdata/";
+ const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture";
const std::string kEchoCommand = "/system/bin/echo";
/*
@@ -586,6 +591,7 @@ class DumpstateTest : public DumpstateBaseTest {
SetDryRun(false);
SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
ds.progress_.reset(new Progress());
+ ds.update_progress_threshold_ = 0;
ds.options_.reset(new Dumpstate::DumpOptions());
}
@@ -610,9 +616,10 @@ class DumpstateTest : public DumpstateBaseTest {
return status;
}
- void SetProgress(long progress, long initial_max) {
- ds.last_reported_percent_progress_ = 0;
+ void SetProgress(long progress, long initial_max, long threshold = 0) {
ds.options_->do_progress_updates = true;
+ ds.update_progress_threshold_ = threshold;
+ ds.last_updated_progress_ = 0;
ds.progress_.reset(new Progress(initial_max, progress, 1.2));
}
@@ -657,8 +664,7 @@ TEST_F(DumpstateTest, RunCommandNoTitle) {
TEST_F(DumpstateTest, RunCommandWithTitle) {
EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
EXPECT_THAT(err, StrEq("stderr\n"));
- // The duration may not get output, depending on how long it takes,
- // so we just check the prefix.
+ // We don't know the exact duration, so we check the prefix and suffix
EXPECT_THAT(out,
StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
}
@@ -693,8 +699,7 @@ TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
TEST_F(DumpstateTest, RunCommandDryRun) {
SetDryRun(true);
EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
- // The duration may not get output, depending on how long it takes,
- // so we just check the prefix.
+ // We don't know the exact duration, so we check the prefix and suffix
EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
") ------\n\t(skipped on dry run)\n"));
EXPECT_THAT(err, IsEmpty());
@@ -790,36 +795,73 @@ TEST_F(DumpstateTest, RunCommandProgress) {
ds.listener_name_ = "FoxMulder";
SetProgress(0, 30);
+ EXPECT_CALL(*listener, onProgressUpdated(20));
EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
EXPECT_THAT(out, StrEq("stdout\n"));
EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
- EXPECT_CALL(*listener, onProgress(80)); // 24/30 %
- EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
- progress_message = GetProgressMessage(ds.listener_name_, 24, 30);
+ EXPECT_CALL(*listener, onProgressUpdated(30));
+ EXPECT_CALL(*listener, onProgress(100)); // 35/35 %
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
+ progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
+ EXPECT_THAT(out, StrEq("stdout\n"));
+ EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
+
+ // Run a command that will increase maximum timeout.
+ EXPECT_CALL(*listener, onProgressUpdated(31));
+ EXPECT_CALL(*listener, onMaxProgressUpdated(37));
+ EXPECT_CALL(*listener, onProgress(83)); // 31/37 %
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
+ progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30); // 20% increase
EXPECT_THAT(out, StrEq("stdout\n"));
EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
// Make sure command ran while in dry_run is counted.
SetDryRun(true);
- EXPECT_CALL(*listener, onProgress(90)); // 27/30 %
- EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
- progress_message = GetProgressMessage(ds.listener_name_, 27, 30);
+ EXPECT_CALL(*listener, onProgressUpdated(35));
+ EXPECT_CALL(*listener, onProgress(94)); // 35/37 %
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
+ progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
EXPECT_THAT(out, IsEmpty());
EXPECT_THAT(err, StrEq(progress_message));
- SetDryRun(false);
- EXPECT_CALL(*listener, onProgress(96)); // 29/30 %
- EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
- progress_message = GetProgressMessage(ds.listener_name_, 29, 30);
+ ds.listener_.clear();
+}
+
+TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) {
+ sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
+ ds.listener_ = listener;
+ ds.listener_name_ = "FoxMulder";
+ SetProgress(0, 8, 5); // 8 max, 5 threshold
+
+ // First update should always be sent.
+ EXPECT_CALL(*listener, onProgressUpdated(1));
+ EXPECT_CALL(*listener, onProgress(12)); // 1/12 %
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
+ std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
EXPECT_THAT(out, StrEq("stdout\n"));
EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
- EXPECT_CALL(*listener, onProgress(100)); // 30/30 %
+ // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5).
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
+ EXPECT_THAT(out, StrEq("stdout\n"));
+ EXPECT_THAT(err, StrEq("stderr\n"));
+
+ // Third update should be sent because it reaches threshold (6 - 1 = 5).
+ EXPECT_CALL(*listener, onProgressUpdated(6));
+ EXPECT_CALL(*listener, onProgress(75)); // 6/8 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
- progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
+ progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
+ EXPECT_THAT(out, StrEq("stdout\n"));
+ EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
+
+ // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5).
+ // But max update should be sent.
+ EXPECT_CALL(*listener, onMaxProgressUpdated(10)); // 9 * 120% = 10.8 = 10
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
+ progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false);
EXPECT_THAT(out, StrEq("stdout\n"));
EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
@@ -995,8 +1037,7 @@ TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
EXPECT_THAT(err, IsEmpty());
- // The duration may not get output, depending on how long it takes,
- // so we just check the prefix.
+ // We don't know the exact duration, so we check the prefix and suffix
EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
"such file or directory\n"));
}
@@ -1047,6 +1088,7 @@ TEST_F(DumpstateTest, DumpFileUpdateProgress) {
ds.listener_name_ = "FoxMulder";
SetProgress(0, 30);
+ EXPECT_CALL(*listener, onProgressUpdated(5));
EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
@@ -1362,6 +1404,14 @@ class DumpstateUtilTest : public DumpstateBaseTest {
return status;
}
+ // Find out the pid of the process_name
+ int FindPidOfProcess(const std::string& process_name) {
+ CaptureStderr();
+ int status = GetPidByName(process_name);
+ err = GetCapturedStderr();
+ return status;
+ }
+
int fd;
// 'fd` output and `stderr` from the last command ran.
@@ -1711,6 +1761,18 @@ TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
}
+TEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) {
+ // init process always has pid 1.
+ EXPECT_EQ(1, FindPidOfProcess("init"));
+ EXPECT_THAT(err, IsEmpty());
+}
+
+TEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) {
+ // find the process with abnormal name.
+ EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543"));
+ EXPECT_THAT(err, StrEq("can't find the pid\n"));
+}
+
} // namespace dumpstate
} // namespace os
} // namespace android
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
new file mode 100644
index 0000000000..0bb80dcfba
--- /dev/null
+++ b/cmds/dumpstate/utils.cpp
@@ -0,0 +1,1012 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define LOG_TAG "dumpstate"
+
+#include "dumpstate.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <math.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/capability.h>
+#include <sys/inotify.h>
+#include <sys/klog.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#include <log/log.h>
+#include <private/android_filesystem_config.h>
+
+#include "DumpstateInternal.h"
+
+// TODO: remove once moved to namespace
+using android::os::dumpstate::CommandOptions;
+using android::os::dumpstate::DumpFileToFd;
+using android::os::dumpstate::PropertiesHelper;
+
+// Keep in sync with
+// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
+
+/* Most simple commands have 10 as timeout, so 5 is a good estimate */
+static const int32_t WEIGHT_FILE = 5;
+
+// TODO: temporary variables and functions used during C++ refactoring
+static Dumpstate& ds = Dumpstate::GetInstance();
+static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
+ const CommandOptions& options = CommandOptions::DEFAULT) {
+ return ds.RunCommand(title, full_command, options);
+}
+
+// Reasonable value for max stats.
+static const int STATS_MAX_N_RUNS = 1000;
+static const long STATS_MAX_AVERAGE = 100000;
+
+CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
+
+// TODO(111441001): Default DumpOptions to sensible values.
+Dumpstate::Dumpstate(const std::string& version)
+ : pid_(getpid()),
+ options_(new Dumpstate::DumpOptions()),
+ version_(version),
+ now_(time(nullptr)) {
+}
+
+Dumpstate& Dumpstate::GetInstance() {
+ static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
+ return singleton_;
+}
+
+DurationReporter::DurationReporter(const std::string& title, bool logcat_only)
+ : title_(title), logcat_only_(logcat_only) {
+ if (!title_.empty()) {
+ started_ = Nanotime();
+ }
+}
+
+DurationReporter::~DurationReporter() {
+ if (!title_.empty()) {
+ float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
+ if (elapsed < .5f) {
+ return;
+ }
+ MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
+ if (logcat_only_) {
+ return;
+ }
+ // Use "Yoda grammar" to make it easier to grep|sort sections.
+ printf("------ %.3fs was the duration of '%s' ------\n", elapsed, title_.c_str());
+ }
+}
+
+const int32_t Progress::kDefaultMax = 5000;
+
+Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
+}
+
+Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
+ : Progress(initial_max, growth_factor, "") {
+ progress_ = progress;
+}
+
+Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
+ : initial_max_(initial_max),
+ progress_(0),
+ max_(initial_max),
+ growth_factor_(growth_factor),
+ n_runs_(0),
+ average_max_(0),
+ path_(path) {
+ if (!path_.empty()) {
+ Load();
+ }
+}
+
+void Progress::Load() {
+ MYLOGD("Loading stats from %s\n", path_.c_str());
+ std::string content;
+ if (!android::base::ReadFileToString(path_, &content)) {
+ MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
+ return;
+ }
+ if (content.empty()) {
+ MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
+ return;
+ }
+ std::vector<std::string> lines = android::base::Split(content, "\n");
+
+ if (lines.size() < 1) {
+ MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
+ (int)lines.size(), max_);
+ return;
+ }
+ char* ptr;
+ n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
+ average_max_ = strtol(ptr, nullptr, 10);
+ if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
+ average_max_ > STATS_MAX_AVERAGE) {
+ MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
+ initial_max_ = Progress::kDefaultMax;
+ } else {
+ initial_max_ = average_max_;
+ }
+ max_ = initial_max_;
+
+ MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
+}
+
+void Progress::Save() {
+ int32_t total = n_runs_ * average_max_ + progress_;
+ int32_t runs = n_runs_ + 1;
+ int32_t average = floor(((float)total) / runs);
+ MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
+ path_.c_str());
+ if (path_.empty()) {
+ return;
+ }
+
+ std::string content = android::base::StringPrintf("%d %d\n", runs, average);
+ if (!android::base::WriteStringToFile(content, path_)) {
+ MYLOGE("Could not save stats on %s\n", path_.c_str());
+ }
+}
+
+int32_t Progress::Get() const {
+ return progress_;
+}
+
+bool Progress::Inc(int32_t delta_sec) {
+ bool changed = false;
+ if (delta_sec >= 0) {
+ progress_ += delta_sec;
+ if (progress_ > max_) {
+ int32_t old_max = max_;
+ max_ = floor((float)progress_ * growth_factor_);
+ MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+int32_t Progress::GetMax() const {
+ return max_;
+}
+
+int32_t Progress::GetInitialMax() const {
+ return initial_max_;
+}
+
+void Progress::Dump(int fd, const std::string& prefix) const {
+ const char* pr = prefix.c_str();
+ dprintf(fd, "%sprogress: %d\n", pr, progress_);
+ dprintf(fd, "%smax: %d\n", pr, max_);
+ dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
+ dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
+ dprintf(fd, "%spath: %s\n", pr, path_.c_str());
+ dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
+ dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
+}
+
+bool Dumpstate::IsZipping() const {
+ return zip_writer_ != nullptr;
+}
+
+std::string Dumpstate::GetPath(const std::string& suffix) const {
+ return GetPath(bugreport_internal_dir_, suffix);
+}
+
+std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
+ return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
+ name_.c_str(), suffix.c_str());
+}
+
+void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
+ progress_ = std::move(progress);
+}
+
+void for_each_userid(void (*func)(int), const char *header) {
+ std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
+ "for_each_userid(%s)", header);
+ DurationReporter duration_reporter(title);
+ if (PropertiesHelper::IsDryRun()) return;
+
+ DIR *d;
+ struct dirent *de;
+
+ if (header) printf("\n------ %s ------\n", header);
+ func(0);
+
+ if (!(d = opendir("/data/system/users"))) {
+ printf("Failed to open /data/system/users (%s)\n", strerror(errno));
+ return;
+ }
+
+ while ((de = readdir(d))) {
+ int userid;
+ if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
+ continue;
+ }
+ func(userid);
+ }
+
+ closedir(d);
+}
+
+static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
+ DIR *d;
+ struct dirent *de;
+
+ if (!(d = opendir("/proc"))) {
+ printf("Failed to open /proc (%s)\n", strerror(errno));
+ return;
+ }
+
+ if (header) printf("\n------ %s ------\n", header);
+ while ((de = readdir(d))) {
+ if (ds.IsUserConsentDenied()) {
+ MYLOGE(
+ "Returning early because user denied consent to share bugreport with calling app.");
+ closedir(d);
+ return;
+ }
+ int pid;
+ int fd;
+ char cmdpath[255];
+ char cmdline[255];
+
+ if (!(pid = atoi(de->d_name))) {
+ continue;
+ }
+
+ memset(cmdline, 0, sizeof(cmdline));
+
+ snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
+ if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+ TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
+ close(fd);
+ if (cmdline[0]) {
+ helper(pid, cmdline, arg);
+ continue;
+ }
+ }
+
+ // if no cmdline, a kernel thread has comm
+ snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
+ if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+ TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
+ close(fd);
+ if (cmdline[1]) {
+ cmdline[0] = '[';
+ size_t len = strcspn(cmdline, "\f\b\r\n");
+ cmdline[len] = ']';
+ cmdline[len+1] = '\0';
+ }
+ }
+ if (!cmdline[0]) {
+ strcpy(cmdline, "N/A");
+ }
+ helper(pid, cmdline, arg);
+ }
+
+ closedir(d);
+}
+
+static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
+ for_each_pid_func *func = (for_each_pid_func*) arg;
+ func(pid, cmdline);
+}
+
+void for_each_pid(for_each_pid_func func, const char *header) {
+ std::string title = header == nullptr ? "for_each_pid"
+ : android::base::StringPrintf("for_each_pid(%s)", header);
+ DurationReporter duration_reporter(title);
+ if (PropertiesHelper::IsDryRun()) return;
+
+ __for_each_pid(for_each_pid_helper, header, (void *) func);
+}
+
+static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
+ DIR *d;
+ struct dirent *de;
+ char taskpath[255];
+ for_each_tid_func *func = (for_each_tid_func *) arg;
+
+ snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
+
+ if (!(d = opendir(taskpath))) {
+ printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
+ return;
+ }
+
+ func(pid, pid, cmdline);
+
+ while ((de = readdir(d))) {
+ if (ds.IsUserConsentDenied()) {
+ MYLOGE(
+ "Returning early because user denied consent to share bugreport with calling app.");
+ closedir(d);
+ return;
+ }
+ int tid;
+ int fd;
+ char commpath[255];
+ char comm[255];
+
+ if (!(tid = atoi(de->d_name))) {
+ continue;
+ }
+
+ if (tid == pid)
+ continue;
+
+ snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
+ memset(comm, 0, sizeof(comm));
+ if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
+ strcpy(comm, "N/A");
+ } else {
+ char *c;
+ TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
+ close(fd);
+
+ c = strrchr(comm, '\n');
+ if (c) {
+ *c = '\0';
+ }
+ }
+ func(pid, tid, comm);
+ }
+
+ closedir(d);
+}
+
+void for_each_tid(for_each_tid_func func, const char *header) {
+ std::string title = header == nullptr ? "for_each_tid"
+ : android::base::StringPrintf("for_each_tid(%s)", header);
+ DurationReporter duration_reporter(title);
+
+ if (PropertiesHelper::IsDryRun()) return;
+
+ __for_each_pid(for_each_tid_helper, header, (void *) func);
+}
+
+void show_wchan(int pid, int tid, const char *name) {
+ if (PropertiesHelper::IsDryRun()) return;
+
+ char path[255];
+ char buffer[255];
+ int fd, ret, save_errno;
+ char name_buffer[255];
+
+ memset(buffer, 0, sizeof(buffer));
+
+ snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
+ if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
+ printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+ return;
+ }
+
+ ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+ save_errno = errno;
+ close(fd);
+
+ if (ret < 0) {
+ printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+ return;
+ }
+
+ snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
+ pid == tid ? 0 : 3, "", name);
+
+ printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
+
+ return;
+}
+
+// print time in centiseconds
+static void snprcent(char *buffer, size_t len, size_t spc,
+ unsigned long long time) {
+ static long hz; // cache discovered hz
+
+ if (hz <= 0) {
+ hz = sysconf(_SC_CLK_TCK);
+ if (hz <= 0) {
+ hz = 1000;
+ }
+ }
+
+ // convert to centiseconds
+ time = (time * 100 + (hz / 2)) / hz;
+
+ char str[16];
+
+ snprintf(str, sizeof(str), " %llu.%02u",
+ time / 100, (unsigned)(time % 100));
+ size_t offset = strlen(buffer);
+ snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+ "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+// print permille as a percent
+static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
+ char str[16];
+
+ snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
+ size_t offset = strlen(buffer);
+ snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+ "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+void show_showtime(int pid, const char *name) {
+ if (PropertiesHelper::IsDryRun()) return;
+
+ char path[255];
+ char buffer[1023];
+ int fd, ret, save_errno;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ snprintf(path, sizeof(path), "/proc/%d/stat", pid);
+ if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
+ printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+ return;
+ }
+
+ ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+ save_errno = errno;
+ close(fd);
+
+ if (ret < 0) {
+ printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+ return;
+ }
+
+ // field 14 is utime
+ // field 15 is stime
+ // field 42 is iotime
+ unsigned long long utime = 0, stime = 0, iotime = 0;
+ if (sscanf(buffer,
+ "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
+ "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
+ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
+ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
+ &utime, &stime, &iotime) != 3) {
+ return;
+ }
+
+ unsigned long long total = utime + stime;
+ if (!total) {
+ return;
+ }
+
+ unsigned permille = (iotime * 1000 + (total / 2)) / total;
+ if (permille > 1000) {
+ permille = 1000;
+ }
+
+ // try to beautify and stabilize columns at <80 characters
+ snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
+ if ((name[0] != '[') || utime) {
+ snprcent(buffer, sizeof(buffer), 57, utime);
+ }
+ snprcent(buffer, sizeof(buffer), 65, stime);
+ if ((name[0] != '[') || iotime) {
+ snprcent(buffer, sizeof(buffer), 73, iotime);
+ }
+ if (iotime) {
+ snprdec(buffer, sizeof(buffer), 79, permille);
+ }
+ puts(buffer); // adds a trailing newline
+
+ return;
+}
+
+void do_dmesg() {
+ const char *title = "KERNEL LOG (dmesg)";
+ DurationReporter duration_reporter(title);
+ printf("------ %s ------\n", title);
+
+ if (PropertiesHelper::IsDryRun()) return;
+
+ /* Get size of kernel buffer */
+ int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
+ if (size <= 0) {
+ printf("Unexpected klogctl return value: %d\n\n", size);
+ return;
+ }
+ char *buf = (char *) malloc(size + 1);
+ if (buf == nullptr) {
+ printf("memory allocation failed\n\n");
+ return;
+ }
+ int retval = klogctl(KLOG_READ_ALL, buf, size);
+ if (retval < 0) {
+ printf("klogctl failure\n\n");
+ free(buf);
+ return;
+ }
+ buf[retval] = '\0';
+ printf("%s\n\n", buf);
+ free(buf);
+ return;
+}
+
+void do_showmap(int pid, const char *name) {
+ char title[255];
+ char arg[255];
+
+ snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
+ snprintf(arg, sizeof(arg), "%d", pid);
+ RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
+}
+
+int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
+ DurationReporter duration_reporter(title);
+
+ int status = DumpFileToFd(STDOUT_FILENO, title, path);
+
+ UpdateProgress(WEIGHT_FILE);
+
+ return status;
+}
+
+int read_file_as_long(const char *path, long int *output) {
+ int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+ if (fd < 0) {
+ int err = errno;
+ MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
+ return -1;
+ }
+ char buffer[50];
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+ if (bytes_read == -1) {
+ MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
+ return -2;
+ }
+ if (bytes_read == 0) {
+ MYLOGE("File %s is empty\n", path);
+ return -3;
+ }
+ *output = atoi(buffer);
+ return 0;
+}
+
+/* calls skip to gate calling dump_from_fd recursively
+ * in the specified directory. dump_from_fd defaults to
+ * dump_file_from_fd above when set to NULL. skip defaults
+ * to false when set to NULL. dump_from_fd will always be
+ * called with title NULL.
+ */
+int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
+ int (*dump_from_fd)(const char* title, const char* path, int fd)) {
+ DurationReporter duration_reporter(title);
+ DIR *dirp;
+ struct dirent *d;
+ char *newpath = nullptr;
+ const char *slash = "/";
+ int retval = 0;
+
+ if (!title.empty()) {
+ printf("------ %s (%s) ------\n", title.c_str(), dir);
+ }
+ if (PropertiesHelper::IsDryRun()) return 0;
+
+ if (dir[strlen(dir) - 1] == '/') {
+ ++slash;
+ }
+ dirp = opendir(dir);
+ if (dirp == nullptr) {
+ retval = -errno;
+ MYLOGE("%s: %s\n", dir, strerror(errno));
+ return retval;
+ }
+
+ if (!dump_from_fd) {
+ dump_from_fd = dump_file_from_fd;
+ }
+ for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
+ if ((d->d_name[0] == '.')
+ && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
+ || (d->d_name[1] == '\0'))) {
+ continue;
+ }
+ asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
+ (d->d_type == DT_DIR) ? "/" : "");
+ if (!newpath) {
+ retval = -errno;
+ continue;
+ }
+ if (skip && (*skip)(newpath)) {
+ continue;
+ }
+ if (d->d_type == DT_DIR) {
+ int ret = dump_files("", newpath, skip, dump_from_fd);
+ if (ret < 0) {
+ retval = ret;
+ }
+ continue;
+ }
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
+ if (fd.get() < 0) {
+ retval = -1;
+ printf("*** %s: %s\n", newpath, strerror(errno));
+ continue;
+ }
+ (*dump_from_fd)(nullptr, newpath, fd.get());
+ }
+ closedir(dirp);
+ if (!title.empty()) {
+ printf("\n");
+ }
+ return retval;
+}
+
+/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
+ * it's possible to avoid issues where opening the file itself can get
+ * stuck.
+ */
+int dump_file_from_fd(const char *title, const char *path, int fd) {
+ if (PropertiesHelper::IsDryRun()) return 0;
+
+ int flags = fcntl(fd, F_GETFL);
+ if (flags == -1) {
+ printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
+ return -1;
+ } else if (!(flags & O_NONBLOCK)) {
+ printf("*** %s: fd must have O_NONBLOCK set.\n", path);
+ return -1;
+ }
+ return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
+}
+
+int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
+ const CommandOptions& options) {
+ DurationReporter duration_reporter(title);
+
+ int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
+
+ /* TODO: for now we're simplifying the progress calculation by using the
+ * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
+ * where its weight should be much higher proportionally to its timeout.
+ * Ideally, it should use a options.EstimatedDuration() instead...*/
+ UpdateProgress(options.Timeout());
+
+ return status;
+}
+
+void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
+ const CommandOptions& options, long dumpsysTimeoutMs) {
+ long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
+ std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
+ dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
+ RunCommand(title, dumpsys, options);
+}
+
+int open_socket(const char *service) {
+ int s = android_get_control_socket(service);
+ if (s < 0) {
+ MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
+ return -1;
+ }
+ fcntl(s, F_SETFD, FD_CLOEXEC);
+ if (listen(s, 4) < 0) {
+ MYLOGE("listen(control socket): %s\n", strerror(errno));
+ return -1;
+ }
+
+ struct sockaddr addr;
+ socklen_t alen = sizeof(addr);
+ int fd = accept(s, &addr, &alen);
+ if (fd < 0) {
+ MYLOGE("accept(control socket): %s\n", strerror(errno));
+ return -1;
+ }
+
+ return fd;
+}
+
+/* redirect output to a service control socket */
+bool redirect_to_socket(FILE* redirect, const char* service) {
+ int fd = open_socket(service);
+ if (fd == -1) {
+ return false;
+ }
+ fflush(redirect);
+ // TODO: handle dup2 failure
+ TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
+ close(fd);
+ return true;
+}
+
+// TODO: should call is_valid_output_file and/or be merged into it.
+void create_parent_dirs(const char *path) {
+ char *chp = const_cast<char *> (path);
+
+ /* skip initial slash */
+ if (chp[0] == '/')
+ chp++;
+
+ /* create leading directories, if necessary */
+ struct stat dir_stat;
+ while (chp && chp[0]) {
+ chp = strchr(chp, '/');
+ if (chp) {
+ *chp = 0;
+ if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
+ MYLOGI("Creating directory %s\n", path);
+ if (mkdir(path, 0770)) { /* drwxrwx--- */
+ MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
+ } else if (chown(path, AID_SHELL, AID_SHELL)) {
+ MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
+ }
+ }
+ *chp++ = '/';
+ }
+ }
+}
+
+bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
+ create_parent_dirs(path);
+
+ int fd = TEMP_FAILURE_RETRY(open(path,
+ O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
+ if (fd < 0) {
+ MYLOGE("%s: %s\n", path, strerror(errno));
+ return false;
+ }
+
+ TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
+ close(fd);
+ return true;
+}
+
+bool redirect_to_file(FILE* redirect, char* path) {
+ return _redirect_to_file(redirect, path, O_TRUNC);
+}
+
+bool redirect_to_existing_file(FILE* redirect, char* path) {
+ return _redirect_to_file(redirect, path, O_APPEND);
+}
+
+void dump_route_tables() {
+ DurationReporter duration_reporter("DUMP ROUTE TABLES");
+ if (PropertiesHelper::IsDryRun()) return;
+ const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
+ ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
+ FILE* fp = fopen(RT_TABLES_PATH, "re");
+ if (!fp) {
+ printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
+ return;
+ }
+ char table[16];
+ // Each line has an integer (the table number), a space, and a string (the table name). We only
+ // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
+ // Add a fixed max limit so this doesn't go awry.
+ for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
+ RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
+ RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
+ }
+ fclose(fp);
+}
+
+// TODO: make this function thread safe if sections are generated in parallel.
+void Dumpstate::UpdateProgress(int32_t delta_sec) {
+ if (progress_ == nullptr) {
+ MYLOGE("UpdateProgress: progress_ not set\n");
+ return;
+ }
+
+ // Always update progess so stats can be tuned...
+ bool max_changed = progress_->Inc(delta_sec);
+
+ // ...but only notifiy listeners when necessary.
+ if (!options_->do_progress_updates) return;
+
+ int progress = progress_->Get();
+ int max = progress_->GetMax();
+
+ // adjusts max on the fly
+ if (max_changed && listener_ != nullptr) {
+ listener_->onMaxProgressUpdated(max);
+ }
+
+ int32_t last_update_delta = progress - last_updated_progress_;
+ if (last_updated_progress_ > 0 && last_update_delta < update_progress_threshold_) {
+ return;
+ }
+ last_updated_progress_ = progress;
+
+ if (control_socket_fd_ >= 0) {
+ dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
+ fsync(control_socket_fd_);
+ }
+
+ int percent = 100 * progress / max;
+ if (listener_ != nullptr) {
+ if (percent % 5 == 0) {
+ // We don't want to spam logcat, so only log multiples of 5.
+ MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max,
+ percent);
+ } else {
+ // stderr is ignored on normal invocations, but useful when calling
+ // /system/bin/dumpstate directly for debuggging.
+ fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
+ progress, max, percent);
+ }
+ // TODO(b/111441001): Remove in favor of onProgress
+ listener_->onProgressUpdated(progress);
+
+ listener_->onProgress(percent);
+ }
+}
+
+void Dumpstate::TakeScreenshot(const std::string& path) {
+ const std::string& real_path = path.empty() ? screenshot_path_ : path;
+ int status =
+ RunCommand("", {"/system/bin/screencap", "-p", real_path},
+ CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
+ if (status == 0) {
+ MYLOGD("Screenshot saved on %s\n", real_path.c_str());
+ } else {
+ MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
+ }
+}
+
+bool is_dir(const char* pathname) {
+ struct stat info;
+ if (stat(pathname, &info) == -1) {
+ return false;
+ }
+ return S_ISDIR(info.st_mode);
+}
+
+time_t get_mtime(int fd, time_t default_mtime) {
+ struct stat info;
+ if (fstat(fd, &info) == -1) {
+ return default_mtime;
+ }
+ return info.st_mtime;
+}
+
+void dump_emmc_ecsd(const char *ext_csd_path) {
+ // List of interesting offsets
+ struct hex {
+ char str[2];
+ };
+ static const size_t EXT_CSD_REV = 192 * sizeof(hex);
+ static const size_t EXT_PRE_EOL_INFO = 267 * sizeof(hex);
+ static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_A = 268 * sizeof(hex);
+ static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_B = 269 * sizeof(hex);
+
+ std::string buffer;
+ if (!android::base::ReadFileToString(ext_csd_path, &buffer)) {
+ return;
+ }
+
+ printf("------ %s Extended CSD ------\n", ext_csd_path);
+
+ if (buffer.length() < (EXT_CSD_REV + sizeof(hex))) {
+ printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
+ return;
+ }
+
+ int ext_csd_rev = 0;
+ std::string sub = buffer.substr(EXT_CSD_REV, sizeof(hex));
+ if (sscanf(sub.c_str(), "%2x", &ext_csd_rev) != 1) {
+ printf("*** %s: EXT_CSD_REV parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
+ return;
+ }
+
+ static const char *ver_str[] = {
+ "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
+ };
+ printf("rev 1.%d (MMC %s)\n", ext_csd_rev,
+ (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ? ver_str[ext_csd_rev]
+ : "Unknown");
+ if (ext_csd_rev < 7) {
+ printf("\n");
+ return;
+ }
+
+ if (buffer.length() < (EXT_PRE_EOL_INFO + sizeof(hex))) {
+ printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
+ return;
+ }
+
+ int ext_pre_eol_info = 0;
+ sub = buffer.substr(EXT_PRE_EOL_INFO, sizeof(hex));
+ if (sscanf(sub.c_str(), "%2x", &ext_pre_eol_info) != 1) {
+ printf("*** %s: PRE_EOL_INFO parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
+ return;
+ }
+
+ static const char *eol_str[] = {
+ "Undefined",
+ "Normal",
+ "Warning (consumed 80% of reserve)",
+ "Urgent (consumed 90% of reserve)"
+ };
+ printf(
+ "PRE_EOL_INFO %d (MMC %s)\n", ext_pre_eol_info,
+ eol_str[(ext_pre_eol_info < (int)(sizeof(eol_str) / sizeof(eol_str[0]))) ? ext_pre_eol_info
+ : 0]);
+
+ for (size_t lifetime = EXT_DEVICE_LIFE_TIME_EST_TYP_A;
+ lifetime <= EXT_DEVICE_LIFE_TIME_EST_TYP_B;
+ lifetime += sizeof(hex)) {
+ int ext_device_life_time_est;
+ static const char *est_str[] = {
+ "Undefined",
+ "0-10% of device lifetime used",
+ "10-20% of device lifetime used",
+ "20-30% of device lifetime used",
+ "30-40% of device lifetime used",
+ "40-50% of device lifetime used",
+ "50-60% of device lifetime used",
+ "60-70% of device lifetime used",
+ "70-80% of device lifetime used",
+ "80-90% of device lifetime used",
+ "90-100% of device lifetime used",
+ "Exceeded the maximum estimated device lifetime",
+ };
+
+ if (buffer.length() < (lifetime + sizeof(hex))) {
+ printf("*** %s: truncated content %zu\n", ext_csd_path, buffer.length());
+ break;
+ }
+
+ ext_device_life_time_est = 0;
+ sub = buffer.substr(lifetime, sizeof(hex));
+ if (sscanf(sub.c_str(), "%2x", &ext_device_life_time_est) != 1) {
+ printf("*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%s\"\n", ext_csd_path,
+ (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
+ sub.c_str());
+ continue;
+ }
+ printf("DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
+ (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
+ ext_device_life_time_est,
+ est_str[(ext_device_life_time_est < (int)(sizeof(est_str) / sizeof(est_str[0])))
+ ? ext_device_life_time_est
+ : 0]);
+ }
+
+ printf("\n");
+}
diff --git a/cmds/dumpsys/TEST_MAPPING b/cmds/dumpsys/TEST_MAPPING
deleted file mode 100644
index dc88ada034..0000000000
--- a/cmds/dumpsys/TEST_MAPPING
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "presubmit": [
- {
- // small test which assumes the output format of dumpsys, however
- // there are many other parts of Android that expect the output
- // to be a specific way (see b/141728094)
- "name": "timezone_data_e2e_tests"
- },
- {
- "name": "dumpsys_test"
- }
- ]
-}
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index abdf168233..4811927106 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -59,13 +59,12 @@ static void usage() {
"usage: dumpsys\n"
" To dump all services.\n"
"or:\n"
- " dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES "
- "| SERVICE [ARGS]]\n"
+ " dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | "
+ "SERVICE [ARGS]]\n"
" --help: shows this help\n"
" -l: only list services, do not dump them\n"
" -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
" -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
- " --pid: dump PID instead of usual dump\n"
" --proto: filter services that support dumping data in proto format. Dumps\n"
" will be in proto format.\n"
" --priority LEVEL: filter services based on specified priority\n"
@@ -121,11 +120,9 @@ int Dumpsys::main(int argc, char* const argv[]) {
bool showListOnly = false;
bool skipServices = false;
bool asProto = false;
- Type type = Type::DUMP;
int timeoutArgMs = 10000;
int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
- static struct option longOptions[] = {{"pid", no_argument, 0, 0},
- {"priority", required_argument, 0, 0},
+ static struct option longOptions[] = {{"priority", required_argument, 0, 0},
{"proto", no_argument, 0, 0},
{"skip", no_argument, 0, 0},
{"help", no_argument, 0, 0},
@@ -160,8 +157,6 @@ int Dumpsys::main(int argc, char* const argv[]) {
usage();
return -1;
}
- } else if (!strcmp(longOptions[optionIndex].name, "pid")) {
- type = Type::PID;
}
break;
@@ -206,13 +201,7 @@ int Dumpsys::main(int argc, char* const argv[]) {
if (i == optind) {
services.add(String16(argv[i]));
} else {
- const String16 arg(argv[i]);
- args.add(arg);
- // For backward compatible, if the proto argument is passed to the service, the
- // dump request is also considered to use proto.
- if (!asProto && !arg.compare(String16(PriorityDumper::PROTO_ARG))) {
- asProto = true;
- }
+ args.add(String16(argv[i]));
}
}
}
@@ -251,7 +240,7 @@ int Dumpsys::main(int argc, char* const argv[]) {
const String16& serviceName = services[i];
if (IsSkipped(skippedServices, serviceName)) continue;
- if (startDumpThread(type, serviceName, args) == OK) {
+ if (startDumpThread(serviceName, args) == OK) {
bool addSeparator = (N > 1);
if (addSeparator) {
writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);
@@ -318,18 +307,7 @@ void Dumpsys::setServiceArgs(Vector<String16>& args, bool asProto, int priorityF
}
}
-static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd) {
- pid_t pid;
- status_t status = service->getDebugPid(&pid);
- if (status != OK) {
- return status;
- }
- WriteStringToFd(std::to_string(pid) + "\n", fd.get());
- return OK;
-}
-
-status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
- const Vector<String16>& args) {
+status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<String16>& args) {
sp<IBinder> service = sm_->checkService(serviceName);
if (service == nullptr) {
aerr << "Can't find service: " << serviceName << endl;
@@ -349,22 +327,16 @@ status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
// dump blocks until completion, so spawn a thread..
activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {
- status_t err = 0;
+ int err = service->dump(remote_end.get(), args);
- switch (type) {
- case Type::DUMP:
- err = service->dump(remote_end.get(), args);
- break;
- case Type::PID:
- err = dumpPidToFd(service, remote_end);
- break;
- default:
- aerr << "Unknown dump type" << static_cast<int>(type) << endl;
- return;
- }
+ // It'd be nice to be able to close the remote end of the socketpair before the dump
+ // call returns, to terminate our reads if the other end closes their copy of the
+ // file descriptor, but then hangs for some reason. There doesn't seem to be a good
+ // way to do this, though.
+ remote_end.reset();
- if (err != OK) {
- aerr << "Error dumping service info status_t: (" << err << ") "
+ if (err != 0) {
+ aerr << "Error dumping service info: (" << strerror(err) << ") "
<< serviceName << endl;
}
});
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 929c55c364..c48a1e959b 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -51,11 +51,6 @@ class Dumpsys {
*/
static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
- enum class Type {
- DUMP, // dump using `dump` function
- PID, // dump pid of server only
- };
-
/**
* Starts a thread to connect to a service and get its dump output. The thread redirects
* the output to a pipe. Thread must be stopped by a subsequent callto {@code
@@ -66,8 +61,7 @@ class Dumpsys {
* {@code NAME_NOT_FOUND} service could not be found.
* {@code != OK} error
*/
- status_t startDumpThread(Type type, const String16& serviceName,
- const Vector<String16>& args);
+ status_t startDumpThread(const String16& serviceName, const Vector<String16>& args);
/**
* Writes a section header to a file descriptor.
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index b9395ba4e2..3ada15398c 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -53,8 +53,7 @@ class ServiceManagerMock : public IServiceManager {
MOCK_CONST_METHOD1(checkService, sp<IBinder>(const String16&));
MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int));
MOCK_METHOD1(listServices, Vector<String16>(int));
- MOCK_METHOD1(waitForService, sp<IBinder>(const String16&));
- MOCK_METHOD1(isDeclared, bool(const String16&));
+
protected:
MOCK_METHOD0(onAsBinder, IBinder*());
};
@@ -195,7 +194,7 @@ class DumpsysTest : public Test {
CaptureStdout();
CaptureStderr();
dump_.setServiceArgs(args, supportsProto, priorityFlags);
- status_t status = dump_.startDumpThread(Dumpsys::Type::DUMP, serviceName, args);
+ status_t status = dump_.startDumpThread(serviceName, args);
EXPECT_THAT(status, Eq(0));
status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false,
elapsedDuration, bytesWritten);
@@ -540,27 +539,6 @@ TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) {
AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
}
-// Tests 'dumpsys --pid'
-TEST_F(DumpsysTest, ListAllServicesWithPid) {
- ExpectListServices({"Locksmith", "Valet"});
- ExpectCheckService("Locksmith");
- ExpectCheckService("Valet");
-
- CallMain({"--pid"});
-
- AssertRunningServices({"Locksmith", "Valet"});
- AssertOutputContains(std::to_string(getpid()));
-}
-
-// Tests 'dumpsys --pid service_name'
-TEST_F(DumpsysTest, ListServiceWithPid) {
- ExpectCheckService("Locksmith");
-
- CallMain({"--pid", "Locksmith"});
-
- AssertOutput(std::to_string(getpid()) + "\n");
-}
-
TEST_F(DumpsysTest, GetBytesWritten) {
const char* serviceName = "service2";
const char* dumpContents = "dump1";
@@ -585,4 +563,4 @@ TEST_F(DumpsysTest, WriteDumpWithoutThreadStart) {
dump_.writeDump(STDOUT_FILENO, String16("service"), std::chrono::milliseconds(500),
/* as_proto = */ false, elapsedDuration, bytesWritten);
EXPECT_THAT(status, Eq(INVALID_OPERATION));
-}
+} \ No newline at end of file
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
deleted file mode 100644
index 40b8dc74f7..0000000000
--- a/cmds/idlcli/Android.bp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-cc_defaults {
- name: "idlcli-defaults",
- shared_libs: [
- "android.hardware.vibrator@1.0",
- "android.hardware.vibrator@1.1",
- "android.hardware.vibrator@1.2",
- "android.hardware.vibrator@1.3",
- "libbase",
- "libhidlbase",
- "liblog",
- "libutils",
- ],
- cflags: [
- "-DLOG_TAG=\"idlcli\"",
- ],
-}
-
-cc_library {
- name: "libidlcli",
- defaults: ["idlcli-defaults"],
- srcs: [
- "CommandVibrator.cpp",
- "vibrator/CommandOff.cpp",
- "vibrator/CommandOn.cpp",
- "vibrator/CommandPerform.cpp",
- "vibrator/CommandSetAmplitude.cpp",
- "vibrator/CommandSetExternalControl.cpp",
- "vibrator/CommandSupportsAmplitudeControl.cpp",
- "vibrator/CommandSupportsExternalControl.cpp",
- ],
- visibility: [":__subpackages__"],
-}
-
-cc_binary {
- name: "idlcli",
- defaults: ["idlcli-defaults"],
- srcs: ["main.cpp"],
- whole_static_libs: ["libidlcli"],
-}
diff --git a/cmds/idlcli/CommandVibrator.cpp b/cmds/idlcli/CommandVibrator.cpp
deleted file mode 100644
index a7a70c38af..0000000000
--- a/cmds/idlcli/CommandVibrator.cpp
+++ /dev/null
@@ -1,40 +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 "utils.h"
-
-namespace android {
-namespace idlcli {
-
-class IdlCli;
-
-class CommandVibrator : public CommandWithSubcommands<CommandVibrator> {
- std::string getDescription() const override { return "Invoke Vibrator HIDL APIs."; }
-
- std::string getUsageSummary() const override { return "<api> [arguments]"; }
-
- UsageDetails getUsageDetails() const override {
- UsageDetails details{
- {"<api>", CommandRegistry<CommandVibrator>::List()},
- };
- return details;
- }
-};
-
-static const auto Command = CommandRegistry<IdlCli>::Register<CommandVibrator>("vibrator");
-
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/IdlCli.h b/cmds/idlcli/IdlCli.h
deleted file mode 100644
index dd8430415e..0000000000
--- a/cmds/idlcli/IdlCli.h
+++ /dev/null
@@ -1,41 +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.
- */
-
-#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
-#define FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
-
-#include "utils.h"
-
-namespace android {
-namespace idlcli {
-
-class IdlCli : public CommandWithSubcommands<IdlCli> {
- std::string getDescription() const override { return "Invoke IDL APIs."; }
-
- std::string getUsageSummary() const override { return "<idl> [arguments]"; }
-
- UsageDetails getUsageDetails() const override {
- UsageDetails details{
- {"<idl>", CommandRegistry<IdlCli>::List()},
- };
- return details;
- }
-};
-
-} // namespace idlcli
-} // namespace android
-
-#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
diff --git a/cmds/idlcli/main.cpp b/cmds/idlcli/main.cpp
deleted file mode 100644
index 9ed9d8216a..0000000000
--- a/cmds/idlcli/main.cpp
+++ /dev/null
@@ -1,23 +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 "IdlCli.h"
-#include "utils.h"
-
-int main(const int argc, const char* const argv[]) {
- using namespace ::android::idlcli;
- return IdlCli{}.main(Args{argc, argv});
-}
diff --git a/cmds/idlcli/utils.h b/cmds/idlcli/utils.h
deleted file mode 100644
index a8e595470d..0000000000
--- a/cmds/idlcli/utils.h
+++ /dev/null
@@ -1,270 +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.
- */
-
-#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
-#define FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
-
-#include <hidl/HidlSupport.h>
-
-#include <iomanip>
-#include <iostream>
-#include <map>
-#include <sstream>
-#include <string>
-#include <vector>
-
-namespace android {
-namespace idlcli {
-
-namespace overrides {
-
-namespace details {
-
-template <typename T>
-inline std::istream &operator>>(std::istream &stream, T &out) {
- auto pos = stream.tellg();
- auto tmp = +out;
- auto min = +std::numeric_limits<T>::min();
- auto max = +std::numeric_limits<T>::max();
- stream >> tmp;
- if (!stream) {
- return stream;
- }
- if (tmp < min || tmp > max) {
- stream.seekg(pos);
- stream.setstate(std::ios_base::failbit);
- return stream;
- }
- out = tmp;
- return stream;
-}
-
-} // namespace details
-
-// override for default behavior of treating as a character
-inline std::istream &operator>>(std::istream &stream, int8_t &out) {
- return details::operator>>(stream, out);
-}
-
-// override for default behavior of treating as a character
-inline std::istream &operator>>(std::istream &stream, uint8_t &out) {
- return details::operator>>(stream, out);
-}
-
-} // namespace overrides
-
-template <typename T, typename R = hardware::hidl_enum_range<T>>
-inline std::istream &operator>>(std::istream &stream, T &out) {
- using overrides::operator>>;
- auto validRange = R();
- auto pos = stream.tellg();
- std::underlying_type_t<T> in;
- T tmp;
- stream >> in;
- if (!stream) {
- return stream;
- }
- tmp = static_cast<T>(in);
- if (tmp < *validRange.begin() || tmp > *std::prev(validRange.end())) {
- stream.seekg(pos);
- stream.setstate(std::ios_base::failbit);
- return stream;
- }
- out = tmp;
- return stream;
-}
-
-enum Status : unsigned int {
- OK,
- USAGE,
- UNAVAILABLE,
- ERROR,
-};
-
-class Args {
-public:
- Args(const int argc, const char *const argv[]) {
- for (int argi = 0; argi < argc; argi++) {
- mArgs.emplace_back(std::string_view(argv[argi]));
- }
- }
-
- template <typename T = std::string>
- std::optional<T> get() {
- return get<T>(false);
- }
-
- template <typename T = std::string>
- std::optional<T> pop() {
- return get<T>(true);
- }
-
- bool empty() { return mArgs.empty(); }
-
-private:
- template <typename T>
- std::optional<T> get(bool erase) {
- using idlcli::operator>>;
- using overrides::operator>>;
- T retValue;
-
- if (mArgs.empty()) {
- return {};
- }
-
- std::stringstream stream{std::string{mArgs.front()}};
- stream >> std::setbase(0) >> retValue;
- if (!stream || !stream.eof()) {
- return {};
- }
-
- if (erase) {
- mArgs.erase(mArgs.begin());
- }
-
- return retValue;
- }
-
- std::vector<std::string_view> mArgs;
-};
-
-class Command {
-protected:
- struct Usage {
- std::string name;
- std::vector<std::string> details;
- };
- using UsageDetails = std::vector<Usage>;
-
-public:
- virtual ~Command() = default;
-
- Status main(Args &&args) {
- Status status = doArgsAndMain(std::move(args));
- if (status == USAGE) {
- printUsage();
- return ERROR;
- }
- if (status == UNAVAILABLE) {
- std::cerr << "The requested operation is unavailable." << std::endl;
- return ERROR;
- }
- return status;
- }
-
-private:
- virtual std::string getDescription() const = 0;
- virtual std::string getUsageSummary() const = 0;
- virtual UsageDetails getUsageDetails() const = 0;
- virtual Status doArgs(Args &args) = 0;
- virtual Status doMain(Args &&args) = 0;
-
- void printUsage() const {
- std::cerr << "Description:\n " << getDescription() << std::endl;
- std::cerr << "Usage:\n " << mName << " " << getUsageSummary() << std::endl;
-
- std::cerr << "Details:" << std::endl;
- size_t entryNameWidth = 0;
- for (auto &entry : getUsageDetails()) {
- entryNameWidth = std::max(entryNameWidth, entry.name.length());
- }
- for (auto &entry : getUsageDetails()) {
- auto prefix = entry.name;
- for (auto &line : entry.details) {
- std::cerr << " " << std::left << std::setw(entryNameWidth + 8) << prefix << line
- << std::endl;
- prefix = "";
- }
- }
- }
-
- Status doArgsAndMain(Args &&args) {
- Status status;
- mName = *args.pop();
- if ((status = doArgs(args)) != OK) {
- return status;
- }
- if ((status = doMain(std::move(args))) != OK) {
- return status;
- }
- return OK;
- }
-
-protected:
- std::string mName;
-};
-
-template <typename T>
-class CommandRegistry {
-private:
- using CommandCreator = std::function<std::unique_ptr<Command>()>;
-
-public:
- template <typename U>
- static CommandCreator Register(const std::string name) {
- Instance()->mCommands[name] = [] { return std::make_unique<U>(); };
- return Instance()->mCommands[name];
- }
-
- static std::unique_ptr<Command> Create(const std::string name) {
- auto it = Instance()->mCommands.find(name);
- if (it == Instance()->mCommands.end()) {
- return nullptr;
- }
- return it->second();
- }
-
- static auto List() {
- std::vector<std::string> list;
- for (auto &it : Instance()->mCommands) {
- list.push_back(it.first);
- }
- std::sort(list.begin(), list.end());
- return list;
- }
-
-private:
- static CommandRegistry *Instance() {
- static CommandRegistry sRegistry;
- return &sRegistry;
- }
-
-private:
- std::map<const std::string, CommandCreator> mCommands;
-};
-
-template <typename T>
-class CommandWithSubcommands : public Command {
-private:
- Status doArgs(Args &args) override {
- mCommand = CommandRegistry<T>::Create(*args.get());
- if (!mCommand) {
- std::cerr << "Invalid Command!" << std::endl;
- return USAGE;
- }
- return OK;
- }
-
- Status doMain(Args &&args) override { return mCommand->main(std::move(args)); }
-
-protected:
- std::unique_ptr<Command> mCommand;
-};
-
-} // namespace idlcli
-} // namespace android
-
-#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h
deleted file mode 100644
index bcb207b7d0..0000000000
--- a/cmds/idlcli/vibrator.h
+++ /dev/null
@@ -1,86 +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.
- */
-
-#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
-#define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
-
-#include <android/hardware/vibrator/1.3/IVibrator.h>
-
-#include "utils.h"
-
-#include "log/log.h"
-
-namespace android {
-
-using hardware::Return;
-
-static constexpr int NUM_TRIES = 2;
-
-// Creates a Return<R> with STATUS::EX_NULL_POINTER.
-template <class R>
-inline Return<R> NullptrStatus() {
- using ::android::hardware::Status;
- return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
-}
-
-template <typename I>
-class HalWrapper {
-public:
- static std::unique_ptr<HalWrapper> Create() {
- // Assume that if getService returns a nullptr, HAL is not available on the
- // device.
- auto hal = I::getService();
- return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
- }
-
- template <class R, class... Args0, class... Args1>
- Return<R> call(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
- return (*mHal.*fn)(std::forward<Args1>(args1)...);
- }
-
-private:
- HalWrapper(sp<I>&& hal) : mHal(std::move(hal)) {}
-
-private:
- sp<I> mHal;
-};
-
-template <typename I>
-static auto getHal() {
- static auto sHalWrapper = HalWrapper<I>::Create();
- return sHalWrapper.get();
-}
-
-template <class R, class I, class... Args0, class... Args1>
-Return<R> halCall(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
- auto hal = getHal<I>();
- return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
-}
-
-namespace idlcli {
-namespace vibrator {
-
-namespace V1_0 = ::android::hardware::vibrator::V1_0;
-namespace V1_1 = ::android::hardware::vibrator::V1_1;
-namespace V1_2 = ::android::hardware::vibrator::V1_2;
-namespace V1_3 = ::android::hardware::vibrator::V1_3;
-
-} // namespace vibrator
-} // namespace idlcli
-
-} // namespace android
-
-#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
diff --git a/cmds/idlcli/vibrator/CommandOff.cpp b/cmds/idlcli/vibrator/CommandOff.cpp
deleted file mode 100644
index a674f0192f..0000000000
--- a/cmds/idlcli/vibrator/CommandOff.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.
- */
-
-#include "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandOff : public Command {
- std::string getDescription() const override { return "Turn off vibrator."; }
-
- std::string getUsageSummary() const override { return ""; }
-
- UsageDetails getUsageDetails() const override {
- UsageDetails details{};
- return details;
- }
-
- Status doArgs(Args &args) override {
- if (!args.empty()) {
- std::cerr << "Unexpected Arguments!" << std::endl;
- return USAGE;
- }
- return OK;
- }
-
- Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_0::IVibrator::off);
-
- if (!ret.isOk()) {
- return UNAVAILABLE;
- }
-
- std::cout << "Status: " << toString(ret) << std::endl;
-
- return ret == V1_0::Status::OK ? OK : ERROR;
- }
-};
-
-static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandOff>("off");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandOn.cpp b/cmds/idlcli/vibrator/CommandOn.cpp
deleted file mode 100644
index 2164b7d149..0000000000
--- a/cmds/idlcli/vibrator/CommandOn.cpp
+++ /dev/null
@@ -1,71 +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 "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandOn : public Command {
- std::string getDescription() const override { return "Turn on vibrator."; }
-
- std::string getUsageSummary() const override { return "<duration>"; }
-
- UsageDetails getUsageDetails() const override {
- UsageDetails details{
- {"<duration>", {"In milliseconds."}},
- };
- return details;
- }
-
- Status doArgs(Args &args) override {
- if (auto duration = args.pop<decltype(mDuration)>()) {
- mDuration = *duration;
- } else {
- std::cerr << "Missing or Invalid Duration!" << std::endl;
- return USAGE;
- }
- if (!args.empty()) {
- std::cerr << "Unexpected Arguments!" << std::endl;
- return USAGE;
- }
- return OK;
- }
-
- Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_0::IVibrator::on, mDuration);
-
- if (!ret.isOk()) {
- return UNAVAILABLE;
- }
-
- std::cout << "Status: " << toString(ret) << std::endl;
-
- return ret == V1_0::Status::OK ? OK : ERROR;
- }
-
- uint32_t mDuration;
-};
-
-static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandOn>("on");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandPerform.cpp b/cmds/idlcli/vibrator/CommandPerform.cpp
deleted file mode 100644
index 688cbd87a1..0000000000
--- a/cmds/idlcli/vibrator/CommandPerform.cpp
+++ /dev/null
@@ -1,107 +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 "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-using V1_0::EffectStrength;
-using V1_3::Effect;
-
-class CommandPerform : public Command {
- std::string getDescription() const override { return "Perform vibration effect."; }
-
- std::string getUsageSummary() const override { return "<effect> <strength>"; }
-
- UsageDetails getUsageDetails() const override {
- UsageDetails details{
- {"<effect>", {"Effect ID."}},
- {"<strength>", {"0-2."}},
- };
- return details;
- }
-
- Status doArgs(Args &args) override {
- if (auto effect = args.pop<decltype(mEffect)>()) {
- mEffect = *effect;
- std::cout << "Effect: " << toString(mEffect) << std::endl;
- } else {
- std::cerr << "Missing or Invalid Effect!" << std::endl;
- return USAGE;
- }
- if (auto strength = args.pop<decltype(mStrength)>()) {
- mStrength = *strength;
- std::cout << "Strength: " << toString(mStrength) << std::endl;
- } else {
- std::cerr << "Missing or Invalid Strength!" << std::endl;
- return USAGE;
- }
- if (!args.empty()) {
- std::cerr << "Unexpected Arguments!" << std::endl;
- return USAGE;
- }
- return OK;
- }
-
- Status doMain(Args && /*args*/) override {
- Return<void> ret;
- V1_0::Status status;
- uint32_t lengthMs;
- auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
- status = retStatus;
- lengthMs = retLengthMs;
- };
-
- if (auto hal = getHal<V1_3::IVibrator>()) {
- ret = hal->call(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(mEffect),
- mStrength, callback);
- } else if (auto hal = getHal<V1_2::IVibrator>()) {
- ret = hal->call(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(mEffect),
- mStrength, callback);
- } else if (auto hal = getHal<V1_1::IVibrator>()) {
- ret = hal->call(&V1_1::IVibrator::perform_1_1, static_cast<V1_1::Effect_1_1>(mEffect),
- mStrength, callback);
- } else if (auto hal = getHal<V1_0::IVibrator>()) {
- ret = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
- mStrength, callback);
- } else {
- ret = NullptrStatus<void>();
- }
-
- if (!ret.isOk()) {
- return UNAVAILABLE;
- }
-
- std::cout << "Status: " << toString(status) << std::endl;
- std::cout << "Length: " << lengthMs << std::endl;
-
- return status == V1_0::Status::OK ? OK : ERROR;
- }
-
- Effect mEffect;
- EffectStrength mStrength;
-};
-
-static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandPerform>("perform");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
deleted file mode 100644
index 38a1dc279b..0000000000
--- a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
+++ /dev/null
@@ -1,72 +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 "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandSetAmplitude : public Command {
- std::string getDescription() const override { return "Set vibration amplitude."; }
-
- std::string getUsageSummary() const override { return "<amplitude>"; }
-
- UsageDetails getUsageDetails() const override {
- UsageDetails details{
- {"<amplitude>", {"1-255."}},
- };
- return details;
- }
-
- Status doArgs(Args &args) override {
- if (auto amplitude = args.pop<decltype(mAmplitude)>()) {
- mAmplitude = *amplitude;
- } else {
- std::cerr << "Missing or Invalid Amplitude!" << std::endl;
- return USAGE;
- }
- if (!args.empty()) {
- std::cerr << "Unexpected Arguments!" << std::endl;
- return USAGE;
- }
- return OK;
- }
-
- Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_0::IVibrator::setAmplitude, mAmplitude);
-
- if (!ret.isOk()) {
- return UNAVAILABLE;
- }
-
- std::cout << "Status: " << toString(ret) << std::endl;
-
- return ret == V1_0::Status::OK ? OK : ERROR;
- }
-
- uint8_t mAmplitude;
-};
-
-static const auto Command =
- CommandRegistry<CommandVibrator>::Register<CommandSetAmplitude>("setAmplitude");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
deleted file mode 100644
index 5fb1faca16..0000000000
--- a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
+++ /dev/null
@@ -1,70 +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 "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandSetExternalControl : public Command {
- std::string getDescription() const override {
- return "Enable/disable vibration external control.";
- }
-
- std::string getUsageSummary() const override { return "<enable>"; }
-
- UsageDetails getUsageDetails() const override {
- UsageDetails details{
- {"<enable>", {"0/1."}},
- };
- return details;
- }
-
- Status doArgs(Args &args) override {
- if (auto enable = args.pop<decltype(mEnable)>()) {
- mEnable = *enable;
- } else {
- std::cerr << "Missing Enable!" << std::endl;
- return USAGE;
- }
- return OK;
- }
-
- Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_3::IVibrator::setExternalControl, mEnable);
-
- if (!ret.isOk()) {
- return UNAVAILABLE;
- }
-
- std::cout << "Status: " << toString(ret) << std::endl;
-
- return ret == V1_0::Status::OK ? OK : ERROR;
- }
-
- bool mEnable;
-};
-
-static const auto Command =
- CommandRegistry<CommandVibrator>::Register<CommandSetExternalControl>("setExternalControl");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
deleted file mode 100644
index cdc529a2f3..0000000000
--- a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
+++ /dev/null
@@ -1,63 +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 "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandSupportsAmplitudeControl : public Command {
- std::string getDescription() const override { return "Check support for amplitude control."; }
-
- std::string getUsageSummary() const override { return ""; }
-
- UsageDetails getUsageDetails() const override {
- UsageDetails details{};
- return details;
- }
-
- Status doArgs(Args &args) override {
- if (!args.empty()) {
- std::cerr << "Unexpected Arguments!" << std::endl;
- return USAGE;
- }
- return OK;
- }
-
- Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_0::IVibrator::supportsAmplitudeControl);
-
- if (!ret.isOk()) {
- return UNAVAILABLE;
- }
-
- std::cout << "Result: " << std::boolalpha << ret << std::endl;
-
- return OK;
- }
-};
-
-static const auto Command =
- CommandRegistry<CommandVibrator>::Register<CommandSupportsAmplitudeControl>(
- "supportsAmplitudeControl");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp b/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
deleted file mode 100644
index ed15d76286..0000000000
--- a/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
+++ /dev/null
@@ -1,63 +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 "utils.h"
-#include "vibrator.h"
-
-namespace android {
-namespace idlcli {
-
-class CommandVibrator;
-
-namespace vibrator {
-
-class CommandSupportsExternalControl : public Command {
- std::string getDescription() const override { return "Check support for external control."; }
-
- std::string getUsageSummary() const override { return ""; }
-
- UsageDetails getUsageDetails() const override {
- UsageDetails details{};
- return details;
- }
-
- Status doArgs(Args &args) override {
- if (!args.empty()) {
- std::cerr << "Unexpected Arguments!" << std::endl;
- return USAGE;
- }
- return OK;
- }
-
- Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_3::IVibrator::supportsExternalControl);
-
- if (!ret.isOk()) {
- return UNAVAILABLE;
- }
-
- std::cout << "Result: " << std::boolalpha << ret << std::endl;
-
- return OK;
- }
-};
-
-static const auto Command =
- CommandRegistry<CommandVibrator>::Register<CommandSupportsExternalControl>(
- "supportsExternalControl");
-
-} // namespace vibrator
-} // namespace idlcli
-} // namespace android
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 75dec371bc..c80ae3bbf6 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -138,7 +138,6 @@ cc_binary {
cc_binary {
name: "otapreopt_chroot",
- defaults: ["libapexd-deps"],
cflags: [
"-Wall",
"-Werror",
@@ -151,11 +150,20 @@ cc_binary {
],
shared_libs: [
"libbase",
+ "libbinder",
"liblog",
+ "libprotobuf-cpp-full",
+ "libselinux",
"libutils",
+ "libziparchive",
],
static_libs: [
+ "libapex",
"libapexd",
+ "lib_apex_manifest_proto",
+ "libavb",
+ "libdm",
+ "libvold_binder",
],
}
@@ -164,7 +172,6 @@ filegroup {
srcs: [
"binder/android/os/IInstalld.aidl",
],
- path: "binder",
}
//
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 4026f29208..34727270e4 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -832,7 +832,7 @@ static int32_t copy_directory_recursive(const char* from, const char* to) {
};
LOG(DEBUG) << "Copying " << from << " to " << to;
- return logwrap_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
+ return android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true);
}
binder::Status InstalldNativeService::snapshotAppData(
@@ -2107,15 +2107,10 @@ binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t
CHECK_ARGUMENT_PATH(dexMetadataPath);
std::lock_guard<std::recursive_mutex> lock(mLock);
- const char* oat_dir = getCStr(outputPath);
- const char* instruction_set = instructionSet.c_str();
- if (oat_dir != nullptr && !createOatDir(oat_dir, instruction_set).isOk()) {
- // Can't create oat dir - let dexopt use cache dir.
- oat_dir = nullptr;
- }
-
const char* apk_path = apkPath.c_str();
const char* pkgname = getCStr(packageName, "*");
+ const char* instruction_set = instructionSet.c_str();
+ const char* oat_dir = getCStr(outputPath);
const char* compiler_filter = compilerFilter.c_str();
const char* volume_uuid = getCStr(uuid);
const char* class_loader_context = getCStr(classLoaderContext);
@@ -2141,26 +2136,6 @@ binder::Status InstalldNativeService::compileLayouts(const std::string& apkPath,
return *_aidl_return ? ok() : error("viewcompiler failed");
}
-binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) {
- ENFORCE_UID(AID_SYSTEM);
- std::lock_guard<std::recursive_mutex> lock(mLock);
-
- const char* instruction_set = instructionSet.c_str();
-
- char boot_marker_path[PKG_PATH_MAX];
- sprintf(boot_marker_path,
- "%s/%s/%s/.booting",
- android_data_dir.c_str(),
- DALVIK_CACHE,
- instruction_set);
-
- ALOGV("mark_boot_complete : %s", boot_marker_path);
- if (unlink(boot_marker_path) != 0) {
- return error(StringPrintf("Failed to unlink %s", boot_marker_path));
- }
- return ok();
-}
-
binder::Status InstalldNativeService::linkNativeLibraryDirectory(
const std::unique_ptr<std::string>& uuid, const std::string& packageName,
const std::string& nativeLibPath32, int32_t userId) {
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 2b7bf33cbc..eba966d4ab 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -123,7 +123,6 @@ public:
int32_t uid);
binder::Status removeIdmap(const std::string& overlayApkPath);
binder::Status rmPackageDir(const std::string& packageDir);
- binder::Status markBootComplete(const std::string& instructionSet);
binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t targetFreeBytes,
int64_t cacheReservedBytes, int32_t flags);
binder::Status linkNativeLibraryDirectory(const std::unique_ptr<std::string>& uuid,
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
index 9a21104131..56739181bb 100644
--- a/cmds/installd/OWNERS
+++ b/cmds/installd/OWNERS
@@ -4,9 +4,7 @@ agampe@google.com
calin@google.com
jsharkey@android.com
maco@google.com
-mast@google.com
mathieuc@google.com
narayan@google.com
ngeoffray@google.com
-rpl@google.com
toddke@google.com
diff --git a/cmds/installd/art_helper/Android.bp b/cmds/installd/art_helper/Android.bp
new file mode 100644
index 0000000000..c47dd722f9
--- /dev/null
+++ b/cmds/installd/art_helper/Android.bp
@@ -0,0 +1,12 @@
+// Inherit image values.
+art_global_defaults {
+ name: "libartimagevalues_defaults",
+}
+
+cc_library_static {
+ name: "libartimagevalues",
+ defaults: ["libartimagevalues_defaults"],
+ srcs: ["art_image_values.cpp"],
+ export_include_dirs: ["."],
+ cflags: ["-Wconversion"],
+}
diff --git a/cmds/installd/art_helper/art_image_values.cpp b/cmds/installd/art_helper/art_image_values.cpp
new file mode 100644
index 0000000000..a139049d9f
--- /dev/null
+++ b/cmds/installd/art_helper/art_image_values.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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 "art_image_values.h"
+
+namespace android {
+namespace installd {
+namespace art {
+
+uint32_t GetImageBaseAddress() {
+ return ART_BASE_ADDRESS;
+}
+int32_t GetImageMinBaseAddressDelta() {
+ return ART_BASE_ADDRESS_MIN_DELTA;
+}
+int32_t GetImageMaxBaseAddressDelta() {
+ return ART_BASE_ADDRESS_MAX_DELTA;
+}
+
+static_assert(ART_BASE_ADDRESS_MIN_DELTA < ART_BASE_ADDRESS_MAX_DELTA, "Inconsistent setup");
+
+} // namespace art
+} // namespace installd
+} // namespace android
diff --git a/services/inputflinger/dispatcher/InputDispatcherFactory.cpp b/cmds/installd/art_helper/art_image_values.h
index 8d7fa7573b..20c44c953f 100644
--- a/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
+++ b/cmds/installd/art_helper/art_image_values.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 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.
@@ -14,14 +14,21 @@
* limitations under the License.
*/
-#include "InputDispatcherFactory.h"
-#include "InputDispatcher.h"
+#ifndef FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
+#define FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
+
+#include <cstdint>
namespace android {
+namespace installd {
+namespace art {
+
+uint32_t GetImageBaseAddress();
+int32_t GetImageMinBaseAddressDelta();
+int32_t GetImageMaxBaseAddressDelta();
-sp<InputDispatcherInterface> createInputDispatcher(
- const sp<InputDispatcherPolicyInterface>& policy) {
- return new android::inputdispatcher::InputDispatcher(policy);
-}
+} // namespace art
+} // namespace installd
+} // namespace android
-} // namespace android
+#endif // FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 26e9984f11..b795c02648 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -75,7 +75,6 @@ interface IInstalld {
void idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid);
void removeIdmap(@utf8InCpp String overlayApkPath);
void rmPackageDir(@utf8InCpp String packageDir);
- void markBootComplete(@utf8InCpp String instructionSet);
void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes,
long cacheReservedBytes, int flags);
void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid,
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 838d11d6d8..5fb13a5c56 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -303,9 +303,6 @@ static const char* ENABLE_APEX_IMAGE = "enable_apex_image";
// Location of the apex image.
static const char* kApexImage = "/system/framework/apex.art";
-// Phenotype property name for enabling profiling the boot class path.
-static const char* PROFILE_BOOT_CLASS_PATH = "profilebootclasspath";
-
class RunDex2Oat : public ExecVHelper {
public:
RunDex2Oat(int zip_fd,
@@ -339,6 +336,10 @@ class RunDex2Oat : public ExecVHelper {
? "dalvik.vm.dex2oat-threads"
: "dalvik.vm.boot-dex2oat-threads";
std::string dex2oat_threads_arg = MapPropertyToArg(threads_property, "-j%s");
+ const char* cpu_set_property = post_bootcomplete
+ ? "dalvik.vm.dex2oat-cpu-set"
+ : "dalvik.vm.boot-dex2oat-cpu-set";
+ std::string dex2oat_cpu_set_arg = MapPropertyToArg(cpu_set_property, "--cpu-set=%s");
std::string bootclasspath;
char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
@@ -405,15 +406,7 @@ class RunDex2Oat : public ExecVHelper {
server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,
ENABLE_APEX_IMAGE,
/*default_value=*/ "");
-
- std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", "");
- profile_boot_class_path =
- server_configurable_flags::GetServerConfigurableFlag(
- RUNTIME_NATIVE_BOOT_NAMESPACE,
- PROFILE_BOOT_CLASS_PATH,
- /*default_value=*/ profile_boot_class_path);
-
- if (use_apex_image == "true" || profile_boot_class_path == "true") {
+ if (use_apex_image == "true") {
boot_image = StringPrintf("-Ximage:%s", kApexImage);
} else {
boot_image = MapPropertyToArg("dalvik.vm.boot-image", "-Ximage:%s");
@@ -518,6 +511,7 @@ class RunDex2Oat : public ExecVHelper {
AddArg(image_block_size_arg);
AddArg(dex2oat_compiler_filter_arg);
AddArg(dex2oat_threads_arg);
+ AddArg(dex2oat_cpu_set_arg);
AddArg(dex2oat_swap_fd);
AddArg(dex2oat_image_fd);
@@ -720,7 +714,8 @@ class RunProfman : public ExecVHelper {
const unique_fd& reference_profile_fd,
const std::vector<unique_fd>& apk_fds,
const std::vector<std::string>& dex_locations,
- bool copy_and_update) {
+ bool copy_and_update,
+ bool store_aggregation_counters) {
// TODO(calin): Assume for now we run in the bg compile job (which is in
// most of the invocation). With the current data flow, is not very easy or
@@ -752,6 +747,10 @@ class RunProfman : public ExecVHelper {
AddArg("--copy-and-update-profile-key");
}
+ if (store_aggregation_counters) {
+ AddArg("--store-aggregation-counters");
+ }
+
// Do not add after dex2oat_flags, they should override others for debugging.
PrepareArgs(profman_bin);
}
@@ -759,12 +758,14 @@ class RunProfman : public ExecVHelper {
void SetupMerge(const std::vector<unique_fd>& profiles_fd,
const unique_fd& reference_profile_fd,
const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(),
- const std::vector<std::string>& dex_locations = std::vector<std::string>()) {
+ const std::vector<std::string>& dex_locations = std::vector<std::string>(),
+ bool store_aggregation_counters = false) {
SetupArgs(profiles_fd,
reference_profile_fd,
apk_fds,
dex_locations,
- /*copy_and_update=*/false);
+ /*copy_and_update=*/false,
+ store_aggregation_counters);
}
void SetupCopyAndUpdate(unique_fd&& profile_fd,
@@ -781,7 +782,8 @@ class RunProfman : public ExecVHelper {
reference_profile_fd_,
apk_fds_,
dex_locations,
- /*copy_and_update=*/true);
+ /*copy_and_update=*/true,
+ /*store_aggregation_counters=*/false);
}
void SetupDump(const std::vector<unique_fd>& profiles_fd,
@@ -795,7 +797,8 @@ class RunProfman : public ExecVHelper {
reference_profile_fd,
apk_fds,
dex_locations,
- /*copy_and_update=*/false);
+ /*copy_and_update=*/false,
+ /*store_aggregation_counters=*/false);
}
void Exec() {
@@ -2119,20 +2122,14 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins
// Create a swap file if necessary.
unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
- // Open the reference profile if needed.
- Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
- pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
-
- if (reference_profile_fd.get() == -1) {
- // We don't create an app image without reference profile since there is no speedup from
- // loading it in that case and instead will be a small overhead.
- generate_app_image = false;
- }
-
// Create the app image file if needed.
Dex2oatFileWrapper image_fd = maybe_open_app_image(
out_oat_path, generate_app_image, is_public, uid, is_secondary_dex);
+ // Open the reference profile if needed.
+ Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
+ pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
+
unique_fd dex_metadata_fd;
if (dex_metadata_path != nullptr) {
dex_metadata_fd.reset(TEMP_FAILURE_RETRY(open(dex_metadata_path, O_RDONLY | O_NOFOLLOW)));
@@ -2830,7 +2827,8 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name,
args.SetupMerge(profiles_fd,
snapshot_fd,
apk_fds,
- dex_locations);
+ dex_locations,
+ /*store_aggregation_counters=*/true);
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index ef739bafd4..a8c48c564e 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -32,15 +32,15 @@ static constexpr int DEX2OAT_FROM_SCRATCH = 1;
static constexpr int DEX2OAT_FOR_BOOT_IMAGE = 2;
static constexpr int DEX2OAT_FOR_FILTER = 3;
-#define ANDROID_ART_APEX_BIN "/apex/com.android.art/bin"
+#define ANDROID_RUNTIME_APEX_BIN "/apex/com.android.runtime/bin"
// Location of binaries in the Android Runtime APEX.
-static constexpr const char* kDex2oatPath = ANDROID_ART_APEX_BIN "/dex2oat";
-static constexpr const char* kDex2oatDebugPath = ANDROID_ART_APEX_BIN "/dex2oatd";
-static constexpr const char* kProfmanPath = ANDROID_ART_APEX_BIN "/profman";
-static constexpr const char* kProfmanDebugPath = ANDROID_ART_APEX_BIN "/profmand";
-static constexpr const char* kDexoptanalyzerPath = ANDROID_ART_APEX_BIN "/dexoptanalyzer";
-static constexpr const char* kDexoptanalyzerDebugPath = ANDROID_ART_APEX_BIN "/dexoptanalyzerd";
-#undef ANDROID_ART_APEX_BIN
+static constexpr const char* kDex2oatPath = ANDROID_RUNTIME_APEX_BIN "/dex2oat";
+static constexpr const char* kDex2oatDebugPath = ANDROID_RUNTIME_APEX_BIN "/dex2oatd";
+static constexpr const char* kProfmanPath = ANDROID_RUNTIME_APEX_BIN "/profman";
+static constexpr const char* kProfmanDebugPath = ANDROID_RUNTIME_APEX_BIN "/profmand";
+static constexpr const char* kDexoptanalyzerPath = ANDROID_RUNTIME_APEX_BIN "/dexoptanalyzer";
+static constexpr const char* kDexoptanalyzerDebugPath = ANDROID_RUNTIME_APEX_BIN "/dexoptanalyzerd";
+#undef ANDROID_RUNTIME_APEX_BIN
// Clear the reference profile identified by the given profile name.
bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index b5bc28c1d3..673ff0d513 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -74,7 +74,7 @@ static int initialize_directories() {
// Read current filesystem layout version to handle upgrade paths
char version_path[PATH_MAX];
- snprintf(version_path, PATH_MAX, "%smisc/installd/layout_version", android_data_dir.c_str());
+ snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.c_str());
int oldVersion;
if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
diff --git a/cmds/installd/migrate_legacy_obb_data.sh b/cmds/installd/migrate_legacy_obb_data.sh
index 0e6d7b9c62..10756881be 100644
--- a/cmds/installd/migrate_legacy_obb_data.sh
+++ b/cmds/installd/migrate_legacy_obb_data.sh
@@ -15,17 +15,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-rm -rf /data/media/Android/obb/test_probe
-mkdir -p /data/media/Android/obb/
-touch /data/media/Android/obb/test_probe
+rm -rf /sdcard/Android/obb/test_probe
+mkdir -p /sdcard/Android/obb/
+touch /sdcard/Android/obb/test_probe
if ! test -f /data/media/0/Android/obb/test_probe ; then
log -p i -t migrate_legacy_obb_data "No support for 'unshared_obb'. Not migrating"
- rm -rf /data/media/Android/obb/test_probe
+ rm -rf /sdcard/Android/obb/test_probe
exit 0
fi
# Delete the test file, and remove the obb folder if it is empty
-rm -rf /data/media/Android/obb/test_probe
+rm -rf /sdcard/Android/obb/test_probe
rmdir /data/media/obb
if ! test -d /data/media/obb ; then
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index db36ce3c9e..9bc5fc81d4 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -445,11 +445,9 @@ private:
}
cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
- int32_t base_offset = ChooseRelocationOffsetDelta(
- art::imagevalues::GetImageMinBaseAddressDelta(),
- art::imagevalues::GetImageMaxBaseAddressDelta());
- cmd.push_back(StringPrintf("--base=0x%x",
- art::imagevalues::GetImageBaseAddress() + base_offset));
+ int32_t base_offset = ChooseRelocationOffsetDelta(art::GetImageMinBaseAddressDelta(),
+ art::GetImageMaxBaseAddressDelta());
+ cmd.push_back(StringPrintf("--base=0x%x", art::GetImageBaseAddress() + base_offset));
cmd.push_back(StringPrintf("--instruction-set=%s", isa));
@@ -466,7 +464,7 @@ private:
"--compiler-filter=",
false,
cmd);
- cmd.push_back("--profile-file=/system/etc/boot-image.prof");
+ cmd.push_back("--image-classes=/system/etc/preloaded-classes");
// TODO: Compiled-classes.
const std::string* extra_opts =
system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags");
@@ -480,6 +478,10 @@ private:
"-j",
false,
cmd);
+ AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-cpu-set",
+ "--cpu-set=",
+ false,
+ cmd);
AddCompilerOptionFromSystemProperty(
StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(),
"--instruction-set-variant=",
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 3ff9d11806..2e2cc182ec 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -64,18 +64,16 @@ static std::vector<apex::ApexFile> ActivateApexPackages() {
// system/apex/apexd/apexd_main.cpp.
//
// Only scan the APEX directory under /system (within the chroot dir).
- // Cast call to void to suppress warn_unused_result.
- static_cast<void>(apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir));
+ apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
return apex::getActivePackages();
}
static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) {
for (const apex::ApexFile& apex_file : active_packages) {
const std::string& package_path = apex_file.GetPath();
- base::Result<void> status = apex::deactivatePackage(package_path);
- if (!status) {
- LOG(ERROR) << "Failed to deactivate " << package_path << ": "
- << status.error();
+ apex::Status status = apex::deactivatePackage(package_path);
+ if (!status.Ok()) {
+ LOG(ERROR) << "Failed to deactivate " << package_path << ": " << status.ErrorMessage();
}
}
}
@@ -233,21 +231,9 @@ static int otapreopt_chroot(const int argc, char **arg) {
}
// Try to mount APEX packages in "/apex" in the chroot dir. We need at least
- // the ART APEX, as it is required by otapreopt to run dex2oat.
+ // the Android Runtime APEX, as it is required by otapreopt to run dex2oat.
std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
- // Check that an ART APEX has been activated; clean up and exit
- // early otherwise.
- if (std::none_of(active_packages.begin(),
- active_packages.end(),
- [](const apex::ApexFile& package){
- return package.GetManifest().name() == "com.android.art";
- })) {
- LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.art APEX package.";
- DeactivateApexPackages(active_packages);
- exit(217);
- }
-
// Now go on and run otapreopt.
// Incoming: cmd + status-fd + target-slot + cmd... | Incoming | = argc
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index bd45005fd1..aa79fdc100 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -89,8 +89,6 @@ cc_test {
"libinstalld",
"liblog",
"liblogwrap",
- "libziparchive",
- "libz",
],
test_config: "installd_dexopt_test.xml",
}
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
index 5a5cb53431..db0907017c 100644
--- a/cmds/installd/tests/installd_cache_test.cpp
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -67,29 +67,29 @@ bool create_cache_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
}
static void mkdir(const char* path) {
- const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
- ::mkdir(fullPath.c_str(), 0755);
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ ::mkdir(fullPath, 0755);
}
static void touch(const char* path, int len, int time) {
- const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
- int fd = ::open(fullPath.c_str(), O_RDWR | O_CREAT, 0644);
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ int fd = ::open(fullPath, O_RDWR | O_CREAT, 0644);
::fallocate(fd, 0, 0, len);
::close(fd);
struct utimbuf times;
times.actime = times.modtime = std::time(0) + time;
- ::utime(fullPath.c_str(), &times);
+ ::utime(fullPath, &times);
}
static int exists(const char* path) {
- const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
- return ::access(fullPath.c_str(), F_OK);
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ return ::access(fullPath, F_OK);
}
static int64_t size(const char* path) {
- const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
struct stat buf;
- if (!stat(fullPath.c_str(), &buf)) {
+ if (!stat(fullPath, &buf)) {
return buf.st_size;
} else {
return -1;
@@ -107,8 +107,8 @@ static int64_t free() {
}
static void setxattr(const char* path, const char* key) {
- const std::string fullPath = StringPrintf("/data/local/tmp/user/0/%s", path);
- ::setxattr(fullPath.c_str(), key, "", 0, 0);
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ ::setxattr(fullPath, key, "", 0, 0);
}
class CacheTest : public testing::Test {
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 0212bc5564..fa2b0d9660 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -41,7 +41,6 @@
#include "globals.h"
#include "tests/test_utils.h"
#include "utils.h"
-#include "ziparchive/zip_writer.h"
using android::base::ReadFully;
using android::base::unique_fd;
@@ -196,7 +195,6 @@ protected:
std::unique_ptr<std::string> volume_uuid_;
std::string package_name_;
std::string apk_path_;
- std::string empty_dm_file_;
std::string app_apk_dir_;
std::string app_private_dir_ce_;
std::string app_private_dir_de_;
@@ -241,14 +239,18 @@ protected:
}
::testing::AssertionResult create_mock_app() {
+ // Create the oat dir.
+ app_oat_dir_ = app_apk_dir_ + "/oat";
// For debug mode, the directory might already exist. Avoid erroring out.
if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0 && !kDebug) {
return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_
<< " : " << strerror(errno);
}
-
- // Initialize the oat dir path.
- app_oat_dir_ = app_apk_dir_ + "/oat";
+ binder::Status status = service_->createOatDir(app_oat_dir_, kRuntimeIsa);
+ if (!status.isOk()) {
+ return ::testing::AssertionFailure() << "Could not create oat dir: "
+ << status.toString8().c_str();
+ }
// Copy the primary apk.
apk_path_ = app_apk_dir_ + "/base.jar";
@@ -258,28 +260,8 @@ protected:
<< " : " << error_msg;
}
- // Create an empty dm file.
- empty_dm_file_ = apk_path_ + ".dm";
- {
- int fd = open(empty_dm_file_.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
- if (fd < 0) {
- return ::testing::AssertionFailure() << "Could not open " << empty_dm_file_;
- }
- FILE* file = fdopen(fd, "wb");
- if (file == nullptr) {
- return ::testing::AssertionFailure() << "Null file for " << empty_dm_file_
- << " fd=" << fd;
- }
- ZipWriter writer(file);
- // Add vdex to zip.
- writer.StartEntry("primary.prof", ZipWriter::kCompress);
- writer.FinishEntry();
- writer.Finish();
- fclose(file);
- }
-
// Create the app user data.
- binder::Status status = service_->createAppData(
+ status = service_->createAppData(
volume_uuid_,
package_name_,
kTestUserId,
@@ -497,7 +479,7 @@ protected:
bool prof_result;
ASSERT_BINDER_SUCCESS(service_->prepareAppProfile(
package_name_, kTestUserId, kTestAppId, *profile_name_ptr, apk_path_,
- dm_path_ptr, &prof_result));
+ /*dex_metadata*/ nullptr, &prof_result));
ASSERT_TRUE(prof_result);
binder::Status result = service_->dexopt(apk_path_,
@@ -643,16 +625,6 @@ TEST_F(DexoptTest, DexoptPrimaryPublic) {
DEX2OAT_FROM_SCRATCH);
}
-TEST_F(DexoptTest, DexoptPrimaryPublicCreateOatDir) {
- LOG(INFO) << "DexoptPrimaryPublic";
- ASSERT_BINDER_SUCCESS(service_->createOatDir(app_oat_dir_, kRuntimeIsa));
- CompilePrimaryDexOk("verify",
- DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
- app_oat_dir_.c_str(),
- kTestAppGid,
- DEX2OAT_FROM_SCRATCH);
-}
-
TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) {
LOG(INFO) << "DexoptPrimaryFailedInvalidFilter";
binder::Status status;
@@ -673,9 +645,7 @@ TEST_F(DexoptTest, DexoptPrimaryProfileNonPublic) {
DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_GENERATE_APP_IMAGE,
app_oat_dir_.c_str(),
kTestAppGid,
- DEX2OAT_FROM_SCRATCH,
- /*binder_result=*/nullptr,
- empty_dm_file_.c_str());
+ DEX2OAT_FROM_SCRATCH);
}
TEST_F(DexoptTest, DexoptPrimaryProfilePublic) {
@@ -685,9 +655,7 @@ TEST_F(DexoptTest, DexoptPrimaryProfilePublic) {
DEXOPT_GENERATE_APP_IMAGE,
app_oat_dir_.c_str(),
kTestAppGid,
- DEX2OAT_FROM_SCRATCH,
- /*binder_result=*/nullptr,
- empty_dm_file_.c_str());
+ DEX2OAT_FROM_SCRATCH);
}
TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) {
@@ -697,9 +665,7 @@ TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) {
DEXOPT_GENERATE_APP_IMAGE,
app_oat_dir_.c_str(),
kTestAppGid,
- DEX2OAT_FROM_SCRATCH,
- /*binder_result=*/nullptr,
- empty_dm_file_.c_str());
+ DEX2OAT_FROM_SCRATCH);
}
TEST_F(DexoptTest, ResolveStartupConstStrings) {
@@ -718,9 +684,7 @@ TEST_F(DexoptTest, ResolveStartupConstStrings) {
DEXOPT_GENERATE_APP_IMAGE,
app_oat_dir_.c_str(),
kTestAppGid,
- DEX2OAT_FROM_SCRATCH,
- /*binder_result=*/nullptr,
- empty_dm_file_.c_str());
+ DEX2OAT_FROM_SCRATCH);
run_cmd_and_process_output(
"oatdump --header-only --oat-file=" + odex,
[&](const std::string& line) {
@@ -737,9 +701,7 @@ TEST_F(DexoptTest, ResolveStartupConstStrings) {
DEXOPT_GENERATE_APP_IMAGE,
app_oat_dir_.c_str(),
kTestAppGid,
- DEX2OAT_FROM_SCRATCH,
- /*binder_result=*/nullptr,
- empty_dm_file_.c_str());
+ DEX2OAT_FROM_SCRATCH);
run_cmd_and_process_output(
"oatdump --header-only --oat-file=" + odex,
[&](const std::string& line) {
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 5afae4b7d3..93d878b607 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -12,13 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_static {
+cc_library_shared {
name: "liblshal",
shared_libs: [
"libbase",
"libcutils",
"libutils",
"libhidlbase",
+ "libhidltransport",
"libhidl-gen-hash",
"libhidl-gen-utils",
"libvintf",
@@ -35,7 +36,6 @@ cc_library_static {
"TableEntry.cpp",
"TextTable.cpp",
"utils.cpp",
- "WaitCommand.cpp",
],
cflags: [
"-Wall",
@@ -47,15 +47,13 @@ cc_defaults {
name: "lshal_defaults",
shared_libs: [
"libbase",
- "libcutils",
- "libutils",
"libhidlbase",
- "libhidl-gen-hash",
"libhidl-gen-utils",
- "libvintf",
+ "libhidltransport",
+ "liblshal",
+ "libutils",
],
static_libs: [
- "liblshal",
"libprocpartition",
],
cflags: ["-Wall", "-Werror"],
@@ -71,16 +69,14 @@ cc_binary {
cc_test {
name: "lshal_test",
- test_suites: ["device-tests"],
defaults: ["lshal_defaults"],
gtest: true,
static_libs: [
- "android.hardware.tests.baz@1.0",
- "libgmock",
+ "libgmock"
],
shared_libs: [
- "libhidlbase",
"libvintf",
+ "android.hardware.tests.baz@1.0"
],
srcs: [
"test.cpp"
diff --git a/cmds/lshal/Command.h b/cmds/lshal/Command.h
index 84809d9a5d..e19e3f7fc2 100644
--- a/cmds/lshal/Command.h
+++ b/cmds/lshal/Command.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_COMMAND_H_
#include "utils.h"
@@ -47,3 +48,5 @@ protected:
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index af22ac9b3d..0952db6e72 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -79,7 +79,7 @@ void DebugCommand::usage() const {
" lshal debug [-E] <interface> [options [options [...]]] \n"
" Print debug information of a specified interface.\n"
" -E: excludes debug output if HAL is actually a subclass.\n"
- " <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
+ " <inteface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
" If instance name is missing `default` is used.\n"
" options: space separated options to IBase::debug.\n";
@@ -88,3 +88,4 @@ void DebugCommand::usage() const {
} // namespace lshal
} // namespace android
+
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
index cd57e31bfc..3c3f56fde5 100644
--- a/cmds/lshal/DebugCommand.h
+++ b/cmds/lshal/DebugCommand.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
#include <string>
@@ -52,3 +53,5 @@ private:
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
diff --git a/cmds/lshal/HelpCommand.h b/cmds/lshal/HelpCommand.h
index bfa850075d..da0cba6f42 100644
--- a/cmds/lshal/HelpCommand.h
+++ b/cmds/lshal/HelpCommand.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_
#include <string>
@@ -43,3 +44,5 @@ public:
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index a7ccf64c50..c706d911ec 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -163,11 +163,11 @@ template <typename ObjectType>
VintfInfo getVintfInfo(const std::shared_ptr<const ObjectType>& object,
const FqInstance& fqInstance, vintf::TransportArch ta, VintfInfo value) {
bool found = false;
- (void)object->forEachHidlInstanceOfVersion(fqInstance.getPackage(), fqInstance.getVersion(),
- [&](const auto& instance) {
- found = match(instance, fqInstance, ta);
- return !found; // continue if not found
- });
+ (void)object->forEachInstanceOfVersion(fqInstance.getPackage(), fqInstance.getVersion(),
+ [&](const auto& instance) {
+ found = match(instance, fqInstance, ta);
+ return !found; // continue if not found
+ });
return found ? value : VINTF_INFO_EMPTY;
}
@@ -453,7 +453,7 @@ bool ListCommand::addEntryWithoutInstance(const TableEntry& entry,
}
bool found = false;
- (void)manifest->forEachHidlInstanceOfVersion(package, version, [&found](const auto&) {
+ (void)manifest->forEachInstanceOfVersion(package, version, [&found](const auto&) {
found = true;
return false; // break
});
@@ -797,9 +797,9 @@ Status ListCommand::fetchManifestHals() {
std::map<std::string, TableEntry> entries;
- manifest->forEachHidlInstance([&] (const vintf::ManifestInstance& manifestInstance) {
+ manifest->forEachInstance([&] (const vintf::ManifestInstance& manifestInstance) {
TableEntry entry{
- .interfaceName = manifestInstance.description(),
+ .interfaceName = manifestInstance.getFqInstance().string(),
.transport = manifestInstance.transport(),
.arch = manifestInstance.arch(),
// TODO(b/71555570): Device manifest does not distinguish HALs from vendor or ODM.
@@ -975,8 +975,7 @@ void ListCommand::registerAllOptions() {
" - DM: if the HAL is in the device manifest\n"
" - DC: if the HAL is in the device compatibility matrix\n"
" - FM: if the HAL is in the framework manifest\n"
- " - FC: if the HAL is in the framework compatibility matrix\n"
- " - X: if the HAL is in none of the above lists"});
+ " - FC: if the HAL is in the framework compatibility matrix"});
mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) {
thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS);
return OK;
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index b3ed23d1fc..85195fcc54 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
#include <getopt.h>
#include <stdint.h>
@@ -205,3 +206,5 @@ private:
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 132b31ebc3..8c83457d3b 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -26,9 +26,7 @@
#include <hidl/HidlTransportUtils.h>
#include "DebugCommand.h"
-#include "HelpCommand.h"
#include "ListCommand.h"
-#include "WaitCommand.h"
#include "PipeRelay.h"
namespace android {
@@ -51,7 +49,6 @@ Lshal::Lshal(std::ostream &out, std::ostream &err,
mRegisteredCommands.push_back({std::make_unique<ListCommand>(*this)});
mRegisteredCommands.push_back({std::make_unique<DebugCommand>(*this)});
mRegisteredCommands.push_back({std::make_unique<HelpCommand>(*this)});
- mRegisteredCommands.push_back({std::make_unique<WaitCommand>(*this)});
}
void Lshal::forEachCommand(const std::function<void(const Command* c)>& f) const {
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index 830bd872ff..9457f1e563 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
#include <iostream>
#include <string>
@@ -24,6 +25,7 @@
#include <utils/StrongPointer.h>
#include "Command.h"
+#include "HelpCommand.h"
#include "NullableOStream.h"
#include "utils.h"
@@ -74,3 +76,5 @@ private:
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
diff --git a/cmds/lshal/NullableOStream.h b/cmds/lshal/NullableOStream.h
index 7cffcf8193..737d3a2963 100644
--- a/cmds/lshal/NullableOStream.h
+++ b/cmds/lshal/NullableOStream.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_
#include <iostream>
@@ -68,3 +69,5 @@ private:
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_
diff --git a/cmds/lshal/PipeRelay.h b/cmds/lshal/PipeRelay.h
index 8350160419..8dc3093742 100644
--- a/cmds/lshal/PipeRelay.h
+++ b/cmds/lshal/PipeRelay.h
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
+
+#define FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
#include <android-base/macros.h>
#include <ostream>
@@ -51,3 +53,6 @@ private:
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
+
diff --git a/cmds/lshal/TEST_MAPPING b/cmds/lshal/TEST_MAPPING
deleted file mode 100644
index 0320624699..0000000000
--- a/cmds/lshal/TEST_MAPPING
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "presubmit": [
- {
- "name": "lshal_test"
- }
- ]
-}
-
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 0ff0c96d38..601b7e25f9 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
#include <stdint.h>
@@ -156,3 +157,5 @@ private:
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
diff --git a/cmds/lshal/TextTable.h b/cmds/lshal/TextTable.h
index be41a08251..301b4bd969 100644
--- a/cmds/lshal/TextTable.h
+++ b/cmds/lshal/TextTable.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_
#include <iostream>
#include <string>
@@ -79,3 +80,5 @@ private:
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index e8d22d9b58..46d817759d 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#pragma once
-
#include <condition_variable>
#include <chrono>
#include <functional>
diff --git a/cmds/lshal/WaitCommand.cpp b/cmds/lshal/WaitCommand.cpp
deleted file mode 100644
index 65b41b95d2..0000000000
--- a/cmds/lshal/WaitCommand.cpp
+++ /dev/null
@@ -1,87 +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 "WaitCommand.h"
-
-#include "Lshal.h"
-
-#include <hidl/ServiceManagement.h>
-#include <hidl-util/FQName.h>
-
-namespace android {
-namespace lshal {
-
-std::string WaitCommand::getName() const {
- return "wait";
-}
-
-std::string WaitCommand::getSimpleDescription() const {
- return "Wait for HAL to start if it is not already started.";
-}
-
-Status WaitCommand::parseArgs(const Arg &arg) {
- if (optind + 1 != arg.argc) {
- return USAGE;
- }
-
- mInterfaceName = arg.argv[optind];
- ++optind;
- return OK;
-}
-
-Status WaitCommand::main(const Arg &arg) {
- Status status = parseArgs(arg);
- if (status != OK) {
- return status;
- }
-
- auto [interface, instance] = splitFirst(mInterfaceName, '/');
- instance = instance.empty() ? "default" : instance;
-
- FQName fqName;
- if (!FQName::parse(interface, &fqName) || fqName.isIdentifier() || !fqName.isFullyQualified()) {
- mLshal.err() << "Invalid fully-qualified name '" << interface << "'\n\n";
- return USAGE;
- }
-
- using android::hidl::manager::V1_0::IServiceManager;
-
- using android::hardware::details::getRawServiceInternal;
- auto service = getRawServiceInternal(interface, instance, true /*retry*/, false /*getStub*/);
-
- if (service == nullptr) {
- mLshal.err() << "Service not found (missing permissions or not in VINTF manifest?).\n";
- return NO_INTERFACE;
- }
-
- return OK;
-}
-
-void WaitCommand::usage() const {
- static const std::string debug =
- "wait:\n"
- " lshal wait <interface/instance> \n"
- " For a HAL that is on the device, wait for the HAL to start.\n"
- " This will not start a HAL unless it is configured as a lazy HAL.\n"
- " <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
- " If instance name is missing `default` is used.\n";
-
- mLshal.err() << debug;
-}
-
-} // namespace lshal
-} // namespace android
-
diff --git a/cmds/lshal/WaitCommand.h b/cmds/lshal/WaitCommand.h
deleted file mode 100644
index c9f67c2b27..0000000000
--- a/cmds/lshal/WaitCommand.h
+++ /dev/null
@@ -1,49 +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 <android-base/macros.h>
-
-#include "Command.h"
-#include "utils.h"
-
-namespace android {
-namespace lshal {
-
-class Lshal;
-
-class WaitCommand : public Command {
-public:
- explicit WaitCommand(Lshal &lshal) : Command(lshal) {}
- ~WaitCommand() = default;
- Status main(const Arg &arg) override;
- void usage() const override;
- std::string getSimpleDescription() const override;
- std::string getName() const override;
-private:
- Status parseArgs(const Arg &arg);
-
- std::string mInterfaceName;
-
- DISALLOW_COPY_AND_ASSIGN(WaitCommand);
-};
-
-
-} // namespace lshal
-} // namespace android
diff --git a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
index ca1e690694..7e864327af 100644
--- a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
+++ b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
#include <sys/types.h>
@@ -43,3 +44,5 @@ Partition getPartition(pid_t pid);
} // namespace procpartition
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 3d550babf4..fc8d58b3d8 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -452,7 +452,7 @@ TEST_F(ListTest, Fetch) {
}
TEST_F(ListTest, DumpVintf) {
- const std::string expected = "<manifest version=\"2.0\" type=\"device\">\n"
+ const std::string expected = "<manifest version=\"1.0\" type=\"device\">\n"
" <hal format=\"hidl\">\n"
" <name>a.h.foo1</name>\n"
" <transport>hwbinder</transport>\n"
@@ -493,19 +493,19 @@ TEST_F(ListTest, DumpVintf) {
TEST_F(ListTest, DumpDefault) {
const std::string expected =
"[fake description 0]\n"
- "VINTF R Interface Thread Use Server Clients\n"
- "X N a.h.foo1@1.0::IFoo/1 11/21 1 2 4\n"
- "X Y a.h.foo2@2.0::IFoo/2 12/22 2 3 5\n"
+ "R Interface Thread Use Server Clients\n"
+ "N a.h.foo1@1.0::IFoo/1 11/21 1 2 4\n"
+ "Y a.h.foo2@2.0::IFoo/2 12/22 2 3 5\n"
"\n"
"[fake description 1]\n"
- "VINTF R Interface Thread Use Server Clients\n"
- "X ? a.h.foo3@3.0::IFoo/3 N/A N/A 4 6\n"
- "X ? a.h.foo4@4.0::IFoo/4 N/A N/A 5 7\n"
+ "R Interface Thread Use Server Clients\n"
+ "? a.h.foo3@3.0::IFoo/3 N/A N/A 4 6\n"
+ "? a.h.foo4@4.0::IFoo/4 N/A N/A 5 7\n"
"\n"
"[fake description 2]\n"
- "VINTF R Interface Thread Use Server Clients\n"
- "X ? a.h.foo5@5.0::IFoo/5 N/A N/A 6 8\n"
- "X ? a.h.foo6@6.0::IFoo/6 N/A N/A 7 9\n"
+ "R Interface Thread Use Server Clients\n"
+ "? a.h.foo5@5.0::IFoo/5 N/A N/A 6 8\n"
+ "? a.h.foo6@6.0::IFoo/6 N/A N/A 7 9\n"
"\n";
optind = 1; // mimic Lshal::parseArg()
diff --git a/cmds/lshal/utils.h b/cmds/lshal/utils.h
index 04f52726e3..240155e4d0 100644
--- a/cmds/lshal/utils.h
+++ b/cmds/lshal/utils.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
#include <iomanip>
#include <iostream>
@@ -87,3 +88,5 @@ void replaceAll(std::string *s, char from, char to);
} // namespace lshal
} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
diff --git a/cmds/service/Android.bp b/cmds/service/Android.bp
index a5b1ac5c5f..9513ec1c23 100644
--- a/cmds/service/Android.bp
+++ b/cmds/service/Android.bp
@@ -4,7 +4,6 @@ cc_binary {
srcs: ["service.cpp"],
shared_libs: [
- "libcutils",
"libutils",
"libbinder",
],
@@ -23,7 +22,6 @@ cc_binary {
srcs: ["service.cpp"],
shared_libs: [
- "libcutils",
"libutils",
"libbinder",
],
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 18b6b58a9e..d5dc6b741d 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -18,18 +18,13 @@
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/TextOutput.h>
-#include <cutils/ashmem.h>
#include <getopt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include <sys/mman.h>
#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
using namespace android;
@@ -75,7 +70,7 @@ int main(int argc, char* const argv[])
{
bool wantsUsage = false;
int result = 0;
-
+
while (1) {
int ic = getopt(argc, argv, "h?");
if (ic < 0)
@@ -102,7 +97,7 @@ int main(int argc, char* const argv[])
aerr << "service: Unable to get default service manager!" << endl;
return 20;
}
-
+
if (optind >= argc) {
wantsUsage = true;
} else if (!wantsUsage) {
@@ -124,8 +119,8 @@ int main(int argc, char* const argv[])
for (unsigned i = 0; i < services.size(); i++) {
String16 name = services[i];
sp<IBinder> service = sm->checkService(name);
- aout << i
- << "\t" << good_old_string(name)
+ aout << i
+ << "\t" << good_old_string(name)
<< ": [" << good_old_string(get_interface_name(service)) << "]"
<< endl;
}
@@ -192,120 +187,69 @@ int main(int argc, char* const argv[])
} else if (strcmp(argv[optind], "null") == 0) {
optind++;
data.writeStrongBinder(nullptr);
- } else if (strcmp(argv[optind], "fd") == 0) {
- optind++;
- if (optind >= argc) {
- aerr << "service: no path supplied for 'fd'" << endl;
- wantsUsage = true;
- result = 10;
- break;
- }
- const char *path = argv[optind++];
- int fd = open(path, O_RDONLY);
- if (fd < 0) {
- aerr << "service: could not open '" << path << "'" << endl;
- wantsUsage = true;
- result = 10;
- break;
- }
- data.writeFileDescriptor(fd, true /* take ownership */);
- } else if (strcmp(argv[optind], "afd") == 0) {
- optind++;
- if (optind >= argc) {
- aerr << "service: no path supplied for 'afd'" << endl;
- wantsUsage = true;
- result = 10;
- break;
- }
- const char *path = argv[optind++];
- int fd = open(path, O_RDONLY);
- struct stat statbuf;
- if (fd < 0 || fstat(fd, &statbuf) != 0) {
- aerr << "service: could not open or stat '" << path << "'" << endl;
- wantsUsage = true;
- result = 10;
- break;
- }
- int afd = ashmem_create_region("test", statbuf.st_size);
- void* ptr = mmap(NULL, statbuf.st_size,
- PROT_READ | PROT_WRITE, MAP_SHARED, afd, 0);
- read(fd, ptr, statbuf.st_size);
- close(fd);
- data.writeFileDescriptor(afd, true /* take ownership */);
- } else if (strcmp(argv[optind], "nfd") == 0) {
- optind++;
- if (optind >= argc) {
- aerr << "service: no file descriptor supplied for 'nfd'" << endl;
- wantsUsage = true;
- result = 10;
- break;
- }
- data.writeFileDescriptor(
- atoi(argv[optind++]), true /* take ownership */);
-
} else if (strcmp(argv[optind], "intent") == 0) {
-
- char* action = nullptr;
- char* dataArg = nullptr;
- char* type = nullptr;
- int launchFlags = 0;
- char* component = nullptr;
- int categoryCount = 0;
- char* categories[16];
-
- char* context1 = nullptr;
-
+
+ char* action = nullptr;
+ char* dataArg = nullptr;
+ char* type = nullptr;
+ int launchFlags = 0;
+ char* component = nullptr;
+ int categoryCount = 0;
+ char* categories[16];
+
+ char* context1 = nullptr;
+
optind++;
-
- while (optind < argc)
- {
- char* key = strtok_r(argv[optind], "=", &context1);
- char* value = strtok_r(nullptr, "=", &context1);
-
+
+ while (optind < argc)
+ {
+ char* key = strtok_r(argv[optind], "=", &context1);
+ char* value = strtok_r(nullptr, "=", &context1);
+
// we have reached the end of the XXX=XXX args.
if (key == nullptr) break;
-
- if (strcmp(key, "action") == 0)
- {
- action = value;
- }
- else if (strcmp(key, "data") == 0)
- {
- dataArg = value;
- }
- else if (strcmp(key, "type") == 0)
- {
- type = value;
- }
- else if (strcmp(key, "launchFlags") == 0)
- {
- launchFlags = atoi(value);
- }
- else if (strcmp(key, "component") == 0)
- {
- component = value;
- }
- else if (strcmp(key, "categories") == 0)
- {
- char* context2 = nullptr;
- categories[categoryCount] = strtok_r(value, ",", &context2);
-
- while (categories[categoryCount] != nullptr)
- {
- categoryCount++;
- categories[categoryCount] = strtok_r(nullptr, ",", &context2);
- }
- }
-
+
+ if (strcmp(key, "action") == 0)
+ {
+ action = value;
+ }
+ else if (strcmp(key, "data") == 0)
+ {
+ dataArg = value;
+ }
+ else if (strcmp(key, "type") == 0)
+ {
+ type = value;
+ }
+ else if (strcmp(key, "launchFlags") == 0)
+ {
+ launchFlags = atoi(value);
+ }
+ else if (strcmp(key, "component") == 0)
+ {
+ component = value;
+ }
+ else if (strcmp(key, "categories") == 0)
+ {
+ char* context2 = nullptr;
+ categories[categoryCount] = strtok_r(value, ",", &context2);
+
+ while (categories[categoryCount] != nullptr)
+ {
+ categoryCount++;
+ categories[categoryCount] = strtok_r(nullptr, ",", &context2);
+ }
+ }
+
optind++;
- }
-
+ }
+
writeString16(data, action);
writeString16(data, dataArg);
writeString16(data, type);
- data.writeInt32(launchFlags);
+ data.writeInt32(launchFlags);
writeString16(data, component);
-
+
if (categoryCount > 0)
{
data.writeInt32(categoryCount);
@@ -317,10 +261,10 @@ int main(int argc, char* const argv[])
else
{
data.writeInt32(0);
- }
-
+ }
+
// for now just set the extra field to be null.
- data.writeInt32(-1);
+ data.writeInt32(-1);
} else {
aerr << "service: unknown option " << argv[optind] << endl;
wantsUsage = true;
@@ -328,7 +272,7 @@ int main(int argc, char* const argv[])
break;
}
}
-
+
service->transact(code, data, &reply);
aout << "Result: " << reply << endl;
} else {
@@ -351,29 +295,23 @@ int main(int argc, char* const argv[])
result = 10;
}
}
-
+
if (wantsUsage) {
aout << "Usage: service [-h|-?]\n"
" service list\n"
" service check SERVICE\n"
- " service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR | null"
- " | fd f | nfd n | afd f ] ...\n"
+ " service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...\n"
"Options:\n"
" i32: Write the 32-bit integer N into the send parcel.\n"
" i64: Write the 64-bit integer N into the send parcel.\n"
" f: Write the 32-bit single-precision number N into the send parcel.\n"
" d: Write the 64-bit double-precision number N into the send parcel.\n"
- " s16: Write the UTF-16 string STR into the send parcel.\n"
- " null: Write a null binder into the send parcel.\n"
- " fd: Write a file descriptor for the file f to the send parcel.\n"
- " nfd: Write file descriptor n to the send parcel.\n"
- " afd: Write an ashmem file descriptor for a region containing the data from"
- " file f to the send parcel.\n";
+ " s16: Write the UTF-16 string STR into the send parcel.\n";
// " intent: Write and Intent int the send parcel. ARGS can be\n"
// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
return result;
}
-
+
return result;
}
diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp
deleted file mode 100644
index b7e520f2f1..0000000000
--- a/cmds/servicemanager/Access.cpp
+++ /dev/null
@@ -1,150 +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 "Access.h"
-
-#include <android-base/logging.h>
-#include <binder/IPCThreadState.h>
-#include <log/log_safetynet.h>
-#include <selinux/android.h>
-#include <selinux/avc.h>
-
-namespace android {
-
-#ifdef VENDORSERVICEMANAGER
-constexpr bool kIsVendor = true;
-#else
-constexpr bool kIsVendor = false;
-#endif
-
-static std::string getPidcon(pid_t pid) {
- android_errorWriteLog(0x534e4554, "121035042");
-
- char* lookup = nullptr;
- if (getpidcon(pid, &lookup) < 0) {
- LOG(ERROR) << "SELinux: getpidcon(pid=" << pid << ") failed to retrieve pid context";
- return "";
- }
- std::string result = lookup;
- freecon(lookup);
- return result;
-}
-
-static struct selabel_handle* getSehandle() {
- static struct selabel_handle* gSehandle = nullptr;
-
- if (gSehandle != nullptr && selinux_status_updated()) {
- selabel_close(gSehandle);
- gSehandle = nullptr;
- }
-
- if (gSehandle == nullptr) {
- gSehandle = kIsVendor
- ? selinux_android_vendor_service_context_handle()
- : selinux_android_service_context_handle();
- }
-
- CHECK(gSehandle != nullptr);
- return gSehandle;
-}
-
-struct AuditCallbackData {
- const Access::CallingContext* context;
- const std::string* tname;
-};
-
-static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
- const AuditCallbackData* ad = reinterpret_cast<AuditCallbackData*>(data);
-
- if (!ad) {
- LOG(ERROR) << "No service manager audit data";
- return 0;
- }
-
- snprintf(buf, len, "pid=%d uid=%d name=%s", ad->context->debugPid, ad->context->uid,
- ad->tname->c_str());
- return 0;
-}
-
-Access::Access() {
- union selinux_callback cb;
-
- cb.func_audit = auditCallback;
- selinux_set_callback(SELINUX_CB_AUDIT, cb);
-
- cb.func_log = kIsVendor ? selinux_vendor_log_callback : selinux_log_callback;
- selinux_set_callback(SELINUX_CB_LOG, cb);
-
- CHECK(selinux_status_open(true /*fallback*/) >= 0);
-
- CHECK(getcon(&mThisProcessContext) == 0);
-}
-
-Access::~Access() {
- freecon(mThisProcessContext);
-}
-
-Access::CallingContext Access::getCallingContext() {
- IPCThreadState* ipc = IPCThreadState::self();
-
- const char* callingSid = ipc->getCallingSid();
- pid_t callingPid = ipc->getCallingPid();
-
- return CallingContext {
- .debugPid = callingPid,
- .uid = ipc->getCallingUid(),
- .sid = callingSid ? std::string(callingSid) : getPidcon(callingPid),
- };
-}
-
-bool Access::canFind(const CallingContext& ctx,const std::string& name) {
- return actionAllowedFromLookup(ctx, name, "find");
-}
-
-bool Access::canAdd(const CallingContext& ctx, const std::string& name) {
- return actionAllowedFromLookup(ctx, name, "add");
-}
-
-bool Access::canList(const CallingContext& ctx) {
- return actionAllowed(ctx, mThisProcessContext, "list", "service_manager");
-}
-
-bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm,
- const std::string& tname) {
- const char* tclass = "service_manager";
-
- AuditCallbackData data = {
- .context = &sctx,
- .tname = &tname,
- };
-
- return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm,
- reinterpret_cast<void*>(&data));
-}
-
-bool Access::actionAllowedFromLookup(const CallingContext& sctx, const std::string& name, const char *perm) {
- char *tctx = nullptr;
- if (selabel_lookup(getSehandle(), &tctx, name.c_str(), SELABEL_CTX_ANDROID_SERVICE) != 0) {
- LOG(ERROR) << "SELinux: No match for " << name << " in service_contexts.\n";
- return false;
- }
-
- bool allowed = actionAllowed(sctx, tctx, perm, name);
- freecon(tctx);
- return allowed;
-}
-
-} // android
diff --git a/cmds/servicemanager/Access.h b/cmds/servicemanager/Access.h
deleted file mode 100644
index 77c2cd4ed6..0000000000
--- a/cmds/servicemanager/Access.h
+++ /dev/null
@@ -1,56 +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 <sys/types.h>
-
-namespace android {
-
-// singleton
-class Access {
-public:
- Access();
- virtual ~Access();
-
- Access(const Access&) = delete;
- Access& operator=(const Access&) = delete;
- Access(Access&&) = delete;
- Access& operator=(Access&&) = delete;
-
- struct CallingContext {
- pid_t debugPid;
- uid_t uid;
- std::string sid;
- };
-
- virtual CallingContext getCallingContext();
-
- virtual bool canFind(const CallingContext& ctx, const std::string& name);
- virtual bool canAdd(const CallingContext& ctx, const std::string& name);
- virtual bool canList(const CallingContext& ctx);
-
-private:
- bool actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm,
- const std::string& tname);
- bool actionAllowedFromLookup(const CallingContext& sctx, const std::string& name,
- const char *perm);
-
- char* mThisProcessContext = nullptr;
-};
-
-};
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 7277e85d99..428561bc8a 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -1,58 +1,51 @@
cc_defaults {
- name: "servicemanager_defaults",
+ name: "servicemanager_flags",
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
+ product_variables: {
+ binder32bit: {
+ cflags: ["-DBINDER_IPC_32BIT=1"],
+ },
+ },
- srcs: [
- "Access.cpp",
- "ServiceManager.cpp",
- ],
+ shared_libs: ["liblog"],
+}
- shared_libs: [
- "libbase",
- "libbinder", // also contains servicemanager_interface
- "libvintf",
- "libcutils",
- "liblog",
- "libutils",
- "libselinux",
+cc_binary {
+ name: "bctest",
+ defaults: ["servicemanager_flags"],
+ srcs: [
+ "bctest.c",
+ "binder.c",
],
-
- target: {
- vendor: {
- exclude_shared_libs: ["libvintf"],
- },
- },
}
cc_binary {
name: "servicemanager",
- defaults: ["servicemanager_defaults"],
+ defaults: ["servicemanager_flags"],
+ srcs: [
+ "service_manager.c",
+ "binder.c",
+ ],
+ shared_libs: ["libcutils", "libselinux"],
init_rc: ["servicemanager.rc"],
- srcs: ["main.cpp"],
}
cc_binary {
name: "vndservicemanager",
- defaults: ["servicemanager_defaults"],
- init_rc: ["vndservicemanager.rc"],
+ defaults: ["servicemanager_flags"],
vendor: true,
+ srcs: [
+ "service_manager.c",
+ "binder.c",
+ ],
cflags: [
"-DVENDORSERVICEMANAGER=1",
],
- srcs: ["main.cpp"],
-}
-
-cc_test {
- name: "servicemanager_test",
- test_suites: ["device-tests"],
- defaults: ["servicemanager_defaults"],
- srcs: [
- "test_sm.cpp",
- ],
- static_libs: ["libgmock"],
+ shared_libs: ["libcutils", "libselinux"],
+ init_rc: ["vndservicemanager.rc"],
}
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
deleted file mode 100644
index 861401c979..0000000000
--- a/cmds/servicemanager/ServiceManager.cpp
+++ /dev/null
@@ -1,336 +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 "ServiceManager.h"
-
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <binder/Stability.h>
-#include <cutils/android_filesystem_config.h>
-#include <cutils/multiuser.h>
-#include <thread>
-
-#ifndef VENDORSERVICEMANAGER
-#include <vintf/VintfObject.h>
-#include <vintf/constants.h>
-#endif // !VENDORSERVICEMANAGER
-
-using ::android::binder::Status;
-using ::android::internal::Stability;
-
-namespace android {
-
-#ifndef VENDORSERVICEMANAGER
-static bool isVintfDeclared(const std::string& name) {
- size_t firstSlash = name.find('/');
- size_t lastDot = name.rfind('.', firstSlash);
- if (firstSlash == std::string::npos || lastDot == std::string::npos) {
- LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
- << "some.package.foo.IFoo/default) but got: " << name;
- return false;
- }
- const std::string package = name.substr(0, lastDot);
- const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1);
- const std::string instance = name.substr(firstSlash+1);
-
- for (const auto& manifest : {
- vintf::VintfObject::GetDeviceHalManifest(),
- vintf::VintfObject::GetFrameworkHalManifest()
- }) {
- if (manifest != nullptr && manifest->hasAidlInstance(package, iface, instance)) {
- return true;
- }
- }
- LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
- << " in the VINTF manifest.";
- return false;
-}
-
-static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) {
- if (!Stability::requiresVintfDeclaration(binder)) {
- return true;
- }
-
- return isVintfDeclared(name);
-}
-#endif // !VENDORSERVICEMANAGER
-
-ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {}
-ServiceManager::~ServiceManager() {
- // this should only happen in tests
-
- for (const auto& [name, callbacks] : mNameToCallback) {
- CHECK(!callbacks.empty()) << name;
- for (const auto& callback : callbacks) {
- CHECK(callback != nullptr) << name;
- }
- }
-
- for (const auto& [name, service] : mNameToService) {
- CHECK(service.binder != nullptr) << name;
- }
-}
-
-Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
- *outBinder = tryGetService(name, true);
- // returns ok regardless of result for legacy reasons
- return Status::ok();
-}
-
-Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
- *outBinder = tryGetService(name, false);
- // returns ok regardless of result for legacy reasons
- return Status::ok();
-}
-
-sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
- auto ctx = mAccess->getCallingContext();
-
- sp<IBinder> out;
- if (auto it = mNameToService.find(name); it != mNameToService.end()) {
- const Service& service = it->second;
-
- if (!service.allowIsolated) {
- uid_t appid = multiuser_get_app_id(ctx.uid);
- bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
-
- if (isIsolated) {
- return nullptr;
- }
- }
- out = service.binder;
- }
-
- if (!mAccess->canFind(ctx, name)) {
- return nullptr;
- }
-
- if (!out && startIfNotFound) {
- tryStartService(name);
- }
-
- return out;
-}
-
-bool isValidServiceName(const std::string& name) {
- if (name.size() == 0) return false;
- if (name.size() > 127) return false;
-
- for (char c : name) {
- if (c == '_' || c == '-' || c == '.' || c == '/') continue;
- if (c >= 'a' && c <= 'z') continue;
- if (c >= 'A' && c <= 'Z') continue;
- if (c >= '0' && c <= '9') continue;
- return false;
- }
-
- return true;
-}
-
-Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
- auto ctx = mAccess->getCallingContext();
-
- // apps cannot add services
- if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
- }
-
- if (!mAccess->canAdd(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
- }
-
- if (binder == nullptr) {
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
- }
-
- if (!isValidServiceName(name)) {
- LOG(ERROR) << "Invalid service name: " << name;
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
- }
-
-#ifndef VENDORSERVICEMANAGER
- if (!meetsDeclarationRequirements(binder, name)) {
- // already logged
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
- }
-#endif // !VENDORSERVICEMANAGER
-
- // implicitly unlinked when the binder is removed
- if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) {
- LOG(ERROR) << "Could not linkToDeath when adding " << name;
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
- }
-
- mNameToService[name] = Service {
- .binder = binder,
- .allowIsolated = allowIsolated,
- .dumpPriority = dumpPriority,
- };
-
- auto it = mNameToCallback.find(name);
- if (it != mNameToCallback.end()) {
- for (const sp<IServiceCallback>& cb : it->second) {
- // permission checked in registerForNotifications
- cb->onRegistration(name, binder);
- }
- }
-
- return Status::ok();
-}
-
-Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) {
- if (!mAccess->canList(mAccess->getCallingContext())) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
- }
-
- size_t toReserve = 0;
- for (auto const& [name, service] : mNameToService) {
- (void) name;
-
- if (service.dumpPriority & dumpPriority) ++toReserve;
- }
-
- CHECK(outList->empty());
-
- outList->reserve(toReserve);
- for (auto const& [name, service] : mNameToService) {
- (void) service;
-
- if (service.dumpPriority & dumpPriority) {
- outList->push_back(name);
- }
- }
-
- return Status::ok();
-}
-
-Status ServiceManager::registerForNotifications(
- const std::string& name, const sp<IServiceCallback>& callback) {
- auto ctx = mAccess->getCallingContext();
-
- if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
- }
-
- if (!isValidServiceName(name)) {
- LOG(ERROR) << "Invalid service name: " << name;
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
- }
-
- if (callback == nullptr) {
- return Status::fromExceptionCode(Status::EX_NULL_POINTER);
- }
-
- if (OK != IInterface::asBinder(callback)->linkToDeath(this)) {
- LOG(ERROR) << "Could not linkToDeath when adding " << name;
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
- }
-
- mNameToCallback[name].push_back(callback);
-
- if (auto it = mNameToService.find(name); it != mNameToService.end()) {
- const sp<IBinder>& binder = it->second.binder;
-
- // never null if an entry exists
- CHECK(binder != nullptr) << name;
- callback->onRegistration(name, binder);
- }
-
- return Status::ok();
-}
-Status ServiceManager::unregisterForNotifications(
- const std::string& name, const sp<IServiceCallback>& callback) {
- auto ctx = mAccess->getCallingContext();
-
- if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
- }
-
- bool found = false;
-
- auto it = mNameToCallback.find(name);
- if (it != mNameToCallback.end()) {
- removeCallback(IInterface::asBinder(callback), &it, &found);
- }
-
- if (!found) {
- LOG(ERROR) << "Trying to unregister callback, but none exists " << name;
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
- }
-
- return Status::ok();
-}
-
-Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) {
- auto ctx = mAccess->getCallingContext();
-
- if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
- }
-
- *outReturn = false;
-
-#ifndef VENDORSERVICEMANAGER
- *outReturn = isVintfDeclared(name);
-#endif
- return Status::ok();
-}
-
-void ServiceManager::removeCallback(const wp<IBinder>& who,
- CallbackMap::iterator* it,
- bool* found) {
- std::vector<sp<IServiceCallback>>& listeners = (*it)->second;
-
- for (auto lit = listeners.begin(); lit != listeners.end();) {
- if (IInterface::asBinder(*lit) == who) {
- if(found) *found = true;
- lit = listeners.erase(lit);
- } else {
- ++lit;
- }
- }
-
- if (listeners.empty()) {
- *it = mNameToCallback.erase(*it);
- } else {
- it++;
- }
-}
-
-void ServiceManager::binderDied(const wp<IBinder>& who) {
- for (auto it = mNameToService.begin(); it != mNameToService.end();) {
- if (who == it->second.binder) {
- it = mNameToService.erase(it);
- } else {
- ++it;
- }
- }
-
- for (auto it = mNameToCallback.begin(); it != mNameToCallback.end();) {
- removeCallback(who, &it, nullptr /*found*/);
- }
-}
-
-void ServiceManager::tryStartService(const std::string& name) {
- ALOGI("Since '%s' could not be found, trying to start it as a lazy AIDL service",
- name.c_str());
-
- std::thread([=] {
- (void)base::SetProperty("ctl.interface_start", "aidl/" + name);
- }).detach();
-}
-
-} // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
deleted file mode 100644
index 7dcdaa4661..0000000000
--- a/cmds/servicemanager/ServiceManager.h
+++ /dev/null
@@ -1,73 +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 <android/os/BnServiceManager.h>
-#include <android/os/IServiceCallback.h>
-
-#include "Access.h"
-
-namespace android {
-
-using os::IServiceCallback;
-
-class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
-public:
- ServiceManager(std::unique_ptr<Access>&& access);
- ~ServiceManager();
-
- // getService will try to start any services it cannot find
- binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
- binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
- binder::Status addService(const std::string& name, const sp<IBinder>& binder,
- bool allowIsolated, int32_t dumpPriority) override;
- binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override;
- binder::Status registerForNotifications(const std::string& name,
- const sp<IServiceCallback>& callback) override;
- binder::Status unregisterForNotifications(const std::string& name,
- const sp<IServiceCallback>& callback) override;
- binder::Status isDeclared(const std::string& name, bool* outReturn) override;
-
- void binderDied(const wp<IBinder>& who) override;
-
-protected:
- virtual void tryStartService(const std::string& name);
-
-private:
- struct Service {
- sp<IBinder> binder; // not null
- bool allowIsolated;
- int32_t dumpPriority;
- };
-
- using CallbackMap = std::map<std::string, std::vector<sp<IServiceCallback>>>;
- using ServiceMap = std::map<std::string, Service>;
-
- // removes a callback from mNameToCallback, removing it if the vector is empty
- // this updates iterator to the next location
- void removeCallback(const wp<IBinder>& who,
- CallbackMap::iterator* it,
- bool* found);
- sp<IBinder> tryGetService(const std::string& name, bool startIfNotFound);
-
- CallbackMap mNameToCallback;
- ServiceMap mNameToService;
-
- std::unique_ptr<Access> mAccess;
-};
-
-} // namespace android
diff --git a/cmds/servicemanager/TEST_MAPPING b/cmds/servicemanager/TEST_MAPPING
deleted file mode 100644
index 739740aa21..0000000000
--- a/cmds/servicemanager/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "servicemanager_test"
- }
- ],
- "imports": [
- {
- "path": "frameworks/native/libs/binder"
- }
- ]
-}
diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c
new file mode 100644
index 0000000000..354df670e5
--- /dev/null
+++ b/cmds/servicemanager/bctest.c
@@ -0,0 +1,107 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "binder.h"
+
+uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name)
+{
+ uint32_t handle;
+ unsigned iodata[512/4];
+ struct binder_io msg, reply;
+
+ bio_init(&msg, iodata, sizeof(iodata), 4);
+ bio_put_uint32(&msg, 0); // strict mode header
+ bio_put_string16_x(&msg, SVC_MGR_NAME);
+ bio_put_string16_x(&msg, name);
+
+ if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
+ return 0;
+
+ handle = bio_get_ref(&reply);
+
+ if (handle)
+ binder_acquire(bs, handle);
+
+ binder_done(bs, &msg, &reply);
+
+ return handle;
+}
+
+int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
+{
+ int status;
+ unsigned iodata[512/4];
+ struct binder_io msg, reply;
+
+ bio_init(&msg, iodata, sizeof(iodata), 4);
+ bio_put_uint32(&msg, 0); // strict mode header
+ bio_put_string16_x(&msg, SVC_MGR_NAME);
+ bio_put_string16_x(&msg, name);
+ bio_put_obj(&msg, ptr);
+
+ if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
+ return -1;
+
+ status = bio_get_uint32(&reply);
+
+ binder_done(bs, &msg, &reply);
+
+ return status;
+}
+
+unsigned token;
+
+int main(int argc, char **argv)
+{
+ struct binder_state *bs;
+ uint32_t svcmgr = BINDER_SERVICE_MANAGER;
+ uint32_t handle;
+
+ bs = binder_open("/dev/binder", 128*1024);
+ if (!bs) {
+ fprintf(stderr, "failed to open binder driver\n");
+ return -1;
+ }
+
+ argc--;
+ argv++;
+ while (argc > 0) {
+ if (!strcmp(argv[0],"alt")) {
+ handle = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr");
+ if (!handle) {
+ fprintf(stderr,"cannot find alt_svc_mgr\n");
+ return -1;
+ }
+ svcmgr = handle;
+ fprintf(stderr,"svcmgr is via %x\n", handle);
+ } else if (!strcmp(argv[0],"lookup")) {
+ if (argc < 2) {
+ fprintf(stderr,"argument required\n");
+ return -1;
+ }
+ handle = svcmgr_lookup(bs, svcmgr, argv[1]);
+ fprintf(stderr,"lookup(%s) = %x\n", argv[1], handle);
+ argc--;
+ argv++;
+ } else if (!strcmp(argv[0],"publish")) {
+ if (argc < 2) {
+ fprintf(stderr,"argument required\n");
+ return -1;
+ }
+ svcmgr_publish(bs, svcmgr, argv[1], &token);
+ argc--;
+ argv++;
+ } else {
+ fprintf(stderr,"unknown command %s\n", argv[0]);
+ return -1;
+ }
+ argc--;
+ argv++;
+ }
+ return 0;
+}
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
new file mode 100644
index 0000000000..cf3b1728b6
--- /dev/null
+++ b/cmds/servicemanager/binder.c
@@ -0,0 +1,682 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#define LOG_TAG "Binder"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <log/log.h>
+
+#include "binder.h"
+
+#define MAX_BIO_SIZE (1 << 30)
+
+#define TRACE 0
+
+void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn);
+
+#if TRACE
+void hexdump(void *_data, size_t len)
+{
+ unsigned char *data = _data;
+ size_t count;
+
+ for (count = 0; count < len; count++) {
+ if ((count & 15) == 0)
+ fprintf(stderr,"%04zu:", count);
+ fprintf(stderr," %02x %c", *data,
+ (*data < 32) || (*data > 126) ? '.' : *data);
+ data++;
+ if ((count & 15) == 15)
+ fprintf(stderr,"\n");
+ }
+ if ((count & 15) != 0)
+ fprintf(stderr,"\n");
+}
+
+void binder_dump_txn(struct binder_transaction_data *txn)
+{
+ struct flat_binder_object *obj;
+ binder_size_t *offs = (binder_size_t *)(uintptr_t)txn->data.ptr.offsets;
+ size_t count = txn->offsets_size / sizeof(binder_size_t);
+
+ fprintf(stderr," target %016"PRIx64" cookie %016"PRIx64" code %08x flags %08x\n",
+ (uint64_t)txn->target.ptr, (uint64_t)txn->cookie, txn->code, txn->flags);
+ fprintf(stderr," pid %8d uid %8d data %"PRIu64" offs %"PRIu64"\n",
+ txn->sender_pid, txn->sender_euid, (uint64_t)txn->data_size, (uint64_t)txn->offsets_size);
+ hexdump((void *)(uintptr_t)txn->data.ptr.buffer, txn->data_size);
+ while (count--) {
+ obj = (struct flat_binder_object *) (((char*)(uintptr_t)txn->data.ptr.buffer) + *offs++);
+ fprintf(stderr," - type %08x flags %08x ptr %016"PRIx64" cookie %016"PRIx64"\n",
+ obj->type, obj->flags, (uint64_t)obj->binder, (uint64_t)obj->cookie);
+ }
+}
+
+#define NAME(n) case n: return #n
+const char *cmd_name(uint32_t cmd)
+{
+ switch(cmd) {
+ NAME(BR_NOOP);
+ NAME(BR_TRANSACTION_COMPLETE);
+ NAME(BR_INCREFS);
+ NAME(BR_ACQUIRE);
+ NAME(BR_RELEASE);
+ NAME(BR_DECREFS);
+ NAME(BR_TRANSACTION);
+ NAME(BR_REPLY);
+ NAME(BR_FAILED_REPLY);
+ NAME(BR_DEAD_REPLY);
+ NAME(BR_DEAD_BINDER);
+ default: return "???";
+ }
+}
+#else
+#define hexdump(a,b) do{} while (0)
+#define binder_dump_txn(txn) do{} while (0)
+#endif
+
+#define BIO_F_SHARED 0x01 /* needs to be buffer freed */
+#define BIO_F_OVERFLOW 0x02 /* ran out of space */
+#define BIO_F_IOERROR 0x04
+#define BIO_F_MALLOCED 0x08 /* needs to be free()'d */
+
+struct binder_state
+{
+ int fd;
+ void *mapped;
+ size_t mapsize;
+};
+
+struct binder_state *binder_open(const char* driver, size_t mapsize)
+{
+ struct binder_state *bs;
+ struct binder_version vers;
+
+ bs = malloc(sizeof(*bs));
+ if (!bs) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ bs->fd = open(driver, O_RDWR | O_CLOEXEC);
+ if (bs->fd < 0) {
+ fprintf(stderr,"binder: cannot open %s (%s)\n",
+ driver, strerror(errno));
+ goto fail_open;
+ }
+
+ if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
+ (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
+ fprintf(stderr,
+ "binder: kernel driver version (%d) differs from user space version (%d)\n",
+ vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
+ goto fail_open;
+ }
+
+ bs->mapsize = mapsize;
+ bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
+ if (bs->mapped == MAP_FAILED) {
+ fprintf(stderr,"binder: cannot map device (%s)\n",
+ strerror(errno));
+ goto fail_map;
+ }
+
+ return bs;
+
+fail_map:
+ close(bs->fd);
+fail_open:
+ free(bs);
+ return NULL;
+}
+
+void binder_close(struct binder_state *bs)
+{
+ munmap(bs->mapped, bs->mapsize);
+ close(bs->fd);
+ free(bs);
+}
+
+int binder_become_context_manager(struct binder_state *bs)
+{
+ struct flat_binder_object obj;
+ memset(&obj, 0, sizeof(obj));
+ obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
+
+ int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);
+
+ // fallback to original method
+ if (result != 0) {
+ android_errorWriteLog(0x534e4554, "121035042");
+
+ result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
+ }
+ return result;
+}
+
+int binder_write(struct binder_state *bs, void *data, size_t len)
+{
+ struct binder_write_read bwr;
+ int res;
+
+ bwr.write_size = len;
+ bwr.write_consumed = 0;
+ bwr.write_buffer = (uintptr_t) data;
+ bwr.read_size = 0;
+ bwr.read_consumed = 0;
+ bwr.read_buffer = 0;
+ res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
+ if (res < 0) {
+ fprintf(stderr,"binder_write: ioctl failed (%s)\n",
+ strerror(errno));
+ }
+ return res;
+}
+
+void binder_free_buffer(struct binder_state *bs,
+ binder_uintptr_t buffer_to_free)
+{
+ struct {
+ uint32_t cmd_free;
+ binder_uintptr_t buffer;
+ } __attribute__((packed)) data;
+ data.cmd_free = BC_FREE_BUFFER;
+ data.buffer = buffer_to_free;
+ binder_write(bs, &data, sizeof(data));
+}
+
+void binder_send_reply(struct binder_state *bs,
+ struct binder_io *reply,
+ binder_uintptr_t buffer_to_free,
+ int status)
+{
+ struct {
+ uint32_t cmd_free;
+ binder_uintptr_t buffer;
+ uint32_t cmd_reply;
+ struct binder_transaction_data txn;
+ } __attribute__((packed)) data;
+
+ data.cmd_free = BC_FREE_BUFFER;
+ data.buffer = buffer_to_free;
+ data.cmd_reply = BC_REPLY;
+ data.txn.target.ptr = 0;
+ data.txn.cookie = 0;
+ data.txn.code = 0;
+ if (status) {
+ data.txn.flags = TF_STATUS_CODE;
+ data.txn.data_size = sizeof(int);
+ data.txn.offsets_size = 0;
+ data.txn.data.ptr.buffer = (uintptr_t)&status;
+ data.txn.data.ptr.offsets = 0;
+ } else {
+ data.txn.flags = 0;
+ data.txn.data_size = reply->data - reply->data0;
+ data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
+ data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
+ data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
+ }
+ binder_write(bs, &data, sizeof(data));
+}
+
+int binder_parse(struct binder_state *bs, struct binder_io *bio,
+ uintptr_t ptr, size_t size, binder_handler func)
+{
+ int r = 1;
+ uintptr_t end = ptr + (uintptr_t) size;
+
+ while (ptr < end) {
+ uint32_t cmd = *(uint32_t *) ptr;
+ ptr += sizeof(uint32_t);
+#if TRACE
+ fprintf(stderr,"%s:\n", cmd_name(cmd));
+#endif
+ switch(cmd) {
+ case BR_NOOP:
+ break;
+ case BR_TRANSACTION_COMPLETE:
+ break;
+ case BR_INCREFS:
+ case BR_ACQUIRE:
+ case BR_RELEASE:
+ case BR_DECREFS:
+#if TRACE
+ fprintf(stderr," %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *)));
+#endif
+ ptr += sizeof(struct binder_ptr_cookie);
+ break;
+ case BR_TRANSACTION_SEC_CTX:
+ case BR_TRANSACTION: {
+ struct binder_transaction_data_secctx txn;
+ if (cmd == BR_TRANSACTION_SEC_CTX) {
+ if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) {
+ ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n");
+ return -1;
+ }
+ memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx));
+ ptr += sizeof(struct binder_transaction_data_secctx);
+ } else /* BR_TRANSACTION */ {
+ if ((end - ptr) < sizeof(struct binder_transaction_data)) {
+ ALOGE("parse: txn too small (binder_transaction_data)!\n");
+ return -1;
+ }
+ memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data));
+ ptr += sizeof(struct binder_transaction_data);
+
+ txn.secctx = 0;
+ }
+
+ binder_dump_txn(&txn.transaction_data);
+ if (func) {
+ unsigned rdata[256/4];
+ struct binder_io msg;
+ struct binder_io reply;
+ int res;
+
+ bio_init(&reply, rdata, sizeof(rdata), 4);
+ bio_init_from_txn(&msg, &txn.transaction_data);
+ res = func(bs, &txn, &msg, &reply);
+ if (txn.transaction_data.flags & TF_ONE_WAY) {
+ binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
+ } else {
+ binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
+ }
+ }
+ break;
+ }
+ case BR_REPLY: {
+ struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
+ if ((end - ptr) < sizeof(*txn)) {
+ ALOGE("parse: reply too small!\n");
+ return -1;
+ }
+ binder_dump_txn(txn);
+ if (bio) {
+ bio_init_from_txn(bio, txn);
+ bio = 0;
+ } else {
+ /* todo FREE BUFFER */
+ }
+ ptr += sizeof(*txn);
+ r = 0;
+ break;
+ }
+ case BR_DEAD_BINDER: {
+ struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
+ ptr += sizeof(binder_uintptr_t);
+ death->func(bs, death->ptr);
+ break;
+ }
+ case BR_FAILED_REPLY:
+ r = -1;
+ break;
+ case BR_DEAD_REPLY:
+ r = -1;
+ break;
+ default:
+ ALOGE("parse: OOPS %d\n", cmd);
+ return -1;
+ }
+ }
+
+ return r;
+}
+
+void binder_acquire(struct binder_state *bs, uint32_t target)
+{
+ uint32_t cmd[2];
+ cmd[0] = BC_ACQUIRE;
+ cmd[1] = target;
+ binder_write(bs, cmd, sizeof(cmd));
+}
+
+void binder_release(struct binder_state *bs, uint32_t target)
+{
+ uint32_t cmd[2];
+ cmd[0] = BC_RELEASE;
+ cmd[1] = target;
+ binder_write(bs, cmd, sizeof(cmd));
+}
+
+void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
+{
+ struct {
+ uint32_t cmd;
+ struct binder_handle_cookie payload;
+ } __attribute__((packed)) data;
+
+ data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
+ data.payload.handle = target;
+ data.payload.cookie = (uintptr_t) death;
+ binder_write(bs, &data, sizeof(data));
+}
+
+int binder_call(struct binder_state *bs,
+ struct binder_io *msg, struct binder_io *reply,
+ uint32_t target, uint32_t code)
+{
+ int res;
+ struct binder_write_read bwr;
+ struct {
+ uint32_t cmd;
+ struct binder_transaction_data txn;
+ } __attribute__((packed)) writebuf;
+ unsigned readbuf[32];
+
+ if (msg->flags & BIO_F_OVERFLOW) {
+ fprintf(stderr,"binder: txn buffer overflow\n");
+ goto fail;
+ }
+
+ writebuf.cmd = BC_TRANSACTION;
+ writebuf.txn.target.handle = target;
+ writebuf.txn.code = code;
+ writebuf.txn.flags = 0;
+ writebuf.txn.data_size = msg->data - msg->data0;
+ writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
+ writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
+ writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0;
+
+ bwr.write_size = sizeof(writebuf);
+ bwr.write_consumed = 0;
+ bwr.write_buffer = (uintptr_t) &writebuf;
+
+ hexdump(msg->data0, msg->data - msg->data0);
+ for (;;) {
+ bwr.read_size = sizeof(readbuf);
+ bwr.read_consumed = 0;
+ bwr.read_buffer = (uintptr_t) readbuf;
+
+ res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
+
+ if (res < 0) {
+ fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
+ goto fail;
+ }
+
+ res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
+ if (res == 0) return 0;
+ if (res < 0) goto fail;
+ }
+
+fail:
+ memset(reply, 0, sizeof(*reply));
+ reply->flags |= BIO_F_IOERROR;
+ return -1;
+}
+
+void binder_loop(struct binder_state *bs, binder_handler func)
+{
+ int res;
+ struct binder_write_read bwr;
+ uint32_t readbuf[32];
+
+ bwr.write_size = 0;
+ bwr.write_consumed = 0;
+ bwr.write_buffer = 0;
+
+ readbuf[0] = BC_ENTER_LOOPER;
+ binder_write(bs, readbuf, sizeof(uint32_t));
+
+ for (;;) {
+ bwr.read_size = sizeof(readbuf);
+ bwr.read_consumed = 0;
+ bwr.read_buffer = (uintptr_t) readbuf;
+
+ res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
+
+ if (res < 0) {
+ ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
+ break;
+ }
+
+ res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
+ if (res == 0) {
+ ALOGE("binder_loop: unexpected reply?!\n");
+ break;
+ }
+ if (res < 0) {
+ ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
+ break;
+ }
+ }
+}
+
+void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn)
+{
+ bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer;
+ bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets;
+ bio->data_avail = txn->data_size;
+ bio->offs_avail = txn->offsets_size / sizeof(size_t);
+ bio->flags = BIO_F_SHARED;
+}
+
+void bio_init(struct binder_io *bio, void *data,
+ size_t maxdata, size_t maxoffs)
+{
+ size_t n = maxoffs * sizeof(size_t);
+
+ if (n > maxdata) {
+ bio->flags = BIO_F_OVERFLOW;
+ bio->data_avail = 0;
+ bio->offs_avail = 0;
+ return;
+ }
+
+ bio->data = bio->data0 = (char *) data + n;
+ bio->offs = bio->offs0 = data;
+ bio->data_avail = maxdata - n;
+ bio->offs_avail = maxoffs;
+ bio->flags = 0;
+}
+
+static void *bio_alloc(struct binder_io *bio, size_t size)
+{
+ size = (size + 3) & (~3);
+ if (size > bio->data_avail) {
+ bio->flags |= BIO_F_OVERFLOW;
+ return NULL;
+ } else {
+ void *ptr = bio->data;
+ bio->data += size;
+ bio->data_avail -= size;
+ return ptr;
+ }
+}
+
+void binder_done(struct binder_state *bs,
+ __unused struct binder_io *msg,
+ struct binder_io *reply)
+{
+ struct {
+ uint32_t cmd;
+ uintptr_t buffer;
+ } __attribute__((packed)) data;
+
+ if (reply->flags & BIO_F_SHARED) {
+ data.cmd = BC_FREE_BUFFER;
+ data.buffer = (uintptr_t) reply->data0;
+ binder_write(bs, &data, sizeof(data));
+ reply->flags = 0;
+ }
+}
+
+static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
+{
+ struct flat_binder_object *obj;
+
+ obj = bio_alloc(bio, sizeof(*obj));
+
+ if (obj && bio->offs_avail) {
+ bio->offs_avail--;
+ *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
+ return obj;
+ }
+
+ bio->flags |= BIO_F_OVERFLOW;
+ return NULL;
+}
+
+void bio_put_uint32(struct binder_io *bio, uint32_t n)
+{
+ uint32_t *ptr = bio_alloc(bio, sizeof(n));
+ if (ptr)
+ *ptr = n;
+}
+
+void bio_put_obj(struct binder_io *bio, void *ptr)
+{
+ struct flat_binder_object *obj;
+
+ obj = bio_alloc_obj(bio);
+ if (!obj)
+ return;
+
+ obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ obj->hdr.type = BINDER_TYPE_BINDER;
+ obj->binder = (uintptr_t)ptr;
+ obj->cookie = 0;
+}
+
+void bio_put_ref(struct binder_io *bio, uint32_t handle)
+{
+ struct flat_binder_object *obj;
+
+ if (handle)
+ obj = bio_alloc_obj(bio);
+ else
+ obj = bio_alloc(bio, sizeof(*obj));
+
+ if (!obj)
+ return;
+
+ obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ obj->hdr.type = BINDER_TYPE_HANDLE;
+ obj->handle = handle;
+ obj->cookie = 0;
+}
+
+void bio_put_string16(struct binder_io *bio, const uint16_t *str)
+{
+ size_t len;
+ uint16_t *ptr;
+
+ if (!str) {
+ bio_put_uint32(bio, 0xffffffff);
+ return;
+ }
+
+ len = 0;
+ while (str[len]) len++;
+
+ if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
+ bio_put_uint32(bio, 0xffffffff);
+ return;
+ }
+
+ /* Note: The payload will carry 32bit size instead of size_t */
+ bio_put_uint32(bio, (uint32_t) len);
+ len = (len + 1) * sizeof(uint16_t);
+ ptr = bio_alloc(bio, len);
+ if (ptr)
+ memcpy(ptr, str, len);
+}
+
+void bio_put_string16_x(struct binder_io *bio, const char *_str)
+{
+ unsigned char *str = (unsigned char*) _str;
+ size_t len;
+ uint16_t *ptr;
+
+ if (!str) {
+ bio_put_uint32(bio, 0xffffffff);
+ return;
+ }
+
+ len = strlen(_str);
+
+ if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
+ bio_put_uint32(bio, 0xffffffff);
+ return;
+ }
+
+ /* Note: The payload will carry 32bit size instead of size_t */
+ bio_put_uint32(bio, len);
+ ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
+ if (!ptr)
+ return;
+
+ while (*str)
+ *ptr++ = *str++;
+ *ptr++ = 0;
+}
+
+static void *bio_get(struct binder_io *bio, size_t size)
+{
+ size = (size + 3) & (~3);
+
+ if (bio->data_avail < size){
+ bio->data_avail = 0;
+ bio->flags |= BIO_F_OVERFLOW;
+ return NULL;
+ } else {
+ void *ptr = bio->data;
+ bio->data += size;
+ bio->data_avail -= size;
+ return ptr;
+ }
+}
+
+uint32_t bio_get_uint32(struct binder_io *bio)
+{
+ uint32_t *ptr = bio_get(bio, sizeof(*ptr));
+ return ptr ? *ptr : 0;
+}
+
+uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz)
+{
+ size_t len;
+
+ /* Note: The payload will carry 32bit size instead of size_t */
+ len = (size_t) bio_get_uint32(bio);
+ if (sz)
+ *sz = len;
+ return bio_get(bio, (len + 1) * sizeof(uint16_t));
+}
+
+static struct flat_binder_object *_bio_get_obj(struct binder_io *bio)
+{
+ size_t n;
+ size_t off = bio->data - bio->data0;
+
+ /* TODO: be smarter about this? */
+ for (n = 0; n < bio->offs_avail; n++) {
+ if (bio->offs[n] == off)
+ return bio_get(bio, sizeof(struct flat_binder_object));
+ }
+
+ bio->data_avail = 0;
+ bio->flags |= BIO_F_OVERFLOW;
+ return NULL;
+}
+
+uint32_t bio_get_ref(struct binder_io *bio)
+{
+ struct flat_binder_object *obj;
+
+ obj = _bio_get_obj(bio);
+ if (!obj)
+ return 0;
+
+ if (obj->hdr.type == BINDER_TYPE_HANDLE)
+ return obj->handle;
+
+ return 0;
+}
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
new file mode 100644
index 0000000000..a9ccc74130
--- /dev/null
+++ b/cmds/servicemanager/binder.h
@@ -0,0 +1,94 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#ifndef _BINDER_H_
+#define _BINDER_H_
+
+#include <linux/android/binder.h>
+#include <sys/ioctl.h>
+
+struct binder_state;
+
+struct binder_io
+{
+ char *data; /* pointer to read/write from */
+ binder_size_t *offs; /* array of offsets */
+ size_t data_avail; /* bytes available in data buffer */
+ size_t offs_avail; /* entries available in offsets array */
+
+ char *data0; /* start of data buffer */
+ binder_size_t *offs0; /* start of offsets buffer */
+ uint32_t flags;
+ uint32_t unused;
+};
+
+struct binder_death {
+ void (*func)(struct binder_state *bs, void *ptr);
+ void *ptr;
+};
+
+/* the one magic handle */
+#define BINDER_SERVICE_MANAGER 0U
+
+#define SVC_MGR_NAME "android.os.IServiceManager"
+
+enum {
+ /* Must match definitions in IBinder.h and IServiceManager.h */
+ PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'),
+ SVC_MGR_GET_SERVICE = 1,
+ SVC_MGR_CHECK_SERVICE,
+ SVC_MGR_ADD_SERVICE,
+ SVC_MGR_LIST_SERVICES,
+};
+
+typedef int (*binder_handler)(struct binder_state *bs,
+ struct binder_transaction_data_secctx *txn,
+ struct binder_io *msg,
+ struct binder_io *reply);
+
+struct binder_state *binder_open(const char* driver, size_t mapsize);
+void binder_close(struct binder_state *bs);
+
+/* initiate a blocking binder call
+ * - returns zero on success
+ */
+int binder_call(struct binder_state *bs,
+ struct binder_io *msg, struct binder_io *reply,
+ uint32_t target, uint32_t code);
+
+/* release any state associate with the binder_io
+ * - call once any necessary data has been extracted from the
+ * binder_io after binder_call() returns
+ * - can safely be called even if binder_call() fails
+ */
+void binder_done(struct binder_state *bs,
+ struct binder_io *msg, struct binder_io *reply);
+
+/* manipulate strong references */
+void binder_acquire(struct binder_state *bs, uint32_t target);
+void binder_release(struct binder_state *bs, uint32_t target);
+
+void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death);
+
+void binder_loop(struct binder_state *bs, binder_handler func);
+
+int binder_become_context_manager(struct binder_state *bs);
+
+/* allocate a binder_io, providing a stack-allocated working
+ * buffer, size of the working buffer, and how many object
+ * offset entries to reserve from the buffer
+ */
+void bio_init(struct binder_io *bio, void *data,
+ size_t maxdata, size_t maxobjects);
+
+void bio_put_obj(struct binder_io *bio, void *ptr);
+void bio_put_ref(struct binder_io *bio, uint32_t handle);
+void bio_put_uint32(struct binder_io *bio, uint32_t n);
+void bio_put_string16(struct binder_io *bio, const uint16_t *str);
+void bio_put_string16_x(struct binder_io *bio, const char *_str);
+
+uint32_t bio_get_uint32(struct binder_io *bio);
+uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz);
+uint32_t bio_get_ref(struct binder_io *bio);
+
+#endif
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
deleted file mode 100644
index 4b12fc6e72..0000000000
--- a/cmds/servicemanager/main.cpp
+++ /dev/null
@@ -1,56 +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 <android-base/logging.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/Status.h>
-#include <utils/StrongPointer.h>
-
-#include "Access.h"
-#include "ServiceManager.h"
-
-using ::android::Access;
-using ::android::IPCThreadState;
-using ::android::ProcessState;
-using ::android::ServiceManager;
-using ::android::os::IServiceManager;
-using ::android::sp;
-
-int main(int argc, char** argv) {
- if (argc > 2) {
- LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
- }
-
- const char* driver = argc == 2 ? argv[1] : "/dev/binder";
-
- sp<ProcessState> ps = ProcessState::initWithDriver(driver);
- ps->setThreadPoolMaxThreadCount(0);
- ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
-
- sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
- if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
- LOG(ERROR) << "Could not self register servicemanager";
- }
-
- IPCThreadState::self()->setTheContextObject(manager);
- ps->becomeContextManager(nullptr, nullptr);
-
- IPCThreadState::self()->joinThreadPool();
-
- // should not be reached
- return EXIT_FAILURE;
-}
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
new file mode 100644
index 0000000000..ec3fac538d
--- /dev/null
+++ b/cmds/servicemanager/service_manager.c
@@ -0,0 +1,442 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/android_filesystem_config.h>
+#include <cutils/multiuser.h>
+
+#include <selinux/android.h>
+#include <selinux/avc.h>
+
+#include "binder.h"
+
+#ifdef VENDORSERVICEMANAGER
+#define LOG_TAG "VendorServiceManager"
+#else
+#define LOG_TAG "ServiceManager"
+#endif
+#include <log/log.h>
+
+struct audit_data {
+ pid_t pid;
+ uid_t uid;
+ const char *name;
+};
+
+const char *str8(const uint16_t *x, size_t x_len)
+{
+ static char buf[128];
+ size_t max = 127;
+ char *p = buf;
+
+ if (x_len < max) {
+ max = x_len;
+ }
+
+ if (x) {
+ while ((max > 0) && (*x != '\0')) {
+ *p++ = *x++;
+ max--;
+ }
+ }
+ *p++ = 0;
+ return buf;
+}
+
+int str16eq(const uint16_t *a, const char *b)
+{
+ while (*a && *b)
+ if (*a++ != *b++) return 0;
+ if (*a || *b)
+ return 0;
+ return 1;
+}
+
+static char *service_manager_context;
+static struct selabel_handle* sehandle;
+
+static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name)
+{
+ char *lookup_sid = NULL;
+ const char *class = "service_manager";
+ bool allowed;
+ struct audit_data ad;
+
+ if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) {
+ ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
+ return false;
+ }
+
+ ad.pid = spid;
+ ad.uid = uid;
+ ad.name = name;
+
+ if (sid == NULL) {
+ android_errorWriteLog(0x534e4554, "121035042");
+ }
+
+ int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad);
+ allowed = (result == 0);
+
+ freecon(lookup_sid);
+ return allowed;
+}
+
+static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm)
+{
+ return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL);
+}
+
+static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name)
+{
+ bool allowed;
+ char *tctx = NULL;
+
+ if (!sehandle) {
+ ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
+ abort();
+ }
+
+ if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
+ ALOGE("SELinux: No match for %s in service_contexts.\n", name);
+ return false;
+ }
+
+ allowed = check_mac_perms(spid, sid, uid, tctx, perm, name);
+ freecon(tctx);
+ return allowed;
+}
+
+static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
+{
+ const char *perm = "add";
+
+ if (multiuser_get_app_id(uid) >= AID_APP) {
+ return 0; /* Don't allow apps to register services */
+ }
+
+ return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
+}
+
+static int svc_can_list(pid_t spid, const char* sid, uid_t uid)
+{
+ const char *perm = "list";
+ return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0;
+}
+
+static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
+{
+ const char *perm = "find";
+ return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
+}
+
+struct svcinfo
+{
+ struct svcinfo *next;
+ uint32_t handle;
+ struct binder_death death;
+ int allow_isolated;
+ uint32_t dumpsys_priority;
+ size_t len;
+ uint16_t name[0];
+};
+
+struct svcinfo *svclist = NULL;
+
+struct svcinfo *find_svc(const uint16_t *s16, size_t len)
+{
+ struct svcinfo *si;
+
+ for (si = svclist; si; si = si->next) {
+ if ((len == si->len) &&
+ !memcmp(s16, si->name, len * sizeof(uint16_t))) {
+ return si;
+ }
+ }
+ return NULL;
+}
+
+void svcinfo_death(struct binder_state *bs, void *ptr)
+{
+ struct svcinfo *si = (struct svcinfo* ) ptr;
+
+ ALOGI("service '%s' died\n", str8(si->name, si->len));
+ if (si->handle) {
+ binder_release(bs, si->handle);
+ si->handle = 0;
+ }
+}
+
+uint16_t svcmgr_id[] = {
+ 'a','n','d','r','o','i','d','.','o','s','.',
+ 'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
+};
+
+
+uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
+{
+ struct svcinfo *si = find_svc(s, len);
+
+ if (!si || !si->handle) {
+ return 0;
+ }
+
+ if (!si->allow_isolated) {
+ // If this service doesn't allow access from isolated processes,
+ // then check the uid to see if it is isolated.
+ uid_t appid = uid % AID_USER;
+ if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
+ return 0;
+ }
+ }
+
+ if (!svc_can_find(s, len, spid, sid, uid)) {
+ return 0;
+ }
+
+ return si->handle;
+}
+
+int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
+ uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
+ struct svcinfo *si;
+
+ //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
+ // allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
+
+ if (!handle || (len == 0) || (len > 127))
+ return -1;
+
+ if (!svc_can_register(s, len, spid, sid, uid)) {
+ ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
+ str8(s, len), handle, uid);
+ return -1;
+ }
+
+ si = find_svc(s, len);
+ if (si) {
+ if (si->handle) {
+ ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
+ str8(s, len), handle, uid);
+ svcinfo_death(bs, si);
+ }
+ si->handle = handle;
+ } else {
+ si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
+ if (!si) {
+ ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
+ str8(s, len), handle, uid);
+ return -1;
+ }
+ si->handle = handle;
+ si->len = len;
+ memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
+ si->name[len] = '\0';
+ si->death.func = (void*) svcinfo_death;
+ si->death.ptr = si;
+ si->allow_isolated = allow_isolated;
+ si->dumpsys_priority = dumpsys_priority;
+ si->next = svclist;
+ svclist = si;
+ }
+
+ binder_acquire(bs, handle);
+ binder_link_to_death(bs, handle, &si->death);
+ return 0;
+}
+
+int svcmgr_handler(struct binder_state *bs,
+ struct binder_transaction_data_secctx *txn_secctx,
+ struct binder_io *msg,
+ struct binder_io *reply)
+{
+ struct svcinfo *si;
+ uint16_t *s;
+ size_t len;
+ uint32_t handle;
+ uint32_t strict_policy;
+ int allow_isolated;
+ uint32_t dumpsys_priority;
+
+ struct binder_transaction_data *txn = &txn_secctx->transaction_data;
+
+ //ALOGI("target=%p code=%d pid=%d uid=%d\n",
+ // (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
+
+ if (txn->target.ptr != BINDER_SERVICE_MANAGER)
+ return -1;
+
+ if (txn->code == PING_TRANSACTION)
+ return 0;
+
+ // Equivalent to Parcel::enforceInterface(), reading the RPC
+ // header with the strict mode policy mask and the interface name.
+ // Note that we ignore the strict_policy and don't propagate it
+ // further (since we do no outbound RPCs anyway).
+ strict_policy = bio_get_uint32(msg);
+ bio_get_uint32(msg); // Ignore worksource header.
+ s = bio_get_string16(msg, &len);
+ if (s == NULL) {
+ return -1;
+ }
+
+ if ((len != (sizeof(svcmgr_id) / 2)) ||
+ memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
+ fprintf(stderr,"invalid id %s\n", str8(s, len));
+ return -1;
+ }
+
+ if (sehandle && selinux_status_updated() > 0) {
+#ifdef VENDORSERVICEMANAGER
+ struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle();
+#else
+ struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
+#endif
+ if (tmp_sehandle) {
+ selabel_close(sehandle);
+ sehandle = tmp_sehandle;
+ }
+ }
+
+ switch(txn->code) {
+ case SVC_MGR_GET_SERVICE:
+ case SVC_MGR_CHECK_SERVICE:
+ s = bio_get_string16(msg, &len);
+ if (s == NULL) {
+ return -1;
+ }
+ handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
+ (const char*) txn_secctx->secctx);
+ if (!handle)
+ break;
+ bio_put_ref(reply, handle);
+ return 0;
+
+ case SVC_MGR_ADD_SERVICE:
+ s = bio_get_string16(msg, &len);
+ if (s == NULL) {
+ return -1;
+ }
+ handle = bio_get_ref(msg);
+ allow_isolated = bio_get_uint32(msg) ? 1 : 0;
+ dumpsys_priority = bio_get_uint32(msg);
+ if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
+ txn->sender_pid, (const char*) txn_secctx->secctx))
+ return -1;
+ break;
+
+ case SVC_MGR_LIST_SERVICES: {
+ uint32_t n = bio_get_uint32(msg);
+ uint32_t req_dumpsys_priority = bio_get_uint32(msg);
+
+ if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
+ ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
+ txn->sender_euid);
+ return -1;
+ }
+ si = svclist;
+ // walk through the list of services n times skipping services that
+ // do not support the requested priority
+ while (si) {
+ if (si->dumpsys_priority & req_dumpsys_priority) {
+ if (n == 0) break;
+ n--;
+ }
+ si = si->next;
+ }
+ if (si) {
+ bio_put_string16(reply, si->name);
+ return 0;
+ }
+ return -1;
+ }
+ default:
+ ALOGE("unknown code %d\n", txn->code);
+ return -1;
+ }
+
+ bio_put_uint32(reply, 0);
+ return 0;
+}
+
+
+static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
+{
+ struct audit_data *ad = (struct audit_data *)data;
+
+ if (!ad || !ad->name) {
+ ALOGE("No service manager audit data");
+ return 0;
+ }
+
+ snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ struct binder_state *bs;
+ union selinux_callback cb;
+ char *driver;
+
+ if (argc > 1) {
+ driver = argv[1];
+ } else {
+ driver = "/dev/binder";
+ }
+
+ bs = binder_open(driver, 128*1024);
+ if (!bs) {
+#ifdef VENDORSERVICEMANAGER
+ ALOGW("failed to open binder driver %s\n", driver);
+ while (true) {
+ sleep(UINT_MAX);
+ }
+#else
+ ALOGE("failed to open binder driver %s\n", driver);
+#endif
+ return -1;
+ }
+
+ if (binder_become_context_manager(bs)) {
+ ALOGE("cannot become context manager (%s)\n", strerror(errno));
+ return -1;
+ }
+
+ cb.func_audit = audit_callback;
+ selinux_set_callback(SELINUX_CB_AUDIT, cb);
+#ifdef VENDORSERVICEMANAGER
+ cb.func_log = selinux_vendor_log_callback;
+#else
+ cb.func_log = selinux_log_callback;
+#endif
+ selinux_set_callback(SELINUX_CB_LOG, cb);
+
+#ifdef VENDORSERVICEMANAGER
+ sehandle = selinux_android_vendor_service_context_handle();
+#else
+ sehandle = selinux_android_service_context_handle();
+#endif
+ selinux_status_open(true);
+
+ if (sehandle == NULL) {
+ ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
+ abort();
+ }
+
+ if (getcon(&service_manager_context) != 0) {
+ ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
+ abort();
+ }
+
+
+ binder_loop(bs, svcmgr_handler);
+
+ return 0;
+}
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
deleted file mode 100644
index 25245beaf7..0000000000
--- a/cmds/servicemanager/test_sm.cpp
+++ /dev/null
@@ -1,429 +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 <android/os/BnServiceCallback.h>
-#include <binder/Binder.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <cutils/android_filesystem_config.h>
-#include <gtest/gtest.h>
-#include <gmock/gmock.h>
-
-#include "Access.h"
-#include "ServiceManager.h"
-
-using android::sp;
-using android::Access;
-using android::BBinder;
-using android::IBinder;
-using android::ServiceManager;
-using android::binder::Status;
-using android::os::BnServiceCallback;
-using android::os::IServiceManager;
-using testing::_;
-using testing::ElementsAre;
-using testing::NiceMock;
-using testing::Return;
-
-static sp<IBinder> getBinder() {
- class LinkableBinder : public BBinder {
- android::status_t linkToDeath(const sp<DeathRecipient>&, void*, uint32_t) override {
- // let SM linkToDeath
- return android::OK;
- }
- };
-
- return new LinkableBinder;
-}
-
-class MockAccess : public Access {
-public:
- MOCK_METHOD0(getCallingContext, CallingContext());
- MOCK_METHOD2(canAdd, bool(const CallingContext&, const std::string& name));
- MOCK_METHOD2(canFind, bool(const CallingContext&, const std::string& name));
- MOCK_METHOD1(canList, bool(const CallingContext&));
-};
-
-class MockServiceManager : public ServiceManager {
- public:
- MockServiceManager(std::unique_ptr<Access>&& access) : ServiceManager(std::move(access)) {}
- MOCK_METHOD1(tryStartService, void(const std::string& name));
-};
-
-static sp<ServiceManager> getPermissiveServiceManager() {
- std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
- ON_CALL(*access, getCallingContext()).WillByDefault(Return(Access::CallingContext{}));
- ON_CALL(*access, canAdd(_, _)).WillByDefault(Return(true));
- ON_CALL(*access, canFind(_, _)).WillByDefault(Return(true));
- ON_CALL(*access, canList(_)).WillByDefault(Return(true));
-
- sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
- return sm;
-}
-
-TEST(AddService, HappyHappy) {
- auto sm = getPermissiveServiceManager();
- EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, EmptyNameDisallowed) {
- auto sm = getPermissiveServiceManager();
- EXPECT_FALSE(sm->addService("", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, JustShortEnoughServiceNameHappy) {
- auto sm = getPermissiveServiceManager();
- EXPECT_TRUE(sm->addService(std::string(127, 'a'), getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, TooLongNameDisallowed) {
- auto sm = getPermissiveServiceManager();
- EXPECT_FALSE(sm->addService(std::string(128, 'a'), getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, WeirdCharactersDisallowed) {
- auto sm = getPermissiveServiceManager();
- EXPECT_FALSE(sm->addService("happy$foo$foo", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, AddNullServiceDisallowed) {
- auto sm = getPermissiveServiceManager();
- EXPECT_FALSE(sm->addService("foo", nullptr, false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, AddDisallowedFromApp) {
- for (uid_t uid : { AID_APP_START, AID_APP_START + 1, AID_APP_END }) {
- std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
- EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{
- .debugPid = 1337,
- .uid = uid,
- }));
- EXPECT_CALL(*access, canAdd(_, _)).Times(0);
- sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
- EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- }
-
-}
-
-TEST(AddService, HappyOverExistingService) {
- auto sm = getPermissiveServiceManager();
- EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(AddService, NoPermissions) {
- std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
- EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
- EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(false));
-
- sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
- EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-}
-
-TEST(GetService, HappyHappy) {
- auto sm = getPermissiveServiceManager();
- sp<IBinder> service = getBinder();
-
- EXPECT_TRUE(sm->addService("foo", service, false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
- sp<IBinder> out;
- EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(service, out);
-}
-
-TEST(GetService, NonExistant) {
- auto sm = getPermissiveServiceManager();
-
- sp<IBinder> out;
- EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(nullptr, out.get());
-}
-
-TEST(GetService, NoPermissionsForGettingService) {
- std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
- EXPECT_CALL(*access, getCallingContext()).WillRepeatedly(Return(Access::CallingContext{}));
- EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
- EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(false));
-
- sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
- EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
- sp<IBinder> out;
- // returns nullptr but has OK status for legacy compatibility
- EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(nullptr, out.get());
-}
-
-TEST(GetService, AllowedFromIsolated) {
- std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
- EXPECT_CALL(*access, getCallingContext())
- // something adds it
- .WillOnce(Return(Access::CallingContext{}))
- // next call is from isolated app
- .WillOnce(Return(Access::CallingContext{
- .uid = AID_ISOLATED_START,
- }));
- EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
- EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
-
- sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
- sp<IBinder> service = getBinder();
- EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
- sp<IBinder> out;
- EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(service, out.get());
-}
-
-TEST(GetService, NotAllowedFromIsolated) {
- std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
- EXPECT_CALL(*access, getCallingContext())
- // something adds it
- .WillOnce(Return(Access::CallingContext{}))
- // next call is from isolated app
- .WillOnce(Return(Access::CallingContext{
- .uid = AID_ISOLATED_START,
- }));
- EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
-
- // TODO(b/136023468): when security check is first, this should be called first
- // EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
-
- sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
- EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
- sp<IBinder> out;
- // returns nullptr but has OK status for legacy compatibility
- EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(nullptr, out.get());
-}
-
-TEST(ListServices, NoPermissions) {
- std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
- EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
- EXPECT_CALL(*access, canList(_)).WillOnce(Return(false));
-
- sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
-
- std::vector<std::string> out;
- EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
- EXPECT_TRUE(out.empty());
-}
-
-TEST(ListServices, AllServices) {
- auto sm = getPermissiveServiceManager();
-
- EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk());
- EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk());
- EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk());
-
- std::vector<std::string> out;
- EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
-
- // all there and in the right order
- EXPECT_THAT(out, ElementsAre("sa", "sb", "sc", "sd"));
-}
-
-TEST(ListServices, CriticalServices) {
- auto sm = getPermissiveServiceManager();
-
- EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk());
- EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk());
- EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/,
- IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk());
-
- std::vector<std::string> out;
- EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL, &out).isOk());
-
- // all there and in the right order
- EXPECT_THAT(out, ElementsAre("sa"));
-}
-
-class CallbackHistorian : public BnServiceCallback {
- Status onRegistration(const std::string& name, const sp<IBinder>& binder) override {
- registrations.push_back(name);
- binders.push_back(binder);
- return Status::ok();
- }
-
- android::status_t linkToDeath(const sp<DeathRecipient>&, void*, uint32_t) override {
- // let SM linkToDeath
- return android::OK;
- }
-
-public:
- std::vector<std::string> registrations;
- std::vector<sp<IBinder>> binders;
-};
-
-TEST(ServiceNotifications, NoPermissionsRegister) {
- std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
- EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
- EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
-
- sp<ServiceManager> sm = new ServiceManager(std::move(access));
-
- sp<CallbackHistorian> cb = new CallbackHistorian;
-
- EXPECT_EQ(sm->registerForNotifications("foofoo", cb).exceptionCode(),
- Status::EX_SECURITY);
-}
-
-TEST(ServiceNotifications, NoPermissionsUnregister) {
- std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
-
- EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
- EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
-
- sp<ServiceManager> sm = new ServiceManager(std::move(access));
-
- sp<CallbackHistorian> cb = new CallbackHistorian;
-
- // should always hit security error first
- EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
- Status::EX_SECURITY);
-}
-
-TEST(ServiceNotifications, InvalidName) {
- auto sm = getPermissiveServiceManager();
-
- sp<CallbackHistorian> cb = new CallbackHistorian;
-
- EXPECT_EQ(sm->registerForNotifications("foo@foo", cb).exceptionCode(),
- Status::EX_ILLEGAL_ARGUMENT);
-}
-
-TEST(ServiceNotifications, NullCallback) {
- auto sm = getPermissiveServiceManager();
-
- EXPECT_EQ(sm->registerForNotifications("foofoo", nullptr).exceptionCode(),
- Status::EX_NULL_POINTER);
-}
-
-TEST(ServiceNotifications, Unregister) {
- auto sm = getPermissiveServiceManager();
-
- sp<CallbackHistorian> cb = new CallbackHistorian;
-
- EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
- EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(), 0);
-}
-
-TEST(ServiceNotifications, UnregisterWhenNoRegistrationExists) {
- auto sm = getPermissiveServiceManager();
-
- sp<CallbackHistorian> cb = new CallbackHistorian;
-
- EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
- Status::EX_ILLEGAL_STATE);
-}
-
-TEST(ServiceNotifications, NoNotification) {
- auto sm = getPermissiveServiceManager();
-
- sp<CallbackHistorian> cb = new CallbackHistorian;
-
- EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
- EXPECT_TRUE(sm->addService("otherservice", getBinder(),
- false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
- EXPECT_THAT(cb->registrations, ElementsAre());
- EXPECT_THAT(cb->binders, ElementsAre());
-}
-
-TEST(ServiceNotifications, GetNotification) {
- auto sm = getPermissiveServiceManager();
-
- sp<CallbackHistorian> cb = new CallbackHistorian;
-
- sp<IBinder> service = getBinder();
-
- EXPECT_TRUE(sm->registerForNotifications("asdfasdf", cb).isOk());
- EXPECT_TRUE(sm->addService("asdfasdf", service,
- false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
- EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf"));
- EXPECT_THAT(cb->binders, ElementsAre(service));
-}
-
-TEST(ServiceNotifications, GetNotificationForAlreadyRegisteredService) {
- auto sm = getPermissiveServiceManager();
-
- sp<CallbackHistorian> cb = new CallbackHistorian;
-
- sp<IBinder> service = getBinder();
-
- EXPECT_TRUE(sm->addService("asdfasdf", service,
- false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
- EXPECT_TRUE(sm->registerForNotifications("asdfasdf", cb).isOk());
-
- EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf"));
- EXPECT_THAT(cb->binders, ElementsAre(service));
-}
-
-TEST(ServiceNotifications, GetMultipleNotification) {
- auto sm = getPermissiveServiceManager();
-
- sp<CallbackHistorian> cb = new CallbackHistorian;
-
- sp<IBinder> binder1 = getBinder();
- sp<IBinder> binder2 = getBinder();
-
- EXPECT_TRUE(sm->registerForNotifications("asdfasdf", cb).isOk());
- EXPECT_TRUE(sm->addService("asdfasdf", binder1,
- false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- EXPECT_TRUE(sm->addService("asdfasdf", binder2,
- false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
-
- EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf", "asdfasdf"));
- EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf", "asdfasdf"));
-}
diff --git a/data/etc/android.hardware.se.omapi.ese.xml b/data/etc/android.hardware.se.omapi.ese.xml
deleted file mode 100644
index 3b1d81cd87..0000000000
--- a/data/etc/android.hardware.se.omapi.ese.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<!-- This feature indicates that the device supports The device supports
- Open Mobile API capable ESE-based secure elements-->
-<permissions>
- <feature name="android.hardware.se.omapi.ese" />
-</permissions>
diff --git a/data/etc/android.hardware.se.omapi.sd.xml b/data/etc/android.hardware.se.omapi.sd.xml
deleted file mode 100644
index 8fc2869d23..0000000000
--- a/data/etc/android.hardware.se.omapi.sd.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<!-- This feature indicates that the device supports The device supports
- Open Mobile API capable SD-based secure elements-->
-<permissions>
- <feature name="android.hardware.se.omapi.sd" />
-</permissions>
diff --git a/data/etc/android.hardware.se.omapi.uicc.xml b/data/etc/android.hardware.se.omapi.uicc.xml
deleted file mode 100644
index 9c6f143990..0000000000
--- a/data/etc/android.hardware.se.omapi.uicc.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<!-- This feature indicates that the device supports The device supports
- Open Mobile API capable UICC-based secure elements-->
-<permissions>
- <feature name="android.hardware.se.omapi.uicc" />
-</permissions>
diff --git a/headers/media_plugin/media/cas/CasAPI.h b/headers/media_plugin/media/cas/CasAPI.h
index 8cc9d365a2..c87ee5655e 100644
--- a/headers/media_plugin/media/cas/CasAPI.h
+++ b/headers/media_plugin/media/cas/CasAPI.h
@@ -56,11 +56,6 @@ typedef void (*CasPluginCallbackExt)(
size_t size,
const CasSessionId *sessionId);
-typedef void (*CasPluginStatusCallback)(
- void *appData,
- int32_t event,
- int32_t arg);
-
struct CasFactory {
CasFactory() {}
virtual ~CasFactory() {}
@@ -96,10 +91,6 @@ struct CasPlugin {
CasPlugin() {}
virtual ~CasPlugin() {}
- // Provide a callback to report plugin status
- virtual status_t setStatusCallback(
- CasPluginStatusCallback callback) = 0;
-
// Provide the CA private data from a CA_descriptor in the conditional
// access table to a CasPlugin.
virtual status_t setPrivateData(
@@ -109,11 +100,6 @@ struct CasPlugin {
// streams.
virtual status_t openSession(CasSessionId *sessionId) = 0;
- // Open a session with intend and mode for descrambling a program, or one
- // or more elementary streams.
- virtual status_t openSession(uint32_t intent, uint32_t mode,
- CasSessionId *sessionId) = 0;
-
// Close a previously opened session.
virtual status_t closeSession(const CasSessionId &sessionId) = 0;
diff --git a/headers/media_plugin/media/openmax/OMX_Video.h b/headers/media_plugin/media/openmax/OMX_Video.h
index 81ee5fb2e5..b6edaa900e 100644
--- a/headers/media_plugin/media/openmax/OMX_Video.h
+++ b/headers/media_plugin/media/openmax/OMX_Video.h
@@ -90,7 +90,6 @@ typedef enum OMX_VIDEO_CODINGTYPE {
OMX_VIDEO_CodingHEVC, /**< ITU H.265/HEVC */
OMX_VIDEO_CodingDolbyVision,/**< Dolby Vision */
OMX_VIDEO_CodingImageHEIC, /**< HEIF image encoded with HEVC */
- OMX_VIDEO_CodingAV1, /**< AV1 */
OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
OMX_VIDEO_CodingMax = 0x7FFFFFFF
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 346861f0a8..44883cc498 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -59,8 +59,6 @@ typedef void (*AChoreographer_frameCallback64)(int64_t frameTimeNanos, void* dat
/**
* Get the AChoreographer instance for the current thread. This must be called
* on an ALooper thread.
- *
- * Available since API level 24.
*/
AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24);
@@ -84,8 +82,6 @@ void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
/**
* Power a callback to be run on the next frame. The data pointer provided will
* be passed to the callback function when it's called.
- *
- * Available since API level 29.
*/
void AChoreographer_postFrameCallback64(AChoreographer* chroreographer,
AChoreographer_frameCallback64 callback, void* data) __INTRODUCED_IN(29);
@@ -94,8 +90,6 @@ void AChoreographer_postFrameCallback64(AChoreographer* chroreographer,
* Post a callback to be run on the frame following the specified delay. The
* data pointer provided will be passed to the callback function when it's
* called.
- *
- * Available since API level 29.
*/
void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) __INTRODUCED_IN(29);
diff --git a/include/android/configuration.h b/include/android/configuration.h
index 331072238b..ef6c5a2f81 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -675,52 +675,50 @@ int32_t AConfiguration_getUiModeNight(AConfiguration* config);
*/
void AConfiguration_setUiModeNight(AConfiguration* config, int32_t uiModeNight);
+#if __ANDROID_API__ >= 13
/**
* Return the current configuration screen width in dp units, or
* ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.
*/
-int32_t AConfiguration_getScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
/**
* Set the configuration's current screen width in dp units.
*/
-void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
/**
* Return the current configuration screen height in dp units, or
* ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.
*/
-int32_t AConfiguration_getScreenHeightDp(AConfiguration* config);
+int32_t AConfiguration_getScreenHeightDp(AConfiguration* config) __INTRODUCED_IN(13);
/**
* Set the configuration's current screen width in dp units.
*/
-void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
/**
* Return the configuration's smallest screen width in dp units, or
* ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.
*/
-int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
/**
* Set the configuration's smallest screen width in dp units.
*/
-void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
+void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
+#endif /* __ANDROID_API__ >= 13 */
#if __ANDROID_API__ >= 17
/**
* Return the configuration's layout direction, or
* ACONFIGURATION_LAYOUTDIR_ANY if not set.
- *
- * Available since API level 17.
*/
int32_t AConfiguration_getLayoutDirection(AConfiguration* config) __INTRODUCED_IN(17);
/**
* Set the configuration's layout direction.
- *
- * Available since API level 17.
*/
void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
#endif /* __ANDROID_API__ >= 17 */
diff --git a/include/android/font.h b/include/android/font.h
index 1618096d69..435a573f51 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -16,7 +16,7 @@
/**
* @addtogroup Font
- * @{
+ * {
*/
/**
@@ -96,8 +96,6 @@ struct AFont;
/**
* Close an AFont.
*
- * Available since API level 29.
- *
* \param font a font returned by ASystemFontIterator_next or AFontMatchert_match.
* Do nothing if NULL is passed.
*/
@@ -118,8 +116,6 @@ void AFont_close(AFont* _Nullable font) __INTRODUCED_IN(29);
* The font file returned is guaranteed to be opend with O_RDONLY.
* Note that the returned pointer is valid until AFont_close() is called for the given font.
*
- * Available since API level 29.
- *
* \param font a font object. Passing NULL is not allowed.
* \return a string of the font file path.
*/
@@ -188,8 +184,6 @@ const char* _Nonnull AFont_getFontFilePath(const AFont* _Nonnull font) __INTRODU
*
* For more information about font weight, read [OpenType usWeightClass](https://docs.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass)
*
- * Available since API level 29.
- *
* \param font a font object. Passing NULL is not allowed.
* \return a positive integer less than or equal to {@link ASYSTEM_FONT_MAX_WEIGHT} is returned.
*/
@@ -198,8 +192,6 @@ uint16_t AFont_getWeight(const AFont* _Nonnull font) __INTRODUCED_IN(29);
/**
* Return true if the current font is italic, otherwise returns false.
*
- * Available since API level 29.
- *
* \param font a font object. Passing NULL is not allowed.
* \return true if italic, otherwise false.
*/
@@ -212,8 +204,6 @@ bool AFont_isItalic(const AFont* _Nonnull font) __INTRODUCED_IN(29);
*
* Note that the returned pointer is valid until AFont_close() is called.
*
- * Available since API level 29.
- *
* \param font a font object. Passing NULL is not allowed.
* \return a IETF BCP47 compliant language tag or nullptr if not available.
*/
@@ -226,8 +216,6 @@ const char* _Nullable AFont_getLocale(const AFont* _Nonnull font) __INTRODUCED_I
* returns a non-negative value as an font offset in the collection. This
* always returns 0 if the target font file is a regular font.
*
- * Available since API level 29.
- *
* \param font a font object. Passing NULL is not allowed.
* \return a font collection index.
*/
@@ -259,8 +247,6 @@ size_t AFont_getCollectionIndex(const AFont* _Nonnull font) __INTRODUCED_IN(29);
*
* For more information about font variation settings, read [Font Variations Table](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar)
*
- * Available since API level 29.
- *
* \param font a font object. Passing NULL is not allowed.
* \return a number of font variation settings.
*/
@@ -272,8 +258,6 @@ size_t AFont_getAxisCount(const AFont* _Nonnull font) __INTRODUCED_IN(29);
*
* See AFont_getAxisCount for more details.
*
- * Available since API level 29.
- *
* \param font a font object. Passing NULL is not allowed.
* \param axisIndex an index to the font variation settings. Passing value larger than or
* equal to {@link AFont_getAxisCount} is not allowed.
@@ -287,8 +271,6 @@ uint32_t AFont_getAxisTag(const AFont* _Nonnull font, uint32_t axisIndex)
*
* See AFont_getAxisCount for more details.
*
- * Available since API level 29.
- *
* \param font a font object. Passing NULL is not allowed.
* \param axisIndex an index to the font variation settings. Passing value larger than or
* equal to {@link ASYstemFont_getAxisCount} is not allwed.
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index d4bd892bf6..e286a4c812 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -16,7 +16,7 @@
/**
* @addtogroup Font
- * @{
+ * {
*/
/**
@@ -130,17 +130,13 @@ struct AFontMatcher;
*/
/**
- * Creates a new AFontMatcher object.
- *
- * Available since API level 29.
+ * Creates a new AFontMatcher object
*/
AFontMatcher* _Nonnull AFontMatcher_create() __INTRODUCED_IN(29);
/**
* Destroy the matcher object.
*
- * Available since API level 29.
- *
* \param matcher a matcher object. Passing NULL is not allowed.
*/
void AFontMatcher_destroy(AFontMatcher* _Nonnull matcher) __INTRODUCED_IN(29);
@@ -151,8 +147,6 @@ void AFontMatcher_destroy(AFontMatcher* _Nonnull matcher) __INTRODUCED_IN(29);
* If this function is not called, the matcher performs with {@link ASYSTEM_FONT_WEIGHT_NORMAL}
* with non-italic style.
*
- * Available since API level 29.
- *
* \param matcher a matcher object. Passing NULL is not allowed.
* \param weight a font weight value. Only from 0 to 1000 value is valid
* \param italic true if italic, otherwise false.
@@ -167,8 +161,6 @@ void AFontMatcher_setStyle(
*
* If this function is not called, the matcher performs with empty locale list.
*
- * Available since API level 29.
- *
* \param matcher a matcher object. Passing NULL is not allowed.
* \param languageTags a null character terminated comma separated IETF BCP47 compliant language
* tags.
@@ -182,8 +174,6 @@ void AFontMatcher_setLocales(
*
* If this function is not called, the matcher performs with {@link AFAMILY_VARIANT_DEFAULT}.
*
- * Available since API level 29.
- *
* \param matcher a matcher object. Passing NULL is not allowed.
* \param familyVariant Must be one of {@link AFAMILY_VARIANT_DEFAULT},
* {@link AFAMILY_VARIANT_COMPACT} or {@link AFAMILY_VARIANT_ELEGANT} is valid.
@@ -200,8 +190,6 @@ void AFontMatcher_setFamilyVariant(
* Even if no font can render the given text, this function will return a non-null result for
* drawing Tofu character.
*
- * Available since API level 29.
- *
* \param matcher a matcher object. Passing NULL is not allowed.
* \param familyName a null character terminated font family name
* \param text a UTF-16 encoded text buffer to be rendered. Do not pass empty string.
diff --git a/include/android/hardware_buffer_jni.h b/include/android/hardware_buffer_jni.h
index 293e5ac469..aedf36903d 100644
--- a/include/android/hardware_buffer_jni.h
+++ b/include/android/hardware_buffer_jni.h
@@ -42,8 +42,6 @@ __BEGIN_DECLS
* that is returned. To keep the AHardwareBuffer live after the Java
* HardwareBuffer object got garbage collected, be sure to use AHardwareBuffer_acquire()
* to acquire an additional reference.
- *
- * Available since API level 26.
*/
AHardwareBuffer* AHardwareBuffer_fromHardwareBuffer(JNIEnv* env,
jobject hardwareBufferObj) __INTRODUCED_IN(26);
@@ -51,8 +49,6 @@ AHardwareBuffer* AHardwareBuffer_fromHardwareBuffer(JNIEnv* env,
/**
* Return a new Java HardwareBuffer object that wraps the passed native
* AHardwareBuffer object.
- *
- * Available since API level 26.
*/
jobject AHardwareBuffer_toHardwareBuffer(JNIEnv* env,
AHardwareBuffer* hardwareBuffer) __INTRODUCED_IN(26);
diff --git a/include/android/input.h b/include/android/input.h
index ce439c6d75..cfade6c806 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -986,8 +986,10 @@ int32_t AMotionEvent_getFlags(const AInputEvent* motion_event);
*/
int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
+#if __ANDROID_API__ >= 14
/** Get the button state of all buttons that are pressed. */
-int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
+int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event) __INTRODUCED_IN(14);
+#endif
/**
* Get a bitfield indicating which edges, if any, were touched by this motion event.
@@ -1052,12 +1054,14 @@ size_t AMotionEvent_getPointerCount(const AInputEvent* motion_event);
*/
int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index);
+#if __ANDROID_API__ >= 14
/**
* Get the tool type of a pointer for the given pointer index.
* The tool type indicates the type of tool used to make contact such as a
* finger or stylus, if known.
*/
-int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
+int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index) __INTRODUCED_IN(14);
+#endif
/**
* Get the original raw X coordinate of this event.
@@ -1147,9 +1151,11 @@ float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_
*/
float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
+#if __ANDROID_API__ >= 13
/** Get the value of the request axis for the given pointer index. */
float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
- int32_t axis, size_t pointer_index);
+ int32_t axis, size_t pointer_index) __INTRODUCED_IN(13);
+#endif
/**
* Get the number of historical points in this event. These are movements that
@@ -1280,12 +1286,14 @@ float AMotionEvent_getHistoricalToolMinor(const AInputEvent* motion_event, size_
float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
+#if __ANDROID_API__ >= 13
/**
* Get the historical value of the request axis for the given pointer index
* that occurred between this event and the previous motion event.
*/
float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event,
- int32_t axis, size_t pointer_index, size_t history_index);
+ int32_t axis, size_t pointer_index, size_t history_index) __INTRODUCED_IN(13);
+#endif
struct AInputQueue;
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 59b1deb595..d31d1f122f 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -69,7 +69,6 @@ typedef uint64_t net_handle_t;
*
* This is the equivalent of: [android.net.Network#bindSocket()](https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket))
*
- * Available since API level 23.
*/
int android_setsocknetwork(net_handle_t network, int fd) __INTRODUCED_IN(23);
@@ -87,7 +86,6 @@ int android_setsocknetwork(net_handle_t network, int fd) __INTRODUCED_IN(23);
*
* This is the equivalent of: [android.net.ConnectivityManager#setProcessDefaultNetwork()](https://developer.android.com/reference/android/net/ConnectivityManager.html#setProcessDefaultNetwork(android.net.Network))
*
- * Available since API level 23.
*/
int android_setprocnetwork(net_handle_t network) __INTRODUCED_IN(23);
@@ -105,7 +103,6 @@ int android_setprocnetwork(net_handle_t network) __INTRODUCED_IN(23);
*
* This is the equivalent of: [android.net.Network#getAllByName()](https://developer.android.com/reference/android/net/Network.html#getAllByName(java.lang.String))
*
- * Available since API level 23.
*/
int android_getaddrinfofornetwork(net_handle_t network,
const char *node, const char *service,
@@ -147,8 +144,6 @@ enum ResNsendFlags : uint32_t {
*
* Returns a file descriptor to watch for read events, or a negative
* POSIX error code (see errno.h) if an immediate error occurs.
- *
- * Available since API level 29.
*/
int android_res_nquery(net_handle_t network,
const char *dname, int ns_class, int ns_type, uint32_t flags) __INTRODUCED_IN(29);
@@ -160,8 +155,6 @@ int android_res_nquery(net_handle_t network,
*
* Returns a file descriptor to watch for read events, or a negative
* POSIX error code (see errno.h) if an immediate error occurs.
- *
- * Available since API level 29.
*/
int android_res_nsend(net_handle_t network,
const uint8_t *msg, size_t msglen, uint32_t flags) __INTRODUCED_IN(29);
@@ -170,8 +163,6 @@ int android_res_nsend(net_handle_t network,
* Read a result for the query associated with the |fd| descriptor.
* Closes |fd| before returning.
*
- * Available since 29.
- *
* Returns:
* < 0: negative POSIX error code (see errno.h for possible values). |rcode| is not set.
* >= 0: length of |answer|. |rcode| is the resolver return code (e.g., ns_r_nxdomain)
@@ -182,8 +173,6 @@ int android_res_nresult(int fd,
/**
* Attempts to cancel the in-progress query associated with the |nsend_fd|
* descriptor.
- *
- * Available since API level 29.
*/
void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 3a77ffe86b..0c196b9671 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -51,8 +51,6 @@ ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
* the ANativeWindow; maintains it through general Java object's life cycle;
* and will automatically release the reference when the Java object gets garbage
* collected.
- *
- * Available since API level 26.
*/
jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
#endif
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 3ebe79fd2e..e9d5c16d0d 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -564,7 +564,6 @@ ASensorManager* ASensorManager_getInstance();
*
* ASensorManager* sensorManager = ASensorManager_getInstanceForPackage("foo.bar.baz");
*
- * Available since API level 26.
*/
ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
#endif
@@ -584,8 +583,6 @@ ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type
/**
* Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
* of this type and wakeUp properties exists.
- *
- * Available since API level 21.
*/
ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
#endif
@@ -612,8 +609,6 @@ int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue*
* Create a direct channel of {@link ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY} to be used
* for configuring sensor direct report.
*
- * Available since API level 26.
- *
* \param manager the {@link ASensorManager} instance obtained from
* {@link ASensorManager_getInstanceForPackage}.
* \param fd file descriptor representing a shared memory created by
@@ -632,8 +627,6 @@ int ASensorManager_createSharedMemoryDirectChannel(ASensorManager* manager, int
* Create a direct channel of {@link ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER} type to be used
* for configuring sensor direct report.
*
- * Available since API level 26.
- *
* \param manager the {@link ASensorManager} instance obtained from
* {@link ASensorManager_getInstanceForPackage}.
* \param buffer {@link AHardwareBuffer} instance created by {@link AHardwareBuffer_allocate}.
@@ -653,8 +646,6 @@ int ASensorManager_createHardwareBufferDirectChannel(
* The buffer used for creating direct channel does not get destroyed with
* {@link ASensorManager_destroy} and has to be close or released separately.
*
- * Available since API level 26.
- *
* \param manager the {@link ASensorManager} instance obtained from
* {@link ASensorManager_getInstanceForPackage}.
* \param channelId channel id (a positive integer) returned from
@@ -687,8 +678,6 @@ void ASensorManager_destroyDirectChannel(ASensorManager* manager, int channelId)
*
* ASensorManager_configureDirectReport(manager, sensor, channel_id, ASENSOR_DIRECT_RATE_FAST);
*
- * Available since API level 26.
- *
* \param manager the {@link ASensorManager} instance obtained from
* {@link ASensorManager_getInstanceForPackage}.
* \param sensor a {@link ASensor} to denote which sensor to be operate. It can be NULL if rate
@@ -791,7 +780,7 @@ int ASensorEventQueue_hasEvents(ASensorEventQueue* queue);
*/
ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count);
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
/**
* Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on
* the given {@link ASensorEventQueue}.
@@ -807,15 +796,13 @@ ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* even
* {@link AAdditionalInfoEvent#type}, as new values may be defined in the future
* and may delivered to the client.
*
- * Available since API level 29.
- *
* \param queue {@link ASensorEventQueue} to configure
* \param enable true to request {@link ASENSOR_TYPE_ADDITIONAL_INFO} events,
* false to stop receiving events
* \return 0 on success or a negative error code on failure
*/
-int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
+int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable);
+#endif /* __ANDROID_API__ >= __ANDRDOID_API_Q__ */
/*****************************************************************************/
@@ -850,36 +837,26 @@ int ASensor_getMinDelay(ASensor const* sensor);
/**
* Returns the maximum size of batches for this sensor. Batches will often be
* smaller, as the hardware fifo might be used for other sensors.
- *
- * Available since API level 21.
*/
int ASensor_getFifoMaxEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns the hardware batch fifo size reserved to this sensor.
- *
- * Available since API level 21.
*/
int ASensor_getFifoReservedEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns this sensor's string type.
- *
- * Available since API level 21.
*/
const char* ASensor_getStringType(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.
- *
- * Available since API level 21.
*/
int ASensor_getReportingMode(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns true if this is a wake up sensor, false otherwise.
- *
- * Available since API level 21.
*/
bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
#endif /* __ANDROID_API__ >= 21 */
@@ -888,8 +865,6 @@ bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Test if sensor supports a certain type of direct channel.
*
- * Available since API level 26.
- *
* \param sensor a {@link ASensor} to denote the sensor to be checked.
* \param channelType Channel type constant, either
* {@ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY}
@@ -899,9 +874,7 @@ bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType) __INTRODUCED_IN(26);
/**
- * Get the highest direct rate level that a sensor supports.
- *
- * Available since API level 26.
+ * Get the highest direct rate level that a sensor support.
*
* \param sensor a {@link ASensor} to denote the sensor to be checked.
*
@@ -912,7 +885,7 @@ bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType
int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
#endif /* __ANDROID_API__ >= 26 */
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
/**
* Returns the sensor's handle.
*
@@ -926,11 +899,9 @@ int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_
* It is important to note that the value returned by {@link ASensor_getHandle} is not the same as
* the value returned by the Java API {@link android.hardware.Sensor#getId} and no mapping exists
* between the values.
- *
- * Available since API level 29.
*/
-int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
+int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(__ANDROID_API_Q__);
+#endif /* __ANDROID_API__ >= ANDROID_API_Q__ */
#ifdef __cplusplus
};
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 90e565359e..ef2ad9998c 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -46,7 +46,7 @@ struct ASurfaceControl;
*/
typedef struct ASurfaceControl ASurfaceControl;
-/**
+/*
* Creates an ASurfaceControl with either ANativeWindow or an ASurfaceControl as its parent.
* |debug_name| is a debug name associated with this surface. It can be used to
* identify this surface in the SurfaceFlinger's layer tree. It must not be
@@ -54,17 +54,10 @@ typedef struct ASurfaceControl ASurfaceControl;
*
* The caller takes ownership of the ASurfaceControl returned and must release it
* using ASurfaceControl_release below.
- *
- * Available since API level 29.
*/
ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* parent, const char* debug_name)
__INTRODUCED_IN(29);
-/**
- * See ASurfaceControl_createFromWindow.
- *
- * Available since API level 29.
- */
ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name)
__INTRODUCED_IN(29);
@@ -72,8 +65,6 @@ ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* deb
* Releases the |surface_control| object. After releasing the ASurfaceControl the caller no longer
* has ownership of the AsurfaceControl. The surface and it's children may remain on display as long
* as their parent remains on display.
- *
- * Available since API level 29.
*/
void ASurfaceControl_release(ASurfaceControl* surface_control) __INTRODUCED_IN(29);
@@ -88,15 +79,11 @@ typedef struct ASurfaceTransaction ASurfaceTransaction;
/**
* The caller takes ownership of the transaction and must release it using
* ASurfaceControl_delete below.
- *
- * Available since API level 29.
*/
ASurfaceTransaction* ASurfaceTransaction_create() __INTRODUCED_IN(29);
/**
* Destroys the |transaction| object.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
@@ -106,8 +93,6 @@ void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_I
* Note that the transaction is guaranteed to be applied atomically. The
* transactions which are applied on the same thread are also guaranteed to be
* applied in order.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_apply(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
@@ -131,8 +116,6 @@ typedef struct ASurfaceTransactionStats ASurfaceTransactionStats;
*
* THREADING
* The transaction completed callback can be invoked on any thread.
- *
- * Available since API level 29.
*/
typedef void (*ASurfaceTransaction_OnComplete)(void* context, ASurfaceTransactionStats* stats)
__INTRODUCED_IN(29);
@@ -140,8 +123,6 @@ typedef void (*ASurfaceTransaction_OnComplete)(void* context, ASurfaceTransactio
/**
* Returns the timestamp of when the frame was latched by the framework. Once a frame is
* latched by the framework, it is presented at the following hardware vsync.
- *
- * Available since API level 29.
*/
int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* surface_transaction_stats)
__INTRODUCED_IN(29);
@@ -150,8 +131,6 @@ int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* surface_
* Returns a sync fence that signals when the transaction has been presented.
* The recipient of the callback takes ownership of the fence and is responsible for closing
* it.
- *
- * Available since API level 29.
*/
int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface_transaction_stats)
__INTRODUCED_IN(29);
@@ -162,8 +141,6 @@ int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface
* When the client is done using the array, it must release it by calling
* ASurfaceTransactionStats_releaseASurfaceControls.
*
- * Available since API level 29.
- *
* |outASurfaceControlsSize| returns the size of the ASurfaceControls array.
*/
void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* surface_transaction_stats,
@@ -173,8 +150,6 @@ void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* surf
/**
* Releases the array of ASurfaceControls that were returned by
* ASurfaceTransactionStats_getASurfaceControls.
- *
- * Available since API level 29.
*/
void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** surface_controls)
__INTRODUCED_IN(29);
@@ -183,8 +158,6 @@ void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** surface_
* Returns the timestamp of when the CURRENT buffer was acquired. A buffer is considered
* acquired when its acquire_fence_fd has signaled. A buffer cannot be latched or presented until
* it is acquired. If no acquire_fence_fd was provided, this timestamp will be set to -1.
- *
- * Available since API level 29.
*/
int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* surface_transaction_stats,
ASurfaceControl* surface_control)
@@ -207,8 +180,6 @@ int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* surfac
*
* The client must ensure that all pending refs on a buffer are released before attempting to reuse
* this buffer, otherwise synchronization errors may occur.
- *
- * Available since API level 29.
*/
int ASurfaceTransactionStats_getPreviousReleaseFenceFd(
ASurfaceTransactionStats* surface_transaction_stats,
@@ -219,8 +190,6 @@ int ASurfaceTransactionStats_getPreviousReleaseFenceFd(
* Sets the callback that will be invoked when the updates from this transaction
* are presented. For details on the callback semantics and data, see the
* comments on the ASurfaceTransaction_OnComplete declaration above.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* context,
ASurfaceTransaction_OnComplete func) __INTRODUCED_IN(29);
@@ -230,8 +199,6 @@ void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* c
* Any children of the* reparented |surface_control| will remain children of the |surface_control|.
*
* The |new_parent| can be null. Surface controls with a null parent do not appear on the display.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_reparent(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, ASurfaceControl* new_parent)
@@ -246,8 +213,6 @@ enum {
* Updates the visibility of |surface_control|. If show is set to
* ASURFACE_TRANSACTION_VISIBILITY_HIDE, the |surface_control| and all surfaces in its subtree will
* be hidden.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, int8_t visibility)
@@ -259,8 +224,6 @@ void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
* the same z order is undefined.
*
* Z orders may be from MIN_INT32 to MAX_INT32. A layer's default z order index is 0.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, int32_t z_order)
@@ -273,8 +236,6 @@ void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction,
*
* The frameworks takes ownership of the |acquire_fence_fd| passed and is responsible
* for closing it.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, AHardwareBuffer* buffer,
@@ -285,8 +246,6 @@ void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
* ASurfaceControl visible in transparent regions of the surface. Colors |r|, |g|,
* and |b| must be within the range that is valid for |dataspace|. |dataspace| and |alpha|
* will be the dataspace and alpha set for the background color layer.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, float r, float g, float b,
@@ -305,8 +264,6 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction,
* |transform| the transform applied after the source rect is applied to the buffer. This parameter
* should be set to 0 for no transform. To specify a transfrom use the NATIVE_WINDOW_TRANSFORM_*
* enum.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, const ARect& source,
@@ -324,8 +281,6 @@ enum {
* Updates whether the content for the buffer associated with this surface is
* completely opaque. If true, every pixel of content inside the buffer must be
* opaque or visual errors can occur.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control,
@@ -335,8 +290,6 @@ void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
/**
* Updates the region for the content on this surface updated in this
* transaction. If unspecified, the complete surface is assumed to be damaged.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, const ARect rects[],
@@ -351,8 +304,6 @@ void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction,
*
* If an earlier transaction has a desired present time of x, and a later transaction has a desired
* present time that is before x, the later transaction will not preempt the earlier transaction.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* transaction,
int64_t desiredPresentTime) __INTRODUCED_IN(29);
@@ -361,8 +312,6 @@ void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* transaction,
* Sets the alpha for the buffer. It uses a premultiplied blending.
*
* The |alpha| must be between 0.0 and 1.0.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, float alpha)
@@ -372,8 +321,6 @@ void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* transaction,
* Sets the data space of the surface_control's buffers.
*
* If no data space is set, the surface control defaults to ADATASPACE_SRGB.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, ADataSpace data_space)
@@ -384,8 +331,6 @@ void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* transaction,
*
* When |metadata| is set to null, the framework does not use any smpte2086 metadata when rendering
* the surface's buffer.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control,
@@ -397,8 +342,6 @@ void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* transacti
*
* When |metadata| is set to null, the framework does not use any cta861.3 metadata when rendering
* the surface's buffer.
- *
- * Available since API level 29.
*/
void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control,
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index dde7eaa0b6..540d23a4c7 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -65,9 +65,6 @@ typedef struct ASurfaceTexture ASurfaceTexture;
* Release the reference to the native ASurfaceTexture acquired with
* ASurfaceTexture_fromSurfaceTexture().
* Failing to do so will result in leaked memory and graphic resources.
- *
- * Available since API level 28.
- *
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
*/
void ASurfaceTexture_release(ASurfaceTexture* st) __INTRODUCED_IN(28);
@@ -76,8 +73,6 @@ void ASurfaceTexture_release(ASurfaceTexture* st) __INTRODUCED_IN(28);
* Returns a reference to an ANativeWindow (i.e. the Producer) for this SurfaceTexture.
* This is equivalent to Java's: Surface sur = new Surface(surfaceTexture);
*
- * Available since API level 28.
- *
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* @return A reference to an ANativeWindow. This reference MUST BE released when no longer needed
* using ANativeWindow_release(). Failing to do so will result in leaked resources. nullptr is
@@ -95,8 +90,6 @@ ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st) __INTRO
* contexts. Note, however, that the image contents are only accessible from one OpenGL ES
* context at a time.
*
- * Available since API level 28.
- *
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* \param texName The name of the OpenGL ES texture that will be created. This texture name
* must be unusued in the OpenGL ES context that is current on the calling thread.
@@ -115,8 +108,6 @@ int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t texName) __I
* contexts. Note, however, that the image contents are only accessible from one OpenGL ES
* context at a time.
*
- * Available since API level 28.
- *
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* \return 0 on success, negative posix error code otherwise (see <errno.h>)
*/
@@ -127,8 +118,6 @@ int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) __INTRODUCED_IN(28)
* called while the OpenGL ES context that owns the texture is current on the calling thread.
* It will implicitly bind its texture to the GL_TEXTURE_EXTERNAL_OES texture target.
*
- * Available since API level 28.
- *
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* \return 0 on success, negative posix error code otherwise (see <errno.h>)
*/
@@ -146,8 +135,6 @@ int ASurfaceTexture_updateTexImage(ASurfaceTexture* st) __INTRODUCED_IN(28);
* The matrix is stored in column-major order so that it may be passed directly to OpenGL ES via
* the glLoadMatrixf or glUniformMatrix4fv functions.
*
- * Available since API level 28.
- *
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* \param mtx the array into which the 4x4 matrix will be stored. The array must have exactly
* 16 elements.
@@ -169,8 +156,6 @@ void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) __IN
* For EGL/Vulkan producers, this timestamp is the desired present time set with the
* EGL_ANDROID_presentation_time or VK_GOOGLE_display_timing extensions
*
- * Available since API level 28.
- *
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
*/
int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
diff --git a/include/android/surface_texture_jni.h b/include/android/surface_texture_jni.h
index 2266d541f6..b0e1edd590 100644
--- a/include/android/surface_texture_jni.h
+++ b/include/android/surface_texture_jni.h
@@ -32,8 +32,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 28
-
/**
* Get a reference to the native ASurfaceTexture from the corresponding java object.
*
@@ -42,17 +40,13 @@ __BEGIN_DECLS
* properly once the Java object gets finalized.
* However, this will not result in program termination.
*
- * Available since API level 28.
- *
* \param env JNI environment
* \param surfacetexture Instance of Java SurfaceTexture object
* \return native ASurfaceTexture reference or nullptr if the java object is not a SurfaceTexture.
* The returned reference MUST BE released when it's no longer needed using
* ASurfaceTexture_release().
*/
-ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) __INTRODUCED_IN(28);
-
-#endif
+ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture);
__END_DECLS
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index 6fd7d2c0ab..dde9055c7a 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -16,7 +16,7 @@
/**
* @addtogroup Font
- * @{
+ * {
*/
/**
@@ -102,8 +102,6 @@ struct ASystemFontIterator;
*
* Use ASystemFont_close() to close the iterator.
*
- * Available since API level 29.
- *
* \return a pointer for a newly allocated iterator, nullptr on failure.
*/
ASystemFontIterator* _Nullable ASystemFontIterator_open() __INTRODUCED_IN(29);
@@ -111,8 +109,6 @@ ASystemFontIterator* _Nullable ASystemFontIterator_open() __INTRODUCED_IN(29);
/**
* Close an opened system font iterator, freeing any related resources.
*
- * Available since API level 29.
- *
* \param iterator a pointer of an iterator for the system fonts. Do nothing if NULL is passed.
*/
void ASystemFontIterator_close(ASystemFontIterator* _Nullable iterator) __INTRODUCED_IN(29);
@@ -120,8 +116,6 @@ void ASystemFontIterator_close(ASystemFontIterator* _Nullable iterator) __INTROD
/**
* Move to the next system font.
*
- * Available since API level 29.
- *
* \param iterator an iterator for the system fonts. Passing NULL is not allowed.
* \return a font. If no more font is available, returns nullptr. You need to release the returned
* font by ASystemFont_close when it is no longer needed.
diff --git a/include/android/trace.h b/include/android/trace.h
index d59690ab2e..bb7ff28f79 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -74,7 +74,7 @@ void ATrace_endSection() __INTRODUCED_IN(23);
#endif /* __ANDROID_API__ >= 23 */
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
/**
* Writes a trace message to indicate that a given section of code has
@@ -83,8 +83,6 @@ void ATrace_endSection() __INTRODUCED_IN(23);
* asynchronous events do not need to be nested. The name and cookie used to
* begin an event must be used to end it.
*
- * Available since API level 29.
- *
* \param sectionName The method name to appear in the trace.
* \param cookie Unique identifier for distinguishing simultaneous events
*/
@@ -95,8 +93,6 @@ void ATrace_beginAsyncSection(const char* sectionName, int32_t cookie) __INTRODU
* Must be called exactly once for each call to {@link ATrace_beginAsyncSection}
* using the same name and cookie.
*
- * Available since API level 29.
- *
* \param methodName The method name to appear in the trace.
* \param cookie Unique identifier for distinguishing simultaneous events
*/
@@ -105,8 +101,6 @@ void ATrace_endAsyncSection(const char* sectionName, int32_t cookie) __INTRODUCE
/**
* Writes trace message to indicate the value of a given counter.
*
- * Available since API level 29.
- *
* \param counterName The counter name to appear in the trace.
* \param counterValue The counter value.
*/
diff --git a/include/audiomanager/OWNERS b/include/audiomanager/OWNERS
deleted file mode 100644
index 2bd527cc3f..0000000000
--- a/include/audiomanager/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elaurent@google.com
-jmtrivi@google.com
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
index 4365a3c4e3..d23e3b7767 100644
--- a/include/input/IInputFlinger.h
+++ b/include/input/IInputFlinger.h
@@ -37,7 +37,6 @@ public:
virtual void setInputWindows(const std::vector<InputWindowInfo>& inputHandles,
const sp<ISetInputWindowsListener>& setInputWindowsListener) = 0;
- virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
virtual void registerInputChannel(const sp<InputChannel>& channel) = 0;
virtual void unregisterInputChannel(const sp<InputChannel>& channel) = 0;
};
@@ -51,8 +50,7 @@ public:
enum {
SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
REGISTER_INPUT_CHANNEL_TRANSACTION,
- UNREGISTER_INPUT_CHANNEL_TRANSACTION,
- TRANSFER_TOUCH_FOCUS
+ UNREGISTER_INPUT_CHANNEL_TRANSACTION
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp
deleted file mode 100644
index 9cf014380c..0000000000
--- a/libs/adbd_auth/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-cc_library {
- name: "libadbd_auth",
- cflags: [
- "-Wall",
- "-Wextra",
- "-Wthread-safety",
- "-Werror",
- ],
- srcs: ["adbd_auth.cpp"],
- export_include_dirs: ["include"],
-
- version_script: "libadbd_auth.map.txt",
- stubs: {
- symbol_file: "libadbd_auth.map.txt",
- },
-
- host_supported: true,
- recovery_available: true,
- target: {
- darwin: {
- enabled: false,
- }
- },
-
- shared_libs: [
- "libbase",
- "libcutils",
- "liblog",
- ],
-}
diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp
deleted file mode 100644
index 64791098ee..0000000000
--- a/libs/adbd_auth/adbd_auth.cpp
+++ /dev/null
@@ -1,443 +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 ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION
-
-#include "include/adbd_auth.h"
-
-#include <inttypes.h>
-#include <sys/epoll.h>
-#include <sys/eventfd.h>
-#include <sys/uio.h>
-
-#include <chrono>
-#include <deque>
-#include <string>
-#include <string_view>
-#include <tuple>
-#include <unordered_map>
-#include <utility>
-#include <variant>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <android-base/strings.h>
-#include <android-base/thread_annotations.h>
-#include <android-base/unique_fd.h>
-#include <cutils/sockets.h>
-
-using android::base::unique_fd;
-
-struct AdbdAuthPacketAuthenticated {
- std::string public_key;
-};
-
-struct AdbdAuthPacketDisconnected {
- std::string public_key;
-};
-
-struct AdbdAuthPacketRequestAuthorization {
- std::string public_key;
-};
-
-using AdbdAuthPacket = std::variant<AdbdAuthPacketAuthenticated, AdbdAuthPacketDisconnected,
- AdbdAuthPacketRequestAuthorization>;
-
-struct AdbdAuthContext {
- static constexpr uint64_t kEpollConstSocket = 0;
- static constexpr uint64_t kEpollConstEventFd = 1;
- static constexpr uint64_t kEpollConstFramework = 2;
-
-public:
- explicit AdbdAuthContext(AdbdAuthCallbacksV1* callbacks) : next_id_(0), callbacks_(*callbacks) {
- epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
- if (epoll_fd_ == -1) {
- PLOG(FATAL) << "failed to create epoll fd";
- }
-
- event_fd_.reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
- if (event_fd_ == -1) {
- PLOG(FATAL) << "failed to create eventfd";
- }
-
- sock_fd_.reset(android_get_control_socket("adbd"));
- if (sock_fd_ == -1) {
- PLOG(ERROR) << "failed to get adbd authentication socket";
- } else {
- if (fcntl(sock_fd_.get(), F_SETFD, FD_CLOEXEC) != 0) {
- PLOG(FATAL) << "failed to make adbd authentication socket cloexec";
- }
-
- if (fcntl(sock_fd_.get(), F_SETFL, O_NONBLOCK) != 0) {
- PLOG(FATAL) << "failed to make adbd authentication socket nonblocking";
- }
-
- if (listen(sock_fd_.get(), 4) != 0) {
- PLOG(FATAL) << "failed to listen on adbd authentication socket";
- }
- }
- }
-
- AdbdAuthContext(const AdbdAuthContext& copy) = delete;
- AdbdAuthContext(AdbdAuthContext&& move) = delete;
- AdbdAuthContext& operator=(const AdbdAuthContext& copy) = delete;
- AdbdAuthContext& operator=(AdbdAuthContext&& move) = delete;
-
- uint64_t NextId() { return next_id_++; }
-
- void DispatchPendingPrompt() REQUIRES(mutex_) {
- if (dispatched_prompt_) {
- LOG(INFO) << "adbd_auth: prompt currently pending, skipping";
- return;
- }
-
- if (pending_prompts_.empty()) {
- LOG(INFO) << "adbd_auth: no prompts to send";
- return;
- }
-
- LOG(INFO) << "adbd_auth: prompting user for adb authentication";
- auto [id, public_key, arg] = std::move(pending_prompts_.front());
- pending_prompts_.pop_front();
-
- this->output_queue_.emplace_back(
- AdbdAuthPacketRequestAuthorization{.public_key = public_key});
-
- Interrupt();
- dispatched_prompt_ = std::make_tuple(id, public_key, arg);
- }
-
- void UpdateFrameworkWritable() REQUIRES(mutex_) {
- // This might result in redundant calls to EPOLL_CTL_MOD if, for example, we get notified
- // at the same time as a framework connection, but that's unlikely and this doesn't need to
- // be fast anyway.
- if (framework_fd_ != -1) {
- struct epoll_event event;
- event.events = EPOLLIN;
- if (!output_queue_.empty()) {
- LOG(INFO) << "marking framework writable";
- event.events |= EPOLLOUT;
- }
- event.data.u64 = kEpollConstFramework;
- CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_MOD, framework_fd_.get(), &event));
- }
- }
-
- void ReplaceFrameworkFd(unique_fd new_fd) REQUIRES(mutex_) {
- LOG(INFO) << "received new framework fd " << new_fd.get()
- << " (current = " << framework_fd_.get() << ")";
-
- // If we already had a framework fd, clean up after ourselves.
- if (framework_fd_ != -1) {
- output_queue_.clear();
- dispatched_prompt_.reset();
- CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, framework_fd_.get(), nullptr));
- framework_fd_.reset();
- }
-
- if (new_fd != -1) {
- struct epoll_event event;
- event.events = EPOLLIN;
- if (!output_queue_.empty()) {
- LOG(INFO) << "marking framework writable";
- event.events |= EPOLLOUT;
- }
- event.data.u64 = kEpollConstFramework;
- CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, new_fd.get(), &event));
- framework_fd_ = std::move(new_fd);
- }
- }
-
- void HandlePacket(std::string_view packet) REQUIRES(mutex_) {
- LOG(INFO) << "received packet: " << packet;
-
- if (packet.length() < 2) {
- LOG(ERROR) << "received packet of invalid length";
- ReplaceFrameworkFd(unique_fd());
- }
-
- if (packet[0] == 'O' && packet[1] == 'K') {
- CHECK(this->dispatched_prompt_.has_value());
- auto& [id, key, arg] = *this->dispatched_prompt_;
- keys_.emplace(id, std::move(key));
-
- this->callbacks_.key_authorized(arg, id);
- this->dispatched_prompt_ = std::nullopt;
- } else if (packet[0] == 'N' && packet[1] == 'O') {
- CHECK_EQ(2UL, packet.length());
- // TODO: Do we want a callback if the key is denied?
- this->dispatched_prompt_ = std::nullopt;
- DispatchPendingPrompt();
- } else {
- LOG(ERROR) << "unhandled packet: " << packet;
- ReplaceFrameworkFd(unique_fd());
- }
- }
-
- bool SendPacket() REQUIRES(mutex_) {
- if (output_queue_.empty()) {
- return false;
- }
-
- CHECK_NE(-1, framework_fd_.get());
-
- auto& packet = output_queue_.front();
- struct iovec iovs[2];
- if (auto* p = std::get_if<AdbdAuthPacketAuthenticated>(&packet)) {
- iovs[0].iov_base = const_cast<char*>("CK");
- iovs[0].iov_len = 2;
- iovs[1].iov_base = p->public_key.data();
- iovs[1].iov_len = p->public_key.size();
- } else if (auto* p = std::get_if<AdbdAuthPacketDisconnected>(&packet)) {
- iovs[0].iov_base = const_cast<char*>("DC");
- iovs[0].iov_len = 2;
- iovs[1].iov_base = p->public_key.data();
- iovs[1].iov_len = p->public_key.size();
- } else if (auto* p = std::get_if<AdbdAuthPacketRequestAuthorization>(&packet)) {
- iovs[0].iov_base = const_cast<char*>("PK");
- iovs[0].iov_len = 2;
- iovs[1].iov_base = p->public_key.data();
- iovs[1].iov_len = p->public_key.size();
- } else {
- LOG(FATAL) << "unhandled packet type?";
- }
-
- output_queue_.pop_front();
-
- ssize_t rc = writev(framework_fd_.get(), iovs, 2);
- if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
- PLOG(ERROR) << "failed to write to framework fd";
- ReplaceFrameworkFd(unique_fd());
- return false;
- }
-
- return true;
- }
-
- void Run() {
- if (sock_fd_ == -1) {
- LOG(ERROR) << "adbd authentication socket unavailable, disabling user prompts";
- } else {
- struct epoll_event event;
- event.events = EPOLLIN;
- event.data.u64 = kEpollConstSocket;
- CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, sock_fd_.get(), &event));
- }
-
- {
- struct epoll_event event;
- event.events = EPOLLIN;
- event.data.u64 = kEpollConstEventFd;
- CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, event_fd_.get(), &event));
- }
-
- while (true) {
- struct epoll_event events[3];
- int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1));
- if (rc == -1) {
- PLOG(FATAL) << "epoll_wait failed";
- } else if (rc == 0) {
- LOG(FATAL) << "epoll_wait returned 0";
- }
-
- bool restart = false;
- for (int i = 0; i < rc; ++i) {
- if (restart) {
- break;
- }
-
- struct epoll_event& event = events[i];
- switch (event.data.u64) {
- case kEpollConstSocket: {
- unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr,
- SOCK_CLOEXEC | SOCK_NONBLOCK));
- if (new_framework_fd == -1) {
- PLOG(FATAL) << "failed to accept framework fd";
- }
-
- LOG(INFO) << "adbd_auth: received a new framework connection";
- std::lock_guard<std::mutex> lock(mutex_);
- ReplaceFrameworkFd(std::move(new_framework_fd));
-
- // Stop iterating over events: one of the later ones might be the old
- // framework fd.
- restart = false;
- break;
- }
-
- case kEpollConstEventFd: {
- // We were woken up to write something.
- uint64_t dummy;
- int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy)));
- if (rc != 8) {
- PLOG(FATAL) << "failed to read from eventfd (rc = " << rc << ")";
- }
-
- std::lock_guard<std::mutex> lock(mutex_);
- UpdateFrameworkWritable();
- break;
- }
-
- case kEpollConstFramework: {
- char buf[4096];
- if (event.events & EPOLLIN) {
- int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf)));
- if (rc == -1) {
- LOG(FATAL) << "failed to read from framework fd";
- } else if (rc == 0) {
- LOG(INFO) << "hit EOF on framework fd";
- std::lock_guard<std::mutex> lock(mutex_);
- ReplaceFrameworkFd(unique_fd());
- } else {
- std::lock_guard<std::mutex> lock(mutex_);
- HandlePacket(std::string_view(buf, rc));
- }
- }
-
- if (event.events & EPOLLOUT) {
- std::lock_guard<std::mutex> lock(mutex_);
- while (SendPacket()) {
- continue;
- }
- UpdateFrameworkWritable();
- }
-
- break;
- }
- }
- }
- }
- }
-
- static constexpr const char* key_paths[] = {"/adb_keys", "/data/misc/adb/adb_keys"};
- void IteratePublicKeys(bool (*callback)(const char*, size_t, void*), void* arg) {
- for (const auto& path : key_paths) {
- if (access(path, R_OK) == 0) {
- LOG(INFO) << "Loading keys from " << path;
- std::string content;
- if (!android::base::ReadFileToString(path, &content)) {
- PLOG(ERROR) << "Couldn't read " << path;
- continue;
- }
- for (const auto& line : android::base::Split(content, "\n")) {
- if (!callback(line.data(), line.size(), arg)) {
- return;
- }
- }
- }
- }
- }
-
- uint64_t PromptUser(std::string_view public_key, void* arg) EXCLUDES(mutex_) {
- uint64_t id = NextId();
-
- std::lock_guard<std::mutex> lock(mutex_);
- pending_prompts_.emplace_back(id, public_key, arg);
- DispatchPendingPrompt();
- return id;
- }
-
- uint64_t NotifyAuthenticated(std::string_view public_key) EXCLUDES(mutex_) {
- uint64_t id = NextId();
- std::lock_guard<std::mutex> lock(mutex_);
- keys_.emplace(id, public_key);
- output_queue_.emplace_back(
- AdbdAuthPacketDisconnected{.public_key = std::string(public_key)});
- return id;
- }
-
- void NotifyDisconnected(uint64_t id) EXCLUDES(mutex_) {
- std::lock_guard<std::mutex> lock(mutex_);
- auto it = keys_.find(id);
- if (it == keys_.end()) {
- LOG(DEBUG) << "couldn't find public key to notify disconnection, skipping";
- return;
- }
- output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)});
- keys_.erase(it);
- }
-
- // Interrupt the worker thread to do some work.
- void Interrupt() {
- uint64_t value = 1;
- ssize_t rc = write(event_fd_.get(), &value, sizeof(value));
- if (rc == -1) {
- PLOG(FATAL) << "write to eventfd failed";
- } else if (rc != sizeof(value)) {
- LOG(FATAL) << "write to eventfd returned short (" << rc << ")";
- }
- }
-
- unique_fd epoll_fd_;
- unique_fd event_fd_;
- unique_fd sock_fd_;
- unique_fd framework_fd_;
-
- std::atomic<uint64_t> next_id_;
- AdbdAuthCallbacksV1 callbacks_;
-
- std::mutex mutex_;
- std::unordered_map<uint64_t, std::string> keys_ GUARDED_BY(mutex_);
-
- // We keep two separate queues: one to handle backpressure from the socket (output_queue_)
- // and one to make sure we only dispatch one authrequest at a time (pending_prompts_).
- std::deque<AdbdAuthPacket> output_queue_;
-
- std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_);
- std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_);
-};
-
-AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) {
- if (callbacks->version != 1) {
- LOG(ERROR) << "received unknown AdbdAuthCallbacks version " << callbacks->version;
- return nullptr;
- }
-
- return new AdbdAuthContext(&callbacks->callbacks.v1);
-}
-
-void adbd_auth_delete(AdbdAuthContext* ctx) {
- delete ctx;
-}
-
-void adbd_auth_run(AdbdAuthContext* ctx) {
- return ctx->Run();
-}
-
-void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
- bool (*callback)(const char* public_key, size_t len, void* arg),
- void* arg) {
- ctx->IteratePublicKeys(callback, arg);
-}
-
-uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) {
- return ctx->NotifyAuthenticated(std::string_view(public_key, len));
-}
-
-void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id) {
- return ctx->NotifyDisconnected(id);
-}
-
-void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
- void* arg) {
- ctx->PromptUser(std::string_view(public_key, len), arg);
-}
-
-bool adbd_auth_supports_feature(AdbdAuthFeature) {
- return false;
-}
diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h
deleted file mode 100644
index b7c1cb88cc..0000000000
--- a/libs/adbd_auth/include/adbd_auth.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-/*
- * 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 <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-extern "C" {
-
-struct AdbdAuthCallbacksV1 {
- // Callback for a successful user authorization.
- void (*key_authorized)(void* arg, uint64_t id);
-};
-
-struct AdbdAuthCallbacks {
- uint32_t version;
- union {
- AdbdAuthCallbacksV1 v1;
- } callbacks;
-};
-
-struct AdbdAuthContext;
-
-AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks);
-void adbd_auth_delete(AdbdAuthContext* ctx);
-
-void adbd_auth_run(AdbdAuthContext* ctx);
-
-// Iterate through the list of authorized public keys.
-// Return false from the callback to stop iteration.
-void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
- bool (*callback)(const char* public_key, size_t len, void* arg),
- void* arg);
-
-// Let system_server know that a key has been successfully used for authentication.
-uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len);
-
-// Let system_server know that a connection has been closed.
-void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id);
-
-// Prompt the user to authorize a public key.
-// When this happens, a callback will be run on the auth thread with the result.
-void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len, void* arg);
-
-enum AdbdAuthFeature {
-};
-
-bool adbd_auth_supports_feature(AdbdAuthFeature f);
-
-}
diff --git a/libs/adbd_auth/libadbd_auth.map.txt b/libs/adbd_auth/libadbd_auth.map.txt
deleted file mode 100644
index d01233c960..0000000000
--- a/libs/adbd_auth/libadbd_auth.map.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-LIBADBD_AUTH {
- global:
- adbd_auth_new; # apex
- adbd_auth_delete; # apex
- adbd_auth_run; # apex
- adbd_auth_get_public_keys; #apex
- adbd_auth_notify_auth; # apex
- adbd_auth_notify_disconnect; # apex
- adbd_auth_prompt_user; # apex
- adbd_auth_supports_feature; # apex
- local:
- *;
-};
diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
index 09a5f39130..9284acbff3 100644
--- a/libs/android_runtime_lazy/Android.bp
+++ b/libs/android_runtime_lazy/Android.bp
@@ -34,7 +34,6 @@ cc_library {
name: "libandroid_runtime_lazy",
vendor_available: true,
double_loadable: true,
- host_supported: true,
cflags: [
"-Wall",
@@ -52,6 +51,10 @@ cc_library {
"libutils",
],
+ required: [
+ "libandroid_runtime",
+ ],
+
export_include_dirs: [
"include",
],
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 2518b1427d..ad8287c203 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -13,18 +13,13 @@
// limitations under the License.
ndk_headers {
- name: "libarect_headers_for_ndk",
+ name: "libarect_headers",
from: "include/android",
to: "android",
srcs: ["include/android/*.h"],
license: "NOTICE",
}
-cc_library_headers {
- name: "libarect_headers",
- export_include_dirs: ["include"],
-}
-
cc_library_static {
name: "libarect",
host_supported: true,
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 5e4c98fc7a..49a94146db 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -114,4 +114,4 @@ status_t ActivityManager::unlinkToDeath(const sp<IBinder::DeathRecipient>& recip
return INVALID_OPERATION;
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 7ee4882b6a..aedf6b0d18 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -16,8 +16,6 @@ cc_library_headers {
name: "libbinder_headers",
export_include_dirs: ["include"],
vendor_available: true,
- host_supported: true,
-
header_libs: [
"libbase_headers",
"libcutils_headers",
@@ -30,28 +28,7 @@ cc_library_headers {
],
}
-// These interfaces are android-specific implementation unrelated to binder
-// transport itself and should be moved to AIDL or in domain-specific libs.
-//
-// Currently, these are only on system android (not vendor, not host)
-libbinder_device_interface_sources = [
- "ActivityManager.cpp",
- "AppOpsManager.cpp",
- "IActivityManager.cpp",
- "IAppOpsCallback.cpp",
- "IAppOpsService.cpp",
- "IBatteryStats.cpp",
- "IMediaResourceMonitor.cpp",
- "IPermissionController.cpp",
- "IProcessInfoService.cpp",
- "IUidObserver.cpp",
- "PermissionCache.cpp",
- "PermissionController.cpp",
- "ProcessInfoService.cpp",
- "IpPrefix.cpp",
-]
-
-cc_library {
+cc_library_shared {
name: "libbinder",
// for vndbinder
@@ -60,61 +37,65 @@ cc_library {
enabled: true,
},
double_loadable: true,
- host_supported: true,
-
- // TODO(b/31559095): get headers from bionic on host
- include_dirs: [
- "bionic/libc/kernel/android/uapi/",
- "bionic/libc/kernel/uapi/",
- ],
-
- // libbinder does not offer a stable wire protocol.
- // if a second copy of it is installed, then it may break after security
- // or dessert updates. Instead, apex users should use libbinder_ndk.
- apex_available: [
- "//apex_available:platform",
- "com.android.vndk.current",
- // TODO(b/139016109) remove these three
- "com.android.media.swcodec",
- "test_com.android.media.swcodec",
- ],
srcs: [
+ "ActivityManager.cpp",
+ "AppOpsManager.cpp",
"Binder.cpp",
"BpBinder.cpp",
"BufferedTextOutput.cpp",
"Debug.cpp",
+ "IActivityManager.cpp",
+ "IAppOpsCallback.cpp",
+ "IAppOpsService.cpp",
+ "IBatteryStats.cpp",
"IInterface.cpp",
+ "IMediaResourceMonitor.cpp",
"IMemory.cpp",
"IPCThreadState.cpp",
+ "IPermissionController.cpp",
+ "IProcessInfoService.cpp",
"IResultReceiver.cpp",
"IServiceManager.cpp",
"IShellCallback.cpp",
+ "IUidObserver.cpp",
"MemoryBase.cpp",
"MemoryDealer.cpp",
"MemoryHeapBase.cpp",
"Parcel.cpp",
"ParcelFileDescriptor.cpp",
+ "PermissionCache.cpp",
+ "PermissionController.cpp",
"PersistableBundle.cpp",
+ "ProcessInfoService.cpp",
"ProcessState.cpp",
"Static.cpp",
- "Stability.cpp",
"Status.cpp",
"TextOutput.cpp",
+ "IpPrefix.cpp",
+ "Value.cpp",
":libbinder_aidl",
],
target: {
- android: {
- srcs: libbinder_device_interface_sources,
-
- // NOT static to keep the wire protocol unfrozen
- static: {
- enabled: false,
- },
- },
vendor: {
- exclude_srcs: libbinder_device_interface_sources,
+ exclude_srcs: [
+ "ActivityManager.cpp",
+ "AppOpsManager.cpp",
+ "IActivityManager.cpp",
+ "IAppOpsCallback.cpp",
+ "IAppOpsService.cpp",
+ "IBatteryStats.cpp",
+ "IMediaResourceMonitor.cpp",
+ "IPermissionController.cpp",
+ "IProcessInfoService.cpp",
+ "IUidObserver.cpp",
+ "PermissionCache.cpp",
+ "PermissionController.cpp",
+ "ProcessInfoService.cpp",
+ "IpPrefix.cpp",
+ ":libbinder_aidl",
+ ],
},
},
@@ -135,6 +116,7 @@ cc_library {
},
shared_libs: [
+ "libbase",
"liblog",
"libcutils",
"libutils",
@@ -160,21 +142,7 @@ filegroup {
name: "libbinder_aidl",
srcs: [
"aidl/android/content/pm/IPackageManagerNative.aidl",
- "aidl/android/os/IServiceCallback.aidl",
- "aidl/android/os/IServiceManager.aidl",
],
- path: "aidl",
}
-aidl_interface {
- name: "libbinder_aidl_test_stub",
- local_include_dir: "aidl",
- srcs: [":libbinder_aidl"],
- visibility: [":__subpackages__"],
- vendor_available: true,
- backend: {
- java: {
- enabled: false,
- },
- },
-}
+subdirs = ["tests"]
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 0a6685e14a..525685c35e 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -147,4 +147,4 @@ int32_t AppOpsManager::permissionToOpCode(const String16& permission) {
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 2f6e9c3a1b..cb0e08d123 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -81,50 +81,6 @@ status_t IBinder::shellCommand(const sp<IBinder>& target, int in, int out, int e
return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
}
-status_t IBinder::getExtension(sp<IBinder>* out) {
- BBinder* local = this->localBinder();
- if (local != nullptr) {
- *out = local->getExtension();
- return OK;
- }
-
- BpBinder* proxy = this->remoteBinder();
- LOG_ALWAYS_FATAL_IF(proxy == nullptr);
-
- Parcel data;
- Parcel reply;
- status_t status = transact(EXTENSION_TRANSACTION, data, &reply);
- if (status != OK) return status;
-
- return reply.readNullableStrongBinder(out);
-}
-
-status_t IBinder::getDebugPid(pid_t* out) {
- BBinder* local = this->localBinder();
- if (local != nullptr) {
- *out = local->getDebugPid();
- return OK;
- }
-
- BpBinder* proxy = this->remoteBinder();
- LOG_ALWAYS_FATAL_IF(proxy == nullptr);
-
- Parcel data;
- Parcel reply;
- status_t status = transact(DEBUG_PID_TRANSACTION, data, &reply);
- if (status != OK) return status;
-
- int32_t pid;
- status = reply.readInt32(&pid);
- if (status != OK) return status;
-
- if (pid < 0 || pid > std::numeric_limits<pid_t>::max()) {
- return BAD_VALUE;
- }
- *out = pid;
- return OK;
-}
-
// ---------------------------------------------------------------------------
class BBinder::Extras
@@ -132,7 +88,6 @@ class BBinder::Extras
public:
// unlocked objects
bool mRequestingSid = false;
- sp<IBinder> mExtension;
// for below objects
Mutex mLock;
@@ -173,20 +128,13 @@ status_t BBinder::transact(
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
- err = pingBinder();
- break;
- case EXTENSION_TRANSACTION:
- err = reply->writeStrongBinder(getExtension());
- break;
- case DEBUG_PID_TRANSACTION:
- err = reply->writeInt32(getDebugPid());
+ reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
- // In case this is being transacted on in the same process.
if (reply != nullptr) {
reply->setDataPosition(0);
}
@@ -273,21 +221,6 @@ void BBinder::setRequestingSid(bool requestingSid)
e->mRequestingSid = requestingSid;
}
-sp<IBinder> BBinder::getExtension() {
- Extras* e = mExtras.load(std::memory_order_acquire);
- if (e == nullptr) return nullptr;
- return e->mExtension;
-}
-
-pid_t BBinder::getDebugPid() {
- return getpid();
-}
-
-void BBinder::setExtension(const sp<IBinder>& extension) {
- Extras* e = getOrCreateExtras();
- e->mExtension = extension;
-}
-
BBinder::~BBinder()
{
Extras* e = mExtras.load(std::memory_order_relaxed);
@@ -419,4 +352,4 @@ bool BpRefBase::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 238c9dcc7f..ec170f7a65 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -21,7 +21,6 @@
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
-#include <binder/Stability.h>
#include <cutils/compiler.h>
#include <utils/Log.h>
@@ -149,10 +148,6 @@ BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
IPCThreadState::self()->incWeakHandle(handle, this);
}
-int32_t BpBinder::handle() const {
- return mHandle;
-}
-
bool BpBinder::isDescriptorCached() const {
Mutex::Autolock _l(mLock);
return mDescriptorCache.size() ? true : false;
@@ -191,7 +186,10 @@ status_t BpBinder::pingBinder()
{
Parcel send;
Parcel reply;
- return transact(PING_TRANSACTION, send, &reply);
+ status_t err = transact(PING_TRANSACTION, send, &reply);
+ if (err != NO_ERROR) return err;
+ if (reply.dataSize() < sizeof(status_t)) return NOT_ENOUGH_DATA;
+ return (status_t)reply.readInt32();
}
status_t BpBinder::dump(int fd, const Vector<String16>& args)
@@ -214,29 +212,9 @@ status_t BpBinder::transact(
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
- bool privateVendor = flags & FLAG_PRIVATE_VENDOR;
- // don't send userspace flags to the kernel
- flags = flags & ~FLAG_PRIVATE_VENDOR;
-
- // user transactions require a given stability level
- if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
- using android::internal::Stability;
-
- auto stability = Stability::get(this);
- auto required = privateVendor ? Stability::VENDOR : Stability::kLocalStability;
-
- if (CC_UNLIKELY(!Stability::check(stability, required))) {
- ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
- Stability::stabilityString(stability).c_str(),
- Stability::stabilityString(required).c_str());
- return BAD_TYPE;
- }
- }
-
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
-
return status;
}
@@ -409,6 +387,21 @@ BpBinder::~BpBinder()
}
}
+ mLock.lock();
+ Vector<Obituary>* obits = mObituaries;
+ if(obits != nullptr) {
+ if (ipc) ipc->clearDeathNotification(mHandle, this);
+ mObituaries = nullptr;
+ }
+ mLock.unlock();
+
+ if (obits != nullptr) {
+ // XXX Should we tell any remaining DeathRecipient
+ // objects that the last strong ref has gone away, so they
+ // are no longer linked?
+ delete obits;
+ }
+
if (ipc) {
ipc->expungeHandle(mHandle, this);
ipc->decWeakHandle(mHandle);
@@ -430,25 +423,6 @@ void BpBinder::onLastStrongRef(const void* /*id*/)
}
IPCThreadState* ipc = IPCThreadState::self();
if (ipc) ipc->decStrongHandle(mHandle);
-
- mLock.lock();
- Vector<Obituary>* obits = mObituaries;
- if(obits != nullptr) {
- if (!obits->isEmpty()) {
- ALOGI("onLastStrongRef automatically unlinking death recipients");
- }
-
- if (ipc) ipc->clearDeathNotification(mHandle, this);
- mObituaries = nullptr;
- }
- mLock.unlock();
-
- if (obits != nullptr) {
- // XXX Should we tell any remaining DeathRecipient
- // objects that the last strong ref has gone away, so they
- // are no longer linked?
- delete obits;
- }
}
bool BpBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
@@ -496,4 +470,4 @@ void BpBinder::setBinderProxyCountWatermarks(int high, int low) {
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index fb424fdcfb..2978b539d7 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -23,12 +23,12 @@
#include <utils/RefBase.h>
#include <utils/Vector.h>
+#include <private/binder/Static.h>
+
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
-#include "Static.h"
-
// ---------------------------------------------------------------------------
namespace android {
@@ -49,9 +49,10 @@ struct BufferedTextOutput::BufferState : public RefBase
}
status_t append(const char* txt, size_t len) {
+ if (len > SIZE_MAX - bufferPos) return NO_MEMORY; // overflow
if ((len+bufferPos) > bufferSize) {
+ if ((len + bufferPos) > SIZE_MAX / 3) return NO_MEMORY; // overflow
size_t newSize = ((len+bufferPos)*3)/2;
- if (newSize < (len+bufferPos)) return NO_MEMORY; // overflow
void* b = realloc(buffer, newSize);
if (!b) return NO_MEMORY;
buffer = (char*)b;
@@ -280,4 +281,4 @@ BufferedTextOutput::BufferState* BufferedTextOutput::getBuffer() const
return mGlobalState;
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index 64c1ff68c0..a1c2a8be08 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -308,5 +308,5 @@ ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf) {
return proc->getKernelReferences(count, buf);
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 1eb5363ae2..377f604d44 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -110,4 +110,4 @@ public:
IMPLEMENT_META_INTERFACE(ActivityManager, "android.app.IActivityManager");
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
index 0ce1dd59cf..aba49673b1 100644
--- a/libs/binder/IAppOpsCallback.cpp
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -22,6 +22,8 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
+#include <private/binder/Static.h>
+
namespace android {
// ----------------------------------------------------------------------
@@ -66,4 +68,4 @@ status_t BnAppOpsCallback::onTransact(
}
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index b2bd9e50b0..66d6e31902 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -22,6 +22,8 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
+#include <private/binder/Static.h>
+
namespace android {
// ----------------------------------------------------------------------
@@ -239,4 +241,4 @@ status_t BnAppOpsService::onTransact(
}
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index a47dbaccfe..b307e3e7b5 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -20,6 +20,8 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
+#include <private/binder/Static.h>
+
namespace android {
// ----------------------------------------------------------------------
@@ -240,4 +242,4 @@ status_t BnBatteryStats::onTransact(
}
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index b19004d454..59d51ed94a 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -46,4 +46,4 @@ sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
index 4198e49259..77e3d239bc 100644
--- a/libs/binder/IMediaResourceMonitor.cpp
+++ b/libs/binder/IMediaResourceMonitor.cpp
@@ -59,4 +59,4 @@ status_t BnMediaResourceMonitor::onTransact( uint32_t code, const Parcel& data,
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 222b32c921..caf2318281 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -149,10 +149,6 @@ void* IMemory::fastPointer(const sp<IBinder>& binder, ssize_t offset) const
return static_cast<char*>(base) + offset;
}
-void* IMemory::unsecurePointer() const {
- return pointer();
-}
-
void* IMemory::pointer() const {
ssize_t offset;
sp<IMemoryHeap> heap = getMemory(&offset);
@@ -514,4 +510,4 @@ void HeapCache::dump_heaps()
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 4981d7a111..9a561cba64 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -31,8 +31,8 @@
#include <utils/threads.h>
#include <private/binder/binder_module.h>
+#include <private/binder/Static.h>
-#include <atomic>
#include <errno.h>
#include <inttypes.h>
#include <pthread.h>
@@ -43,8 +43,6 @@
#include <sys/resource.h>
#include <unistd.h>
-#include "Static.h"
-
#if LOG_NDEBUG
#define IF_LOG_TRANSACTIONS() if (false)
@@ -118,7 +116,7 @@ static const int64_t kWorkSourcePropagatedBitIndex = 32;
static const char* getReturnString(uint32_t cmd)
{
- size_t idx = cmd & _IOC_NRMASK;
+ size_t idx = cmd & 0xff;
if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[0]))
return kReturnStrings[idx];
else
@@ -280,14 +278,14 @@ static const void* printCommand(TextOutput& out, const void* _cmd)
}
static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
-static std::atomic<bool> gHaveTLS(false);
+static bool gHaveTLS = false;
static pthread_key_t gTLS = 0;
-static std::atomic<bool> gShutdown = false;
-static std::atomic<bool> gDisableBackgroundScheduling = false;
+static bool gShutdown = false;
+static bool gDisableBackgroundScheduling = false;
IPCThreadState* IPCThreadState::self()
{
- if (gHaveTLS.load(std::memory_order_acquire)) {
+ if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
@@ -295,14 +293,13 @@ restart:
return new IPCThreadState;
}
- // Racey, heuristic test for simultaneous shutdown.
- if (gShutdown.load(std::memory_order_relaxed)) {
+ if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return nullptr;
}
pthread_mutex_lock(&gTLSMutex);
- if (!gHaveTLS.load(std::memory_order_relaxed)) {
+ if (!gHaveTLS) {
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
if (key_create_value != 0) {
pthread_mutex_unlock(&gTLSMutex);
@@ -310,7 +307,7 @@ restart:
strerror(key_create_value));
return nullptr;
}
- gHaveTLS.store(true, std::memory_order_release);
+ gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
@@ -318,7 +315,7 @@ restart:
IPCThreadState* IPCThreadState::selfOrNull()
{
- if (gHaveTLS.load(std::memory_order_acquire)) {
+ if (gHaveTLS) {
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
return st;
@@ -328,9 +325,9 @@ IPCThreadState* IPCThreadState::selfOrNull()
void IPCThreadState::shutdown()
{
- gShutdown.store(true, std::memory_order_relaxed);
+ gShutdown = true;
- if (gHaveTLS.load(std::memory_order_acquire)) {
+ if (gHaveTLS) {
// XXX Need to wait for all thread pool threads to exit!
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS);
if (st) {
@@ -338,18 +335,18 @@ void IPCThreadState::shutdown()
pthread_setspecific(gTLS, nullptr);
}
pthread_key_delete(gTLS);
- gHaveTLS.store(false, std::memory_order_release);
+ gHaveTLS = false;
}
}
void IPCThreadState::disableBackgroundScheduling(bool disable)
{
- gDisableBackgroundScheduling.store(disable, std::memory_order_relaxed);
+ gDisableBackgroundScheduling = disable;
}
bool IPCThreadState::backgroundSchedulingDisabled()
{
- return gDisableBackgroundScheduling.load(std::memory_order_relaxed);
+ return gDisableBackgroundScheduling;
}
sp<ProcessState> IPCThreadState::process()
@@ -465,7 +462,7 @@ void IPCThreadState::clearCaller()
void IPCThreadState::flushCommands()
{
- if (mProcess->mDriverFD < 0)
+ if (mProcess->mDriverFD <= 0)
return;
talkWithDriver(false);
// The flush could have caused post-write refcount decrements to have
@@ -597,8 +594,9 @@ void IPCThreadState::joinThreadPool(bool isMain)
result = getAndExecuteCommand();
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
- LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
+ ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
mProcess->mDriverFD, result);
+ abort();
}
// Let this thread exit the thread pool if it is no longer
@@ -617,7 +615,7 @@ void IPCThreadState::joinThreadPool(bool isMain)
int IPCThreadState::setupPolling(int* fd)
{
- if (mProcess->mDriverFD < 0) {
+ if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
@@ -676,11 +674,11 @@ status_t IPCThreadState::transact(int32_t handle,
if ((flags & TF_ONE_WAY) == 0) {
if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
- ALOGE("Process making non-oneway call (code: %u) but is restricted.", code);
+ ALOGE("Process making non-oneway call but is restricted.");
CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
ANDROID_LOG_ERROR);
} else /* FATAL_IF_NOT_ONEWAY */ {
- LOG_ALWAYS_FATAL("Process may not make oneway calls (code: %u).", code);
+ LOG_ALWAYS_FATAL("Process may not make oneway calls.");
}
}
@@ -923,7 +921,7 @@ finish:
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
- if (mProcess->mDriverFD < 0) {
+ if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
@@ -981,7 +979,7 @@ status_t IPCThreadState::talkWithDriver(bool doReceive)
#else
err = INVALID_OPERATION;
#endif
- if (mProcess->mDriverFD < 0) {
+ if (mProcess->mDriverFD <= 0) {
err = -EBADF;
}
IF_LOG_COMMANDS() {
@@ -998,7 +996,7 @@ status_t IPCThreadState::talkWithDriver(bool doReceive)
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
- LOG_ALWAYS_FATAL("Driver did not consume write buffer");
+ mOut.remove(0, bwr.write_consumed);
else {
mOut.setDataSize(0);
processPostWriteDerefs();
@@ -1062,7 +1060,7 @@ status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
sp<BBinder> the_context_object;
-void IPCThreadState::setTheContextObject(sp<BBinder> obj)
+void setTheContextObject(sp<BBinder> obj)
{
the_context_object = obj;
}
@@ -1300,7 +1298,7 @@ void IPCThreadState::threadDestructor(void *st)
if (self) {
self->flushCommands();
#if defined(__ANDROID__)
- if (self->mProcess->mDriverFD >= 0) {
+ if (self->mProcess->mDriverFD > 0) {
ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0);
}
#endif
@@ -1325,4 +1323,4 @@ void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data,
state->mOut.writePointer((uintptr_t)data);
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index d9bf3cc7b6..6b99150edf 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -22,6 +22,8 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
+#include <private/binder/Static.h>
+
namespace android {
// ----------------------------------------------------------------------
@@ -172,4 +174,4 @@ status_t BnPermissionController::onTransact(
}
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IProcessInfoService.cpp b/libs/binder/IProcessInfoService.cpp
index a38a27ad39..96e1a8c239 100644
--- a/libs/binder/IProcessInfoService.cpp
+++ b/libs/binder/IProcessInfoService.cpp
@@ -88,4 +88,4 @@ IMPLEMENT_META_INTERFACE(ProcessInfoService, "android.os.IProcessInfoService");
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
index 556288c5dd..159763d5bf 100644
--- a/libs/binder/IResultReceiver.cpp
+++ b/libs/binder/IResultReceiver.cpp
@@ -22,6 +22,8 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
+#include <private/binder/Static.h>
+
namespace android {
// ----------------------------------------------------------------------
@@ -65,4 +67,4 @@ status_t BnResultReceiver::onTransact(
}
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 4f47db199e..4ba6c2a923 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -18,86 +18,31 @@
#include <binder/IServiceManager.h>
-#include <android/os/BnServiceCallback.h>
-#include <android/os/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <binder/Parcel.h>
#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/SystemClock.h>
-
+#include <binder/IPCThreadState.h>
#ifndef __ANDROID_VNDK__
#include <binder/IPermissionController.h>
#endif
-
-#ifdef __ANDROID__
+#include <binder/Parcel.h>
#include <cutils/properties.h>
-#endif
+#include <utils/String8.h>
+#include <utils/SystemClock.h>
-#include "Static.h"
+#include <private/binder/Static.h>
#include <unistd.h>
namespace android {
-using AidlServiceManager = android::os::IServiceManager;
-using android::binder::Status;
-
-// libbinder's IServiceManager.h can't rely on the values generated by AIDL
-// because many places use its headers via include_dirs (meaning, without
-// declaring the dependency in the build system). So, for now, we can just check
-// the values here.
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_CRITICAL == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_HIGH == IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_NORMAL == IServiceManager::DUMP_FLAG_PRIORITY_NORMAL);
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_DEFAULT == IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
-static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_ALL == IServiceManager::DUMP_FLAG_PRIORITY_ALL);
-static_assert(AidlServiceManager::DUMP_FLAG_PROTO == IServiceManager::DUMP_FLAG_PROTO);
-
-const String16& IServiceManager::getInterfaceDescriptor() const {
- return AidlServiceManager::descriptor;
-}
-IServiceManager::IServiceManager() {}
-IServiceManager::~IServiceManager() {}
-
-// From the old libbinder IServiceManager interface to IServiceManager.
-class ServiceManagerShim : public IServiceManager
-{
-public:
- explicit ServiceManagerShim (const sp<AidlServiceManager>& impl);
-
- sp<IBinder> getService(const String16& name) const override;
- sp<IBinder> checkService(const String16& name) const override;
- status_t addService(const String16& name, const sp<IBinder>& service,
- bool allowIsolated, int dumpsysPriority) override;
- Vector<String16> listServices(int dumpsysPriority) override;
- sp<IBinder> waitForService(const String16& name16) override;
- bool isDeclared(const String16& name) override;
-
- // for legacy ABI
- const String16& getInterfaceDescriptor() const override {
- return mTheRealServiceManager->getInterfaceDescriptor();
- }
- IBinder* onAsBinder() override {
- return IInterface::asBinder(mTheRealServiceManager).get();
- }
-private:
- sp<AidlServiceManager> mTheRealServiceManager;
-};
-
sp<IServiceManager> defaultServiceManager()
{
- static Mutex gDefaultServiceManagerLock;
- static sp<IServiceManager> gDefaultServiceManager;
-
if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == nullptr) {
- gDefaultServiceManager = new ServiceManagerShim(
- interface_cast<AidlServiceManager>(
- ProcessState::self()->getContextObject(nullptr)));
+ gDefaultServiceManager = interface_cast<IServiceManager>(
+ ProcessState::self()->getContextObject(nullptr));
if (gDefaultServiceManager == nullptr)
sleep(1);
}
@@ -106,7 +51,7 @@ sp<IServiceManager> defaultServiceManager()
return gDefaultServiceManager;
}
-#if !defined(__ANDROID_VNDK__) && defined(__ANDROID__)
+#ifndef __ANDROID_VNDK__
// IPermissionController is not accessible to vendors
bool checkCallingPermission(const String16& permission)
@@ -129,13 +74,10 @@ bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t
bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
{
- static Mutex gPermissionControllerLock;
- static sp<IPermissionController> gPermissionController;
-
sp<IPermissionController> pc;
- gPermissionControllerLock.lock();
+ gDefaultServiceManagerLock.lock();
pc = gPermissionController;
- gPermissionControllerLock.unlock();
+ gDefaultServiceManagerLock.unlock();
int64_t startTime = 0;
@@ -159,11 +101,11 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
}
// Object is dead!
- gPermissionControllerLock.lock();
+ gDefaultServiceManagerLock.lock();
if (gPermissionController == pc) {
gPermissionController = nullptr;
}
- gPermissionControllerLock.unlock();
+ gDefaultServiceManagerLock.unlock();
}
// Need to retrieve the permission controller.
@@ -179,9 +121,9 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
} else {
pc = interface_cast<IPermissionController>(binder);
// Install the new permission controller, and try again.
- gPermissionControllerLock.lock();
+ gDefaultServiceManagerLock.lock();
gPermissionController = pc;
- gPermissionControllerLock.unlock();
+ gDefaultServiceManagerLock.unlock();
}
}
}
@@ -190,144 +132,84 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
// ----------------------------------------------------------------------
-ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl)
- : mTheRealServiceManager(impl)
-{}
-
-sp<IBinder> ServiceManagerShim::getService(const String16& name) const
+class BpServiceManager : public BpInterface<IServiceManager>
{
- static bool gSystemBootCompleted = false;
-
- sp<IBinder> svc = checkService(name);
- if (svc != nullptr) return svc;
-
- const bool isVendorService =
- strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
- const long timeout = uptimeMillis() + 5000;
- // Vendor code can't access system properties
- if (!gSystemBootCompleted && !isVendorService) {
-#ifdef __ANDROID__
- char bootCompleted[PROPERTY_VALUE_MAX];
- property_get("sys.boot_completed", bootCompleted, "0");
- gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
-#else
- gSystemBootCompleted = true;
-#endif
+public:
+ explicit BpServiceManager(const sp<IBinder>& impl)
+ : BpInterface<IServiceManager>(impl)
+ {
}
- // retry interval in millisecond; note that vendor services stay at 100ms
- const long sleepTime = gSystemBootCompleted ? 1000 : 100;
-
- int n = 0;
- while (uptimeMillis() < timeout) {
- n++;
- ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
- ProcessState::self()->getDriverName().c_str());
- usleep(1000*sleepTime);
+ virtual sp<IBinder> getService(const String16& name) const
+ {
sp<IBinder> svc = checkService(name);
if (svc != nullptr) return svc;
- }
- ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
- return nullptr;
-}
-
-sp<IBinder> ServiceManagerShim::checkService(const String16& name) const
-{
- sp<IBinder> ret;
- if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
- return nullptr;
- }
- return ret;
-}
-
-status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
- bool allowIsolated, int dumpsysPriority)
-{
- Status status = mTheRealServiceManager->addService(
- String8(name).c_str(), service, allowIsolated, dumpsysPriority);
- return status.exceptionCode();
-}
-
-Vector<String16> ServiceManagerShim::listServices(int dumpsysPriority)
-{
- std::vector<std::string> ret;
- if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) {
- return {};
- }
-
- Vector<String16> res;
- res.setCapacity(ret.size());
- for (const std::string& name : ret) {
- res.push(String16(name.c_str()));
- }
- return res;
-}
-sp<IBinder> ServiceManagerShim::waitForService(const String16& name16)
-{
- class Waiter : public android::os::BnServiceCallback {
- Status onRegistration(const std::string& /*name*/,
- const sp<IBinder>& binder) override {
- std::unique_lock<std::mutex> lock(mMutex);
- mBinder = binder;
- lock.unlock();
- mCv.notify_one();
- return Status::ok();
+ const bool isVendorService =
+ strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
+ const long timeout = uptimeMillis() + 5000;
+ if (!gSystemBootCompleted && !isVendorService) {
+ // Vendor code can't access system properties
+ char bootCompleted[PROPERTY_VALUE_MAX];
+ property_get("sys.boot_completed", bootCompleted, "0");
+ gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
}
- public:
- sp<IBinder> mBinder;
- std::mutex mMutex;
- std::condition_variable mCv;
- };
-
- const std::string name = String8(name16).c_str();
-
- sp<IBinder> out;
- if (!mTheRealServiceManager->getService(name, &out).isOk()) {
+ // retry interval in millisecond; note that vendor services stay at 100ms
+ const long sleepTime = gSystemBootCompleted ? 1000 : 100;
+
+ int n = 0;
+ while (uptimeMillis() < timeout) {
+ n++;
+ ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
+ ProcessState::self()->getDriverName().c_str());
+ usleep(1000*sleepTime);
+
+ sp<IBinder> svc = checkService(name);
+ if (svc != nullptr) return svc;
+ }
+ ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
return nullptr;
}
- if(out != nullptr) return out;
- sp<Waiter> waiter = new Waiter;
- if (!mTheRealServiceManager->registerForNotifications(
- name, waiter).isOk()) {
- return nullptr;
+ virtual sp<IBinder> checkService( const String16& name) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
+ data.writeString16(name);
+ remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
+ return reply.readStrongBinder();
}
- while(true) {
- {
- std::unique_lock<std::mutex> lock(waiter->mMutex);
- using std::literals::chrono_literals::operator""s;
- waiter->mCv.wait_for(lock, 1s, [&] {
- return waiter->mBinder != nullptr;
- });
- if (waiter->mBinder != nullptr) return waiter->mBinder;
- }
+ virtual status_t addService(const String16& name, const sp<IBinder>& service,
+ bool allowIsolated, int dumpsysPriority) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
+ data.writeString16(name);
+ data.writeStrongBinder(service);
+ data.writeInt32(allowIsolated ? 1 : 0);
+ data.writeInt32(dumpsysPriority);
+ status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
+ return err == NO_ERROR ? reply.readExceptionCode() : err;
+ }
- // Handle race condition for lazy services. Here is what can happen:
- // - the service dies (not processed by init yet).
- // - sm processes death notification.
- // - sm gets getService and calls init to start service.
- // - init gets the start signal, but the service already appears
- // started, so it does nothing.
- // - init gets death signal, but doesn't know it needs to restart
- // the service
- // - we need to request service again to get it to start
- if (!mTheRealServiceManager->getService(name, &out).isOk()) {
- return nullptr;
+ virtual Vector<String16> listServices(int dumpsysPriority) {
+ Vector<String16> res;
+ int n = 0;
+
+ for (;;) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
+ data.writeInt32(n++);
+ data.writeInt32(dumpsysPriority);
+ status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
+ if (err != NO_ERROR)
+ break;
+ res.add(reply.readString16());
}
- if(out != nullptr) return out;
-
- ALOGW("Waited one second for %s", name.c_str());
+ return res;
}
-}
+};
-bool ServiceManagerShim::isDeclared(const String16& name) {
- bool declared;
- if (!mTheRealServiceManager->isDeclared(String8(name).c_str(), &declared).isOk()) {
- return false;
- }
- return declared;
-}
+IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index a3e2b67bc6..6c697decca 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -25,6 +25,8 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
+#include <private/binder/Static.h>
+
namespace android {
// ----------------------------------------------------------------------
@@ -85,4 +87,4 @@ status_t BnShellCallback::onTransact(
}
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IUidObserver.cpp b/libs/binder/IUidObserver.cpp
index 038e6bf6ea..82f9047595 100644
--- a/libs/binder/IUidObserver.cpp
+++ b/libs/binder/IUidObserver.cpp
@@ -112,4 +112,4 @@ status_t BnUidObserver::onTransact(
}
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp
index 8d622668cc..3a8a63c46e 100644
--- a/libs/binder/IpPrefix.cpp
+++ b/libs/binder/IpPrefix.cpp
@@ -30,6 +30,7 @@ using android::NO_ERROR;
using android::Parcel;
using android::status_t;
using android::UNEXPECTED_NULL;
+using namespace ::android::binder;
namespace android {
diff --git a/libs/binder/MemoryBase.cpp b/libs/binder/MemoryBase.cpp
index 32300dfbb6..033066bea3 100644
--- a/libs/binder/MemoryBase.cpp
+++ b/libs/binder/MemoryBase.cpp
@@ -43,4 +43,4 @@ MemoryBase::~MemoryBase()
}
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index ebf91f925e..eacad3b6b3 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -481,4 +481,4 @@ void SimpleBestFitAllocator::dump_l(String8& result,
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index e4ea60f699..4c300b47c6 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -181,4 +181,4 @@ off_t MemoryHeapBase::getOffset() const {
}
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9be06cdd19..11441eca64 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -35,9 +35,9 @@
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
-#include <binder/Stability.h>
#include <binder/Status.h>
#include <binder/TextOutput.h>
+#include <binder/Value.h>
#include <cutils/ashmem.h>
#include <utils/Debug.h>
@@ -48,7 +48,11 @@
#include <utils/String16.h>
#include <private/binder/binder_module.h>
-#include "Static.h"
+#include <private/binder/Static.h>
+
+#ifndef INT32_MAX
+#define INT32_MAX ((int32_t)(2147483647))
+#endif
#define LOG_REFS(...)
//#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
@@ -63,8 +67,8 @@
#define PAD_SIZE_UNSAFE(s) (((s)+3)&~3)
static size_t pad_size(size_t s) {
- if (s > (std::numeric_limits<size_t>::max() - 3)) {
- LOG_ALWAYS_FATAL("pad size too big %zu", s);
+ if (s > (SIZE_T_MAX - 3)) {
+ abort();
}
return PAD_SIZE_UNSAFE(s);
}
@@ -74,9 +78,6 @@ static size_t pad_size(size_t s) {
namespace android {
-// many things compile this into prebuilts on the stack
-static_assert(sizeof(Parcel) == 60 || sizeof(Parcel) == 120);
-
static pthread_mutex_t gParcelGlobalAllocSizeLock = PTHREAD_MUTEX_INITIALIZER;
static size_t gParcelGlobalAllocSize = 0;
static size_t gParcelGlobalAllocCount = 0;
@@ -92,7 +93,7 @@ enum {
BLOB_ASHMEM_MUTABLE = 2,
};
-static void acquire_object(const sp<ProcessState>& proc,
+void acquire_object(const sp<ProcessState>& proc,
const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
{
switch (obj.hdr.type) {
@@ -102,6 +103,10 @@ static void acquire_object(const sp<ProcessState>& proc,
reinterpret_cast<IBinder*>(obj.cookie)->incStrong(who);
}
return;
+ case BINDER_TYPE_WEAK_BINDER:
+ if (obj.binder)
+ reinterpret_cast<RefBase::weakref_type*>(obj.binder)->incWeak(who);
+ return;
case BINDER_TYPE_HANDLE: {
const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
if (b != nullptr) {
@@ -110,6 +115,11 @@ static void acquire_object(const sp<ProcessState>& proc,
}
return;
}
+ case BINDER_TYPE_WEAK_HANDLE: {
+ const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
+ if (b != nullptr) b.get_refs()->incWeak(who);
+ return;
+ }
case BINDER_TYPE_FD: {
if ((obj.cookie != 0) && (outAshmemSize != nullptr) && ashmem_valid(obj.handle)) {
// If we own an ashmem fd, keep track of how much memory it refers to.
@@ -125,6 +135,12 @@ static void acquire_object(const sp<ProcessState>& proc,
ALOGD("Invalid object type 0x%08x", obj.hdr.type);
}
+void acquire_object(const sp<ProcessState>& proc,
+ const flat_binder_object& obj, const void* who)
+{
+ acquire_object(proc, obj, who, nullptr);
+}
+
static void release_object(const sp<ProcessState>& proc,
const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
{
@@ -135,6 +151,10 @@ static void release_object(const sp<ProcessState>& proc,
reinterpret_cast<IBinder*>(obj.cookie)->decStrong(who);
}
return;
+ case BINDER_TYPE_WEAK_BINDER:
+ if (obj.binder)
+ reinterpret_cast<RefBase::weakref_type*>(obj.binder)->decWeak(who);
+ return;
case BINDER_TYPE_HANDLE: {
const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
if (b != nullptr) {
@@ -143,6 +163,11 @@ static void release_object(const sp<ProcessState>& proc,
}
return;
}
+ case BINDER_TYPE_WEAK_HANDLE: {
+ const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
+ if (b != nullptr) b.get_refs()->decWeak(who);
+ return;
+ }
case BINDER_TYPE_FD: {
if (obj.cookie != 0) { // owned
if ((outAshmemSize != nullptr) && ashmem_valid(obj.handle)) {
@@ -164,31 +189,20 @@ static void release_object(const sp<ProcessState>& proc,
ALOGE("Invalid object type 0x%08x", obj.hdr.type);
}
-status_t Parcel::finishFlattenBinder(
- const sp<IBinder>& binder, const flat_binder_object& flat)
+void release_object(const sp<ProcessState>& proc,
+ const flat_binder_object& obj, const void* who)
{
- status_t status = writeObject(flat, false);
- if (status != OK) return status;
-
- internal::Stability::tryMarkCompilationUnit(binder.get());
- return writeInt32(internal::Stability::get(binder.get()));
+ release_object(proc, obj, who, nullptr);
}
-status_t Parcel::finishUnflattenBinder(
- const sp<IBinder>& binder, sp<IBinder>* out) const
+inline static status_t finish_flatten_binder(
+ const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
- int32_t stability;
- status_t status = readInt32(&stability);
- if (status != OK) return status;
-
- status = internal::Stability::set(binder.get(), stability, true /*log*/);
- if (status != OK) return status;
-
- *out = binder;
- return OK;
+ return out->writeObject(flat, false);
}
-status_t Parcel::flattenBinder(const sp<IBinder>& binder)
+status_t flatten_binder(const sp<ProcessState>& /*proc*/,
+ const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
@@ -226,24 +240,108 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder)
obj.cookie = 0;
}
- return finishFlattenBinder(binder, obj);
+ return finish_flatten_binder(binder, obj, out);
+}
+
+status_t flatten_binder(const sp<ProcessState>& /*proc*/,
+ const wp<IBinder>& binder, Parcel* out)
+{
+ flat_binder_object obj;
+
+ obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ if (binder != nullptr) {
+ sp<IBinder> real = binder.promote();
+ if (real != nullptr) {
+ IBinder *local = real->localBinder();
+ if (!local) {
+ BpBinder *proxy = real->remoteBinder();
+ if (proxy == nullptr) {
+ ALOGE("null proxy");
+ }
+ const int32_t handle = proxy ? proxy->handle() : 0;
+ obj.hdr.type = BINDER_TYPE_WEAK_HANDLE;
+ obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
+ obj.handle = handle;
+ obj.cookie = 0;
+ } else {
+ obj.hdr.type = BINDER_TYPE_WEAK_BINDER;
+ obj.binder = reinterpret_cast<uintptr_t>(binder.get_refs());
+ obj.cookie = reinterpret_cast<uintptr_t>(binder.unsafe_get());
+ }
+ return finish_flatten_binder(real, obj, out);
+ }
+
+ // XXX How to deal? In order to flatten the given binder,
+ // we need to probe it for information, which requires a primary
+ // reference... but we don't have one.
+ //
+ // The OpenBinder implementation uses a dynamic_cast<> here,
+ // but we can't do that with the different reference counting
+ // implementation we are using.
+ ALOGE("Unable to unflatten Binder weak reference!");
+ obj.hdr.type = BINDER_TYPE_BINDER;
+ obj.binder = 0;
+ obj.cookie = 0;
+ return finish_flatten_binder(nullptr, obj, out);
+
+ } else {
+ obj.hdr.type = BINDER_TYPE_BINDER;
+ obj.binder = 0;
+ obj.cookie = 0;
+ return finish_flatten_binder(nullptr, obj, out);
+ }
+}
+
+inline static status_t finish_unflatten_binder(
+ BpBinder* /*proxy*/, const flat_binder_object& /*flat*/,
+ const Parcel& /*in*/)
+{
+ return NO_ERROR;
}
-status_t Parcel::unflattenBinder(sp<IBinder>* out) const
+status_t unflatten_binder(const sp<ProcessState>& proc,
+ const Parcel& in, sp<IBinder>* out)
{
- const flat_binder_object* flat = readObject(false);
+ const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->hdr.type) {
- case BINDER_TYPE_BINDER: {
- sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
- return finishUnflattenBinder(binder, out);
- }
- case BINDER_TYPE_HANDLE: {
- sp<IBinder> binder =
- ProcessState::self()->getStrongProxyForHandle(flat->handle);
- return finishUnflattenBinder(binder, out);
- }
+ case BINDER_TYPE_BINDER:
+ *out = reinterpret_cast<IBinder*>(flat->cookie);
+ return finish_unflatten_binder(nullptr, *flat, in);
+ case BINDER_TYPE_HANDLE:
+ *out = proc->getStrongProxyForHandle(flat->handle);
+ return finish_unflatten_binder(
+ static_cast<BpBinder*>(out->get()), *flat, in);
+ }
+ }
+ return BAD_TYPE;
+}
+
+status_t unflatten_binder(const sp<ProcessState>& proc,
+ const Parcel& in, wp<IBinder>* out)
+{
+ const flat_binder_object* flat = in.readObject(false);
+
+ if (flat) {
+ switch (flat->hdr.type) {
+ case BINDER_TYPE_BINDER:
+ *out = reinterpret_cast<IBinder*>(flat->cookie);
+ return finish_unflatten_binder(nullptr, *flat, in);
+ case BINDER_TYPE_WEAK_BINDER:
+ if (flat->binder != 0) {
+ out->set_object_and_refs(
+ reinterpret_cast<IBinder*>(flat->cookie),
+ reinterpret_cast<RefBase::weakref_type*>(flat->binder));
+ } else {
+ *out = nullptr;
+ }
+ return finish_unflatten_binder(nullptr, *flat, in);
+ case BINDER_TYPE_HANDLE:
+ case BINDER_TYPE_WEAK_HANDLE:
+ *out = proc->getWeakProxyForHandle(flat->handle);
+ return finish_unflatten_binder(
+ static_cast<BpBinder*>(out->unsafe_get()), *flat, in);
}
}
return BAD_TYPE;
@@ -291,7 +389,7 @@ size_t Parcel::dataAvail() const
{
size_t result = dataSize() - dataPosition();
if (result > INT32_MAX) {
- LOG_ALWAYS_FATAL("result too big: %zu", result);
+ abort();
}
return result;
}
@@ -328,7 +426,7 @@ void Parcel::setDataPosition(size_t pos) const
if (pos > INT32_MAX) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
- LOG_ALWAYS_FATAL("pos too big: %zu", pos);
+ abort();
}
mDataPos = pos;
@@ -422,8 +520,10 @@ status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
const sp<ProcessState> proc(ProcessState::self());
// grow objects
if (mObjectsCapacity < mObjectsSize + numObjects) {
+ if ((size_t) numObjects > SIZE_MAX - mObjectsSize) return NO_MEMORY; // overflow
+ if (mObjectsSize + numObjects > SIZE_MAX / 3) return NO_MEMORY; // overflow
size_t newSize = ((mObjectsSize + numObjects)*3)/2;
- if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY; // overflow
+ if (newSize > SIZE_MAX / sizeof(binder_size_t)) return NO_MEMORY; // overflow
binder_size_t *objects =
(binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
if (objects == (binder_size_t*)nullptr) {
@@ -505,12 +605,6 @@ void Parcel::updateWorkSourceRequestHeaderPosition() const {
}
}
-#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
-constexpr int32_t kHeader = B_PACK_CHARS('V', 'N', 'D', 'R');
-#else
-constexpr int32_t kHeader = B_PACK_CHARS('S', 'Y', 'S', 'T');
-#endif
-
// Write RPC headers. (previously just the interface token)
status_t Parcel::writeInterfaceToken(const String16& interface)
{
@@ -519,7 +613,6 @@ status_t Parcel::writeInterfaceToken(const String16& interface)
updateWorkSourceRequestHeaderPosition();
writeInt32(threadState->shouldPropagateWorkSource() ?
threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource);
- writeInt32(kHeader);
// currently the interface identification token is just its name as a string
return writeString16(interface);
}
@@ -537,7 +630,7 @@ bool Parcel::replaceCallingWorkSourceUid(uid_t uid)
return err == NO_ERROR;
}
-uid_t Parcel::readCallingWorkSourceUid() const
+uid_t Parcel::readCallingWorkSourceUid()
{
if (!mRequestHeaderPresent) {
return IPCThreadState::kUnsetWorkSource;
@@ -577,12 +670,6 @@ bool Parcel::enforceInterface(const String16& interface,
updateWorkSourceRequestHeaderPosition();
int32_t workSource = readInt32();
threadState->setCallingWorkSourceUidWithoutPropagation(workSource);
- // vendor header
- int32_t header = readInt32();
- if (header != kHeader) {
- ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, header);
- return false;
- }
// Interface descriptor.
const String16 str(readString16());
if (str == interface) {
@@ -594,6 +681,11 @@ bool Parcel::enforceInterface(const String16& interface,
}
}
+const binder_size_t* Parcel::objects() const
+{
+ return mObjects;
+}
+
size_t Parcel::objectsCount() const
{
return mObjectsSize;
@@ -746,37 +838,61 @@ status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) {
return writeUtf8AsUtf16(*str);
}
-status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) {
- if (size > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
+namespace {
+
+template<typename T>
+status_t writeByteVectorInternal(Parcel* parcel, const std::vector<T>& val)
+{
+ status_t status;
+ if (val.size() > std::numeric_limits<int32_t>::max()) {
+ status = BAD_VALUE;
+ return status;
}
- status_t status = writeInt32(size);
+ status = parcel->writeInt32(val.size());
if (status != OK) {
return status;
}
- return write(data, size);
+ void* data = parcel->writeInplace(val.size());
+ if (!data) {
+ status = BAD_VALUE;
+ return status;
+ }
+
+ memcpy(data, val.data(), val.size());
+ return status;
+}
+
+template<typename T>
+status_t writeByteVectorInternalPtr(Parcel* parcel,
+ const std::unique_ptr<std::vector<T>>& val)
+{
+ if (!val) {
+ return parcel->writeInt32(-1);
+ }
+
+ return writeByteVectorInternal(parcel, *val);
}
+} // namespace
+
status_t Parcel::writeByteVector(const std::vector<int8_t>& val) {
- return writeByteVectorInternal(val.data(), val.size());
+ return writeByteVectorInternal(this, val);
}
status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
{
- if (!val) return writeInt32(-1);
- return writeByteVectorInternal(val->data(), val->size());
+ return writeByteVectorInternalPtr(this, val);
}
status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) {
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
+ return writeByteVectorInternal(this, val);
}
status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
{
- if (!val) return writeInt32(-1);
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
+ return writeByteVectorInternalPtr(this, val);
}
status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
@@ -1019,7 +1135,7 @@ status_t Parcel::writeString16(const char16_t* str, size_t len)
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
- return flattenBinder(val);
+ return flatten_binder(ProcessState::self(), val, this);
}
status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val)
@@ -1040,6 +1156,11 @@ status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const {
return readTypedVector(val, &Parcel::readStrongBinder);
}
+status_t Parcel::writeWeakBinder(const wp<IBinder>& val)
+{
+ return flatten_binder(ProcessState::self(), val, this);
+}
+
status_t Parcel::writeRawNullableParcelable(const Parcelable* parcelable) {
if (!parcelable) {
return writeInt32(0);
@@ -1056,6 +1177,10 @@ status_t Parcel::writeParcelable(const Parcelable& parcelable) {
return parcelable.writeToParcel(this);
}
+status_t Parcel::writeValue(const binder::Value& value) {
+ return value.writeToParcel(this);
+}
+
status_t Parcel::writeNativeHandle(const native_handle* handle)
{
if (!handle || handle->version != sizeof(native_handle))
@@ -1276,8 +1401,10 @@ restart_write:
if (err != NO_ERROR) return err;
}
if (!enoughObjects) {
+ if (mObjectsSize > SIZE_MAX - 2) return NO_MEMORY; // overflow
+ if ((mObjectsSize + 2) > SIZE_MAX / 3) return NO_MEMORY; // overflow
size_t newSize = ((mObjectsSize+2)*3)/2;
- if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY; // overflow
+ if (newSize > SIZE_MAX / sizeof(binder_size_t)) return NO_MEMORY; // overflow
binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
if (objects == nullptr) return NO_MEMORY;
mObjects = objects;
@@ -1293,6 +1420,125 @@ status_t Parcel::writeNoException()
return status.writeToParcel(this);
}
+status_t Parcel::writeMap(const ::android::binder::Map& map_in)
+{
+ using ::std::map;
+ using ::android::binder::Value;
+ using ::android::binder::Map;
+
+ Map::const_iterator iter;
+ status_t ret;
+
+ ret = writeInt32(map_in.size());
+
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ for (iter = map_in.begin(); iter != map_in.end(); ++iter) {
+ ret = writeValue(Value(iter->first));
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ ret = writeValue(iter->second);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+status_t Parcel::writeNullableMap(const std::unique_ptr<binder::Map>& map)
+{
+ if (map == nullptr) {
+ return writeInt32(-1);
+ }
+
+ return writeMap(*map.get());
+}
+
+status_t Parcel::readMap(::android::binder::Map* map_out)const
+{
+ using ::std::map;
+ using ::android::String16;
+ using ::android::String8;
+ using ::android::binder::Value;
+ using ::android::binder::Map;
+
+ status_t ret = NO_ERROR;
+ int32_t count;
+
+ ret = readInt32(&count);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ if (count < 0) {
+ ALOGE("readMap: Unexpected count: %d", count);
+ return (count == -1)
+ ? UNEXPECTED_NULL
+ : BAD_VALUE;
+ }
+
+ map_out->clear();
+
+ while (count--) {
+ Map::key_type key;
+ Value value;
+
+ ret = readValue(&value);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ if (!value.getString(&key)) {
+ ALOGE("readMap: Key type not a string (parcelType = %d)", value.parcelType());
+ return BAD_VALUE;
+ }
+
+ ret = readValue(&value);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ (*map_out)[key] = value;
+ }
+
+ return ret;
+}
+
+status_t Parcel::readNullableMap(std::unique_ptr<binder::Map>* map) const
+{
+ const size_t start = dataPosition();
+ int32_t count;
+ status_t status = readInt32(&count);
+ map->reset();
+
+ if (status != OK || count == -1) {
+ return status;
+ }
+
+ setDataPosition(start);
+ map->reset(new binder::Map());
+
+ status = readMap(map->get());
+
+ if (status != OK) {
+ map->reset();
+ }
+
+ return status;
+}
+
+
+
+void Parcel::remove(size_t /*start*/, size_t /*amt*/)
+{
+ LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!");
+}
+
status_t Parcel::validateReadData(size_t upperBound) const
{
// Don't allow non-object reads on object data
@@ -1449,38 +1695,81 @@ restart_write:
return err;
}
+namespace {
+
+template<typename T>
+status_t readByteVectorInternal(const Parcel* parcel,
+ std::vector<T>* val) {
+ val->clear();
+
+ int32_t size;
+ status_t status = parcel->readInt32(&size);
+
+ if (status != OK) {
+ return status;
+ }
+
+ if (size < 0) {
+ status = UNEXPECTED_NULL;
+ return status;
+ }
+ if (size_t(size) > parcel->dataAvail()) {
+ status = BAD_VALUE;
+ return status;
+ }
+
+ T* data = const_cast<T*>(reinterpret_cast<const T*>(parcel->readInplace(size)));
+ if (!data) {
+ status = BAD_VALUE;
+ return status;
+ }
+ val->reserve(size);
+ val->insert(val->end(), data, data + size);
+
+ return status;
+}
+
+template<typename T>
+status_t readByteVectorInternalPtr(
+ const Parcel* parcel,
+ std::unique_ptr<std::vector<T>>* val) {
+ const int32_t start = parcel->dataPosition();
+ int32_t size;
+ status_t status = parcel->readInt32(&size);
+ val->reset();
+
+ if (status != OK || size < 0) {
+ return status;
+ }
+
+ parcel->setDataPosition(start);
+ val->reset(new (std::nothrow) std::vector<T>());
+
+ status = readByteVectorInternal(parcel, val->get());
+
+ if (status != OK) {
+ val->reset();
+ }
+
+ return status;
+}
+
+} // namespace
+
status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- return readByteVectorInternal(val, size);
+ return readByteVectorInternal(this, val);
}
status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- return readByteVectorInternal(val, size);
+ return readByteVectorInternal(this, val);
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- if (val->get() == nullptr) {
- // reserveOutVector does not create the out vector if size is < 0.
- // This occurs when writing a null byte vector.
- return OK;
- }
- return readByteVectorInternal(val->get(), size);
+ return readByteVectorInternalPtr(this, val);
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- if (val->get() == nullptr) {
- // reserveOutVector does not create the out vector if size is < 0.
- // This occurs when writing a null byte vector.
- return OK;
- }
- return readByteVectorInternal(val->get(), size);
+ return readByteVectorInternalPtr(this, val);
}
status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
@@ -1922,7 +2211,7 @@ status_t Parcel::readStrongBinder(sp<IBinder>* val) const
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
- return unflattenBinder(val);
+ return unflatten_binder(ProcessState::self(), *this, val);
}
sp<IBinder> Parcel::readStrongBinder() const
@@ -1935,6 +2224,13 @@ sp<IBinder> Parcel::readStrongBinder() const
return val;
}
+wp<IBinder> Parcel::readWeakBinder() const
+{
+ wp<IBinder> val;
+ unflatten_binder(ProcessState::self(), *this, &val);
+ return val;
+}
+
status_t Parcel::readParcelable(Parcelable* parcelable) const {
int32_t have_parcelable = 0;
status_t status = readInt32(&have_parcelable);
@@ -1947,6 +2243,10 @@ status_t Parcel::readParcelable(Parcelable* parcelable) const {
return parcelable->readFromParcel(this);
}
+status_t Parcel::readValue(binder::Value* value) const {
+ return value->readFromParcel(this);
+}
+
int32_t Parcel::readExceptionCode() const
{
binder::Status status;
@@ -2298,7 +2598,7 @@ void Parcel::print(TextOutput& to, uint32_t /*flags*/) const
} else if (dataSize() > 0) {
const uint8_t* DATA = data();
to << indent << HexDump(DATA, dataSize()) << dedent;
- const binder_size_t* OBJS = mObjects;
+ const binder_size_t* OBJS = objects();
const size_t N = objectsCount();
for (size_t i=0; i<N; i++) {
const flat_binder_object* flat
@@ -2389,6 +2689,8 @@ status_t Parcel::growData(size_t len)
return BAD_VALUE;
}
+ if (len > SIZE_MAX - mDataSize) return NO_MEMORY; // overflow
+ if (mDataSize + len > SIZE_MAX / 3) return NO_MEMORY; // overflow
size_t newSize = ((mDataSize+len)*3)/2;
return (newSize <= mDataSize)
? (status_t) NO_MEMORY
@@ -2543,11 +2845,13 @@ status_t Parcel::continueWrite(size_t desired)
if (objectsSize == 0) {
free(mObjects);
mObjects = nullptr;
+ mObjectsCapacity = 0;
} else {
binder_size_t* objects =
(binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
if (objects) {
mObjects = objects;
+ mObjectsCapacity = objectsSize;
}
}
mObjectsSize = objectsSize;
@@ -2706,4 +3010,4 @@ void Parcel::Blob::clear() {
mMutable = false;
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
index 75a6d22969..a4c28ad74e 100644
--- a/libs/binder/PermissionCache.cpp
+++ b/libs/binder/PermissionCache.cpp
@@ -110,4 +110,4 @@ bool PermissionCache::checkPermission(
}
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/PermissionController.cpp b/libs/binder/PermissionController.cpp
index 0c8924503d..34b2ca5170 100644
--- a/libs/binder/PermissionController.cpp
+++ b/libs/binder/PermissionController.cpp
@@ -85,4 +85,4 @@ int PermissionController::getPackageUid(const String16& package, int flags)
return service != nullptr ? service->getPackageUid(package, flags) : -1;
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index 97a6c94635..c0aec0a979 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "PersistableBundle"
#include <binder/PersistableBundle.h>
+#include <private/binder/ParcelValTypes.h>
#include <limits>
@@ -25,8 +26,6 @@
#include <log/log.h>
#include <utils/Errors.h>
-#include "ParcelValTypes.h"
-
using android::BAD_TYPE;
using android::BAD_VALUE;
using android::NO_ERROR;
diff --git a/libs/binder/ProcessInfoService.cpp b/libs/binder/ProcessInfoService.cpp
index 00d6eefabe..5cb2033b07 100644
--- a/libs/binder/ProcessInfoService.cpp
+++ b/libs/binder/ProcessInfoService.cpp
@@ -101,4 +101,4 @@ void ProcessInfoService::updateBinderLocked() {
ANDROID_SINGLETON_STATIC_INSTANCE(ProcessInfoService);
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index ea61dc5aff..63f49ddba7 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -21,14 +21,14 @@
#include <binder/BpBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
-#include <binder/Stability.h>
#include <cutils/atomic.h>
#include <utils/Log.h>
#include <utils/String8.h>
+#include <utils/String8.h>
#include <utils/threads.h>
#include <private/binder/binder_module.h>
-#include "Static.h"
+#include <private/binder/Static.h>
#include <errno.h>
#include <fcntl.h>
@@ -108,15 +108,56 @@ sp<ProcessState> ProcessState::selfOrNull()
return gProcess;
}
+void ProcessState::setContextObject(const sp<IBinder>& object)
+{
+ setContextObject(object, String16("default"));
+}
+
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
- sp<IBinder> context = getStrongProxyForHandle(0);
+ return getStrongProxyForHandle(0);
+}
+
+void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name)
+{
+ AutoMutex _l(mLock);
+ mContexts.add(name, object);
+}
- // The root object is special since we get it directly from the driver, it is never
- // written by Parcell::writeStrongBinder.
- internal::Stability::tryMarkCompilationUnit(context.get());
+sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinder>& caller)
+{
+ mLock.lock();
+ sp<IBinder> object(
+ mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : nullptr);
+ mLock.unlock();
+
+ //printf("Getting context object %s for %p\n", String8(name).string(), caller.get());
+
+ if (object != nullptr) return object;
- return context;
+ // Don't attempt to retrieve contexts if we manage them
+ if (mManagesContexts) {
+ ALOGE("getContextObject(%s) failed, but we manage the contexts!\n",
+ String8(name).string());
+ return nullptr;
+ }
+
+ IPCThreadState* ipc = IPCThreadState::self();
+ {
+ Parcel data, reply;
+ // no interface token on this magic transaction
+ data.writeString16(name);
+ data.writeStrongBinder(caller);
+ status_t result = ipc->transact(0 /*magic*/, 0, data, &reply, 0);
+ if (result == NO_ERROR) {
+ object = reply.readStrongBinder();
+ }
+ }
+
+ ipc->flushCommands();
+
+ if (object != nullptr) setContextObject(object, name);
+ return object;
}
void ProcessState::startThreadPool()
@@ -128,33 +169,41 @@ void ProcessState::startThreadPool()
}
}
+bool ProcessState::isContextManager(void) const
+{
+ return mManagesContexts;
+}
+
bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData)
{
- AutoMutex _l(mLock);
- mBinderContextCheckFunc = checkFunc;
- mBinderContextUserData = userData;
+ if (!mManagesContexts) {
+ AutoMutex _l(mLock);
+ mBinderContextCheckFunc = checkFunc;
+ mBinderContextUserData = userData;
- flat_binder_object obj {
- .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
- };
+ flat_binder_object obj {
+ .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
+ };
- int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
+ status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
- // fallback to original method
- if (result != 0) {
- android_errorWriteLog(0x534e4554, "121035042");
+ // fallback to original method
+ if (result != 0) {
+ android_errorWriteLog(0x534e4554, "121035042");
- int dummy = 0;
- result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
- }
+ int dummy = 0;
+ result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
+ }
- if (result == -1) {
- mBinderContextCheckFunc = nullptr;
- mBinderContextUserData = nullptr;
- ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
+ if (result == 0) {
+ mManagesContexts = true;
+ } else if (result == -1) {
+ mBinderContextCheckFunc = nullptr;
+ mBinderContextUserData = nullptr;
+ ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
+ }
}
-
- return result == 0;
+ return mManagesContexts;
}
// Get references to userspace objects held by the kernel binder driver
@@ -188,33 +237,8 @@ ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf)
return count;
}
-// Queries the driver for the current strong reference count of the node
-// that the handle points to. Can only be used by the servicemanager.
-//
-// Returns -1 in case of failure, otherwise the strong reference count.
-ssize_t ProcessState::getStrongRefCountForNodeByHandle(int32_t handle) {
- binder_node_info_for_ref info;
- memset(&info, 0, sizeof(binder_node_info_for_ref));
-
- info.handle = handle;
-
- status_t result = ioctl(mDriverFD, BINDER_GET_NODE_INFO_FOR_REF, &info);
-
- if (result != OK) {
- static bool logged = false;
- if (!logged) {
- ALOGW("Kernel does not support BINDER_GET_NODE_INFO_FOR_REF.");
- logged = true;
- }
- return -1;
- }
-
- return info.strong_count;
-}
-
void ProcessState::setCallRestriction(CallRestriction restriction) {
- LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull() != nullptr,
- "Call restrictions must be set before the threadpool is started.");
+ LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull(), "Call restrictions must be set before the threadpool is started.");
mCallRestriction = restriction;
}
@@ -242,12 +266,8 @@ sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
if (e != nullptr) {
// We need to create a new BpBinder if there isn't currently one, OR we
- // are unable to acquire a weak reference on this current one. The
- // attemptIncWeak() is safe because we know the BpBinder destructor will always
- // call expungeHandle(), which acquires the same lock we are holding now.
- // We need to do this because there is a race condition between someone
- // releasing a reference on this BpBinder, and a new reference on its handle
- // arriving from the driver.
+ // are unable to acquire a weak reference on this current one. See comment
+ // in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
@@ -293,6 +313,37 @@ sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
return result;
}
+wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle)
+{
+ wp<IBinder> result;
+
+ AutoMutex _l(mLock);
+
+ handle_entry* e = lookupHandleLocked(handle);
+
+ if (e != nullptr) {
+ // We need to create a new BpBinder if there isn't currently one, OR we
+ // are unable to acquire a weak reference on this current one. The
+ // attemptIncWeak() is safe because we know the BpBinder destructor will always
+ // call expungeHandle(), which acquires the same lock we are holding now.
+ // We need to do this because there is a race condition between someone
+ // releasing a reference on this BpBinder, and a new reference on its handle
+ // arriving from the driver.
+ IBinder* b = e->binder;
+ if (b == nullptr || !e->refs->attemptIncWeak(this)) {
+ b = BpBinder::create(handle);
+ result = b;
+ e->binder = b;
+ if (b) e->refs = b->getWeakRefs();
+ } else {
+ result = b;
+ e->refs->decWeak(this);
+ }
+ }
+
+ return result;
+}
+
void ProcessState::expungeHandle(int32_t handle, IBinder* binder)
{
AutoMutex _l(mLock);
@@ -379,6 +430,7 @@ ProcessState::ProcessState(const char *driver)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
+ , mManagesContexts(false)
, mBinderContextCheckFunc(nullptr)
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
@@ -397,7 +449,7 @@ ProcessState::ProcessState(const char *driver)
}
}
- LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened. Terminating.", driver);
+ LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
ProcessState::~ProcessState()
@@ -411,4 +463,4 @@ ProcessState::~ProcessState()
mDriverFD = -1;
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
deleted file mode 100644
index 7ce5e36292..0000000000
--- a/libs/binder/Stability.cpp
+++ /dev/null
@@ -1,124 +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 <binder/Stability.h>
-
-namespace android {
-namespace internal {
-
-void Stability::markCompilationUnit(IBinder* binder) {
- status_t result = set(binder, kLocalStability, true /*log*/);
- LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
-}
-
-void Stability::markVintf(IBinder* binder) {
- status_t result = set(binder, Level::VINTF, true /*log*/);
- LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
-}
-
-void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& binder) {
- ALOGE("%s: stability is %s", tag.c_str(), stabilityString(get(binder.get())).c_str());
-}
-
-void Stability::markVndk(IBinder* binder) {
- status_t result = set(binder, Level::VENDOR, true /*log*/);
- LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
-}
-
-bool Stability::requiresVintfDeclaration(const sp<IBinder>& binder) {
- return check(get(binder.get()), Level::VINTF);
-}
-
-void Stability::tryMarkCompilationUnit(IBinder* binder) {
- (void) set(binder, kLocalStability, false /*log*/);
-}
-
-status_t Stability::set(IBinder* binder, int32_t stability, bool log) {
- Level currentStability = get(binder);
-
- // null binder is always written w/ 'UNDECLARED' stability
- if (binder == nullptr) {
- if (stability == UNDECLARED) {
- return OK;
- } else {
- if (log) {
- ALOGE("Null binder written with stability %s.",
- stabilityString(stability).c_str());
- }
- return BAD_TYPE;
- }
- }
-
- if (!isDeclaredStability(stability)) {
- if (log) {
- ALOGE("Can only set known stability, not %d.", stability);
- }
- return BAD_TYPE;
- }
-
- if (currentStability != Level::UNDECLARED && currentStability != stability) {
- if (log) {
- ALOGE("Interface being set with %s but it is already marked as %s.",
- stabilityString(stability).c_str(), stabilityString(currentStability).c_str());
- }
- return BAD_TYPE;
- }
-
- if (currentStability == stability) return OK;
-
- binder->attachObject(
- reinterpret_cast<void*>(&Stability::get),
- reinterpret_cast<void*>(stability),
- nullptr /*cleanupCookie*/,
- nullptr /*cleanup function*/);
-
- return OK;
-}
-
-Stability::Level Stability::get(IBinder* binder) {
- if (binder == nullptr) return UNDECLARED;
-
- return static_cast<Level>(reinterpret_cast<intptr_t>(
- binder->findObject(reinterpret_cast<void*>(&Stability::get))));
-}
-
-bool Stability::check(int32_t provided, Level required) {
- bool stable = (provided & required) == required;
-
- if (!isDeclaredStability(provided) && provided != UNDECLARED) {
- ALOGE("Unknown stability when checking interface stability %d.", provided);
-
- stable = false;
- }
-
- return stable;
-}
-
-bool Stability::isDeclaredStability(int32_t stability) {
- return stability == VENDOR || stability == SYSTEM || stability == VINTF;
-}
-
-std::string Stability::stabilityString(int32_t stability) {
- switch (stability) {
- case Level::UNDECLARED: return "undeclared stability";
- case Level::VENDOR: return "vendor stability";
- case Level::SYSTEM: return "system stability";
- case Level::VINTF: return "vintf stability";
- }
- return "unknown stability " + std::to_string(stability);
-}
-
-} // namespace internal
-} // namespace stability
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index bd40536884..bd0e6f9a11 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -17,7 +17,7 @@
// All static variables go here, to control initialization and
// destruction order in the library.
-#include "Static.h"
+#include <private/binder/Static.h>
#include <binder/BufferedTextOutput.h>
#include <binder/IPCThreadState.h>
@@ -54,9 +54,7 @@ public:
protected:
virtual status_t writeLines(const struct iovec& vec, size_t N)
{
- ssize_t ret = writev(mFD, &vec, N);
- if (ret == -1) return -errno;
- if (static_cast<size_t>(ret) != N) return UNKNOWN_ERROR;
+ writev(mFD, &vec, N);
return NO_ERROR;
}
@@ -77,4 +75,13 @@ TextOutput& aerr(gStderrTextOutput);
Mutex& gProcessMutex = *new Mutex;
sp<ProcessState> gProcess;
+// ------------ IServiceManager.cpp
+
+Mutex gDefaultServiceManagerLock;
+sp<IServiceManager> gDefaultServiceManager;
+#ifndef __ANDROID_VNDK__
+sp<IPermissionController> gPermissionController;
+#endif
+bool gSystemBootCompleted = false;
+
} // namespace android
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
deleted file mode 100644
index b3afd817c1..0000000000
--- a/libs/binder/TEST_MAPPING
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "presubmit": [
- {
- "name": "binderSafeInterfaceTest"
- },
- {
- "name": "binderVendorDoubleLoadTest"
- },
- {
- "name": "binderDriverInterfaceTest"
- },
- {
- "name": "binderTextOutputTest"
- },
- {
- "name": "binderLibTest"
- },
- {
- "name": "binderStabilityTest"
- },
- {
- "name": "CtsNdkBinderTestCases"
- }
- ]
-}
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index 684a7dcc51..101eba318f 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -69,4 +69,4 @@ TextOutput& operator<<(TextOutput& to, const HexDump& val)
return to;
}
-} // namespace android
+}; // namespace android
diff --git a/libs/binder/Value.cpp b/libs/binder/Value.cpp
new file mode 100644
index 0000000000..19c57ba128
--- /dev/null
+++ b/libs/binder/Value.cpp
@@ -0,0 +1,420 @@
+/*
+ * 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 "Value"
+
+#include <binder/Value.h>
+
+#include <limits>
+
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+#include <binder/Map.h>
+#include <private/binder/ParcelValTypes.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+
+using android::BAD_TYPE;
+using android::BAD_VALUE;
+using android::NO_ERROR;
+using android::UNEXPECTED_NULL;
+using android::Parcel;
+using android::sp;
+using android::status_t;
+using std::map;
+using std::set;
+using std::vector;
+using android::binder::Value;
+using android::IBinder;
+using android::os::PersistableBundle;
+using namespace android::binder;
+
+// ====================================================================
+
+#define RETURN_IF_FAILED(calledOnce) \
+ do { \
+ status_t returnStatus = calledOnce; \
+ if (returnStatus) { \
+ ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
+ return returnStatus; \
+ } \
+ } while(false)
+
+// ====================================================================
+
+/* These `internal_type_ptr()` functions allow this
+ * class to work without C++ RTTI support. This technique
+ * only works properly when called directly from this file,
+ * but that is OK because that is the only place we will
+ * be calling them from. */
+template<class T> const void* internal_type_ptr()
+{
+ static const T *marker;
+ return (void*)&marker;
+}
+
+/* Allows the type to be specified by the argument
+ * instead of inside angle brackets. */
+template<class T> const void* internal_type_ptr(const T&)
+{
+ return internal_type_ptr<T>();
+}
+
+// ====================================================================
+
+namespace android {
+
+namespace binder {
+
+class Value::ContentBase {
+public:
+ virtual ~ContentBase() = default;
+ virtual const void* type_ptr() const = 0;
+ virtual ContentBase * clone() const = 0;
+ virtual bool operator==(const ContentBase& rhs) const = 0;
+
+#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+ virtual const std::type_info &type() const = 0;
+#endif
+
+ template<typename T> bool get(T* out) const;
+};
+
+/* This is the actual class that holds the value. */
+template<typename T> class Value::Content : public Value::ContentBase {
+public:
+ Content() = default;
+ explicit Content(const T & value) : mValue(value) { }
+
+ virtual ~Content() = default;
+
+#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+ virtual const std::type_info &type() const override
+ {
+ return typeid(T);
+ }
+#endif
+
+ virtual const void* type_ptr() const override
+ {
+ return internal_type_ptr<T>();
+ }
+
+ virtual ContentBase * clone() const override
+ {
+ return new Content(mValue);
+ };
+
+ virtual bool operator==(const ContentBase& rhs) const override
+ {
+ if (type_ptr() != rhs.type_ptr()) {
+ return false;
+ }
+ return mValue == static_cast<const Content<T>* >(&rhs)->mValue;
+ }
+
+ T mValue;
+};
+
+template<typename T> bool Value::ContentBase::get(T* out) const
+{
+ if (internal_type_ptr(*out) != type_ptr())
+ {
+ return false;
+ }
+
+ *out = static_cast<const Content<T>*>(this)->mValue;
+
+ return true;
+}
+
+// ====================================================================
+
+Value::Value() : mContent(nullptr)
+{
+}
+
+Value::Value(const Value& value)
+ : mContent(value.mContent ? value.mContent->clone() : nullptr)
+{
+}
+
+Value::~Value()
+{
+ delete mContent;
+}
+
+bool Value::operator==(const Value& rhs) const
+{
+ const Value& lhs(*this);
+
+ if (lhs.empty() && rhs.empty()) {
+ return true;
+ }
+
+ if ( (lhs.mContent == nullptr)
+ || (rhs.mContent == nullptr)
+ ) {
+ return false;
+ }
+
+ return *lhs.mContent == *rhs.mContent;
+}
+
+Value& Value::swap(Value &rhs)
+{
+ std::swap(mContent, rhs.mContent);
+ return *this;
+}
+
+Value& Value::operator=(const Value& rhs)
+{
+ if (this != &rhs) {
+ delete mContent;
+ mContent = rhs.mContent
+ ? rhs.mContent->clone()
+ : nullptr;
+ }
+ return *this;
+}
+
+bool Value::empty() const
+{
+ return mContent == nullptr;
+}
+
+void Value::clear()
+{
+ delete mContent;
+ mContent = nullptr;
+}
+
+int32_t Value::parcelType() const
+{
+ const void* t_info(mContent ? mContent->type_ptr() : nullptr);
+
+ if (t_info == internal_type_ptr<bool>()) return VAL_BOOLEAN;
+ if (t_info == internal_type_ptr<uint8_t>()) return VAL_BYTE;
+ if (t_info == internal_type_ptr<int32_t>()) return VAL_INTEGER;
+ if (t_info == internal_type_ptr<int64_t>()) return VAL_LONG;
+ if (t_info == internal_type_ptr<double>()) return VAL_DOUBLE;
+ if (t_info == internal_type_ptr<String16>()) return VAL_STRING;
+
+ if (t_info == internal_type_ptr<vector<bool>>()) return VAL_BOOLEANARRAY;
+ if (t_info == internal_type_ptr<vector<uint8_t>>()) return VAL_BYTEARRAY;
+ if (t_info == internal_type_ptr<vector<int32_t>>()) return VAL_INTARRAY;
+ if (t_info == internal_type_ptr<vector<int64_t>>()) return VAL_LONGARRAY;
+ if (t_info == internal_type_ptr<vector<double>>()) return VAL_DOUBLEARRAY;
+ if (t_info == internal_type_ptr<vector<String16>>()) return VAL_STRINGARRAY;
+
+ if (t_info == internal_type_ptr<Map>()) return VAL_MAP;
+ if (t_info == internal_type_ptr<PersistableBundle>()) return VAL_PERSISTABLEBUNDLE;
+
+ return VAL_NULL;
+}
+
+#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+const std::type_info& Value::type() const
+{
+ return mContent != nullptr
+ ? mContent->type()
+ : typeid(void);
+}
+#endif // ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+
+#define DEF_TYPE_ACCESSORS(T, TYPENAME) \
+ bool Value::is ## TYPENAME() const \
+ { \
+ return mContent \
+ ? internal_type_ptr<T>() == mContent->type_ptr() \
+ : false; \
+ } \
+ bool Value::get ## TYPENAME(T* out) const \
+ { \
+ return mContent \
+ ? mContent->get(out) \
+ : false; \
+ } \
+ void Value::put ## TYPENAME(const T& in) \
+ { \
+ *this = in; \
+ } \
+ Value& Value::operator=(const T& rhs) \
+ { \
+ delete mContent; \
+ mContent = new Content< T >(rhs); \
+ return *this; \
+ } \
+ Value::Value(const T& value) \
+ : mContent(new Content< T >(value)) \
+ { }
+
+DEF_TYPE_ACCESSORS(bool, Boolean)
+DEF_TYPE_ACCESSORS(int8_t, Byte)
+DEF_TYPE_ACCESSORS(int32_t, Int)
+DEF_TYPE_ACCESSORS(int64_t, Long)
+DEF_TYPE_ACCESSORS(double, Double)
+DEF_TYPE_ACCESSORS(String16, String)
+
+DEF_TYPE_ACCESSORS(std::vector<bool>, BooleanVector)
+DEF_TYPE_ACCESSORS(std::vector<uint8_t>, ByteVector)
+DEF_TYPE_ACCESSORS(std::vector<int32_t>, IntVector)
+DEF_TYPE_ACCESSORS(std::vector<int64_t>, LongVector)
+DEF_TYPE_ACCESSORS(std::vector<double>, DoubleVector)
+DEF_TYPE_ACCESSORS(std::vector<String16>, StringVector)
+
+DEF_TYPE_ACCESSORS(::android::binder::Map, Map)
+DEF_TYPE_ACCESSORS(PersistableBundle, PersistableBundle)
+
+bool Value::getString(String8* out) const
+{
+ String16 val;
+ bool ret = getString(&val);
+ if (ret) {
+ *out = String8(val);
+ }
+ return ret;
+}
+
+bool Value::getString(::std::string* out) const
+{
+ String8 val;
+ bool ret = getString(&val);
+ if (ret) {
+ *out = val.string();
+ }
+ return ret;
+}
+
+status_t Value::writeToParcel(Parcel* parcel) const
+{
+ // This implementation needs to be kept in sync with the writeValue
+ // implementation in frameworks/base/core/java/android/os/Parcel.java
+
+#define BEGIN_HANDLE_WRITE() \
+ do { \
+ const void* t_info(mContent?mContent->type_ptr():nullptr); \
+ if (false) { }
+#define HANDLE_WRITE_TYPE(T, TYPEVAL, TYPEMETHOD) \
+ else if (t_info == internal_type_ptr<T>()) { \
+ RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL)); \
+ RETURN_IF_FAILED(parcel->TYPEMETHOD(static_cast<const Content<T>*>(mContent)->mValue)); \
+ }
+#define HANDLE_WRITE_PARCELABLE(T, TYPEVAL) \
+ else if (t_info == internal_type_ptr<T>()) { \
+ RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL)); \
+ RETURN_IF_FAILED(static_cast<const Content<T>*>(mContent)->mValue.writeToParcel(parcel)); \
+ }
+#define END_HANDLE_WRITE() \
+ else { \
+ ALOGE("writeToParcel: Type not supported"); \
+ return BAD_TYPE; \
+ } \
+ } while (false);
+
+ BEGIN_HANDLE_WRITE()
+
+ HANDLE_WRITE_TYPE(bool, VAL_BOOLEAN, writeBool)
+ HANDLE_WRITE_TYPE(int8_t, VAL_BYTE, writeByte)
+ HANDLE_WRITE_TYPE(int8_t, VAL_BYTE, writeByte)
+ HANDLE_WRITE_TYPE(int32_t, VAL_INTEGER, writeInt32)
+ HANDLE_WRITE_TYPE(int64_t, VAL_LONG, writeInt64)
+ HANDLE_WRITE_TYPE(double, VAL_DOUBLE, writeDouble)
+ HANDLE_WRITE_TYPE(String16, VAL_STRING, writeString16)
+
+ HANDLE_WRITE_TYPE(vector<bool>, VAL_BOOLEANARRAY, writeBoolVector)
+ HANDLE_WRITE_TYPE(vector<uint8_t>, VAL_BYTEARRAY, writeByteVector)
+ HANDLE_WRITE_TYPE(vector<int8_t>, VAL_BYTEARRAY, writeByteVector)
+ HANDLE_WRITE_TYPE(vector<int32_t>, VAL_INTARRAY, writeInt32Vector)
+ HANDLE_WRITE_TYPE(vector<int64_t>, VAL_LONGARRAY, writeInt64Vector)
+ HANDLE_WRITE_TYPE(vector<double>, VAL_DOUBLEARRAY, writeDoubleVector)
+ HANDLE_WRITE_TYPE(vector<String16>, VAL_STRINGARRAY, writeString16Vector)
+
+ HANDLE_WRITE_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
+
+ END_HANDLE_WRITE()
+
+ return NO_ERROR;
+
+#undef BEGIN_HANDLE_WRITE
+#undef HANDLE_WRITE_TYPE
+#undef HANDLE_WRITE_PARCELABLE
+#undef END_HANDLE_WRITE
+}
+
+status_t Value::readFromParcel(const Parcel* parcel)
+{
+ // This implementation needs to be kept in sync with the readValue
+ // implementation in frameworks/base/core/java/android/os/Parcel.javai
+
+#define BEGIN_HANDLE_READ() \
+ switch(value_type) { \
+ default: \
+ ALOGE("readFromParcel: Parcel type %d is not supported", value_type); \
+ return BAD_TYPE;
+#define HANDLE_READ_TYPE(T, TYPEVAL, TYPEMETHOD) \
+ case TYPEVAL: \
+ mContent = new Content<T>(); \
+ RETURN_IF_FAILED(parcel->TYPEMETHOD(&static_cast<Content<T>*>(mContent)->mValue)); \
+ break;
+#define HANDLE_READ_PARCELABLE(T, TYPEVAL) \
+ case TYPEVAL: \
+ mContent = new Content<T>(); \
+ RETURN_IF_FAILED(static_cast<Content<T>*>(mContent)->mValue.readFromParcel(parcel)); \
+ break;
+#define END_HANDLE_READ() \
+ }
+
+ int32_t value_type = VAL_NULL;
+
+ delete mContent;
+ mContent = nullptr;
+
+ RETURN_IF_FAILED(parcel->readInt32(&value_type));
+
+ BEGIN_HANDLE_READ()
+
+ HANDLE_READ_TYPE(bool, VAL_BOOLEAN, readBool)
+ HANDLE_READ_TYPE(int8_t, VAL_BYTE, readByte)
+ HANDLE_READ_TYPE(int32_t, VAL_INTEGER, readInt32)
+ HANDLE_READ_TYPE(int64_t, VAL_LONG, readInt64)
+ HANDLE_READ_TYPE(double, VAL_DOUBLE, readDouble)
+ HANDLE_READ_TYPE(String16, VAL_STRING, readString16)
+
+ HANDLE_READ_TYPE(vector<bool>, VAL_BOOLEANARRAY, readBoolVector)
+ HANDLE_READ_TYPE(vector<uint8_t>, VAL_BYTEARRAY, readByteVector)
+ HANDLE_READ_TYPE(vector<int32_t>, VAL_INTARRAY, readInt32Vector)
+ HANDLE_READ_TYPE(vector<int64_t>, VAL_LONGARRAY, readInt64Vector)
+ HANDLE_READ_TYPE(vector<double>, VAL_DOUBLEARRAY, readDoubleVector)
+ HANDLE_READ_TYPE(vector<String16>, VAL_STRINGARRAY, readString16Vector)
+
+ HANDLE_READ_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
+
+ END_HANDLE_READ()
+
+ return NO_ERROR;
+
+#undef BEGIN_HANDLE_READ
+#undef HANDLE_READ_TYPE
+#undef HANDLE_READ_PARCELABLE
+#undef END_HANDLE_READ
+}
+
+} // namespace binder
+
+} // namespace android
+
+/* vim: set ts=4 sw=4 tw=0 et :*/
diff --git a/libs/binder/aidl/android/os/IServiceCallback.aidl b/libs/binder/aidl/android/os/IServiceCallback.aidl
deleted file mode 100644
index b29dfedf70..0000000000
--- a/libs/binder/aidl/android/os/IServiceCallback.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * @hide
- */
-oneway interface IServiceCallback {
- /**
- * Called when a service is registered.
- *
- * @param name the service name that has been registered with
- * @param binder the binder that is registered
- */
- void onRegistration(@utf8InCpp String name, IBinder binder);
-}
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
deleted file mode 100644
index 8c7ebbaf36..0000000000
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.
- */
-
-package android.os;
-
-import android.os.IServiceCallback;
-
-/**
- * Basic interface for finding and publishing system services.
- *
- * You likely want to use android.os.ServiceManager in Java or
- * android::IServiceManager in C++ in order to use this interface.
- *
- * @hide
- */
-interface IServiceManager {
- /*
- * Must update values in IServiceManager.h
- */
- /* Allows services to dump sections according to priorities. */
- const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
- const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1;
- const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2;
- /**
- * Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the
- * same priority as NORMAL priority but the services are not called with dump priority
- * arguments.
- */
- const int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3;
-
- const int DUMP_FLAG_PRIORITY_ALL = 15;
- // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
- // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
-
- /* Allows services to dump sections in protobuf format. */
- const int DUMP_FLAG_PROTO = 1 << 4;
-
- /**
- * Retrieve an existing service called @a name from the
- * service manager.
- *
- * This is the same as checkService (returns immediately) but
- * exists for legacy purposes.
- *
- * Returns null if the service does not exist.
- */
- @UnsupportedAppUsage
- IBinder getService(@utf8InCpp String name);
-
- /**
- * Retrieve an existing service called @a name from the service
- * manager. Non-blocking. Returns null if the service does not
- * exist.
- */
- @UnsupportedAppUsage
- IBinder checkService(@utf8InCpp String name);
-
- /**
- * Place a new @a service called @a name into the service
- * manager.
- */
- void addService(@utf8InCpp String name, IBinder service,
- boolean allowIsolated, int dumpPriority);
-
- /**
- * Return a list of all currently running services.
- */
- @utf8InCpp String[] listServices(int dumpPriority);
-
- /**
- * Request a callback when a service is registered.
- */
- void registerForNotifications(@utf8InCpp String name, IServiceCallback callback);
-
- /**
- * Unregisters all requests for notifications for a specific callback.
- */
- void unregisterForNotifications(@utf8InCpp String name, IServiceCallback callback);
-
- /**
- * Returns whether a given interface is declared on the device, even if it
- * is not started yet. For instance, this could be a service declared in the VINTF
- * manifest.
- */
- boolean isDeclared(@utf8InCpp String name);
-}
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 9108e31758..5f324c7965 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -89,7 +89,7 @@ private:
};
-} // namespace android
+}; // namespace android
// ---------------------------------------------------------------------------
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index b19cde75b6..17493b4252 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -133,7 +133,7 @@ private:
};
-} // namespace android
+}; // namespace android
// ---------------------------------------------------------------------------
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 3be61f9409..cf3ef84caa 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -38,7 +38,7 @@ public:
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
- uint32_t flags = 0) final;
+ uint32_t flags = 0);
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
@@ -54,9 +54,9 @@ public:
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
- object_cleanup_func func) final;
- virtual void* findObject(const void* objectID) const final;
- virtual void detachObject(const void* objectID) final;
+ object_cleanup_func func);
+ virtual void* findObject(const void* objectID) const;
+ virtual void detachObject(const void* objectID);
virtual BBinder* localBinder();
@@ -64,12 +64,6 @@ public:
// This must be called before the object is sent to another process. Not thread safe.
void setRequestingSid(bool requestSid);
- sp<IBinder> getExtension();
- // This must be called before the object is sent to another process. Not thread safe.
- void setExtension(const sp<IBinder>& extension);
-
- pid_t getDebugPid();
-
protected:
virtual ~BBinder();
@@ -114,7 +108,7 @@ private:
std::atomic<int32_t> mState;
};
-} // namespace android
+}; // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
index c17ae6f5fe..9230e89cdf 100644
--- a/libs/binder/include/binder/BinderService.h
+++ b/libs/binder/include/binder/BinderService.h
@@ -62,6 +62,6 @@ private:
};
-} // namespace android
+}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_BINDER_SERVICE_H
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 7dca733b52..1d4f88113a 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -34,7 +34,7 @@ class BpBinder : public IBinder
public:
static BpBinder* create(int32_t handle);
- int32_t handle() const;
+ inline int32_t handle() const { return mHandle; }
virtual const String16& getInterfaceDescriptor() const;
virtual bool isBinderAlive() const;
@@ -45,7 +45,7 @@ public:
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
- uint32_t flags = 0) final;
+ uint32_t flags = 0);
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
@@ -61,12 +61,13 @@ public:
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
- object_cleanup_func func) final;
- virtual void* findObject(const void* objectID) const final;
- virtual void detachObject(const void* objectID) final;
+ object_cleanup_func func);
+ virtual void* findObject(const void* objectID) const;
+ virtual void detachObject(const void* objectID);
virtual BpBinder* remoteBinder();
+ status_t setConstantData(const void* data, size_t size);
void sendObituary();
static uint32_t getBinderProxyCount(uint32_t uid);
@@ -144,7 +145,7 @@ private:
static bool sBinderProxyThrottleCreate;
};
-} // namespace android
+}; // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/BufferedTextOutput.h b/libs/binder/include/binder/BufferedTextOutput.h
index 1b27bb2249..feae93dea1 100644
--- a/libs/binder/include/binder/BufferedTextOutput.h
+++ b/libs/binder/include/binder/BufferedTextOutput.h
@@ -62,6 +62,6 @@ private:
};
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_BUFFEREDTEXTOUTPUT_H
diff --git a/libs/binder/include/binder/Debug.h b/libs/binder/include/binder/Debug.h
index 324e5c1c81..58e2b32b3a 100644
--- a/libs/binder/include/binder/Debug.h
+++ b/libs/binder/include/binder/Debug.h
@@ -44,6 +44,6 @@ ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
__END_DECLS
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_BINDER_DEBUG_H
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
index e0248f6624..6abc071c45 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -51,7 +51,7 @@ public:
// ------------------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IAppOpsCallback.h b/libs/binder/include/binder/IAppOpsCallback.h
index 76642606fc..b500219e37 100644
--- a/libs/binder/include/binder/IAppOpsCallback.h
+++ b/libs/binder/include/binder/IAppOpsCallback.h
@@ -52,7 +52,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index b74c623e44..3dbd0d9f7a 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -79,7 +79,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IBatteryStats.h b/libs/binder/include/binder/IBatteryStats.h
index b786f89f74..48da865702 100644
--- a/libs/binder/include/binder/IBatteryStats.h
+++ b/libs/binder/include/binder/IBatteryStats.h
@@ -77,7 +77,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 64604b74f0..aa44285b6e 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -22,8 +22,9 @@
#include <utils/String16.h>
#include <utils/Vector.h>
-// linux/binder.h defines this, but we don't want to include it here in order to
-// avoid exporting the kernel headers
+
+// linux/binder.h already defines this, but we can't just include it from there
+// because there are host builds that include this file.
#ifndef B_PACK_CHARS
#define B_PACK_CHARS(c1, c2, c3, c4) \
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
@@ -58,15 +59,9 @@ public:
SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
- EXTENSION_TRANSACTION = B_PACK_CHARS('_', 'E', 'X', 'T'),
- DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
// Corresponds to TF_ONE_WAY -- an asynchronous call.
- FLAG_ONEWAY = 0x00000001,
-
- // Private userspace flag for transaction which is being requested from
- // a vendor context.
- FLAG_PRIVATE_VENDOR = 0x10000000,
+ FLAG_ONEWAY = 0x00000001
};
IBinder();
@@ -91,54 +86,6 @@ public:
Vector<String16>& args, const sp<IShellCallback>& callback,
const sp<IResultReceiver>& resultReceiver);
- /**
- * This allows someone to add their own additions to an interface without
- * having to modify the original interface.
- *
- * For instance, imagine if we have this interface:
- * interface IFoo { void doFoo(); }
- *
- * If an unrelated owner (perhaps in a downstream codebase) wants to make a
- * change to the interface, they have two options:
- *
- * A). Historical option that has proven to be BAD! Only the original
- * author of an interface should change an interface. If someone
- * downstream wants additional functionality, they should not ever
- * change the interface or use this method.
- *
- * BAD TO DO: interface IFoo { BAD TO DO
- * BAD TO DO: void doFoo(); BAD TO DO
- * BAD TO DO: + void doBar(); // adding a method BAD TO DO
- * BAD TO DO: } BAD TO DO
- *
- * B). Option that this method enables!
- * Leave the original interface unchanged (do not change IFoo!).
- * Instead, create a new interface in a downstream package:
- *
- * package com.<name>; // new functionality in a new package
- * interface IBar { void doBar(); }
- *
- * When registering the interface, add:
- * sp<MyFoo> foo = new MyFoo; // class in AOSP codebase
- * sp<MyBar> bar = new MyBar; // custom extension class
- * foo->setExtension(bar); // use method in BBinder
- *
- * Then, clients of IFoo can get this extension:
- * sp<IBinder> binder = ...;
- * sp<IFoo> foo = interface_cast<IFoo>(binder); // handle if null
- * sp<IBinder> barBinder;
- * ... handle error ... = binder->getExtension(&barBinder);
- * sp<IBar> bar = interface_cast<IBar>(barBinder);
- * // if bar is null, then there is no extension or a different
- * // type of extension
- */
- status_t getExtension(sp<IBinder>* out);
-
- /**
- * Dump PID for a binder, for debugging.
- */
- status_t getDebugPid(pid_t* outPid);
-
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t transact( uint32_t code,
const Parcel& data,
@@ -246,7 +193,7 @@ protected:
private:
};
-} // namespace android
+}; // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 28ffa48e32..0d305608ca 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -88,12 +88,8 @@ private: \
public: \
-#define __IINTF_CONCAT(x, y) (x ## y)
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
- const ::android::StaticString16 \
- I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));\
- const ::android::String16 I##INTERFACE::descriptor( \
- I##INTERFACE##_descriptor_static_str16); \
+ const ::android::String16 I##INTERFACE::descriptor(NAME); \
const ::android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
@@ -172,6 +168,6 @@ inline IBinder* BpInterface<INTERFACE>::onAsBinder()
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_IINTERFACE_H
diff --git a/libs/binder/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
index da2b7cf62d..213ee63ea8 100644
--- a/libs/binder/include/binder/IMediaResourceMonitor.h
+++ b/libs/binder/include/binder/IMediaResourceMonitor.h
@@ -52,7 +52,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IMemory.h b/libs/binder/include/binder/IMemory.h
index 98e92c4441..071946f50c 100644
--- a/libs/binder/include/binder/IMemory.h
+++ b/libs/binder/include/binder/IMemory.h
@@ -76,8 +76,6 @@ public:
// NOLINTNEXTLINE(google-default-arguments)
virtual sp<IMemoryHeap> getMemory(ssize_t* offset=nullptr, size_t* size=nullptr) const = 0;
- void* unsecurePointer() const;
-
// helpers
void* fastPointer(const sp<IBinder>& heap, ssize_t offset) const;
void* pointer() const;
@@ -102,6 +100,6 @@ protected:
// ----------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_IMEMORY_H
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index ff9244e08a..614b0b33dd 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -110,8 +110,6 @@ public:
// the maximum number of binder threads threads allowed for this process.
void blockUntilThreadAvailable();
- // Service manager registration
- void setTheContextObject(sp<BBinder> obj);
// Is this thread currently serving a binder call. This method
// returns true if while traversing backwards from the function call
@@ -196,7 +194,7 @@ private:
ProcessState::CallRestriction mCallRestriction;
};
-} // namespace android
+}; // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
index 4b66df8d6e..26a1b23a9a 100644
--- a/libs/binder/include/binder/IPermissionController.h
+++ b/libs/binder/include/binder/IPermissionController.h
@@ -65,7 +65,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IProcessInfoService.h b/libs/binder/include/binder/IProcessInfoService.h
index ca30ad3b95..033c145363 100644
--- a/libs/binder/include/binder/IProcessInfoService.h
+++ b/libs/binder/include/binder/IProcessInfoService.h
@@ -46,7 +46,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/IResultReceiver.h b/libs/binder/include/binder/IResultReceiver.h
index 70e99e7c38..00b3d8954c 100644
--- a/libs/binder/include/binder/IResultReceiver.h
+++ b/libs/binder/include/binder/IResultReceiver.h
@@ -50,7 +50,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_IRESULT_RECEIVER_H
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 2c4326393e..aeea1a2676 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -26,22 +26,12 @@ namespace android {
// ----------------------------------------------------------------------
-/**
- * Service manager for C++ services.
- *
- * IInterface is only for legacy ABI compatibility
- */
class IServiceManager : public IInterface
{
public:
- // for ABI compatibility
- virtual const String16& getInterfaceDescriptor() const;
-
- IServiceManager();
- virtual ~IServiceManager();
-
+ DECLARE_META_INTERFACE(ServiceManager)
/**
- * Must match values in IServiceManager.aidl
+ * Must match values in IServiceManager.java
*/
/* Allows services to dump sections according to priorities. */
static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
@@ -82,59 +72,17 @@ public:
// NOLINTNEXTLINE(google-default-arguments)
virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
- /**
- * Efficiently wait for a service.
- *
- * Returns nullptr only for permission problem or fatal error.
- */
- virtual sp<IBinder> waitForService(const String16& name) = 0;
-
- /**
- * Check if a service is declared (e.g. VINTF manifest).
- *
- * If this returns true, waitForService should always be able to return the
- * service.
- */
- virtual bool isDeclared(const String16& name) = 0;
+ enum {
+ GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ CHECK_SERVICE_TRANSACTION,
+ ADD_SERVICE_TRANSACTION,
+ LIST_SERVICES_TRANSACTION,
+ };
};
sp<IServiceManager> defaultServiceManager();
template<typename INTERFACE>
-sp<INTERFACE> waitForService(const String16& name) {
- const sp<IServiceManager> sm = defaultServiceManager();
- return interface_cast<INTERFACE>(sm->waitForService(name));
-}
-
-template<typename INTERFACE>
-sp<INTERFACE> waitForDeclaredService(const String16& name) {
- const sp<IServiceManager> sm = defaultServiceManager();
- if (!sm->isDeclared(name)) return nullptr;
- return interface_cast<INTERFACE>(sm->waitForService(name));
-}
-
-template <typename INTERFACE>
-sp<INTERFACE> checkDeclaredService(const String16& name) {
- const sp<IServiceManager> sm = defaultServiceManager();
- if (!sm->isDeclared(name)) return nullptr;
- return interface_cast<INTERFACE>(sm->checkService(name));
-}
-
-template<typename INTERFACE>
-sp<INTERFACE> waitForVintfService(
- const String16& instance = String16("default")) {
- return waitForDeclaredService<INTERFACE>(
- INTERFACE::descriptor + String16("/") + instance);
-}
-
-template<typename INTERFACE>
-sp<INTERFACE> checkVintfService(
- const String16& instance = String16("default")) {
- return checkDeclaredService<INTERFACE>(
- INTERFACE::descriptor + String16("/") + instance);
-}
-
-template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
const sp<IServiceManager> sm = defaultServiceManager();
@@ -150,7 +98,7 @@ bool checkCallingPermission(const String16& permission,
int32_t* outPid, int32_t* outUid);
bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
-} // namespace android
+}; // namespace android
#endif // ANDROID_ISERVICE_MANAGER_H
diff --git a/libs/binder/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
index b7ab6eab88..67156787d3 100644
--- a/libs/binder/include/binder/IShellCallback.h
+++ b/libs/binder/include/binder/IShellCallback.h
@@ -51,7 +51,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_ISHELL_CALLBACK_H
diff --git a/libs/binder/include/binder/IUidObserver.h b/libs/binder/include/binder/IUidObserver.h
index 09e50a9de8..a1f530dc71 100644
--- a/libs/binder/include/binder/IUidObserver.h
+++ b/libs/binder/include/binder/IUidObserver.h
@@ -58,7 +58,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/services/inputflinger/dispatcher/InputDispatcherThread.cpp b/libs/binder/include/binder/Map.h
index 18b1b8c10a..96a4f8a2a5 100644
--- a/services/inputflinger/dispatcher/InputDispatcherThread.cpp
+++ b/libs/binder/include/binder/Map.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2005 The Android Open 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,20 +14,26 @@
* limitations under the License.
*/
-#include "InputDispatcherThread.h"
+#ifndef ANDROID_MAP_H
+#define ANDROID_MAP_H
-#include "InputDispatcherInterface.h"
+#include <map>
+#include <string>
+// ---------------------------------------------------------------------------
namespace android {
+namespace binder {
-InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher)
- : Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {}
+class Value;
-InputDispatcherThread::~InputDispatcherThread() {}
-
-bool InputDispatcherThread::threadLoop() {
- mDispatcher->dispatchOnce();
- return true;
-}
+/**
+ * Convenience typedef for ::std::map<::std::string,::android::binder::Value>
+ */
+typedef ::std::map<::std::string, Value> Map;
+} // namespace binder
} // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_MAP_H
diff --git a/libs/binder/include/binder/MemoryBase.h b/libs/binder/include/binder/MemoryBase.h
index 4dd363808c..463e26d977 100644
--- a/libs/binder/include/binder/MemoryBase.h
+++ b/libs/binder/include/binder/MemoryBase.h
@@ -46,6 +46,6 @@ private:
};
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_MEMORY_BASE_H
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index 6c1c4122d8..b483be0fd5 100644
--- a/libs/binder/include/binder/MemoryDealer.h
+++ b/libs/binder/include/binder/MemoryDealer.h
@@ -59,6 +59,6 @@ private:
// ----------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_MEMORY_DEALER_H
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index 3fccddcc59..100d784a83 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -98,6 +98,6 @@ private:
};
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_MEMORY_HEAP_BASE_H
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index d4bb85b102..e5219a5590 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -17,11 +17,11 @@
#ifndef ANDROID_PARCEL_H
#define ANDROID_PARCEL_H
-#include <map> // for legacy reasons
#include <string>
-#include <type_traits>
#include <vector>
+#include <linux/android/binder.h>
+
#include <android-base/unique_fd.h>
#include <cutils/native_handle.h>
#include <utils/Errors.h>
@@ -32,26 +32,23 @@
#include <binder/IInterface.h>
#include <binder/Parcelable.h>
-
-#ifdef BINDER_IPC_32BIT
-typedef unsigned int binder_size_t;
-#else
-typedef unsigned long long binder_size_t;
-#endif
-
+#include <binder/Map.h>
// ---------------------------------------------------------------------------
namespace android {
template <typename T> class Flattenable;
template <typename T> class LightFlattenable;
-struct flat_binder_object;
class IBinder;
class IPCThreadState;
class ProcessState;
class String8;
class TextOutput;
+namespace binder {
+class Value;
+};
+
class Parcel {
friend class IPCThreadState;
public:
@@ -70,7 +67,7 @@ public:
status_t setDataSize(size_t size);
void setDataPosition(size_t pos) const;
status_t setDataCapacity(size_t size);
-
+
status_t setData(const uint8_t* buffer, size_t len);
status_t appendFrom(const Parcel *parcel,
@@ -100,6 +97,10 @@ public:
void freeData();
+private:
+ const binder_size_t* objects() const;
+
+public:
size_t objectsCount() const;
status_t errorCheck() const;
@@ -120,6 +121,7 @@ public:
status_t writeString16(const std::unique_ptr<String16>& str);
status_t writeString16(const char16_t* str, size_t len);
status_t writeStrongBinder(const sp<IBinder>& val);
+ status_t writeWeakBinder(const wp<IBinder>& val);
status_t writeInt32Array(size_t len, const int32_t *val);
status_t writeByteArray(size_t len, const uint8_t *val);
status_t writeBool(bool val);
@@ -158,18 +160,6 @@ public:
status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
- // Write an Enum vector with underlying type int8_t.
- // Does not use padding; each byte is contiguous.
- template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::vector<T>& val);
- template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
- // Write an Enum vector with underlying type != int8_t.
- template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::vector<T>& val);
- template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
-
template<typename T>
status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
template<typename T>
@@ -182,6 +172,8 @@ public:
status_t writeParcelable(const Parcelable& parcelable);
+ status_t writeValue(const binder::Value& value);
+
template<typename T>
status_t write(const Flattenable<T>& val);
@@ -193,6 +185,9 @@ public:
template<typename T>
status_t writeVectorSize(const std::unique_ptr<std::vector<T>>& val);
+ status_t writeMap(const binder::Map& map);
+ status_t writeNullableMap(const std::unique_ptr<binder::Map>& map);
+
// Place a native_handle into the parcel (the native_handle's file-
// descriptors are dup'ed, so it is safe to delete the native_handle
// when this function returns).
@@ -249,6 +244,8 @@ public:
// Currently the native implementation doesn't do any of the StrictMode
// stack gathering and serialization that the Java implementation does.
status_t writeNoException();
+
+ void remove(size_t start, size_t amt);
status_t read(void* outData, size_t len) const;
const void* readInplace(size_t len) const;
@@ -287,19 +284,7 @@ public:
sp<IBinder> readStrongBinder() const;
status_t readStrongBinder(sp<IBinder>* val) const;
status_t readNullableStrongBinder(sp<IBinder>* val) const;
-
-
- // Read an Enum vector with underlying type int8_t.
- // Does not use padding; each byte is contiguous.
- template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::vector<T>* val) const;
- template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
- // Read an Enum vector with underlying type != int8_t.
- template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::vector<T>* val) const;
- template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+ wp<IBinder> readWeakBinder() const;
template<typename T>
status_t readParcelableVector(
@@ -312,6 +297,8 @@ public:
template<typename T>
status_t readParcelable(std::unique_ptr<T>* parcelable) const;
+ status_t readValue(binder::Value* value) const;
+
template<typename T>
status_t readStrongBinder(sp<T>* val) const;
@@ -356,11 +343,9 @@ public:
status_t resizeOutVector(std::vector<T>* val) const;
template<typename T>
status_t resizeOutVector(std::unique_ptr<std::vector<T>>* val) const;
- template<typename T>
- status_t reserveOutVector(std::vector<T>* val, size_t* size) const;
- template<typename T>
- status_t reserveOutVector(std::unique_ptr<std::vector<T>>* val,
- size_t* size) const;
+
+ status_t readMap(binder::Map* map)const;
+ status_t readNullableMap(std::unique_ptr<binder::Map>* map) const;
// Like Parcel.java's readExceptionCode(). Reads the first int32
// off of a Parcel's header, returning 0 or the negative error
@@ -414,7 +399,8 @@ public:
bool replaceCallingWorkSourceUid(uid_t uid);
// Returns the work source provided by the caller. This can only be trusted for trusted calling
// uid.
- uid_t readCallingWorkSourceUid() const;
+ uid_t readCallingWorkSourceUid();
+ void readRequestHeaders() const;
private:
typedef void (*release_func)(Parcel* parcel,
@@ -451,13 +437,7 @@ private:
void scanForFds() const;
status_t validateReadData(size_t len) const;
void updateWorkSourceRequestHeaderPosition() const;
-
- status_t finishFlattenBinder(const sp<IBinder>& binder,
- const flat_binder_object& flat);
- status_t finishUnflattenBinder(const sp<IBinder>& binder, sp<IBinder>* out) const;
- status_t flattenBinder(const sp<IBinder>& binder);
- status_t unflattenBinder(sp<IBinder>* out) const;
-
+
template<class T>
status_t readAligned(T *pArg) const;
@@ -469,20 +449,6 @@ private:
status_t writeRawNullableParcelable(const Parcelable*
parcelable);
- template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
- status_t writeEnum(const T& val);
- template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
- status_t writeEnum(const T& val);
-
- template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
- status_t readEnum(T* pArg) const;
- template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
- status_t readEnum(T* pArg) const;
-
- status_t writeByteVectorInternal(const int8_t* data, size_t size);
- template<typename T>
- status_t readByteVectorInternal(std::vector<T>* val, size_t size) const;
-
template<typename T, typename U>
status_t unsafeReadTypedVector(std::vector<T>* val,
status_t(Parcel::*read_func)(U*) const) const;
@@ -726,42 +692,6 @@ status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const {
}
template<typename T>
-status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const {
- int32_t read_size;
- status_t err = readInt32(&read_size);
- if (err != NO_ERROR) {
- return err;
- }
-
- if (read_size < 0) {
- return UNEXPECTED_NULL;
- }
- *size = static_cast<size_t>(read_size);
- val->reserve(*size);
- return OK;
-}
-
-template<typename T>
-status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val,
- size_t* size) const {
- int32_t read_size;
- status_t err = readInt32(&read_size);
- if (err != NO_ERROR) {
- return err;
- }
-
- if (read_size >= 0) {
- *size = static_cast<size_t>(read_size);
- val->reset(new std::vector<T>());
- (*val)->reserve(*size);
- } else {
- val->reset();
- }
-
- return OK;
-}
-
-template<typename T>
status_t Parcel::readStrongBinder(sp<T>* val) const {
sp<IBinder> tmp;
status_t ret = readStrongBinder(&tmp);
@@ -994,79 +924,6 @@ status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::un
return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
}
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
-status_t Parcel::writeEnum(const T& val) {
- return writeInt32(static_cast<int32_t>(val));
-}
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
-status_t Parcel::writeEnum(const T& val) {
- return writeInt64(static_cast<int64_t>(val));
-}
-
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::vector<T>& val) {
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
- if (!val) return writeInt32(-1);
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::vector<T>& val) {
- return writeTypedVector(val, &Parcel::writeEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
- return writeNullableTypedVector(val, &Parcel::writeEnum);
-}
-
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
-status_t Parcel::readEnum(T* pArg) const {
- return readInt32(reinterpret_cast<int32_t *>(pArg));
-}
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
-status_t Parcel::readEnum(T* pArg) const {
- return readInt64(reinterpret_cast<int64_t *>(pArg));
-}
-
-template<typename T>
-inline status_t Parcel::readByteVectorInternal(std::vector<T>* val, size_t size) const {
- // readByteVectorInternal expects a vector that has been reserved (but not
- // resized) to have the provided size.
- const T* data = reinterpret_cast<const T*>(readInplace(size));
- if (!data) return BAD_VALUE;
- val->clear();
- val->insert(val->begin(), data, data+size);
- return NO_ERROR;
-}
-
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::vector<T>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- return readByteVectorInternal(val, size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- if (val->get() == nullptr) {
- // reserveOutVector does not create the out vector if size is < 0.
- // This occurs when writing a null Enum vector.
- return OK;
- }
- return readByteVectorInternal(val->get(), size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::vector<T>* val) const {
- return readTypedVector(val, &Parcel::readEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
- return readNullableTypedVector(val, &Parcel::readEnum);
-}
-
// ---------------------------------------------------------------------------
inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
@@ -1075,7 +932,24 @@ inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
return to;
}
-} // namespace android
+// ---------------------------------------------------------------------------
+
+// Generic acquire and release of objects.
+void acquire_object(const sp<ProcessState>& proc,
+ const flat_binder_object& obj, const void* who);
+void release_object(const sp<ProcessState>& proc,
+ const flat_binder_object& obj, const void* who);
+
+void flatten_binder(const sp<ProcessState>& proc,
+ const sp<IBinder>& binder, flat_binder_object* out);
+void flatten_binder(const sp<ProcessState>& proc,
+ const wp<IBinder>& binder, flat_binder_object* out);
+status_t unflatten_binder(const sp<ProcessState>& proc,
+ const flat_binder_object& flat, sp<IBinder>* out);
+status_t unflatten_binder(const sp<ProcessState>& proc,
+ const flat_binder_object& flat, wp<IBinder>* out);
+
+}; // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index 4635ad84c6..662e56e864 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -42,24 +42,6 @@ public:
android::status_t writeToParcel(android::Parcel* parcel) const override;
android::status_t readFromParcel(const android::Parcel* parcel) override;
- inline bool operator!=(const ParcelFileDescriptor& rhs) const {
- return mFd != rhs.mFd;
- }
- inline bool operator<(const ParcelFileDescriptor& rhs) const {
- return mFd < rhs.mFd;
- }
- inline bool operator<=(const ParcelFileDescriptor& rhs) const {
- return mFd <= rhs.mFd;
- }
- inline bool operator==(const ParcelFileDescriptor& rhs) const {
- return mFd == rhs.mFd;
- }
- inline bool operator>(const ParcelFileDescriptor& rhs) const {
- return mFd > rhs.mFd;
- }
- inline bool operator>=(const ParcelFileDescriptor& rhs) const {
- return mFd >= rhs.mFd;
- }
private:
android::base::unique_fd mFd;
};
diff --git a/libs/binder/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
index c2582150df..95eabff7ac 100644
--- a/libs/binder/include/binder/PermissionCache.h
+++ b/libs/binder/include/binder/PermissionCache.h
@@ -77,7 +77,7 @@ public:
};
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h
index 4db522ab1f..d81f5142bc 100644
--- a/libs/binder/include/binder/PermissionController.h
+++ b/libs/binder/include/binder/PermissionController.h
@@ -60,7 +60,7 @@ private:
};
-} // namespace android
+}; // namespace android
// ---------------------------------------------------------------------------
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/ProcessInfoService.h b/libs/binder/include/binder/ProcessInfoService.h
index 6bfd1bc17d..a03aae98ee 100644
--- a/libs/binder/include/binder/ProcessInfoService.h
+++ b/libs/binder/include/binder/ProcessInfoService.h
@@ -78,7 +78,7 @@ public:
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#else // __ANDROID_VNDK__
#error "This header is not visible to vendors"
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index e57ff1c260..224cb36807 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -45,19 +45,27 @@ public:
*/
static sp<ProcessState> initWithDriver(const char *driver);
+ void setContextObject(const sp<IBinder>& object);
sp<IBinder> getContextObject(const sp<IBinder>& caller);
+
+ void setContextObject(const sp<IBinder>& object,
+ const String16& name);
+ sp<IBinder> getContextObject(const String16& name,
+ const sp<IBinder>& caller);
void startThreadPool();
typedef bool (*context_check_func)(const String16& name,
const sp<IBinder>& caller,
void* userData);
-
+
+ bool isContextManager(void) const;
bool becomeContextManager(
context_check_func checkFunc,
void* userData);
sp<IBinder> getStrongProxyForHandle(int32_t handle);
+ wp<IBinder> getWeakProxyForHandle(int32_t handle);
void expungeHandle(int32_t handle, IBinder* binder);
void spawnPooledThread(bool isMain);
@@ -69,14 +77,6 @@ public:
ssize_t getKernelReferences(size_t count, uintptr_t* buf);
- // Only usable by the context manager.
- // This refcount includes:
- // 1. Strong references to the node by this and other processes
- // 2. Temporary strong references held by the kernel during a
- // transaction on the node.
- // It does NOT include local strong references to the node
- ssize_t getStrongRefCountForNodeByHandle(int32_t handle);
-
enum class CallRestriction {
// all calls okay
NONE,
@@ -124,9 +124,14 @@ private:
Vector<handle_entry>mHandleToObject;
+ bool mManagesContexts;
context_check_func mBinderContextCheckFunc;
void* mBinderContextUserData;
+ KeyedVector<String16, sp<IBinder> >
+ mContexts;
+
+
String8 mRootDir;
bool mThreadPoolStarted;
volatile int32_t mThreadPoolSeq;
@@ -134,7 +139,7 @@ private:
CallRestriction mCallRestriction;
};
-} // namespace android
+}; // namespace android
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
deleted file mode 100644
index b2f51d381c..0000000000
--- a/libs/binder/include/binder/Stability.h
+++ /dev/null
@@ -1,105 +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 <binder/IBinder.h>
-#include <string>
-
-namespace android {
-
-class BpBinder;
-class ProcessState;
-
-namespace internal {
-
-// WARNING: These APIs are only ever expected to be called by auto-generated code.
-// Instead of calling them, you should set the stability of a .aidl interface
-class Stability final {
-public:
- // WARNING: This is only ever expected to be called by auto-generated code. You likely want to
- // change or modify the stability class of the interface you are using.
- // This must be called as soon as the binder in question is constructed. No thread safety
- // is provided.
- // E.g. stability is according to libbinder compilation unit
- static void markCompilationUnit(IBinder* binder);
- // WARNING: This is only ever expected to be called by auto-generated code. You likely want to
- // change or modify the stability class of the interface you are using.
- // This must be called as soon as the binder in question is constructed. No thread safety
- // is provided.
- // E.g. stability is according to libbinder_ndk or Java SDK AND the interface
- // expressed here is guaranteed to be stable for multiple years (Stable AIDL)
- static void markVintf(IBinder* binder);
-
- // WARNING: for debugging only
- static void debugLogStability(const std::string& tag, const sp<IBinder>& binder);
-
- // WARNING: This is only ever expected to be called by auto-generated code or tests.
- // You likely want to change or modify the stability of the interface you are using.
- // This must be called as soon as the binder in question is constructed. No thread safety
- // is provided.
- // E.g. stability is according to libbinder_ndk or Java SDK AND the interface
- // expressed here is guaranteed to be stable for multiple years (Stable AIDL)
- // If this is called when __ANDROID_VNDK__ is not defined, then it is UB and will likely
- // break the device during GSI or other tests.
- static void markVndk(IBinder* binder);
-
- // Returns true if the binder needs to be declared in the VINTF manifest or
- // else false if the binder is local to the current partition.
- static bool requiresVintfDeclaration(const sp<IBinder>& binder);
-private:
- // Parcel needs to read/write stability level in an unstable format.
- friend ::android::Parcel;
-
- // only expose internal APIs inside of libbinder, for checking stability
- friend ::android::BpBinder;
-
- // so that it can mark the context object (only the root object doesn't go
- // through Parcel)
- friend ::android::ProcessState;
-
- static void tryMarkCompilationUnit(IBinder* binder);
-
- enum Level : int32_t {
- UNDECLARED = 0,
-
- VENDOR = 0b000011,
- SYSTEM = 0b001100,
- VINTF = 0b111111,
- };
-
-#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
- static constexpr Level kLocalStability = Level::VENDOR;
-#else
- static constexpr Level kLocalStability = Level::SYSTEM;
-#endif
-
- // applies stability to binder if stability level is known
- __attribute__((warn_unused_result))
- static status_t set(IBinder* binder, int32_t stability, bool log);
-
- static Level get(IBinder* binder);
-
- static bool check(int32_t provided, Level required);
-
- static bool isDeclaredStability(int32_t stability);
- static std::string stabilityString(int32_t stability);
-
- Stability();
-};
-
-} // namespace internal
-} // namespace android
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index f66406f7d4..5b5f76688b 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -199,6 +199,6 @@ inline size_t HexDump::alignment() const { return mAlignment; }
inline bool HexDump::carrayStyle() const { return mCArrayStyle; }
// ---------------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_TEXTOUTPUT_H
diff --git a/libs/binder/include/binder/Value.h b/libs/binder/include/binder/Value.h
new file mode 100644
index 0000000000..735f40eb1f
--- /dev/null
+++ b/libs/binder/include/binder/Value.h
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_VALUE_H
+#define ANDROID_VALUE_H
+
+#include <stdint.h>
+#include <map>
+#include <set>
+#include <vector>
+#include <string>
+
+#include <binder/Parcelable.h>
+#include <binder/PersistableBundle.h>
+#include <binder/Map.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class Parcel;
+
+namespace binder {
+
+/**
+ * A limited C++ generic type. The purpose of this class is to allow C++
+ * programs to make use of (or implement) Binder interfaces which make use
+ * the Java "Object" generic type (either via the use of the Map type or
+ * some other mechanism).
+ *
+ * This class only supports a limited set of types, but additional types
+ * may be easily added to this class in the future as needed---without
+ * breaking binary compatability.
+ *
+ * This class was written in such a way as to help avoid type errors by
+ * giving each type their own explicity-named accessor methods (rather than
+ * overloaded methods).
+ *
+ * When reading or writing this class to a Parcel, use the `writeValue()`
+ * and `readValue()` methods.
+ */
+class Value {
+public:
+ Value();
+ virtual ~Value();
+
+ Value& swap(Value &);
+
+ bool empty() const;
+
+ void clear();
+
+#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
+ const std::type_info& type() const;
+#endif
+
+ int32_t parcelType() const;
+
+ bool operator==(const Value& rhs) const;
+ bool operator!=(const Value& rhs) const { return !this->operator==(rhs); }
+
+ Value(const Value& value);
+ Value(const bool& value); // NOLINT(google-explicit-constructor)
+ Value(const int8_t& value); // NOLINT(google-explicit-constructor)
+ Value(const int32_t& value); // NOLINT(google-explicit-constructor)
+ Value(const int64_t& value); // NOLINT(google-explicit-constructor)
+ Value(const double& value); // NOLINT(google-explicit-constructor)
+ Value(const String16& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<bool>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<uint8_t>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<int32_t>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<int64_t>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<double>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<String16>& value); // NOLINT(google-explicit-constructor)
+ Value(const os::PersistableBundle& value); // NOLINT(google-explicit-constructor)
+ Value(const binder::Map& value); // NOLINT(google-explicit-constructor)
+
+ Value& operator=(const Value& rhs);
+ Value& operator=(const int8_t& rhs);
+ Value& operator=(const bool& rhs);
+ Value& operator=(const int32_t& rhs);
+ Value& operator=(const int64_t& rhs);
+ Value& operator=(const double& rhs);
+ Value& operator=(const String16& rhs);
+ Value& operator=(const std::vector<bool>& rhs);
+ Value& operator=(const std::vector<uint8_t>& rhs);
+ Value& operator=(const std::vector<int32_t>& rhs);
+ Value& operator=(const std::vector<int64_t>& rhs);
+ Value& operator=(const std::vector<double>& rhs);
+ Value& operator=(const std::vector<String16>& rhs);
+ Value& operator=(const os::PersistableBundle& rhs);
+ Value& operator=(const binder::Map& rhs);
+
+ void putBoolean(const bool& value);
+ void putByte(const int8_t& value);
+ void putInt(const int32_t& value);
+ void putLong(const int64_t& value);
+ void putDouble(const double& value);
+ void putString(const String16& value);
+ void putBooleanVector(const std::vector<bool>& value);
+ void putByteVector(const std::vector<uint8_t>& value);
+ void putIntVector(const std::vector<int32_t>& value);
+ void putLongVector(const std::vector<int64_t>& value);
+ void putDoubleVector(const std::vector<double>& value);
+ void putStringVector(const std::vector<String16>& value);
+ void putPersistableBundle(const os::PersistableBundle& value);
+ void putMap(const binder::Map& value);
+
+ bool getBoolean(bool* out) const;
+ bool getByte(int8_t* out) const;
+ bool getInt(int32_t* out) const;
+ bool getLong(int64_t* out) const;
+ bool getDouble(double* out) const;
+ bool getString(String16* out) const;
+ bool getBooleanVector(std::vector<bool>* out) const;
+ bool getByteVector(std::vector<uint8_t>* out) const;
+ bool getIntVector(std::vector<int32_t>* out) const;
+ bool getLongVector(std::vector<int64_t>* out) const;
+ bool getDoubleVector(std::vector<double>* out) const;
+ bool getStringVector(std::vector<String16>* out) const;
+ bool getPersistableBundle(os::PersistableBundle* out) const;
+ bool getMap(binder::Map* out) const;
+
+ bool isBoolean() const;
+ bool isByte() const;
+ bool isInt() const;
+ bool isLong() const;
+ bool isDouble() const;
+ bool isString() const;
+ bool isBooleanVector() const;
+ bool isByteVector() const;
+ bool isIntVector() const;
+ bool isLongVector() const;
+ bool isDoubleVector() const;
+ bool isStringVector() const;
+ bool isPersistableBundle() const;
+ bool isMap() const;
+
+ // String Convenience Adapters
+ // ---------------------------
+
+ explicit Value(const String8& value): Value(String16(value)) { }
+ explicit Value(const ::std::string& value): Value(String8(value.c_str())) { }
+ void putString(const String8& value) { return putString(String16(value)); }
+ void putString(const ::std::string& value) { return putString(String8(value.c_str())); }
+ Value& operator=(const String8& rhs) { return *this = String16(rhs); }
+ Value& operator=(const ::std::string& rhs) { return *this = String8(rhs.c_str()); }
+ bool getString(String8* out) const;
+ bool getString(::std::string* out) const;
+
+private:
+
+ // This allows ::android::Parcel to call the two methods below.
+ friend class ::android::Parcel;
+
+ // This is called by ::android::Parcel::writeValue()
+ status_t writeToParcel(Parcel* parcel) const;
+
+ // This is called by ::android::Parcel::readValue()
+ status_t readFromParcel(const Parcel* parcel);
+
+ template<typename T> class Content;
+ class ContentBase;
+
+ ContentBase* mContent;
+};
+
+} // namespace binder
+
+} // namespace android
+
+#endif // ANDROID_VALUE_H
diff --git a/libs/binder/ParcelValTypes.h b/libs/binder/include/private/binder/ParcelValTypes.h
index 666d22a57f..666d22a57f 100644
--- a/libs/binder/ParcelValTypes.h
+++ b/libs/binder/include/private/binder/ParcelValTypes.h
diff --git a/libs/binder/Static.h b/libs/binder/include/private/binder/Static.h
index f8e0ee5f8d..171be7791e 100644
--- a/libs/binder/Static.h
+++ b/libs/binder/include/private/binder/Static.h
@@ -21,6 +21,10 @@
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
+#ifndef __ANDROID_VNDK__
+#include <binder/IPermissionController.h>
+#endif
+#include <binder/IServiceManager.h>
namespace android {
@@ -31,4 +35,12 @@ extern Vector<int32_t> gTextBuffers;
extern Mutex& gProcessMutex;
extern sp<ProcessState> gProcess;
+// For IServiceManager.cpp
+extern Mutex gDefaultServiceManagerLock;
+extern sp<IServiceManager> gDefaultServiceManager;
+#ifndef __ANDROID_VNDK__
+extern sp<IPermissionController> gPermissionController;
+#endif
+extern bool gSystemBootCompleted;
+
} // namespace android
diff --git a/libs/binder/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h
index c22be9f786..2f11622e70 100644
--- a/libs/binder/include/private/binder/binder_module.h
+++ b/libs/binder/include/private/binder/binder_module.h
@@ -23,16 +23,6 @@ namespace android {
/* obtain structures and constants from the kernel header */
-// TODO(b/31559095): bionic on host
-#ifndef __ANDROID__
-#define __packed __attribute__((__packed__))
-#endif
-
-// TODO(b/31559095): bionic on host
-#if defined(B_PACK_CHARS) && !defined(_UAPI_LINUX_BINDER_H)
-#undef B_PACK_CHARS
-#endif
-
#include <sys/ioctl.h>
#include <linux/android/binder.h>
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index c0ea6d7b1e..21bef2e930 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -14,30 +14,13 @@
* limitations under the License.
*/
-// TODO(b/31559095): bionic on host should define this
-cc_defaults {
- name: "libbinder_ndk_host_user",
- target: {
- host: {
- cflags: [
- "-D__INTRODUCED_IN(n)=",
- "-D__assert(a,b,c)=",
- // We want all the APIs to be available on the host.
- "-D__ANDROID_API__=10000",
- ],
- },
- },
-}
-
-cc_library_shared {
+cc_library {
name: "libbinder_ndk",
-
- defaults: ["libbinder_ndk_host_user"],
- host_supported: true,
+ vendor_available: true,
export_include_dirs: [
"include_ndk",
- "include_platform",
+ "include_apex",
],
cflags: [
@@ -51,7 +34,6 @@ cc_library_shared {
"ibinder_jni.cpp",
"parcel.cpp",
"process.cpp",
- "stability.cpp",
"status.cpp",
"service_manager.cpp",
],
@@ -70,17 +52,10 @@ cc_library_shared {
"jni_headers",
],
- target: {
- linux: {
- version_script: "libbinder_ndk.map.txt",
- },
- },
+ version_script: "libbinder_ndk.map.txt",
stubs: {
symbol_file: "libbinder_ndk.map.txt",
- versions: [
- "29",
- "30",
- ],
+ versions: ["29"],
},
}
@@ -99,12 +74,3 @@ ndk_library {
symbol_file: "libbinder_ndk.map.txt",
first_version: "29",
}
-
-llndk_library {
- name: "libbinder_ndk",
- symbol_file: "libbinder_ndk.map.txt",
- export_include_dirs: [
- "include_ndk",
- "include_platform",
- ],
-}
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index e752c45d60..bd6886d1ee 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -17,7 +17,6 @@
#include <android/binder_ibinder.h>
#include "ibinder_internal.h"
-#include <android/binder_stability.h>
#include <android/binder_status.h>
#include "parcel_internal.h"
#include "status_internal.h"
@@ -543,8 +542,7 @@ binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, APa
return STATUS_UNKNOWN_TRANSACTION;
}
- constexpr binder_flags_t kAllFlags = FLAG_PRIVATE_VENDOR | FLAG_ONEWAY;
- if ((flags & ~kAllFlags) != 0) {
+ if ((flags & ~FLAG_ONEWAY) != 0) {
LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
return STATUS_BAD_VALUE;
}
@@ -591,40 +589,3 @@ void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) {
recipient->decStrong(nullptr);
}
-
-binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) {
- if (binder == nullptr || outExt == nullptr) {
- if (outExt != nullptr) {
- *outExt = nullptr;
- }
- return STATUS_UNEXPECTED_NULL;
- }
-
- sp<IBinder> ext;
- status_t res = binder->getBinder()->getExtension(&ext);
-
- if (res != android::OK) {
- *outExt = nullptr;
- return PruneStatusT(res);
- }
-
- sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(ext);
- if (ret != nullptr) ret->incStrong(binder);
-
- *outExt = ret.get();
- return STATUS_OK;
-}
-
-binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) {
- if (binder == nullptr || ext == nullptr) {
- return STATUS_UNEXPECTED_NULL;
- }
-
- ABBinder* rawBinder = binder->asABBinder();
- if (rawBinder == nullptr) {
- return STATUS_INVALID_OPERATION;
- }
-
- rawBinder->setExtension(ext->getBinder());
- return STATUS_OK;
-}
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_apex/android/binder_manager.h
index 055c79bca1..055c79bca1 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_apex/android/binder_manager.h
diff --git a/libs/binder/ndk/include_platform/android/binder_process.h b/libs/binder/ndk/include_apex/android/binder_process.h
index fdefbb4b8a..69e6387bcb 100644
--- a/libs/binder/ndk/include_platform/android/binder_process.h
+++ b/libs/binder/ndk/include_apex/android/binder_process.h
@@ -27,7 +27,7 @@ __BEGIN_DECLS
void ABinderProcess_startThreadPool();
/**
* This sets the maximum number of threads that can be started in the threadpool. By default, after
- * startThreadPool is called, this is 15. If it is called additional times, it will only prevent
+ * startThreadPool is called, this is one. If it is called additional times, it will only prevent
* the kernel from starting new threads and will not delete already existing threads.
*/
bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads);
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index 946ccb79a5..c6868b07ef 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -21,7 +21,7 @@
/**
* @file binder_auto_utils.h
- * @brief These objects provide a more C++-like thin interface to the binder.
+ * @brief These objects provide a more C++-like thin interface to the .
*/
#pragma once
@@ -159,17 +159,13 @@ class ScopedAResource {
*/
T* getR() { return &mT; }
- // copy-constructing/assignment is disallowed
+ // copy-constructing, or move/copy assignment is disallowed
ScopedAResource(const ScopedAResource&) = delete;
ScopedAResource& operator=(const ScopedAResource&) = delete;
+ ScopedAResource& operator=(ScopedAResource&&) = delete;
- // move-constructing/assignment is okay
+ // move-constructing is okay
ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; }
- ScopedAResource& operator=(ScopedAResource&& other) {
- set(other.mT);
- other.mT = DEFAULT;
- return *this;
- }
private:
T mT;
@@ -201,54 +197,16 @@ class ScopedAStatus : public impl::ScopedAResource<AStatus*, void, AStatus_delet
explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {}
~ScopedAStatus() {}
ScopedAStatus(ScopedAStatus&&) = default;
- ScopedAStatus& operator=(ScopedAStatus&&) = default;
/**
* See AStatus_isOk.
*/
- bool isOk() const { return get() != nullptr && AStatus_isOk(get()); }
-
- /**
- * See AStatus_getExceptionCode
- */
- binder_exception_t getExceptionCode() const { return AStatus_getExceptionCode(get()); }
+ bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
/**
- * See AStatus_getServiceSpecificError
- */
- int32_t getServiceSpecificError() const { return AStatus_getServiceSpecificError(get()); }
-
- /**
- * See AStatus_getStatus
- */
- binder_status_t getStatus() const { return AStatus_getStatus(get()); }
-
- /**
- * See AStatus_getMessage
- */
- const char* getMessage() const { return AStatus_getMessage(get()); }
-
- /**
- * Convenience methods for creating scoped statuses.
+ * Convenience method for okay status.
*/
static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); }
- static ScopedAStatus fromExceptionCode(binder_exception_t exception) {
- return ScopedAStatus(AStatus_fromExceptionCode(exception));
- }
- static ScopedAStatus fromExceptionCodeWithMessage(binder_exception_t exception,
- const char* message) {
- return ScopedAStatus(AStatus_fromExceptionCodeWithMessage(exception, message));
- }
- static ScopedAStatus fromServiceSpecificError(int32_t serviceSpecific) {
- return ScopedAStatus(AStatus_fromServiceSpecificError(serviceSpecific));
- }
- static ScopedAStatus fromServiceSpecificErrorWithMessage(int32_t serviceSpecific,
- const char* message) {
- return ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(serviceSpecific, message));
- }
- static ScopedAStatus fromStatus(binder_status_t status) {
- return ScopedAStatus(AStatus_fromStatus(status));
- }
};
/**
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 4d5c044232..80d12541be 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -34,7 +34,7 @@
#include <android/binder_status.h>
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
// Also see TF_* in kernel's binder.h
typedef uint32_t binder_flags_t;
@@ -165,8 +165,6 @@ typedef binder_status_t (*AIBinder_Class_onTransact)(AIBinder* binder, transacti
*
* None of these parameters can be null.
*
- * Available since API level 29.
- *
* \param interfaceDescriptor this is a unique identifier for the class. This is used internally for
* sanity checks on transactions.
* \param onCreate see AIBinder_Class_onCreate.
@@ -201,8 +199,6 @@ typedef binder_status_t (*AIBinder_onDump)(AIBinder* binder, int fd, const char*
* If this isn't set, nothing will be dumped when dump is called (for instance with
* android.os.Binder#dump). Must be called before any instance of the class is created.
*
- * Available since API level 29.
- *
* \param dump function to call when an instance of this binder class is being dumped.
*/
void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29);
@@ -224,8 +220,6 @@ void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __I
* these two objects are actually equal using the AIBinder pointer alone (which they should be able
* to do). Also see the suggested memory ownership model suggested above.
*
- * Available since API level 29.
- *
* \param clazz the type of the object to be created.
* \param args the args to pass to AIBinder_onCreate for that class.
*
@@ -237,8 +231,6 @@ __attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class*
/**
* If this is hosted in a process other than the current one.
*
- * Available since API level 29.
- *
* \param binder the binder being queried.
*
* \return true if the AIBinder represents an object in another process.
@@ -252,8 +244,6 @@ bool AIBinder_isRemote(const AIBinder* binder) __INTRODUCED_IN(29);
* updated as the result of a transaction made using AIBinder_transact, but it will also be updated
* based on the results of bookkeeping or other transactions made internally.
*
- * Available since API level 29.
- *
* \param binder the binder being queried.
*
* \return true if the binder is alive.
@@ -265,8 +255,6 @@ bool AIBinder_isAlive(const AIBinder* binder) __INTRODUCED_IN(29);
* return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
* sanity check.
*
- * Available since API level 29.
- *
* \param binder the binder being queried.
*
* \return STATUS_OK if the ping succeeds.
@@ -276,9 +264,7 @@ binder_status_t AIBinder_ping(AIBinder* binder) __INTRODUCED_IN(29);
/**
* Built-in transaction for all binder objects. This dumps information about a given binder.
*
- * See also AIBinder_Class_setOnDump, AIBinder_onDump.
- *
- * Available since API level 29.
+ * See also AIBinder_Class_setOnDump, AIBinder_onDump
*
* \param binder the binder to dump information about
* \param fd where information should be dumped to
@@ -301,8 +287,6 @@ binder_status_t AIBinder_dump(AIBinder* binder, int fd, const char** args, uint3
*
* If binder is local, this will return STATUS_INVALID_OPERATION.
*
- * Available since API level 29.
- *
* \param binder the binder object you want to receive death notifications from.
* \param recipient the callback that will receive notifications when/if the binder dies.
* \param cookie the value that will be passed to the death recipient on death.
@@ -322,8 +306,6 @@ binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient*
* If the binder dies, it will automatically unlink. If the binder is deleted, it will be
* automatically unlinked.
*
- * Available since API level 29.
- *
* \param binder the binder object to remove a previously linked death recipient from.
* \param recipient the callback to remove.
* \param cookie the cookie used to link to death.
@@ -340,11 +322,9 @@ binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient
* This can be used with higher-level system services to determine the caller's identity and check
* permissions.
*
- * Available since API level 29.
- *
* \return calling uid or the current process's UID if this thread isn't processing a transaction.
*/
-uid_t AIBinder_getCallingUid() __INTRODUCED_IN(29);
+uid_t AIBinder_getCallingUid();
/**
* This returns the calling PID assuming that this thread is called from a thread that is processing
@@ -355,18 +335,14 @@ uid_t AIBinder_getCallingUid() __INTRODUCED_IN(29);
* calling process dies and is replaced with another process with elevated permissions and the same
* PID.
*
- * Available since API level 29.
- *
* \return calling pid or the current process's PID if this thread isn't processing a transaction.
* If the transaction being processed is a oneway transaction, then this method will return 0.
*/
-pid_t AIBinder_getCallingPid() __INTRODUCED_IN(29);
+pid_t AIBinder_getCallingPid();
/**
* This can only be called if a strong reference to this object already exists in process.
*
- * Available since API level 29.
- *
* \param binder the binder object to add a refcount to.
*/
void AIBinder_incStrong(AIBinder* binder) __INTRODUCED_IN(29);
@@ -374,8 +350,6 @@ void AIBinder_incStrong(AIBinder* binder) __INTRODUCED_IN(29);
/**
* This will delete the object and call onDestroy once the refcount reaches zero.
*
- * Available since API level 29.
- *
* \param binder the binder object to remove a refcount from.
*/
void AIBinder_decStrong(AIBinder* binder) __INTRODUCED_IN(29);
@@ -383,8 +357,6 @@ void AIBinder_decStrong(AIBinder* binder) __INTRODUCED_IN(29);
/**
* For debugging only!
*
- * Available since API level 29.
- *
* \param binder the binder object to retrieve the refcount of.
*
* \return the number of strong-refs on this binder in this process. If binder is null, this will be
@@ -401,8 +373,6 @@ int32_t AIBinder_debugGetRefCount(AIBinder* binder) __INTRODUCED_IN(29);
* This returns true if the class association succeeds. If it fails, no change is made to the
* binder object.
*
- * Available since API level 29.
- *
* \param binder the object to attach the class to.
* \param clazz the clazz to attach to binder.
*
@@ -413,8 +383,6 @@ bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) __IN
/**
* Returns the class that this binder was constructed with or associated with.
*
- * Available since API level 29.
- *
* \param binder the object that is being queried.
*
* \return the class that this binder is associated with. If this binder wasn't created with
@@ -426,8 +394,6 @@ const AIBinder_Class* AIBinder_getClass(AIBinder* binder) __INTRODUCED_IN(29);
* Value returned by onCreate for a local binder. For stateless classes (if onCreate returns
* null), this also returns null. For a remote binder, this will always return null.
*
- * Available since API level 29.
- *
* \param binder the object that is being queried.
*
* \return the userdata returned from AIBinder_onCreate when this object was created. This may be
@@ -456,8 +422,6 @@ void* AIBinder_getUserData(AIBinder* binder) __INTRODUCED_IN(29);
* AIBinder_transact. Alternatively, if there is an error while filling out the parcel, it can be
* deleted with AParcel_delete.
*
- * Available since API level 29.
- *
* \param binder the binder object to start a transaction on.
* \param in out parameter for input data to the transaction.
*
@@ -478,8 +442,6 @@ binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) __IN
* This does not affect the ownership of binder. The out parcel's ownership is passed to the caller
* and must be released with AParcel_delete when finished reading.
*
- * Available since API level 29.
- *
* \param binder the binder object to transact on.
* \param code the implementation-specific code representing which transaction should be taken.
* \param in the implementation-specific input data to this transaction.
@@ -497,8 +459,6 @@ binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, APa
* This does not take any ownership of the input binder, but it can be used to retrieve it if
* something else in some process still holds a reference to it.
*
- * Available since API level 29.
- *
* \param binder object to create a weak pointer to.
*
* \return object representing a weak pointer to binder (or null if binder is null).
@@ -509,8 +469,6 @@ __attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* b
/**
* Deletes the weak reference. This will have no impact on the lifetime of the binder.
*
- * Available since API level 29.
- *
* \param weakBinder object created with AIBinder_Weak_new.
*/
void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) __INTRODUCED_IN(29);
@@ -519,8 +477,6 @@ void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) __INTRODUCED_IN(29);
* If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
* null.
*
- * Available since API level 29.
- *
* \param weakBinder weak pointer to attempt retrieving the original object from.
*
* \return an AIBinder object with one refcount given to the caller or null.
@@ -531,8 +487,6 @@ __attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Wea
/**
* This function is executed on death receipt. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
*
- * Available since API level 29.
- *
* \param cookie the cookie passed to AIBinder_linkToDeath.
*/
typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie) __INTRODUCED_IN(29);
@@ -540,8 +494,6 @@ typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie) __INTRODUCED_
/**
* Creates a new binder death recipient. This can be attached to multiple different binder objects.
*
- * Available since API level 29.
- *
* \param onBinderDied the callback to call when this death recipient is invoked.
*
* \return the newly constructed object (or null if onBinderDied is null).
@@ -553,87 +505,11 @@ __attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecip
* Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before
* calling this as these will all be automatically unlinked.
*
- * Available since API level 29.
- *
* \param recipient the binder to delete (previously created with AIBinder_DeathRecipient_new).
*/
void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
-/**
- * Gets the extension registered with AIBinder_setExtension.
- *
- * See AIBinder_setExtension.
- *
- * Available since API level 30.
- *
- * \param binder the object to get the extension of.
- * \param outExt the returned extension object. Will be null if there is no extension set or
- * non-null with one strong ref count.
- *
- * \return error of getting the interface (may be a transaction error if this is
- * remote binder). STATUS_UNEXPECTED_NULL if binder is null.
- */
-binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) __INTRODUCED_IN(30);
-
-/**
- * Gets the extension of a binder interface. This allows a downstream developer to add
- * an extension to an interface without modifying its interface file. This should be
- * called immediately when the object is created before it is passed to another thread.
- * No thread safety is required.
- *
- * For instance, imagine if we have this interface:
- * interface IFoo { void doFoo(); }
- *
- * A). Historical option that has proven to be BAD! Only the original
- * author of an interface should change an interface. If someone
- * downstream wants additional functionality, they should not ever
- * change the interface or use this method.
- *
- * BAD TO DO: interface IFoo { BAD TO DO
- * BAD TO DO: void doFoo(); BAD TO DO
- * BAD TO DO: + void doBar(); // adding a method BAD TO DO
- * BAD TO DO: } BAD TO DO
- *
- * B). Option that this method enables.
- * Leave the original interface unchanged (do not change IFoo!).
- * Instead, create a new interface in a downstream package:
- *
- * package com.<name>; // new functionality in a new package
- * interface IBar { void doBar(); }
- *
- * When registering the interface, add:
- * std::shared_ptr<MyFoo> foo = new MyFoo; // class in AOSP codebase
- * std::shared_ptr<MyBar> bar = new MyBar; // custom extension class
- * ... = AIBinder_setExtension(foo->asBinder().get(), bar->asBinder().get());
- * // handle error
- *
- * Then, clients of IFoo can get this extension:
- * SpAIBinder binder = ...;
- * std::shared_ptr<IFoo> foo = IFoo::fromBinder(binder); // handle if null
- * SpAIBinder barBinder;
- * ... = AIBinder_getExtension(barBinder.get());
- * // handle error
- * std::shared_ptr<IBar> bar = IBar::fromBinder(barBinder);
- * // type is checked with AIBinder_associateClass
- * // if bar is null, then there is no extension or a different
- * // type of extension
- *
- * Available since API level 30.
- *
- * \param binder the object to get the extension on. Must be local.
- * \param ext the extension to set (binder will hold a strong reference to this)
- *
- * \return OK on success, STATUS_INVALID_OPERATION if binder is not local, STATUS_UNEXPECTED_NULL
- * if either binder is null.
- */
-binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30);
-
-#endif //__ANDROID_API__ >= 30
-
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
index be3029c3ff..124f36c55b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
@@ -31,7 +31,7 @@
#include <jni.h>
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
/**
* Converts an android.os.IBinder object into an AIBinder* object.
@@ -40,8 +40,6 @@ __BEGIN_DECLS
* AIBinder object, the original object is returned. The returned object has one refcount
* associated with it, and so this should be accompanied with an AIBinder_decStrong call.
*
- * Available since API level 29.
- *
* \param env Java environment.
* \param binder android.os.IBinder java object.
*
@@ -57,8 +55,6 @@ __attribute__((warn_unused_result)) AIBinder* AIBinder_fromJavaBinder(JNIEnv* en
* If either env or the binder is null, null is returned. If this binder object was originally an
* IBinder object, the original java object will be returned.
*
- * Available since API level 29.
- *
* \param env Java environment.
* \param binder the object to convert.
*
@@ -67,7 +63,7 @@ __attribute__((warn_unused_result)) AIBinder* AIBinder_fromJavaBinder(JNIEnv* en
__attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder)
__INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= 29
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 86b75b8c61..2258210f2e 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -26,7 +26,6 @@
#pragma once
-#include <stddef.h>
#include <sys/cdefs.h>
#include <android/binder_status.h>
@@ -35,7 +34,7 @@ struct AIBinder;
typedef struct AIBinder AIBinder;
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
/**
* This object represents a package of data that can be sent between processes. When transacting, an
@@ -49,8 +48,6 @@ typedef struct AParcel AParcel;
/**
* Cleans up a parcel.
*
- * Available since API level 29.
- *
* \param parcel A parcel returned by AIBinder_prepareTransaction or AIBinder_transact when a
* transaction is being aborted.
*/
@@ -59,8 +56,6 @@ void AParcel_delete(AParcel* parcel) __INTRODUCED_IN(29);
/**
* Sets the position within the parcel.
*
- * Available since API level 29.
- *
* \param parcel The parcel of which to set the position.
* \param position Position of the parcel to set. This must be a value returned by
* AParcel_getDataPosition. Positions are constant for a given parcel between processes.
@@ -73,8 +68,6 @@ binder_status_t AParcel_setDataPosition(const AParcel* parcel, int32_t position)
/**
* Gets the current position within the parcel.
*
- * Available since API level 29.
- *
* \param parcel The parcel of which to get the position.
*
* \return The size of the parcel. This will always be greater than 0. The values returned by this
@@ -395,8 +388,6 @@ typedef bool (*AParcel_byteArrayAllocator)(void* arrayData, int32_t length, int8
* Writes an AIBinder to the next location in a non-null parcel. Can be null. This does not take any
* refcounts of ownership of the binder from the client.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param binder the value to write to the parcel.
*
@@ -408,8 +399,6 @@ binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) __I
* Reads an AIBinder from the next location in a non-null parcel. One strong ref-count of ownership
* is passed to the caller of this function.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param binder the out parameter for what is read from the parcel. This may be null.
*
@@ -424,14 +413,12 @@ binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binde
*
* This corresponds to the SDK's android.os.ParcelFileDescriptor.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param fd the value to write to the parcel (-1 to represent a null ParcelFileDescriptor).
*
* \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) __INTRODUCED_IN(29);
+binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd);
/**
* Reads an int from the next location in a non-null parcel.
@@ -440,16 +427,13 @@ binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) __INT
*
* This corresponds to the SDK's android.os.ParcelFileDescriptor.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param fd the out parameter for what is read from the parcel (or -1 to represent a null
* ParcelFileDescriptor)
*
* \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd)
- __INTRODUCED_IN(29);
+binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd);
/**
* Writes an AStatus object to the next location in a non-null parcel.
@@ -460,8 +444,6 @@ binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd)
* this happens or if writing the status object itself fails, the return value from this function
* should be propagated to the client, and AParcel_readStatusHeader shouldn't be called.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param status the value to write to the parcel.
*
@@ -474,8 +456,6 @@ binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status
* Reads an AStatus from the next location in a non-null parcel. Ownership is passed to the caller
* of this function.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param status the out parameter for what is read from the parcel.
*
@@ -489,8 +469,6 @@ binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status
*
* If length is -1, and string is nullptr, this will write a 'null' string to the parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param string the null-terminated string to write to the parcel, at least of size 'length'.
* \param length the length of the string to be written.
@@ -508,8 +486,6 @@ binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t
* the output buffer from this read. If there is a 'null' string on the binder buffer, the allocator
* will be called with length -1.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param stringData some external representation of a string.
* \param allocator allocator that will be called once the size of the string is known.
@@ -527,8 +503,6 @@ binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
* returned from this function will be used to fill out the data from the parcel. If length is -1,
* this will write a 'null' string array to the binder buffer.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData some external representation of an array.
* \param length the length of the array to be written.
@@ -551,8 +525,6 @@ binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData,
* the contents of the string that is read. If the string array being read is 'null', this will
* instead just pass -1 to AParcel_stringArrayAllocator.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called with arrayData once the size of the output
@@ -570,8 +542,6 @@ binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData,
/**
* Writes an array of parcelables (user-defined types) to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
* \param length the length of arrayData or -1 if this represents a null array.
@@ -591,8 +561,6 @@ binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayD
* length is greater than zero, elementReader will be called for every index to read the
* corresponding parcelable.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -609,8 +577,6 @@ binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayDa
/**
* Writes int32_t value to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param value the value to write to the parcel.
*
@@ -621,8 +587,6 @@ binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) __INTRODUCED_
/**
* Writes uint32_t value to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param value the value to write to the parcel.
*
@@ -633,8 +597,6 @@ binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) __INTRODUCE
/**
* Writes int64_t value to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param value the value to write to the parcel.
*
@@ -645,8 +607,6 @@ binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) __INTRODUCED_
/**
* Writes uint64_t value to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param value the value to write to the parcel.
*
@@ -657,8 +617,6 @@ binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) __INTRODUCE
/**
* Writes float value to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param value the value to write to the parcel.
*
@@ -669,8 +627,6 @@ binder_status_t AParcel_writeFloat(AParcel* parcel, float value) __INTRODUCED_IN
/**
* Writes double value to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param value the value to write to the parcel.
*
@@ -681,8 +637,6 @@ binder_status_t AParcel_writeDouble(AParcel* parcel, double value) __INTRODUCED_
/**
* Writes bool value to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param value the value to write to the parcel.
*
@@ -693,8 +647,6 @@ binder_status_t AParcel_writeBool(AParcel* parcel, bool value) __INTRODUCED_IN(2
/**
* Writes char16_t value to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param value the value to write to the parcel.
*
@@ -705,8 +657,6 @@ binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) __INTRODUCED_
/**
* Writes int8_t value to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param value the value to write to the parcel.
*
@@ -717,8 +667,6 @@ binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) __INTRODUCED_IN
/**
* Reads into int32_t value from the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param value the value to read from the parcel.
*
@@ -729,8 +677,6 @@ binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) __INTRO
/**
* Reads into uint32_t value from the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param value the value to read from the parcel.
*
@@ -741,8 +687,6 @@ binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) __INT
/**
* Reads into int64_t value from the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param value the value to read from the parcel.
*
@@ -753,8 +697,6 @@ binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) __INTRO
/**
* Reads into uint64_t value from the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param value the value to read from the parcel.
*
@@ -765,8 +707,6 @@ binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) __INT
/**
* Reads into float value from the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param value the value to read from the parcel.
*
@@ -777,8 +717,6 @@ binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) __INTRODU
/**
* Reads into double value from the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param value the value to read from the parcel.
*
@@ -789,8 +727,6 @@ binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) __INTRO
/**
* Reads into bool value from the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param value the value to read from the parcel.
*
@@ -801,8 +737,6 @@ binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) __INTRODUCE
/**
* Reads into char16_t value from the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param value the value to read from the parcel.
*
@@ -813,8 +747,6 @@ binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) __INTRO
/**
* Reads into int8_t value from the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param value the value to read from the parcel.
*
@@ -825,8 +757,6 @@ binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) __INTRODU
/**
* Writes an array of int32_t to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
* \param length the length of arrayData or -1 if this represents a null array.
@@ -839,8 +769,6 @@ binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayDat
/**
* Writes an array of uint32_t to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
* \param length the length of arrayData or -1 if this represents a null array.
@@ -853,8 +781,6 @@ binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* arrayD
/**
* Writes an array of int64_t to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
* \param length the length of arrayData or -1 if this represents a null array.
@@ -867,8 +793,6 @@ binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayDat
/**
* Writes an array of uint64_t to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
* \param length the length of arrayData or -1 if this represents a null array.
@@ -881,8 +805,6 @@ binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* arrayD
/**
* Writes an array of float to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
* \param length the length of arrayData or -1 if this represents a null array.
@@ -895,8 +817,6 @@ binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData,
/**
* Writes an array of double to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
* \param length the length of arrayData or -1 if this represents a null array.
@@ -912,8 +832,6 @@ binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayDat
* getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying
* values to write to the parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData some external representation of an array.
* \param length the length of arrayData (or -1 if this represents a null array).
@@ -927,8 +845,6 @@ binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData, i
/**
* Writes an array of char16_t to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
* \param length the length of arrayData or -1 if this represents a null array.
@@ -941,8 +857,6 @@ binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* arrayDat
/**
* Writes an array of int8_t to the next location in a non-null parcel.
*
- * Available since API level 29.
- *
* \param parcel the parcel to write to.
* \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
* \param length the length of arrayData or -1 if this represents a null array.
@@ -959,8 +873,6 @@ binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData,
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -977,8 +889,6 @@ binder_status_t AParcel_readInt32Array(const AParcel* parcel, void* arrayData,
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -995,8 +905,6 @@ binder_status_t AParcel_readUint32Array(const AParcel* parcel, void* arrayData,
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -1013,8 +921,6 @@ binder_status_t AParcel_readInt64Array(const AParcel* parcel, void* arrayData,
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -1031,8 +937,6 @@ binder_status_t AParcel_readUint64Array(const AParcel* parcel, void* arrayData,
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -1049,8 +953,6 @@ binder_status_t AParcel_readFloatArray(const AParcel* parcel, void* arrayData,
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -1066,8 +968,6 @@ binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void* arrayData,
* First, allocator will be called with the length of the array. Then, for every i in [0, length),
* setter(arrayData, i, x) will be called where x is the value at the associated index.
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -1087,8 +987,6 @@ binder_status_t AParcel_readBoolArray(const AParcel* parcel, void* arrayData,
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -1105,8 +1003,6 @@ binder_status_t AParcel_readCharArray(const AParcel* parcel, void* arrayData,
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
*
- * Available since API level 29.
- *
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
* \param allocator the callback that will be called to allocate the array.
@@ -1118,7 +1014,7 @@ binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData,
// @END-PRIMITIVE-READ-WRITE
-#endif //__ANDROID_API__ >= 29
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index 78d70f87ba..2671b9b6fc 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -30,7 +30,7 @@
#include <sys/cdefs.h>
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= __ANDROID_API_Q__
enum {
STATUS_OK = 0,
@@ -105,8 +105,6 @@ typedef struct AStatus AStatus;
/**
* New status which is considered a success.
*
- * Available since API level 29.
- *
* \return a newly constructed status object that the caller owns.
*/
__attribute__((warn_unused_result)) AStatus* AStatus_newOk() __INTRODUCED_IN(29);
@@ -114,8 +112,6 @@ __attribute__((warn_unused_result)) AStatus* AStatus_newOk() __INTRODUCED_IN(29)
/**
* New status with exception code.
*
- * Available since API level 29.
- *
* \param exception the code that this status should represent. If this is EX_NONE, then this
* constructs an non-error status object.
*
@@ -127,8 +123,6 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCode(binder_ex
/**
* New status with exception code and message.
*
- * Available since API level 29.
- *
* \param exception the code that this status should represent. If this is EX_NONE, then this
* constructs an non-error status object.
* \param message the error message to associate with this status object.
@@ -143,8 +137,6 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCodeWithMessag
*
* This is considered to be EX_TRANSACTION_FAILED with extra information.
*
- * Available since API level 29.
- *
* \param serviceSpecific an implementation defined error code.
*
* \return a newly constructed status object that the caller owns.
@@ -157,8 +149,6 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificError(
*
* This is considered to be EX_TRANSACTION_FAILED with extra information.
*
- * Available since API level 29.
- *
* \param serviceSpecific an implementation defined error code.
* \param message the error message to associate with this status object.
*
@@ -172,8 +162,6 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificErrorWit
* is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning
* an AStatus instance.
*
- * Available since API level 29.
- *
* \param a low-level error to associate with this status object.
*
* \return a newly constructed status object that the caller owns.
@@ -185,8 +173,6 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromStatus(binder_status_t
* Whether this object represents a successful transaction. If this function returns true, then
* AStatus_getExceptionCode will return EX_NONE.
*
- * Available since API level 29.
- *
* \param status the status being queried.
*
* \return whether the status represents a successful transaction. For more details, see below.
@@ -196,8 +182,6 @@ bool AStatus_isOk(const AStatus* status) __INTRODUCED_IN(29);
/**
* The exception that this status object represents.
*
- * Available since API level 29.
- *
* \param status the status being queried.
*
* \return the exception code that this object represents.
@@ -210,8 +194,6 @@ binder_exception_t AStatus_getExceptionCode(const AStatus* status) __INTRODUCED_
* 0, the status object may still represent a different exception or status. To find out if this
* transaction as a whole is okay, use AStatus_isOk instead.
*
- * Available since API level 29.
- *
* \param status the status being queried.
*
* \return the service-specific error code if the exception code is EX_SERVICE_SPECIFIC or 0.
@@ -224,8 +206,6 @@ int32_t AStatus_getServiceSpecificError(const AStatus* status) __INTRODUCED_IN(2
* object may represent a different exception or a service specific error. To find out if this
* transaction as a whole is okay, use AStatus_isOk instead.
*
- * Available since API level 29.
- *
* \param status the status being queried.
*
* \return the status code if the exception code is EX_TRANSACTION_FAILED or 0.
@@ -238,8 +218,6 @@ binder_status_t AStatus_getStatus(const AStatus* status) __INTRODUCED_IN(29);
*
* The returned string has the lifetime of the status object passed into this function.
*
- * Available since API level 29.
- *
* \param status the status being queried.
*
* \return the message associated with this error.
@@ -249,13 +227,11 @@ const char* AStatus_getMessage(const AStatus* status) __INTRODUCED_IN(29);
/**
* Deletes memory associated with the status instance.
*
- * Available since API level 29.
- *
* \param status the status to delete, returned from AStatus_newOk or one of the AStatus_from* APIs.
*/
void AStatus_delete(AStatus* status) __INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= 29
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
deleted file mode 100644
index 2a4ded8691..0000000000
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ /dev/null
@@ -1,73 +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 <android/binder_ibinder.h>
-
-__BEGIN_DECLS
-
-/**
- * Private addition to binder_flag_t.
- */
-enum {
- /**
- * Indicates that this transaction is coupled w/ vendor.img
- */
- FLAG_PRIVATE_VENDOR = 0x10000000,
-};
-
-#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || \
- (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
-
-enum {
- FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
-};
-
-/**
- * This interface has the stability of the vendor image.
- */
-void AIBinder_markVendorStability(AIBinder* binder);
-
-static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
- AIBinder_markVendorStability(binder);
-}
-
-#else // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
- // !defined(__ANDROID_APEX__))
-
-enum {
- FLAG_PRIVATE_LOCAL = 0,
-};
-
-/**
- * This interface has the stability of the system image.
- */
-void AIBinder_markSystemStability(AIBinder* binder);
-
-static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
- AIBinder_markSystemStability(binder);
-}
-
-#endif // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
- // !defined(__ANDROID_APEX__))
-
-/**
- * This interface has system<->vendor stability
- */
-void AIBinder_markVintfStability(AIBinder* binder);
-
-__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index d4d5387f33..7e6581736f 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -89,24 +89,12 @@ LIBBINDER_NDK { # introduced=29
AStatus_getStatus;
AStatus_isOk;
AStatus_newOk;
- ABinderProcess_joinThreadPool; # apex vndk
- ABinderProcess_setThreadPoolMaxThreadCount; # apex vndk
- ABinderProcess_startThreadPool; # apex vndk
- AServiceManager_addService; # apex vndk
- AServiceManager_checkService; # apex vndk
- AServiceManager_getService; # apex vndk
- local:
- *;
-};
-
-LIBBINDER_NDK30 { # introduced=30
- global:
- AIBinder_getExtension;
- AIBinder_setExtension;
-
- AIBinder_markSystemStability; # apex
- AIBinder_markVendorStability; # vndk
- AIBinder_markVintfStability; # apex vndk
+ ABinderProcess_joinThreadPool; # apex
+ ABinderProcess_setThreadPoolMaxThreadCount; # apex
+ ABinderProcess_startThreadPool; # apex
+ AServiceManager_addService; # apex
+ AServiceManager_checkService; # apex
+ AServiceManager_getService; # apex
local:
*;
};
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index f18e118bc9..ae2276e794 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -50,7 +50,7 @@ binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int
if (length < -1) return STATUS_BAD_VALUE;
if (!isNullArray && length < 0) {
- LOG(ERROR) << __func__ << ": non-null array but length is " << length;
+ LOG(ERROR) << __func__ << ": null array must be used with length == -1.";
return STATUS_BAD_VALUE;
}
if (isNullArray && length > 0) {
diff --git a/libs/binder/ndk/scripts/format.sh b/libs/binder/ndk/scripts/format.sh
new file mode 100755
index 0000000000..698d291cb1
--- /dev/null
+++ b/libs/binder/ndk/scripts/format.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# 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.
+
+set -e
+
+echo "Formatting code"
+
+bpfmt -w $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -name "Android.bp")
+clang-format -i $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -\( -name "*.cpp" -o -name "*.h" -\))
diff --git a/libs/binder/ndk/scripts/init_map.sh b/libs/binder/ndk/scripts/init_map.sh
new file mode 100755
index 0000000000..3529b725ce
--- /dev/null
+++ b/libs/binder/ndk/scripts/init_map.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+# Simple helper for ease of development until this API is frozen.
+
+echo "LIBBINDER_NDK { # introduced=29"
+echo " global:"
+{
+ grep -oP "AIBinder_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_ibinder.h;
+ grep -oP "AIBinder_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_ibinder_jni.h;
+ grep -oP "AParcel_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_parcel.h;
+ grep -oP "AStatus_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_status.h;
+} | sort | uniq | awk '{ print " " $0 ";"; }'
+{
+ grep -oP "AServiceManager_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_manager.h;
+ grep -oP "ABinderProcess_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_process.h;
+} | sort | uniq | awk '{ print " " $0 "; # apex"; }'
+echo " local:"
+echo " *;"
+echo "};"
diff --git a/libs/binder/ndk/stability.cpp b/libs/binder/ndk/stability.cpp
deleted file mode 100644
index a5b3ecea4a..0000000000
--- a/libs/binder/ndk/stability.cpp
+++ /dev/null
@@ -1,45 +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 <android/binder_stability.h>
-
-#include <binder/Stability.h>
-#include "ibinder_internal.h"
-
-#include <log/log.h>
-
-using ::android::internal::Stability;
-
-#ifdef __ANDROID_VNDK__
-#error libbinder_ndk should only be built in a system context
-#endif
-
-#ifdef __ANDROID_NDK__
-#error libbinder_ndk should only be built in a system context
-#endif
-
-// explicit extern because symbol is only declared in header when __ANDROID_VNDK__
-extern "C" void AIBinder_markVendorStability(AIBinder* binder) {
- Stability::markVndk(binder->getBinder().get());
-}
-
-void AIBinder_markSystemStability(AIBinder* binder) {
- Stability::markCompilationUnit(binder->getBinder().get());
-}
-
-void AIBinder_markVintfStability(AIBinder* binder) {
- Stability::markVintf(binder->getBinder().get());
-}
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index ebd08b2f71..8cd4e033df 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -44,10 +44,10 @@ cc_defaults {
"libandroid_runtime_lazy",
"libbase",
"libbinder",
- "libbinder_ndk",
"libutils",
],
static_libs: [
+ "libbinder_ndk",
"test_libbinder_ndk_library",
],
}
@@ -67,32 +67,3 @@ cc_test {
srcs: ["main_server.cpp"],
gtest: false,
}
-
-cc_test {
- name: "binderVendorDoubleLoadTest",
- vendor: true,
- srcs: [
- "binderVendorDoubleLoadTest.cpp",
- ],
- static_libs: [
- "IBinderVendorDoubleLoadTest-cpp",
- "IBinderVendorDoubleLoadTest-ndk_platform",
- "libbinder_aidl_test_stub-ndk_platform",
- ],
- shared_libs: [
- "libbase",
- "libbinder",
- "libbinder_ndk",
- "libutils",
- ],
- test_suites: ["device-tests"],
-}
-
-aidl_interface {
- name: "IBinderVendorDoubleLoadTest",
- // TODO(b/119771576): only vendor is needed
- vendor_available: true,
- srcs: [
- "IBinderVendorDoubleLoadTest.aidl",
- ],
-}
diff --git a/libs/binder/ndk/test/AndroidTest.xml b/libs/binder/ndk/test/AndroidTest.xml
deleted file mode 100644
index 89646f7776..0000000000
--- a/libs/binder/ndk/test/AndroidTest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Runs binderVendorDoubleLoadTest.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-native" />
-
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
-
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="push" value="binderVendorDoubleLoadTest->/data/nativetest/vendor/binderVendorDoubleLoadTest" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/nativetest/vendor" />
- <option name="module-name" value="binderVendorDoubleLoadTest" />
- </test>
-</configuration>
-
diff --git a/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
deleted file mode 100644
index 3a5bd9cc56..0000000000
--- a/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
+++ /dev/null
@@ -1,19 +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.
- */
-
-interface IBinderVendorDoubleLoadTest {
- @utf8InCpp String RepeatString(@utf8InCpp String toRepeat);
-}
diff --git a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
deleted file mode 100644
index d3ccdc2878..0000000000
--- a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
+++ /dev/null
@@ -1,168 +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 <BnBinderVendorDoubleLoadTest.h>
-#include <aidl/BnBinderVendorDoubleLoadTest.h>
-#include <aidl/android/os/IServiceManager.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <android/binder_ibinder.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-#include <android/binder_stability.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <binder/Stability.h>
-#include <binder/Status.h>
-#include <gtest/gtest.h>
-
-#include <sys/prctl.h>
-
-using namespace android;
-using ::android::base::EndsWith;
-using ::android::base::GetProperty;
-using ::android::base::Split;
-using ::android::binder::Status;
-using ::android::internal::Stability;
-using ::ndk::ScopedAStatus;
-using ::ndk::SharedRefBase;
-using ::ndk::SpAIBinder;
-
-static const std::string kLocalNdkServerName = "NdkServer-local-IBinderVendorDoubleLoadTest";
-static const std::string kRemoteNdkServerName = "NdkServer-remote-IBinderVendorDoubleLoadTest";
-
-class NdkServer : public aidl::BnBinderVendorDoubleLoadTest {
- ScopedAStatus RepeatString(const std::string& in, std::string* out) override {
- *out = in;
- return ScopedAStatus::ok();
- }
-};
-class CppServer : public BnBinderVendorDoubleLoadTest {
- Status RepeatString(const std::string& in, std::string* out) override {
- *out = in;
- return Status::ok();
- }
-};
-
-TEST(DoubleBinder, VendorCppCantCallIntoSystem) {
- Vector<String16> services = defaultServiceManager()->listServices();
- EXPECT_TRUE(services.empty());
-}
-
-TEST(DoubleBinder, VendorCppCantRegisterService) {
- sp<CppServer> cppServer = new CppServer;
- status_t status = defaultServiceManager()->addService(String16("anything"), cppServer);
- EXPECT_EQ(EX_TRANSACTION_FAILED, status);
-}
-
-TEST(DoubleBinder, CppVendorCantManuallyMarkVintfStability) {
- // this test also implies that stability logic is turned on in vendor
- ASSERT_DEATH(
- {
- sp<IBinder> binder = new CppServer();
- Stability::markVintf(binder.get());
- },
- "Should only mark known object.");
-}
-
-TEST(DoubleBinder, NdkVendorCantManuallyMarkVintfStability) {
- // this test also implies that stability logic is turned on in vendor
- ASSERT_DEATH(
- {
- std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
- AIBinder_markVintfStability(ndkServer->asBinder().get());
- },
- "Should only mark known object.");
-}
-
-TEST(DoubleBinder, CallIntoNdk) {
- for (const std::string& serviceName : {kLocalNdkServerName, kRemoteNdkServerName}) {
- SpAIBinder binder = SpAIBinder(AServiceManager_checkService(serviceName.c_str()));
- ASSERT_NE(nullptr, binder.get()) << serviceName;
- EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())) << serviceName;
-
- std::shared_ptr<aidl::IBinderVendorDoubleLoadTest> server =
- aidl::IBinderVendorDoubleLoadTest::fromBinder(binder);
-
- ASSERT_NE(nullptr, server.get()) << serviceName;
-
- EXPECT_EQ(STATUS_OK, AIBinder_ping(server->asBinder().get()));
-
- std::string outString;
- ScopedAStatus status = server->RepeatString("foo", &outString);
- EXPECT_EQ(STATUS_OK, AStatus_getExceptionCode(status.get())) << serviceName;
- EXPECT_EQ("foo", outString) << serviceName;
- }
-}
-
-TEST(DoubleBinder, CallIntoSystemStabilityNdk) {
- // picking an arbitrary system service
- SpAIBinder binder = SpAIBinder(AServiceManager_checkService("manager"));
- ASSERT_NE(nullptr, binder.get());
-
- // can make stable transaction to system server
- EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
-
- using aidl::android::os::IServiceManager;
- std::shared_ptr<IServiceManager> manager = IServiceManager::fromBinder(binder);
- ASSERT_NE(nullptr, manager.get());
-
- std::vector<std::string> services;
- ASSERT_EQ(
- STATUS_BAD_TYPE,
- manager->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &services).getStatus());
-}
-
-void initDrivers() {
- // Explicitly instantiated with the same driver that system would use.
- // __ANDROID_VNDK__ right now uses /dev/vndbinder by default.
- ProcessState::initWithDriver("/dev/binder");
- ProcessState::self()->startThreadPool();
- ABinderProcess_startThreadPool();
-}
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
-
- if (fork() == 0) {
- // child process
-
- prctl(PR_SET_PDEATHSIG, SIGHUP);
-
- initDrivers();
-
- // REMOTE SERVERS
- std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
- CHECK(STATUS_OK == AServiceManager_addService(ndkServer->asBinder().get(),
- kRemoteNdkServerName.c_str()));
-
- // OR sleep forever or whatever, it doesn't matter
- IPCThreadState::self()->joinThreadPool(true);
- exit(1); // should not reach
- }
-
- sleep(1);
-
- initDrivers();
-
- // LOCAL SERVERS
- std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
- AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str());
-
- return RUN_ALL_TESTS();
-}
diff --git a/libs/binder/ndk/update.sh b/libs/binder/ndk/update.sh
new file mode 100755
index 0000000000..9a4577ffff
--- /dev/null
+++ b/libs/binder/ndk/update.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+# 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.
+
+
+set -ex
+
+# This script makes sure that the source code is in sync with the various scripts
+./scripts/gen_parcel_helper.py
+./scripts/format.sh
+./scripts/init_map.sh > libbinder_ndk.map.txt
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 5a7f9a97fa..c451780dd7 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -19,34 +19,45 @@ cc_defaults {
cflags: [
"-Wall",
"-Werror",
+ "-Wno-unused-private-field",
+ "-Wno-unused-variable",
],
}
cc_test {
name: "binderDriverInterfaceTest_IPC_32",
- defaults: ["binder_test_defaults"],
srcs: ["binderDriverInterfaceTest.cpp"],
+ defaults: ["binder_test_defaults"],
compile_multilib: "32",
cflags: ["-DBINDER_IPC_32BIT=1"],
}
cc_test {
- name: "binderDriverInterfaceTest",
- defaults: ["binder_test_defaults"],
product_variables: {
binder32bit: {
cflags: ["-DBINDER_IPC_32BIT=1"],
},
},
+ name: "binderDriverInterfaceTest",
srcs: ["binderDriverInterfaceTest.cpp"],
- test_suites: ["device-tests"],
+ defaults: ["binder_test_defaults"],
}
cc_test {
- name: "binderLibTest_IPC_32",
+ name: "binderValueTypeTest",
+ srcs: ["binderValueTypeTest.cpp"],
defaults: ["binder_test_defaults"],
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ ],
+}
+
+cc_test {
+ name: "binderLibTest_IPC_32",
srcs: ["binderLibTest.cpp"],
+ defaults: ["binder_test_defaults"],
shared_libs: [
"libbinder",
"libutils",
@@ -56,27 +67,25 @@ cc_test {
}
cc_test {
- name: "binderLibTest",
- defaults: ["binder_test_defaults"],
product_variables: {
binder32bit: {
cflags: ["-DBINDER_IPC_32BIT=1"],
},
},
+ defaults: ["binder_test_defaults"],
+ name: "binderLibTest",
srcs: ["binderLibTest.cpp"],
shared_libs: [
"libbinder",
"libutils",
],
- test_suites: ["device-tests"],
- require_root: true,
}
cc_test {
name: "binderThroughputTest",
- defaults: ["binder_test_defaults"],
srcs: ["binderThroughputTest.cpp"],
+ defaults: ["binder_test_defaults"],
shared_libs: [
"libbinder",
"libutils",
@@ -92,20 +101,19 @@ cc_test {
cc_test {
name: "binderTextOutputTest",
- defaults: ["binder_test_defaults"],
srcs: ["binderTextOutputTest.cpp"],
+ defaults: ["binder_test_defaults"],
shared_libs: [
"libbinder",
"libutils",
"libbase",
],
- test_suites: ["device-tests"],
}
cc_test {
name: "schd-dbg",
- defaults: ["binder_test_defaults"],
srcs: ["schd-dbg.cpp"],
+ defaults: ["binder_test_defaults"],
shared_libs: [
"libbinder",
"libutils",
@@ -115,11 +123,16 @@ cc_test {
cc_test {
name: "binderSafeInterfaceTest",
- defaults: ["binder_test_defaults"],
srcs: ["binderSafeInterfaceTest.cpp"],
+ defaults: ["binder_test_defaults"],
cppflags: [
- "-Wextra",
+ "-Weverything",
+ "-Wno-c++98-compat",
+ "-Wno-c++98-compat-pedantic",
+ "-Wno-global-constructors",
+ "-Wno-padded",
+ "-Wno-weak-vtables",
],
cpp_std: "experimental",
@@ -131,35 +144,4 @@ cc_test {
"liblog",
"libutils",
],
- test_suites: ["device-tests"],
- require_root: true,
-}
-
-aidl_interface {
- name: "binderStabilityTestIface",
- srcs: [
- "IBinderStabilityTest.aidl",
- ],
-}
-
-cc_test {
- name: "binderStabilityTest",
- defaults: ["binder_test_defaults"],
- srcs: [
- "binderStabilityTest.cpp",
- ],
-
- shared_libs: [
- "libbinder_ndk",
- "libbinder",
- "liblog",
- "libutils",
- ],
- static_libs: [
- "binderStabilityTestIface-cpp",
- "binderStabilityTestIface-ndk_platform",
- ],
-
- test_suites: ["device-tests"],
- require_root: true,
}
diff --git a/libs/binder/tests/IBinderStabilityTest.aidl b/libs/binder/tests/IBinderStabilityTest.aidl
deleted file mode 100644
index 36e1c2cbc4..0000000000
--- a/libs/binder/tests/IBinderStabilityTest.aidl
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-// THIS IS ONLY FOR TESTING!
-interface IBinderStabilityTest {
- // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
- // THIS IS ONLY FOR TESTING!
- void sendBinder(IBinder binder);
-
- // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
- // THIS IS ONLY FOR TESTING!
- void sendAndCallBinder(IBinder binder);
-
- // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
- // THIS IS ONLY FOR TESTING!
- IBinder returnNoStabilityBinder();
-
- // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
- // THIS IS ONLY FOR TESTING!
- IBinder returnLocalStabilityBinder();
-
- // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
- // THIS IS ONLY FOR TESTING!
- IBinder returnVintfStabilityBinder();
-
- // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
- // THIS IS ONLY FOR TESTING!
- IBinder returnVendorStabilityBinder();
-}
-// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
-// THIS IS ONLY FOR TESTING!
-// Construct and return a binder with a specific stability
diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp
index f3ed6a613c..77ebac8f5a 100644
--- a/libs/binder/tests/binderDriverInterfaceTest.cpp
+++ b/libs/binder/tests/binderDriverInterfaceTest.cpp
@@ -230,6 +230,7 @@ TEST_F(BinderDriverInterfaceTest, IncRefsAcquireReleaseDecRefs) {
}
TEST_F(BinderDriverInterfaceTest, Transaction) {
+ binder_uintptr_t cookie = 1234;
struct {
uint32_t cmd1;
struct binder_transaction_data arg1;
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 5e0574ad8a..78f11594b9 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -28,7 +28,6 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
-#include <private/binder/binder_module.h>
#include <sys/epoll.h>
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
@@ -67,6 +66,7 @@ enum BinderLibTestTranscationCode {
BINDER_LIB_TEST_LINK_DEATH_TRANSACTION,
BINDER_LIB_TEST_WRITE_FILE_TRANSACTION,
BINDER_LIB_TEST_WRITE_PARCEL_FILE_DESCRIPTOR_TRANSACTION,
+ BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION,
BINDER_LIB_TEST_EXIT_TRANSACTION,
BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION,
BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION,
@@ -553,6 +553,50 @@ TEST_F(BinderLibTest, AddServer)
ASSERT_TRUE(server != nullptr);
}
+TEST_F(BinderLibTest, DeathNotificationNoRefs)
+{
+ status_t ret;
+
+ sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
+
+ {
+ sp<IBinder> binder = addServer();
+ ASSERT_TRUE(binder != nullptr);
+ ret = binder->linkToDeath(testDeathRecipient);
+ EXPECT_EQ(NO_ERROR, ret);
+ }
+ IPCThreadState::self()->flushCommands();
+ ret = testDeathRecipient->waitEvent(5);
+ EXPECT_EQ(NO_ERROR, ret);
+#if 0 /* Is there an unlink api that does not require a strong reference? */
+ ret = binder->unlinkToDeath(testDeathRecipient);
+ EXPECT_EQ(NO_ERROR, ret);
+#endif
+}
+
+TEST_F(BinderLibTest, DeathNotificationWeakRef)
+{
+ status_t ret;
+ wp<IBinder> wbinder;
+
+ sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
+
+ {
+ sp<IBinder> binder = addServer();
+ ASSERT_TRUE(binder != nullptr);
+ ret = binder->linkToDeath(testDeathRecipient);
+ EXPECT_EQ(NO_ERROR, ret);
+ wbinder = binder;
+ }
+ IPCThreadState::self()->flushCommands();
+ ret = testDeathRecipient->waitEvent(5);
+ EXPECT_EQ(NO_ERROR, ret);
+#if 0 /* Is there an unlink api that does not require a strong reference? */
+ ret = binder->unlinkToDeath(testDeathRecipient);
+ EXPECT_EQ(NO_ERROR, ret);
+#endif
+}
+
TEST_F(BinderLibTest, DeathNotificationStrongRef)
{
status_t ret;
@@ -770,22 +814,20 @@ TEST_F(BinderLibTest, PromoteLocal) {
EXPECT_TRUE(strong_from_weak == nullptr);
}
-TEST_F(BinderLibTest, LocalGetExtension) {
- sp<BBinder> binder = new BBinder();
- sp<IBinder> ext = new BBinder();
- binder->setExtension(ext);
- EXPECT_EQ(ext, binder->getExtension());
-}
-
-TEST_F(BinderLibTest, RemoteGetExtension) {
+TEST_F(BinderLibTest, PromoteRemote) {
+ int ret;
+ Parcel data, reply;
+ sp<IBinder> strong = new BBinder();
sp<IBinder> server = addServer();
+
ASSERT_TRUE(server != nullptr);
+ ASSERT_TRUE(strong != nullptr);
- sp<IBinder> extension;
- EXPECT_EQ(NO_ERROR, server->getExtension(&extension));
- ASSERT_NE(nullptr, extension.get());
+ ret = data.writeWeakBinder(strong);
+ EXPECT_EQ(NO_ERROR, ret);
- EXPECT_EQ(NO_ERROR, extension->pingBinder());
+ ret = server->transact(BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION, data, &reply);
+ EXPECT_GE(ret, 0);
}
TEST_F(BinderLibTest, CheckHandleZeroBinderHighBitsZeroCookie) {
@@ -813,6 +855,7 @@ TEST_F(BinderLibTest, FreedBinder) {
wp<IBinder> keepFreedBinder;
{
Parcel data, reply;
+ data.writeBool(false); /* request weak reference */
ret = server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, data, &reply);
ASSERT_EQ(NO_ERROR, ret);
struct flat_binder_object *freed = (struct flat_binder_object *)(reply.data());
@@ -821,9 +864,8 @@ TEST_F(BinderLibTest, FreedBinder) {
* delete its reference to it - otherwise the transaction
* fails regardless of whether the driver is fixed.
*/
- keepFreedBinder = reply.readStrongBinder();
+ keepFreedBinder = reply.readWeakBinder();
}
- IPCThreadState::self()->flushCommands();
{
Parcel data, reply;
data.writeStrongBinder(server);
@@ -973,6 +1015,9 @@ TEST_F(BinderLibTest, WorkSourceRestored)
TEST_F(BinderLibTest, PropagateFlagSet)
{
+ status_t ret;
+ Parcel data, reply;
+
IPCThreadState::self()->clearPropagateWorkSource();
IPCThreadState::self()->setCallingWorkSourceUid(100);
EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource());
@@ -980,6 +1025,9 @@ TEST_F(BinderLibTest, PropagateFlagSet)
TEST_F(BinderLibTest, PropagateFlagCleared)
{
+ status_t ret;
+ Parcel data, reply;
+
IPCThreadState::self()->setCallingWorkSourceUid(100);
IPCThreadState::self()->clearPropagateWorkSource();
EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource());
@@ -987,6 +1035,9 @@ TEST_F(BinderLibTest, PropagateFlagCleared)
TEST_F(BinderLibTest, PropagateFlagRestored)
{
+ status_t ret;
+ Parcel data, reply;
+
int token = IPCThreadState::self()->setCallingWorkSourceUid(100);
IPCThreadState::self()->restoreCallingWorkSource(token);
@@ -1085,6 +1136,7 @@ class BinderLibTestService : public BBinder
case BINDER_LIB_TEST_ADD_POLL_SERVER:
case BINDER_LIB_TEST_ADD_SERVER: {
int ret;
+ uint8_t buf[1] = { 0 };
int serverid;
if (m_id != 0) {
@@ -1282,6 +1334,29 @@ class BinderLibTestService : public BBinder
if (ret != size) return UNKNOWN_ERROR;
return NO_ERROR;
}
+ case BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION: {
+ int ret;
+ wp<IBinder> weak;
+ sp<IBinder> strong;
+ Parcel data2, reply2;
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> server = sm->getService(binderLibTestServiceName);
+
+ weak = data.readWeakBinder();
+ if (weak == nullptr) {
+ return BAD_VALUE;
+ }
+ strong = weak.promote();
+
+ ret = server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data2, &reply2);
+ if (ret != NO_ERROR)
+ exit(EXIT_FAILURE);
+
+ if (strong == nullptr) {
+ reply->setError(1);
+ }
+ return NO_ERROR;
+ }
case BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION:
alarm(10);
return NO_ERROR;
@@ -1290,8 +1365,13 @@ class BinderLibTestService : public BBinder
;
exit(EXIT_SUCCESS);
case BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION: {
+ bool strongRef = data.readBool();
sp<IBinder> binder = new BBinder();
- reply->writeStrongBinder(binder);
+ if (strongRef) {
+ reply->writeStrongBinder(binder);
+ } else {
+ reply->writeWeakBinder(binder);
+ }
return NO_ERROR;
}
case BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION: {
@@ -1319,6 +1399,7 @@ class BinderLibTestService : public BBinder
bool m_serverStartRequested;
sp<IBinder> m_serverStarted;
sp<IBinder> m_strongRef;
+ bool m_callbackPending;
sp<IBinder> m_callback;
};
@@ -1331,13 +1412,6 @@ int run_server(int index, int readypipefd, bool usePoll)
BinderLibTestService* testServicePtr;
{
sp<BinderLibTestService> testService = new BinderLibTestService(index);
-
- /*
- * Normally would also contain functionality as well, but we are only
- * testing the extension mechanism.
- */
- testService->setExtension(new BBinder());
-
/*
* We need this below, but can't hold a sp<> because it prevents the
* node from being cleaned up automatically. It's safe in this case
@@ -1387,7 +1461,7 @@ int run_server(int index, int readypipefd, bool usePoll)
* We simulate a single-threaded process using the binder poll
* interface; besides handling binder commands, it can also
* issue outgoing transactions, by storing a callback in
- * m_callback.
+ * m_callback and setting m_callbackPending.
*
* processPendingCall() will then issue that transaction.
*/
@@ -1414,6 +1488,8 @@ int run_server(int index, int readypipefd, bool usePoll)
}
int main(int argc, char **argv) {
+ int ret;
+
if (argc == 4 && !strcmp(argv[1], "--servername")) {
binderservername = argv[2];
} else {
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 09f58cc833..3b1db27749 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -75,7 +75,7 @@ public:
private:
int32_t mValue = 0;
- __attribute__((unused)) uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
+ uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
};
struct TestFlattenable : Flattenable<TestFlattenable> {
@@ -743,7 +743,6 @@ TEST_F(SafeInterfaceTest, TestIncremementParcelableVector) {
const std::vector<TestParcelable> a{TestParcelable{1}, TestParcelable{2}};
std::vector<TestParcelable> aPlusOne;
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
- ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(a.size(), aPlusOne.size());
for (size_t i = 0; i < a.size(); ++i) {
ASSERT_EQ(a[i].getValue() + 1, aPlusOne[i].getValue());
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
deleted file mode 100644
index 1f2779abf0..0000000000
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ /dev/null
@@ -1,328 +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 <android/binder_manager.h>
-#include <android/binder_stability.h>
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/Parcel.h>
-#include <binder/Stability.h>
-#include <gtest/gtest.h>
-
-#include <sys/prctl.h>
-
-#include "aidl/BnBinderStabilityTest.h"
-#include "BnBinderStabilityTest.h"
-
-using namespace android;
-using namespace ndk;
-using android::binder::Status;
-using android::internal::Stability; // for testing only!
-
-const String16 kSystemStabilityServer = String16("binder_stability_test_service_system");
-
-// This is handwritten so that we can test different stability levels w/o having the AIDL
-// compiler assign them. Hand-writing binder interfaces is considered a bad practice
-// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
-class BadStableBinder : public BBinder {
-public:
- static constexpr uint32_t USER_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION;
- static String16 kDescriptor;
-
- bool gotUserTransaction = false;
-
- static status_t doUserTransaction(const sp<IBinder>& binder) {
- Parcel data, reply;
- data.writeInterfaceToken(kDescriptor);
- return binder->transact(USER_TRANSACTION, data, &reply, 0/*flags*/);
- }
-
- status_t onTransact(uint32_t code,
- const Parcel& data, Parcel* reply, uint32_t flags) override {
- if (code == USER_TRANSACTION) {
- // not interested in this kind of stability. Make sure
- // we have a test failure
- LOG_ALWAYS_FATAL_IF(!data.enforceInterface(kDescriptor));
-
- gotUserTransaction = true;
-
- ALOGE("binder stability: Got user transaction");
- return OK;
- }
- return BBinder::onTransact(code, data, reply, flags);
- }
-
- static sp<BadStableBinder> undef() {
- sp<BadStableBinder> iface = new BadStableBinder();
- return iface;
- }
-
- static sp<BadStableBinder> system() {
- sp<BadStableBinder> iface = new BadStableBinder();
- Stability::markCompilationUnit(iface.get()); // <- for test only
- return iface;
- }
-
- static sp<BadStableBinder> vintf() {
- sp<BadStableBinder> iface = new BadStableBinder();
- Stability::markVintf(iface.get()); // <- for test only
- return iface;
- }
-
- static sp<BadStableBinder> vendor() {
- sp<BadStableBinder> iface = new BadStableBinder();
- Stability::markVndk(iface.get()); // <- for test only
- return iface;
- }
-};
-String16 BadStableBinder::kDescriptor = String16("BadStableBinder.test");
-
-// NO! NO! NO! Do not even think of doing something like this!
-// This is for testing! If a class like this was actually used in production,
-// it would ruin everything!
-class MyBinderStabilityTest : public BnBinderStabilityTest {
-public:
- Status sendBinder(const sp<IBinder>& /*binder*/) override {
- return Status::ok();
- }
- Status sendAndCallBinder(const sp<IBinder>& binder) override {
- Stability::debugLogStability("sendAndCallBinder got binder", binder);
- return Status::fromExceptionCode(BadStableBinder::doUserTransaction(binder));
- }
- Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override {
- *_aidl_return = BadStableBinder::undef();
- return Status::ok();
- }
- Status returnLocalStabilityBinder(sp<IBinder>* _aidl_return) override {
- *_aidl_return = BadStableBinder::system();
- return Status::ok();
- }
- Status returnVintfStabilityBinder(sp<IBinder>* _aidl_return) override {
- *_aidl_return = BadStableBinder::vintf();
- return Status::ok();
- }
- Status returnVendorStabilityBinder(sp<IBinder>* _aidl_return) override {
- *_aidl_return = BadStableBinder::vendor();
- return Status::ok();
- }
-};
-
-TEST(BinderStability, OnlyVintfStabilityBinderNeedsVintfDeclaration) {
- EXPECT_FALSE(Stability::requiresVintfDeclaration(nullptr));
- EXPECT_FALSE(Stability::requiresVintfDeclaration(BadStableBinder::undef()));
- EXPECT_FALSE(Stability::requiresVintfDeclaration(BadStableBinder::system()));
- EXPECT_FALSE(Stability::requiresVintfDeclaration(BadStableBinder::vendor()));
-
- EXPECT_TRUE(Stability::requiresVintfDeclaration(BadStableBinder::vintf()));
-}
-
-TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) {
- sp<IBinder> vintfServer = BadStableBinder::vintf();
-
- for (const char* instance8 : {
- ".", "/", "/.", "a.d.IFoo", "foo", "a.d.IFoo/foo"
- }) {
- String16 instance (instance8);
-
- EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
- android::defaultServiceManager()->addService(String16("."), vintfServer)) << instance8;
- EXPECT_FALSE(android::defaultServiceManager()->isDeclared(instance)) << instance8;
- }
-}
-
-TEST(BinderStability, CantCallVendorBinderInSystemContext) {
- sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
- auto server = interface_cast<IBinderStabilityTest>(serverBinder);
-
- ASSERT_NE(nullptr, server.get());
- ASSERT_NE(nullptr, IInterface::asBinder(server)->remoteBinder());
-
- EXPECT_TRUE(server->sendBinder(BadStableBinder::undef()).isOk());
- EXPECT_TRUE(server->sendBinder(BadStableBinder::system()).isOk());
- EXPECT_TRUE(server->sendBinder(BadStableBinder::vintf()).isOk());
- EXPECT_TRUE(server->sendBinder(BadStableBinder::vendor()).isOk());
-
- {
- sp<BadStableBinder> binder = BadStableBinder::undef();
- EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
- EXPECT_TRUE(binder->gotUserTransaction);
- }
- {
- sp<BadStableBinder> binder = BadStableBinder::system();
- EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
- EXPECT_TRUE(binder->gotUserTransaction);
- }
- {
- sp<BadStableBinder> binder = BadStableBinder::vintf();
- EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
- EXPECT_TRUE(binder->gotUserTransaction);
- }
- {
- // !!! user-defined transaction may not be stable for remote server !!!
- // !!! so, it does not work !!!
- sp<BadStableBinder> binder = BadStableBinder::vendor();
- EXPECT_EQ(BAD_TYPE, server->sendAndCallBinder(binder).exceptionCode());
- EXPECT_FALSE(binder->gotUserTransaction);
- }
-
- sp<IBinder> out;
- EXPECT_TRUE(server->returnNoStabilityBinder(&out).isOk());
- ASSERT_NE(nullptr, out.get());
- EXPECT_EQ(OK, out->pingBinder());
- EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
-
- EXPECT_TRUE(server->returnLocalStabilityBinder(&out).isOk());
- ASSERT_NE(nullptr, out.get());
- EXPECT_EQ(OK, out->pingBinder());
- EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
-
- EXPECT_TRUE(server->returnVintfStabilityBinder(&out).isOk());
- ASSERT_NE(nullptr, out.get());
- EXPECT_EQ(OK, out->pingBinder());
- EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
-
- EXPECT_TRUE(server->returnVendorStabilityBinder(&out).isOk());
- ASSERT_NE(nullptr, out.get());
-
- // !!! libbinder-defined transaction works !!!
- EXPECT_EQ(OK, out->pingBinder());
-
- // !!! user-defined transaction may not be stable !!!
- // !!! so, it does not work !!!
- EXPECT_EQ(BAD_TYPE, BadStableBinder::doUserTransaction(out));
-}
-
-// This is handwritten so that we can test different stability levels w/o having the AIDL
-// compiler assign them. Hand-writing binder interfaces is considered a bad practice
-// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
-
-struct NdkBinderStable_DataClass {
- bool gotUserTransaction = false;
-};
-void* NdkBadStableBinder_Class_onCreate(void* args) {
- LOG_ALWAYS_FATAL_IF(args != nullptr, "Takes no args");
- return static_cast<void*>(new NdkBinderStable_DataClass);
-}
-void NdkBadStableBinder_Class_onDestroy(void* userData) {
- delete static_cast<NdkBinderStable_DataClass*>(userData);
-}
-NdkBinderStable_DataClass* NdkBadStableBinder_getUserData(AIBinder* binder) {
- LOG_ALWAYS_FATAL_IF(binder == nullptr);
- void* userData = AIBinder_getUserData(binder);
- LOG_ALWAYS_FATAL_IF(userData == nullptr, "null data - binder is remote?");
-
- return static_cast<NdkBinderStable_DataClass*>(userData);
-}
-binder_status_t NdkBadStableBinder_Class_onTransact(
- AIBinder* binder, transaction_code_t code, const AParcel* /*in*/, AParcel* /*out*/) {
-
- if (code == BadStableBinder::USER_TRANSACTION) {
- ALOGE("ndk binder stability: Got user transaction");
- NdkBadStableBinder_getUserData(binder)->gotUserTransaction = true;
- return STATUS_OK;
- }
-
- return STATUS_UNKNOWN_TRANSACTION;
-}
-
-static AIBinder_Class* kNdkBadStableBinder =
- AIBinder_Class_define(String8(BadStableBinder::kDescriptor).c_str(),
- NdkBadStableBinder_Class_onCreate,
- NdkBadStableBinder_Class_onDestroy,
- NdkBadStableBinder_Class_onTransact);
-
-// for testing only to get around __ANDROID_VNDK__ guard.
-extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY
-
-TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) {
- SpAIBinder binder = SpAIBinder(AServiceManager_getService(
- String8(kSystemStabilityServer).c_str()));
-
- std::shared_ptr<aidl::IBinderStabilityTest> remoteServer =
- aidl::IBinderStabilityTest::fromBinder(binder);
-
- ASSERT_NE(nullptr, remoteServer.get());
-
- SpAIBinder comp = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
- EXPECT_TRUE(remoteServer->sendBinder(comp).isOk());
- EXPECT_TRUE(remoteServer->sendAndCallBinder(comp).isOk());
- EXPECT_TRUE(NdkBadStableBinder_getUserData(comp.get())->gotUserTransaction);
-
- SpAIBinder vendor = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
- AIBinder_markVendorStability(vendor.get());
- EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk());
- EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk());
- EXPECT_FALSE(NdkBadStableBinder_getUserData(vendor.get())->gotUserTransaction);
-}
-
-class MarksStabilityInConstructor : public BBinder {
-public:
- static bool gDestructed;
-
- MarksStabilityInConstructor() {
- Stability::markCompilationUnit(this);
- }
- ~MarksStabilityInConstructor() {
- gDestructed = true;
- }
-};
-bool MarksStabilityInConstructor::gDestructed = false;
-
-TEST(BinderStability, MarkingObjectNoDestructTest) {
- ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
-
- // best practice is to put this directly in an sp, but for this test, we
- // want to explicitly check what happens before that happens
- MarksStabilityInConstructor* binder = new MarksStabilityInConstructor();
- ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
-
- sp<MarksStabilityInConstructor> binderSp = binder;
- ASSERT_FALSE(MarksStabilityInConstructor::gDestructed);
-
- binderSp = nullptr;
- ASSERT_TRUE(MarksStabilityInConstructor::gDestructed);
-}
-
-TEST(BinderStability, RemarkDies) {
- ASSERT_DEATH({
- sp<IBinder> binder = new BBinder();
- Stability::markCompilationUnit(binder.get()); // <-- only called for tests
- Stability::markVndk(binder.get()); // <-- only called for tests
- }, "Should only mark known object.");
-}
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
-
- if (fork() == 0) {
- // child process
- prctl(PR_SET_PDEATHSIG, SIGHUP);
-
- sp<IBinder> server = new MyBinderStabilityTest;
- android::defaultServiceManager()->addService(kSystemStabilityServer, server);
-
- IPCThreadState::self()->joinThreadPool(true);
- exit(1); // should not reach
- }
-
- // This is not racey. Just giving these services some time to register before we call
- // getService which sleeps for much longer...
- usleep(10000);
-
- return RUN_ALL_TESTS();
-}
diff --git a/libs/binder/tests/binderValueTypeTest.cpp b/libs/binder/tests/binderValueTypeTest.cpp
new file mode 100644
index 0000000000..f8922b0784
--- /dev/null
+++ b/libs/binder/tests/binderValueTypeTest.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 <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits>
+#include <cstddef>
+#include <vector>
+
+#include "android-base/file.h"
+#include <gtest/gtest.h>
+
+#include <binder/Parcel.h>
+#include <binder/Value.h>
+#include <binder/Debug.h>
+
+using ::android::binder::Value;
+using ::android::os::PersistableBundle;
+using ::android::String16;
+using ::std::vector;
+
+#define VALUE_TYPE_TEST(T, TYPENAME, VAL) \
+ TEST(ValueType, Handles ## TYPENAME) { \
+ T x = VAL; \
+ T y = T(); \
+ Value value = VAL; \
+ ASSERT_FALSE(value.empty()); \
+ ASSERT_TRUE(value.is ## TYPENAME ()); \
+ ASSERT_TRUE(value.get ## TYPENAME (&y)); \
+ ASSERT_EQ(x, y); \
+ ASSERT_EQ(value, Value(y)); \
+ value.put ## TYPENAME (x); \
+ ASSERT_EQ(value, Value(y)); \
+ value = Value(); \
+ ASSERT_TRUE(value.empty()); \
+ ASSERT_NE(value, Value(y)); \
+ value = y; \
+ ASSERT_EQ(value, Value(x)); \
+ }
+
+#define VALUE_TYPE_VECTOR_TEST(T, TYPENAME, VAL) \
+ TEST(ValueType, Handles ## TYPENAME ## Vector) { \
+ vector<T> x; \
+ vector<T> y; \
+ x.push_back(VAL); \
+ x.push_back(T()); \
+ Value value(x); \
+ ASSERT_FALSE(value.empty()); \
+ ASSERT_TRUE(value.is ## TYPENAME ## Vector()); \
+ ASSERT_TRUE(value.get ## TYPENAME ## Vector(&y)); \
+ ASSERT_EQ(x, y); \
+ ASSERT_EQ(value, Value(y)); \
+ value.put ## TYPENAME ## Vector(x); \
+ ASSERT_EQ(value, Value(y)); \
+ value = Value(); \
+ ASSERT_TRUE(value.empty()); \
+ ASSERT_NE(value, Value(y)); \
+ value = y; \
+ ASSERT_EQ(value, Value(x)); \
+ }
+
+VALUE_TYPE_TEST(bool, Boolean, true)
+VALUE_TYPE_TEST(int32_t, Int, 31337)
+VALUE_TYPE_TEST(int64_t, Long, 13370133701337L)
+VALUE_TYPE_TEST(double, Double, 3.14159265358979323846)
+VALUE_TYPE_TEST(String16, String, String16("Lovely"))
+
+VALUE_TYPE_VECTOR_TEST(bool, Boolean, true)
+VALUE_TYPE_VECTOR_TEST(int32_t, Int, 31337)
+VALUE_TYPE_VECTOR_TEST(int64_t, Long, 13370133701337L)
+VALUE_TYPE_VECTOR_TEST(double, Double, 3.14159265358979323846)
+VALUE_TYPE_VECTOR_TEST(String16, String, String16("Lovely"))
+
+VALUE_TYPE_TEST(PersistableBundle, PersistableBundle, PersistableBundle())
+
+TEST(ValueType, HandlesClear) {
+ Value value;
+ ASSERT_TRUE(value.empty());
+ value.putInt(31337);
+ ASSERT_FALSE(value.empty());
+ value.clear();
+ ASSERT_TRUE(value.empty());
+}
+
+TEST(ValueType, HandlesSwap) {
+ Value value_a, value_b;
+ int32_t int_x;
+ value_a.putInt(31337);
+ ASSERT_FALSE(value_a.empty());
+ ASSERT_TRUE(value_b.empty());
+ value_a.swap(value_b);
+ ASSERT_FALSE(value_b.empty());
+ ASSERT_TRUE(value_a.empty());
+ ASSERT_TRUE(value_b.getInt(&int_x));
+ ASSERT_EQ(31337, int_x);
+}
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index ab4c56a6af..ec9534abac 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -290,7 +290,6 @@ static void* thread_start(void* p) {
sta = tickNow();
status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
- ASSERT(ret == NO_ERROR);
end = tickNow();
results_fifo->add_time(tickNano(sta, end));
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index ee1a6a4860..512b0698d3 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -20,8 +20,6 @@ cc_library {
enabled: true,
support_system_process: true,
},
- host_supported: true,
-
srcs: [
"IPCThreadStateBase.cpp",
],
diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp
index e403d36da1..3412e14f17 100644
--- a/libs/dumputils/Android.bp
+++ b/libs/dumputils/Android.bp
@@ -17,7 +17,9 @@ cc_library {
shared_libs: [
"libbase",
+ "libbinder",
"libhidlbase",
+ "libhidltransport",
"liblog",
"libutils",
],
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 250f902f9d..047780171e 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -16,7 +16,9 @@
#include <set>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <dumputils/dump_utils.h>
#include <log/log.h>
@@ -62,16 +64,40 @@ static const char* hal_interfaces_to_dump[] {
"android.hardware.sensors@1.0::ISensors",
"android.hardware.thermal@2.0::IThermal",
"android.hardware.vr@1.0::IVr",
+ "android.hardware.automotive.audiocontrol@1.0::IAudioControl",
+ "android.hardware.automotive.vehicle@2.0::IVehicle",
+ "android.hardware.automotive.evs@1.0::IEvsCamera",
NULL,
};
-bool should_dump_hal_interface(const char* interface) {
+/* list of extra hal interfaces to dump containing process during native dumps */
+// This is filled when dumpstate is called.
+static std::set<const std::string> extra_hal_interfaces_to_dump;
+
+static void read_extra_hals_to_dump_from_property() {
+ // extra hals to dump are already filled
+ if (extra_hal_interfaces_to_dump.size() > 0) {
+ return;
+ }
+ std::string value = android::base::GetProperty("ro.dump.hals.extra", "");
+ std::vector<std::string> tokens = android::base::Split(value, ",");
+ for (const auto &token : tokens) {
+ std::string trimmed_token = android::base::Trim(token);
+ if (trimmed_token.length() == 0) {
+ continue;
+ }
+ extra_hal_interfaces_to_dump.insert(trimmed_token);
+ }
+}
+
+// check if interface is included in either default hal list or extra hal list
+bool should_dump_hal_interface(const std::string& interface) {
for (const char** i = hal_interfaces_to_dump; *i; i++) {
- if (!strcmp(*i, interface)) {
+ if (interface == *i) {
return true;
}
}
- return false;
+ return extra_hal_interfaces_to_dump.find(interface) != extra_hal_interfaces_to_dump.end();
}
bool should_dump_native_traces(const char* path) {
@@ -91,13 +117,15 @@ std::set<int> get_interesting_hal_pids() {
sp<IServiceManager> manager = IServiceManager::getService();
std::set<int> pids;
+ read_extra_hals_to_dump_from_property();
+
Return<void> ret = manager->debugDump([&](auto& hals) {
for (const auto &info : hals) {
if (info.pid == static_cast<int>(IServiceManager::PidConstant::NO_PID)) {
continue;
}
- if (!should_dump_hal_interface(info.interfaceName.c_str())) {
+ if (!should_dump_hal_interface(info.interfaceName)) {
continue;
}
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index bb9e263ac4..6e59cc5040 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -139,12 +139,8 @@ static const std::string getSystemNativeLibraries(NativeLibrary type) {
return env;
}
-int GraphicsEnv::getCanLoadSystemLibraries() {
- if (property_get_bool("ro.debuggable", false) && prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
- // Return an integer value since this crosses library boundaries
- return 1;
- }
- return 0;
+bool GraphicsEnv::isDebuggable() {
+ return prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) > 0;
}
void GraphicsEnv::setDriverPathAndSphalLibraries(const std::string path,
diff --git a/libs/graphicsenv/OWNERS b/libs/graphicsenv/OWNERS
deleted file mode 100644
index c0bb75f982..0000000000
--- a/libs/graphicsenv/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-chrisforbes@google.com
-cnorthrop@google.com
-courtneygo@google.com
-lpy@google.com
-timvp@google.com
-zzyiwei@google.com
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 937bcd9ac6..227b4587cc 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -84,7 +84,16 @@ private:
public:
static GraphicsEnv& getInstance();
- int getCanLoadSystemLibraries();
+ // Check if the process is debuggable. It returns false except in any of the
+ // following circumstances:
+ // 1. ro.debuggable=1 (global debuggable enabled).
+ // 2. android:debuggable="true" in the manifest for an individual app.
+ // 3. An app which explicitly calls prctl(PR_SET_DUMPABLE, 1).
+ // 4. GraphicsEnv calls prctl(PR_SET_DUMPABLE, 1) in the presence of
+ // <meta-data android:name="com.android.graphics.injectLayers.enable"
+ // android:value="true"/>
+ // in the application manifest.
+ bool isDebuggable();
// Set a search path for loading graphics drivers. The path is a list of
// directories separated by ':'. A directory can be contained in a zip file
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 166775b89a..e3e63ee54e 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -15,18 +15,6 @@ cc_library_headers {
name: "libgui_headers",
vendor_available: true,
export_include_dirs: ["include"],
-
- // we must build this module to get the required header as that is generated
- export_shared_lib_headers: [
- "android.hidl.token@1.0-utils",
- "android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.graphics.bufferqueue@2.0",
- ],
- shared_libs: [
- "android.hidl.token@1.0-utils",
- "android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.graphics.bufferqueue@2.0",
- ],
}
cc_library_shared {
@@ -178,6 +166,8 @@ cc_defaults {
"libEGL",
"libGLESv2",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"liblog",
"libnativewindow",
"libsync",
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 528bfb194e..3a7cb44450 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -166,7 +166,9 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
mCore->mFreeBuffers.push_back(front->mSlot);
}
- listener = mCore->mConnectedProducerListener;
+ if (mCore->mBufferReleasedCbEnabled) {
+ listener = mCore->mConnectedProducerListener;
+ }
++numDroppedBuffers;
}
@@ -457,7 +459,9 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
mCore->mFreeBuffers.push_back(slot);
}
- listener = mCore->mConnectedProducerListener;
+ if (mCore->mBufferReleasedCbEnabled) {
+ listener = mCore->mConnectedProducerListener;
+ }
BQ_LOGV("releaseBuffer: releasing slot %d", slot);
mCore->mDequeueCondition.notify_all();
@@ -668,7 +672,7 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
VALIDATE_CONSISTENCY();
- if (delta < 0) {
+ if (delta < 0 && mCore->mBufferReleasedCbEnabled) {
listener = mCore->mConsumerListener;
}
}
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index e0e3431ca5..0264bd24a6 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -65,6 +65,7 @@ BufferQueueCore::BufferQueueCore() :
mConnectedApi(NO_CONNECTED_API),
mLinkedToDeath(),
mConnectedProducerListener(),
+ mBufferReleasedCbEnabled(false),
mSlots(),
mQueue(),
mFreeSlots(),
@@ -260,6 +261,12 @@ void BufferQueueCore::freeAllBuffersLocked() {
}
void BufferQueueCore::discardFreeBuffersLocked() {
+ // Notify producer about the discarded buffers.
+ if (mConnectedProducerListener != nullptr && mFreeBuffers.size() > 0) {
+ std::vector<int32_t> freeBuffers(mFreeBuffers.begin(), mFreeBuffers.end());
+ mConnectedProducerListener->onBuffersDiscarded(freeBuffers);
+ }
+
for (int s : mFreeBuffers) {
mFreeSlots.insert(s);
clearBufferSlotLocked(s);
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 92ab41019e..a317aaf2f2 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1221,9 +1221,8 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
}
mCore->mLinkedToDeath = listener;
}
- if (listener->needsReleaseNotify()) {
- mCore->mConnectedProducerListener = listener;
- }
+ mCore->mConnectedProducerListener = listener;
+ mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();
}
break;
default:
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index 936063a5bd..808e3369f1 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -24,6 +24,7 @@ namespace android {
enum {
ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION,
NEEDS_RELEASE_NOTIFY,
+ ON_BUFFERS_DISCARDED,
};
class BpProducerListener : public BpInterface<IProducerListener>
@@ -56,6 +57,13 @@ public:
}
return result;
}
+
+ virtual void onBuffersDiscarded(const std::vector<int>& discardedSlots) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
+ data.writeInt32Vector(discardedSlots);
+ remote()->transact(ON_BUFFERS_DISCARDED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -76,6 +84,10 @@ public:
virtual bool needsReleaseNotify() override {
return mBase->needsReleaseNotify();
}
+
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& discardedSlots) override {
+ return mBase->onBuffersDiscarded(discardedSlots);
+ }
};
IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener,
@@ -92,6 +104,17 @@ status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data,
CHECK_INTERFACE(IProducerListener, data, reply);
reply->writeBool(needsReleaseNotify());
return NO_ERROR;
+ case ON_BUFFERS_DISCARDED: {
+ CHECK_INTERFACE(IProducerListener, data, reply);
+ std::vector<int32_t> discardedSlots;
+ status_t result = data.readInt32Vector(&discardedSlots);
+ if (result != NO_ERROR) {
+ ALOGE("ON_BUFFERS_DISCARDED failed to read discardedSlots: %d", result);
+ return result;
+ }
+ onBuffersDiscarded(discardedSlots);
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
@@ -104,4 +127,7 @@ bool BnProducerListener::needsReleaseNotify() {
return true;
}
+void BnProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*discardedSlots*/) {
+}
+
} // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 12deaf0bd6..e487792c87 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -88,7 +88,7 @@ public:
data.writeStrongBinder(applyToken);
commands.write(data);
data.writeInt64(desiredPresentTime);
- data.writeStrongBinder(uncacheBuffer.token.promote());
+ data.writeWeakBinder(uncacheBuffer.token);
data.writeUint64(uncacheBuffer.id);
if (data.writeVectorSize(listenerCallbacks) == NO_ERROR) {
@@ -1036,7 +1036,7 @@ status_t BnSurfaceComposer::onTransact(
int64_t desiredPresentTime = data.readInt64();
client_cache_t uncachedBuffer;
- uncachedBuffer.token = data.readStrongBinder();
+ uncachedBuffer.token = data.readWeakBinder();
uncachedBuffer.id = data.readUint64();
std::vector<ListenerCallbacks> listenerCallbacks;
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 42eb9213d6..6066421faf 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -87,7 +87,7 @@ status_t layer_state_t::write(Parcel& output) const
colorTransform.asArray(), 16 * sizeof(float));
output.writeFloat(cornerRadius);
output.writeBool(hasListenerCallbacks);
- output.writeStrongBinder(cachedBuffer.token.promote());
+ output.writeWeakBinder(cachedBuffer.token);
output.writeUint64(cachedBuffer.id);
output.writeParcelable(metadata);
@@ -157,7 +157,7 @@ status_t layer_state_t::read(const Parcel& input)
colorTransform = mat4(static_cast<const float*>(input.readInplace(16 * sizeof(float))));
cornerRadius = input.readFloat();
hasListenerCallbacks = input.readBool();
- cachedBuffer.token = input.readStrongBinder();
+ cachedBuffer.token = input.readWeakBinder();
cachedBuffer.id = input.readUint64();
input.readParcelable(&metadata);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 9fe5de82d1..b822319d22 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -35,6 +35,7 @@
#include <ui/DisplayStatInfo.h>
#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
#include <ui/HdrCapabilities.h>
#include <ui/Region.h>
@@ -1287,6 +1288,14 @@ int Surface::connect(int api, const sp<IProducerListener>& listener) {
}
int Surface::connect(
+ int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) {
+ if (sListener != nullptr) {
+ mListenerProxy = new ProducerListenerProxy(this, sListener);
+ }
+ return connect(api, mListenerProxy, reportBufferRemoval);
+}
+
+int Surface::connect(
int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) {
ATRACE_CALL();
ALOGV("Surface::connect");
@@ -1684,6 +1693,28 @@ void Surface::freeAllBuffers() {
}
}
+status_t Surface::getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots,
+ std::vector<sp<GraphicBuffer>>* outBuffers) {
+ ALOGV("Surface::getAndFlushBuffersFromSlots");
+ for (int32_t i : slots) {
+ if (i < 0 || i >= NUM_BUFFER_SLOTS) {
+ ALOGE("%s: Invalid slotIndex: %d", __FUNCTION__, i);
+ return BAD_VALUE;
+ }
+ }
+
+ Mutex::Autolock lock(mMutex);
+ for (int32_t i : slots) {
+ if (mSlots[i].buffer == nullptr) {
+ ALOGW("%s: Discarded slot %d doesn't contain buffer!", __FUNCTION__, i);
+ continue;
+ }
+ outBuffers->push_back(mSlots[i].buffer);
+ mSlots[i].buffer = nullptr;
+ }
+ return OK;
+}
+
void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
ATRACE_CALL();
ALOGV("Surface::setSurfaceDamage");
@@ -1951,4 +1982,22 @@ status_t Surface::attachAndQueueBufferWithDataspace(Surface* surface, sp<Graphic
return err;
}
+void Surface::ProducerListenerProxy::onBuffersDiscarded(const std::vector<int32_t>& slots) {
+ ATRACE_CALL();
+ sp<Surface> parent = mParent.promote();
+ if (parent == nullptr) {
+ return;
+ }
+
+ std::vector<sp<GraphicBuffer>> discardedBufs;
+ status_t res = parent->getAndFlushBuffersFromSlots(slots, &discardedBufs);
+ if (res != OK) {
+ ALOGE("%s: Failed to get buffers from slots: %s(%d)", __FUNCTION__,
+ strerror(-res), res);
+ return;
+ }
+
+ mSurfaceListener->onBuffersDiscarded(discardedBufs);
+}
+
}; // namespace android
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 690a85f395..17617bce13 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -189,8 +189,12 @@ private:
sp<IProducerListener> mLinkedToDeath;
// mConnectedProducerListener is used to handle the onBufferReleased
- // notification.
+ // and onBuffersDiscarded notification.
sp<IProducerListener> mConnectedProducerListener;
+ // mBufferReleasedCbEnabled is used to indicate whether onBufferReleased()
+ // callback is registered by the listener. When set to false,
+ // mConnectedProducerListener will not trigger onBufferReleased() callback.
+ bool mBufferReleasedCbEnabled;
// mSlots is an array of buffer slots that must be mirrored on the producer
// side. This allows buffer ownership to be transferred between the producer
diff --git a/libs/gui/include/gui/IProducerListener.h b/libs/gui/include/gui/IProducerListener.h
index a13d8e4945..32a3690ff2 100644
--- a/libs/gui/include/gui/IProducerListener.h
+++ b/libs/gui/include/gui/IProducerListener.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_GUI_IPRODUCERLISTENER_H
#define ANDROID_GUI_IPRODUCERLISTENER_H
+#include <vector>
+
#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
#include <android/hardware/graphics/bufferqueue/2.0/IProducerListener.h>
#include <binder/IInterface.h>
@@ -44,6 +46,9 @@ public:
// multiple threads.
virtual void onBufferReleased() = 0; // Asynchronous
virtual bool needsReleaseNotify() = 0;
+ // onBuffersFreed is called from IGraphicBufferConsumer::discardFreeBuffers
+ // to notify the producer that certain free buffers are discarded by the consumer.
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) = 0; // Asynchronous
};
class IProducerListener : public ProducerListener, public IInterface
@@ -65,6 +70,7 @@ public:
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0);
virtual bool needsReleaseNotify();
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& slots);
};
class DummyProducerListener : public BnProducerListener
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 5c6a1ee383..a5641b07e5 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -20,6 +20,7 @@
#include <gui/BufferQueueDefs.h>
#include <gui/HdrMetadata.h>
#include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
#include <ui/ANativeObjectBase.h>
#include <ui/GraphicTypes.h>
@@ -35,6 +36,21 @@ namespace android {
class ISurfaceComposer;
+/* This is the same as ProducerListener except that onBuffersDiscarded is
+ * called with a vector of graphic buffers instead of buffer slots.
+ */
+class SurfaceListener : public virtual RefBase
+{
+public:
+ SurfaceListener() = default;
+ virtual ~SurfaceListener() = default;
+
+ virtual void onBufferReleased() = 0;
+ virtual bool needsReleaseNotify() = 0;
+
+ virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) = 0;
+};
+
/*
* An implementation of ANativeWindow that feeds graphics buffers into a
* BufferQueue.
@@ -283,6 +299,10 @@ public:
sp<Fence>* outFence);
virtual int attachBuffer(ANativeWindowBuffer*);
+ virtual int connect(
+ int api, bool reportBufferRemoval,
+ const sp<SurfaceListener>& sListener);
+
// When client connects to Surface with reportBufferRemoval set to true, any buffers removed
// from this Surface will be collected and returned here. Once this method returns, these
// buffers will no longer be referenced by this Surface unless they are attached to this
@@ -299,6 +319,26 @@ protected:
enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
+ class ProducerListenerProxy : public BnProducerListener {
+ public:
+ ProducerListenerProxy(wp<Surface> parent, sp<SurfaceListener> listener)
+ : mParent(parent), mSurfaceListener(listener) {}
+ virtual ~ProducerListenerProxy() {}
+
+ virtual void onBufferReleased() {
+ mSurfaceListener->onBufferReleased();
+ }
+
+ virtual bool needsReleaseNotify() {
+ return mSurfaceListener->needsReleaseNotify();
+ }
+
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& slots);
+ private:
+ wp<Surface> mParent;
+ sp<SurfaceListener> mSurfaceListener;
+ };
+
void querySupportedTimestampsLocked() const;
void freeAllBuffers();
@@ -466,6 +506,10 @@ protected:
bool mReportRemovedBuffers = false;
std::vector<sp<GraphicBuffer>> mRemovedBuffers;
+
+ sp<IProducerListener> mListenerProxy;
+ status_t getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots,
+ std::vector<sp<GraphicBuffer>>* outBuffers);
};
} // namespace android
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index cbda6b23ff..ab6dcaa3f6 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -47,6 +47,7 @@ cc_test {
"libcutils",
"libgui",
"libhidlbase",
+ "libhidltransport",
"libinput",
"libui",
"libutils",
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 119e888edb..406f21faf6 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -998,12 +998,31 @@ TEST_F(BufferQueueTest, TestOccupancyHistory) {
ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
}
+struct BufferDiscardedListener : public BnProducerListener {
+public:
+ BufferDiscardedListener() = default;
+ virtual ~BufferDiscardedListener() = default;
+
+ virtual void onBufferReleased() {}
+ virtual bool needsReleaseNotify() { return false; }
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
+ mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
+ }
+
+ const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
+private:
+ // No need to use lock given the test triggers the listener in the same
+ // thread context.
+ std::vector<int32_t> mDiscardedSlots;
+};
+
TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
createBufferQueue();
sp<DummyConsumer> dc(new DummyConsumer);
ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+ sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
+ ASSERT_EQ(OK, mProducer->connect(pl,
NATIVE_WINDOW_API_CPU, false, &output));
int slot = BufferQueue::INVALID_BUFFER_SLOT;
@@ -1044,12 +1063,19 @@ TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ int releasedSlot = item.mSlot;
+
// Acquire 1 buffer, leaving 1 filled buffer in queue
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
// Now discard the free buffers
ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
+ // Check onBuffersDiscarded is called with correct slots
+ auto buffersDiscarded = pl->getDiscardedSlots();
+ ASSERT_EQ(buffersDiscarded.size(), 1);
+ ASSERT_EQ(buffersDiscarded[0], releasedSlot);
+
// Check no free buffers in dump
String8 dumpString;
mConsumer->dumpState(String8{}, &dumpString);
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 0babd23573..66a8a04c82 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -133,27 +133,6 @@ public:
EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
}
- void expectMotionEvent(int motionEventType, int x, int y) {
- InputEvent *ev = consumeEvent();
- ASSERT_NE(ev, nullptr);
- ASSERT_EQ(ev->getType(), AINPUT_EVENT_TYPE_MOTION);
- MotionEvent *mev = static_cast<MotionEvent *>(ev);
- EXPECT_EQ(motionEventType, mev->getAction());
- EXPECT_EQ(x, mev->getX(0));
- EXPECT_EQ(y, mev->getY(0));
- }
-
- void expectNoMotionEvent(int motionEventType) {
- InputEvent *ev = consumeEvent();
- if (ev == nullptr || ev->getType() != AINPUT_EVENT_TYPE_MOTION) {
- // Didn't find an event or a motion event so assume action didn't occur.
- return;
- }
-
- MotionEvent *mev = static_cast<MotionEvent *>(ev);
- EXPECT_NE(motionEventType, mev->getAction());
- }
-
~InputSurface() {
mInputFlinger->unregisterInputChannel(mServerChannel);
}
@@ -278,15 +257,6 @@ void injectTap(int x, int y) {
}
}
-void injectMotionEvent(std::string event, int x, int y) {
- char *buf1, *buf2;
- asprintf(&buf1, "%d", x);
- asprintf(&buf2, "%d", y);
- if (fork() == 0) {
- execlp("input", "input", "motionevent", event.c_str(), buf1, buf2, NULL);
- }
-}
-
TEST_F(InputSurfacesTest, can_receive_input) {
std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
surface->showAt(100, 100);
@@ -410,19 +380,6 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) {
bgSurface->expectTap(1, 1);
}
-TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) {
- std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
- // In case we pass the very big inset without any checking.
- fgSurface->mInputInfo.surfaceInset = INT32_MAX;
- fgSurface->showAt(100, 100);
-
- fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
-
- // expect no crash for overflow, and inset size to be clamped to surface size
- injectTap(202, 202);
- fgSurface->expectTap(1, 1);
-}
-
// Ensure we ignore transparent region when getting screen bounds when positioning input frame.
TEST_F(InputSurfacesTest, input_ignores_transparent_region) {
std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
@@ -506,26 +463,6 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) {
bgSurface->expectTap(1, 1);
}
-TEST_F(InputSurfacesTest, transfer_touch_focus) {
- std::unique_ptr<InputSurface> fromSurface = makeSurface(100, 100);
-
- fromSurface->showAt(10, 10);
- injectMotionEvent("DOWN", 11, 11);
- fromSurface->expectMotionEvent(AMOTION_EVENT_ACTION_DOWN, 1, 1);
-
- std::unique_ptr<InputSurface> toSurface = makeSurface(100, 100);
- toSurface->showAt(10, 10);
-
- sp<IBinder> fromToken = fromSurface->mServerChannel->getToken();
- sp<IBinder> toToken = toSurface->mServerChannel->getToken();
- SurfaceComposerClient::Transaction t;
- t.transferTouchFocus(fromToken, toToken).apply(true);
-
- injectMotionEvent("UP", 11, 11);
- toSurface->expectMotionEvent(AMOTION_EVENT_ACTION_UP, 1, 1);
- fromSurface->expectNoMotionEvent(AMOTION_EVENT_ACTION_UP);
-}
-
TEST_F(InputSurfacesTest, input_respects_outscreen) {
std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
surface->showAt(-1, -1);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index d3708586f5..a8516872fd 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -57,6 +57,37 @@ class FakeProducerFrameEventHistory;
static constexpr uint64_t NO_FRAME_INDEX = std::numeric_limits<uint64_t>::max();
+class DummySurfaceListener : public SurfaceListener {
+public:
+ DummySurfaceListener(bool enableReleasedCb = false) :
+ mEnableReleaseCb(enableReleasedCb),
+ mBuffersReleased(0) {}
+ virtual ~DummySurfaceListener() = default;
+
+ virtual void onBufferReleased() {
+ mBuffersReleased++;
+ }
+ virtual bool needsReleaseNotify() {
+ return mEnableReleaseCb;
+ }
+ virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) {
+ mDiscardedBuffers.insert(mDiscardedBuffers.end(), buffers.begin(), buffers.end());
+ }
+
+ int getReleaseNotifyCount() const {
+ return mBuffersReleased;
+ }
+ const std::vector<sp<GraphicBuffer>>& getDiscardedBuffers() const {
+ return mDiscardedBuffers;
+ }
+private:
+ // No need to use lock given the test triggers the listener in the same
+ // thread context.
+ bool mEnableReleaseCb;
+ int32_t mBuffersReleased;
+ std::vector<sp<GraphicBuffer>> mDiscardedBuffers;
+};
+
class SurfaceTest : public ::testing::Test {
protected:
SurfaceTest() {
@@ -88,6 +119,86 @@ protected:
mComposerClient->dispose();
}
+ void testSurfaceListener(bool hasSurfaceListener, bool enableReleasedCb,
+ int32_t extraDiscardedBuffers) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+ consumer->consumerConnect(dummyConsumer, false);
+ consumer->setConsumerName(String8("TestConsumer"));
+
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+ sp<DummySurfaceListener> listener;
+ if (hasSurfaceListener) {
+ listener = new DummySurfaceListener(enableReleasedCb);
+ }
+ ASSERT_EQ(OK, surface->connect(
+ NATIVE_WINDOW_API_CPU,
+ /*reportBufferRemoval*/true,
+ /*listener*/listener));
+ const int BUFFER_COUNT = 4 + extraDiscardedBuffers;
+ ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(window.get(), BUFFER_COUNT));
+
+ ANativeWindowBuffer* buffers[BUFFER_COUNT];
+ // Dequeue first to allocate a number of buffers
+ for (int i = 0; i < BUFFER_COUNT; i++) {
+ ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffers[i]));
+ }
+ for (int i = 0; i < BUFFER_COUNT; i++) {
+ ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], -1));
+ }
+
+ ANativeWindowBuffer* buffer;
+ // Fill BUFFER_COUNT-1 buffers
+ for (int i = 0; i < BUFFER_COUNT-1; i++) {
+ ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffer));
+ ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, -1));
+ }
+
+ // Dequeue 1 buffer
+ ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffer));
+
+ // Acquire and free 1+extraDiscardedBuffers buffer, check onBufferReleased is called.
+ std::vector<BufferItem> releasedItems;
+ releasedItems.resize(1+extraDiscardedBuffers);
+ for (int i = 0; i < releasedItems.size(); i++) {
+ ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&releasedItems[i], 0));
+ ASSERT_EQ(NO_ERROR, consumer->releaseBuffer(releasedItems[i].mSlot,
+ releasedItems[i].mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
+ Fence::NO_FENCE));
+ }
+ int32_t expectedReleaseCb = (enableReleasedCb ? releasedItems.size() : 0);
+ if (hasSurfaceListener) {
+ ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount());
+ }
+
+ // Acquire 1 buffer, leaving 1+extraDiscardedBuffers filled buffer in queue
+ BufferItem item;
+ ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&item, 0));
+
+ // Discard free buffers
+ ASSERT_EQ(NO_ERROR, consumer->discardFreeBuffers());
+
+ if (hasSurfaceListener) {
+ ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount());
+
+ // Check onBufferDiscarded is called with correct buffer
+ auto discardedBuffers = listener->getDiscardedBuffers();
+ ASSERT_EQ(discardedBuffers.size(), releasedItems.size());
+ for (int i = 0; i < releasedItems.size(); i++) {
+ ASSERT_EQ(discardedBuffers[i], releasedItems[i].mGraphicBuffer);
+ }
+
+ ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount());
+ }
+
+ // Disconnect the surface
+ ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU));
+ }
+
sp<Surface> mSurface;
sp<SurfaceComposerClient> mComposerClient;
sp<SurfaceControl> mSurfaceControl;
@@ -480,6 +591,21 @@ TEST_F(SurfaceTest, GetAndFlushRemovedBuffers) {
ASSERT_LE(removedBuffers.size(), 1u);
}
+TEST_F(SurfaceTest, SurfaceListenerTest) {
+ // Test discarding 1 free buffers with no listener
+ testSurfaceListener(/*hasListener*/false, /*enableReleaseCb*/false, /*extraDiscardedBuffers*/0);
+ // Test discarding 2 free buffers with no listener
+ testSurfaceListener(/*hasListener*/false, /*enableReleaseCb*/false, /*extraDiscardedBuffers*/1);
+ // Test discarding 1 free buffers with a listener, disabling onBufferReleased
+ testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/false, /*extraDiscardedBuffers*/0);
+ // Test discarding 2 free buffers with a listener, disabling onBufferReleased
+ testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/false, /*extraDiscardedBuffers*/1);
+ // Test discarding 1 free buffers with a listener, enabling onBufferReleased
+ testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/true, /*extraDiscardedBuffers*/0);
+ // Test discarding 3 free buffers with a listener, enabling onBufferReleased
+ testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/true, /*extraDiscardedBuffers*/2);
+}
+
TEST_F(SurfaceTest, TestGetLastDequeueStartTime) {
sp<ANativeWindow> anw(mSurface);
ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU));
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index d6a73bfd27..de3a23d76e 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -45,16 +45,6 @@ public:
IBinder::FLAG_ONEWAY);
}
- virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
- Parcel data, reply;
- data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
-
- data.writeStrongBinder(fromToken);
- data.writeStrongBinder(toToken);
- remote()->transact(BnInputFlinger::TRANSFER_TOUCH_FOCUS, data, &reply,
- IBinder::FLAG_ONEWAY);
- }
-
virtual void registerInputChannel(const sp<InputChannel>& channel) {
Parcel data, reply;
data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
@@ -104,13 +94,6 @@ status_t BnInputFlinger::onTransact(
unregisterInputChannel(channel);
break;
}
- case TRANSFER_TOUCH_FOCUS: {
- CHECK_INTERFACE(IInputFlinger, data, reply);
- sp<IBinder> fromToken = data.readStrongBinder();
- sp<IBinder> toToken = data.readStrongBinder();
- transferTouchFocus(fromToken, toToken);
- break;
- }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index ec28757933..5a60347ed3 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -99,7 +99,7 @@ status_t InputWindowInfo::write(Parcel& output) const {
applicationInfo.write(output);
output.write(touchableRegion);
output.writeBool(replaceTouchableRegionWithCrop);
- output.writeStrongBinder(touchableRegionCropHandle.promote());
+ output.writeWeakBinder(touchableRegionCropHandle);
return OK;
}
@@ -142,7 +142,7 @@ InputWindowInfo InputWindowInfo::read(const Parcel& from) {
ret.applicationInfo = InputApplicationInfo::read(from);
from.read(ret.touchableRegion);
ret.replaceTouchableRegionWithCrop = from.readBool();
- ret.touchableRegionCropHandle = from.readStrongBinder();
+ ret.touchableRegionCropHandle = from.readWeakBinder();
return ret;
}
diff --git a/libs/input/TouchVideoFrame.cpp b/libs/input/TouchVideoFrame.cpp
index 8a4298a36f..ce76e3fa6d 100644
--- a/libs/input/TouchVideoFrame.cpp
+++ b/libs/input/TouchVideoFrame.cpp
@@ -42,13 +42,13 @@ const struct timeval& TouchVideoFrame::getTimestamp() const { return mTimestamp;
void TouchVideoFrame::rotate(int32_t orientation) {
switch (orientation) {
case DISPLAY_ORIENTATION_90:
- rotateQuarterTurn(true /*clockwise*/);
+ rotateQuarterTurn(false /*clockwise*/);
break;
case DISPLAY_ORIENTATION_180:
rotate180();
break;
case DISPLAY_ORIENTATION_270:
- rotateQuarterTurn(false /*clockwise*/);
+ rotateQuarterTurn(true /*clockwise*/);
break;
}
}
diff --git a/libs/input/tests/TouchVideoFrame_test.cpp b/libs/input/tests/TouchVideoFrame_test.cpp
index 815424ee31..fe06cad72c 100644
--- a/libs/input/tests/TouchVideoFrame_test.cpp
+++ b/libs/input/tests/TouchVideoFrame_test.cpp
@@ -85,14 +85,14 @@ TEST(TouchVideoFrame, Rotate90_1x1) {
TEST(TouchVideoFrame, Rotate90_2x2) {
TouchVideoFrame frame(2, 2, {1, 2, 3, 4}, TIMESTAMP);
- TouchVideoFrame frameRotated(2, 2, {3, 1, 4, 2}, TIMESTAMP);
+ TouchVideoFrame frameRotated(2, 2, {2, 4, 1, 3}, TIMESTAMP);
frame.rotate(DISPLAY_ORIENTATION_90);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate90_3x2) {
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
- TouchVideoFrame frameRotated(2, 3, {5, 3, 1, 6, 4, 2}, TIMESTAMP);
+ TouchVideoFrame frameRotated(2, 3, {2, 4, 6, 1, 3, 5}, TIMESTAMP);
frame.rotate(DISPLAY_ORIENTATION_90);
ASSERT_EQ(frame, frameRotated);
}
@@ -170,14 +170,14 @@ TEST(TouchVideoFrame, Rotate270_1x1) {
TEST(TouchVideoFrame, Rotate270_2x2) {
TouchVideoFrame frame(2, 2, {1, 2, 3, 4}, TIMESTAMP);
- TouchVideoFrame frameRotated(2, 2, {2, 4, 1, 3}, TIMESTAMP);
+ TouchVideoFrame frameRotated(2, 2, {3, 1, 4, 2}, TIMESTAMP);
frame.rotate(DISPLAY_ORIENTATION_270);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate270_3x2) {
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
- TouchVideoFrame frameRotated(2, 3, {2, 4, 6, 1, 3, 5}, TIMESTAMP);
+ TouchVideoFrame frameRotated(2, 3, {5, 3, 1, 6, 4, 2}, TIMESTAMP);
frame.rotate(DISPLAY_ORIENTATION_270);
ASSERT_EQ(frame, frameRotated);
}
diff --git a/libs/math/include/math/quat.h b/libs/math/include/math/quat.h
index 07573c5ecf..1936a2baec 100644
--- a/libs/math/include/math/quat.h
+++ b/libs/math/include/math/quat.h
@@ -109,7 +109,7 @@ public:
// initialize from 4 values to w + xi + yj + zk
template<typename A, typename B, typename C, typename D>
- constexpr TQuaternion(A w, B x, C y, D z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)), w(static_cast<T>(w)) { }
+ constexpr TQuaternion(A w, B x, C y, D z) : x(x), y(y), z(z), w(w) { }
// initialize from a vec3 + a value to : v.xi + v.yj + v.zk + w
template<typename A, typename B>
diff --git a/libs/math/include/math/vec2.h b/libs/math/include/math/vec2.h
index e0adb7f6cc..a34763347c 100644
--- a/libs/math/include/math/vec2.h
+++ b/libs/math/include/math/vec2.h
@@ -89,7 +89,7 @@ public:
constexpr TVec2(A v) : x(v), y(v) { }
template<typename A, typename B>
- constexpr TVec2(A x, B y) : x(static_cast<T>(x)), y(static_cast<T>(y)) { }
+ constexpr TVec2(A x, B y) : x(x), y(y) { }
template<typename A>
explicit
diff --git a/libs/math/include/math/vec3.h b/libs/math/include/math/vec3.h
index 21fb684efc..009fd84e3b 100644
--- a/libs/math/include/math/vec3.h
+++ b/libs/math/include/math/vec3.h
@@ -86,13 +86,13 @@ public:
// handles implicit conversion to a tvec4. must not be explicit.
template<typename A, typename = typename std::enable_if<std::is_arithmetic<A>::value >::type>
- constexpr TVec3(A v) : x(static_cast<T>(v)), y(static_cast<T>(v)), z(static_cast<T>(v)) { }
+ constexpr TVec3(A v) : x(v), y(v), z(v) { }
template<typename A, typename B, typename C>
- constexpr TVec3(A x, B y, C z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)) { }
+ constexpr TVec3(A x, B y, C z) : x(x), y(y), z(z) { }
template<typename A, typename B>
- constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(static_cast<T>(z)) { }
+ constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(z) { }
template<typename A>
explicit
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 1ec73ce961..9bd30955f3 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -266,10 +266,10 @@ int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int so
char buf[CMSG_SPACE(kFdBufferSize)];
struct msghdr msg = {
- .msg_iov = &iov[0],
- .msg_iovlen = 1,
.msg_control = buf,
.msg_controllen = sizeof(buf),
+ .msg_iov = &iov[0],
+ .msg_iovlen = 1,
};
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
@@ -306,10 +306,10 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out
iov[0].iov_len = kMessageBufferSize;
struct msghdr msg = {
- .msg_iov = &iov[0],
- .msg_iovlen = 1,
.msg_control = fdBuf,
.msg_controllen = sizeof(fdBuf),
+ .msg_iov = &iov[0],
+ .msg_iovlen = 1,
};
int result;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index ae5e47ba97..da959e36d2 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -342,8 +342,6 @@ typedef struct AHardwareBuffer AHardwareBuffer;
* not compatible with its usage flags, the results are undefined and
* may include program termination.
*
- * Available since API level 26.
- *
* \return 0 on success, or an error number of the allocation fails for
* any reason. The returned buffer has a reference count of 1.
*/
@@ -354,24 +352,18 @@ int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
*
* This prevents the object from being deleted until the last reference
* is removed.
- *
- * Available since API level 26.
*/
void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
/**
* Remove a reference that was previously acquired with
* AHardwareBuffer_acquire() or AHardwareBuffer_allocate().
- *
- * Available since API level 26.
*/
void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
/**
* Return a description of the AHardwareBuffer in the passed
* AHardwareBuffer_Desc struct.
- *
- * Available since API level 26.
*/
void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26);
@@ -421,8 +413,6 @@ void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
* simultaneously, and the contents of the buffer behave like shared
* memory.
*
- * Available since API level 26.
- *
* \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags
* are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer
* has more than one layer. Error number if the lock fails for any other
@@ -451,8 +441,6 @@ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage,
*
* See the AHardwareBuffer_lock documentation for all other locking semantics.
*
- * Available since API level 29.
- *
* \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags
* are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer
* has more than one layer. Error number if the lock fails for any other
@@ -474,8 +462,6 @@ int AHardwareBuffer_lockPlanes(AHardwareBuffer* buffer, uint64_t usage,
* completed before the function returned and no further operations are
* necessary.
*
- * Available since API level 26.
- *
* \return 0 on success. -EINVAL if \a buffer is NULL. Error number if
* the unlock fails for any reason.
*/
@@ -484,8 +470,6 @@ int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED
/**
* Send the AHardwareBuffer to an AF_UNIX socket.
*
- * Available since API level 26.
- *
* \return 0 on success, -EINVAL if \a buffer is NULL, or an error
* number if the operation fails for any reason.
*/
@@ -494,8 +478,6 @@ int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int so
/**
* Receive an AHardwareBuffer from an AF_UNIX socket.
*
- * Available since API level 26.
- *
* \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error
* number if the operation fails for any reason.
*/
@@ -519,8 +501,6 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out
* some implementations have implementation-defined limits on texture
* size and layer count.
*
- * Available since API level 29.
- *
* \return 1 if the format and usage flag combination is allocatable,
* 0 otherwise.
*/
@@ -534,8 +514,6 @@ int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) __INTRODUCED_I
* of the locked buffer. If the bytes per pixel or bytes per stride are unknown
* or variable, or if the underlying mapper implementation does not support returning
* additional information, then this call will fail with INVALID_OPERATION
- *
- * Available since API level 29.
*/
int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
int32_t fence, const ARect* rect, void** outVirtualAddress,
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 3e436e3b07..6730596ec7 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -189,8 +189,6 @@ int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
/**
* Set a transform that will be applied to future buffers posted to the window.
*
- * Available since API level 26.
- *
* \param transform combination of {@link ANativeWindowTransform} flags
* \return 0 for success, or -EINVAL if \p transform is invalid
*/
@@ -210,8 +208,6 @@ int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transfo
* measurement data instead of color images. The default dataSpace is 0,
* ADATASPACE_UNKNOWN, unless it has been overridden by the producer.
*
- * Available since API level 28.
- *
* \param dataSpace data space of all buffers queued after this call.
* \return 0 for success, -EINVAL if window is invalid or the dataspace is not
* supported.
@@ -220,9 +216,6 @@ int32_t ANativeWindow_setBuffersDataSpace(ANativeWindow* window, int32_t dataSpa
/**
* Get the dataspace of the buffers in window.
- *
- * Available since API level 28.
- *
* \return the dataspace of buffers in window, ADATASPACE_UNKNOWN is returned if
* dataspace is unknown, or -EINVAL if window is invalid.
*/
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
index e8154a6931..940ff5afbc 100644
--- a/libs/sensor/Android.bp
+++ b/libs/sensor/Android.bp
@@ -21,7 +21,22 @@ cc_library_shared {
"-Werror",
],
cppflags: [
- "-Wextra",
+ "-Weverything",
+
+ // The static constructors and destructors in this library have not been noted to
+ // introduce significant overheads
+ "-Wno-exit-time-destructors",
+ "-Wno-global-constructors",
+
+ // We only care about compiling as C++14
+ "-Wno-c++98-compat-pedantic",
+
+ // android/sensors.h uses nested anonymous unions and anonymous structs
+ "-Wno-nested-anon-types",
+ "-Wno-gnu-anonymous-struct",
+
+ // Don't warn about struct padding
+ "-Wno-padded",
],
srcs: [
diff --git a/libs/sensor/OWNERS b/libs/sensor/OWNERS
index 90c233030e..81099e895c 100644
--- a/libs/sensor/OWNERS
+++ b/libs/sensor/OWNERS
@@ -1,3 +1,3 @@
arthuri@google.com
bduddie@google.com
-stange@google.com
+bstack@google.com
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index bf8b9f73fe..96d5eb9d1f 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -150,7 +150,7 @@ status_t SensorManager::assertStateLocked() {
class DeathObserver : public IBinder::DeathRecipient {
SensorManager& mSensorManager;
virtual void binderDied(const wp<IBinder>& who) {
- ALOGW("sensorservice died [%p]", static_cast<void*>(who.unsafe_get()));
+ ALOGW("sensorservice died [%p]", who.unsafe_get());
mSensorManager.sensorManagerDied();
}
public:
diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp
index 4a606ffec2..e0e3469fbb 100644
--- a/libs/sensorprivacy/Android.bp
+++ b/libs/sensorprivacy/Android.bp
@@ -28,7 +28,8 @@ cc_library_shared {
],
srcs: [
- ":libsensorprivacy_aidl",
+ "aidl/android/hardware/ISensorPrivacyListener.aidl",
+ "aidl/android/hardware/ISensorPrivacyManager.aidl",
"SensorPrivacyManager.cpp",
],
@@ -44,12 +45,3 @@ cc_library_shared {
export_shared_lib_headers: ["libbinder"],
}
-
-filegroup {
- name: "libsensorprivacy_aidl",
- srcs: [
- "aidl/android/hardware/ISensorPrivacyListener.aidl",
- "aidl/android/hardware/ISensorPrivacyManager.aidl",
- ],
- path: "aidl",
-}
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index db15e17524..0407d8802c 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -26,7 +26,27 @@ cc_library_shared {
"-Werror",
],
cppflags: [
- "-Wextra",
+ "-Weverything",
+
+ // The static constructors and destructors in this library have not been noted to
+ // introduce significant overheads
+ "-Wno-exit-time-destructors",
+ "-Wno-global-constructors",
+
+ // We only care about compiling as C++14
+ "-Wno-c++98-compat-pedantic",
+
+ // We are aware of the risks inherent in comparing floats for equality
+ "-Wno-float-equal",
+
+ // We use four-character constants for the GraphicBuffer header, and don't care
+ // that they're non-portable as long as they're consistent within one execution
+ "-Wno-four-char-constants",
+
+ // Don't warn about struct padding
+ "-Wno-padded",
+
+ "-Wno-switch-enum",
],
sanitize: {
@@ -75,7 +95,10 @@ cc_library_shared {
"android.hardware.graphics.mapper@3.0",
"libbase",
"libcutils",
+ "libhardware",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"libsync",
"libutils",
"liblog",
diff --git a/libs/ui/ColorSpace.cpp b/libs/ui/ColorSpace.cpp
index df390e2588..7a14af1c9d 100644
--- a/libs/ui/ColorSpace.cpp
+++ b/libs/ui/ColorSpace.cpp
@@ -364,11 +364,7 @@ std::unique_ptr<float3[]> ColorSpace::createLUT(uint32_t size, const ColorSpace&
for (uint32_t z = 0; z < size; z++) {
for (int32_t y = int32_t(size - 1); y >= 0; y--) {
for (uint32_t x = 0; x < size; x++) {
- *data++ = connector.transform({
- static_cast<float>(x) * m,
- static_cast<float>(y) * m,
- static_cast<float>(z) * m,
- });
+ *data++ = connector.transform({x * m, y * m, z * m});
}
}
}
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index d02bb94a05..d588346dfb 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -81,7 +81,7 @@ void GraphicBufferAllocator::dump(std::string& result) const {
if (rec.size) {
StringAppendF(&result,
"%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64 " | %s\n",
- list.keyAt(i), static_cast<double>(rec.size) / 1024.0, rec.width, rec.stride, rec.height,
+ list.keyAt(i), rec.size / 1024.0, rec.width, rec.stride, rec.height,
rec.layerCount, rec.format, rec.usage, rec.requestorName.c_str());
} else {
StringAppendF(&result,
@@ -91,7 +91,7 @@ void GraphicBufferAllocator::dump(std::string& result) const {
}
total += rec.size;
}
- StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", static_cast<double>(total) / 1024.0);
+ StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", total / 1024.0);
result.append(mAllocator->dumpDebugInfo());
}
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 1222cd6fad..55e3b99aa1 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -339,10 +339,10 @@ Region& Region::scaleSelf(float sx, float sy) {
size_t count = mStorage.size();
Rect* rects = mStorage.editArray();
while (count) {
- rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f);
- rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f);
- rects->top = static_cast<int32_t>(static_cast<float>(rects->top) * sy + 0.5f);
- rects->bottom = static_cast<int32_t>(static_cast<float>(rects->bottom) * sy + 0.5f);
+ rects->left = static_cast<int32_t>(rects->left * sx + 0.5f);
+ rects->right = static_cast<int32_t>(rects->right * sx + 0.5f);
+ rects->top = static_cast<int32_t>(rects->top * sy + 0.5f);
+ rects->bottom = static_cast<int32_t>(rects->bottom * sy + 0.5f);
rects++;
count--;
}
diff --git a/libs/ui/include/ui/Size.h b/libs/ui/include/ui/Size.h
index d9b713df4c..c39d8af1d6 100644
--- a/libs/ui/include/ui/Size.h
+++ b/libs/ui/include/ui/Size.h
@@ -132,7 +132,7 @@ struct Size {
// Otherwise we leverage implicit conversion to safely compare values of
// different types, to ensure we return a value clamped to the range of
// ToType.
- return v < toLowest ? toLowest : (static_cast<ToType>(v) > toHighest ? toHighest : static_cast<ToType>(v));
+ return v < toLowest ? toLowest : (v > toHighest ? toHighest : static_cast<ToType>(v));
}
};
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 0a07a48bd1..15f4b6407c 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -58,6 +58,7 @@ cc_test {
"android.frameworks.bufferhub@1.0",
"libcutils",
"libhidlbase",
+ "libhwbinder",
"libui",
"libutils",
],
@@ -78,6 +79,7 @@ cc_test {
"android.frameworks.bufferhub@1.0",
"libcutils",
"libhidlbase",
+ "libhwbinder",
"liblog",
"libui",
"libutils"
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 2fcee7bee6..6d202aec05 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -29,9 +29,11 @@ sourceFiles = [
sharedLibraries = [
"libbase",
"libcutils",
+ "libhardware",
"liblog",
"libui",
"libutils",
+ "libnativewindow",
"libpdx_default_transport",
]
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 77c79112de..9f72c05f0c 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -26,8 +26,10 @@ staticLibraries = [
]
sharedLibraries = [
+ "libbase",
"libbinder",
"libcutils",
+ "libhardware",
"liblog",
"libui",
"libutils",
diff --git a/libs/vr/libdisplay/vsync_service.cpp b/libs/vr/libdisplay/vsync_service.cpp
index 04d4f30140..4668b9836c 100644
--- a/libs/vr/libdisplay/vsync_service.cpp
+++ b/libs/vr/libdisplay/vsync_service.cpp
@@ -45,8 +45,8 @@ public:
ALOGE("onVsync failed to writeInt64: %d", result);
return result;
}
- result = remote()->transact(BnVsyncCallback::ON_VSYNC, data, &reply,
- IBinder::FLAG_ONEWAY);
+ result = remote()->transact(
+ BnVsyncCallback::ON_VSYNC, data, &reply, TF_ONE_WAY);
if (result != OK) {
ALOGE("onVsync failed to transact: %d", result);
return result;
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 12ce74b1ea..282935307c 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -57,6 +57,7 @@ sharedLibraries = [
"libgui",
"libsync",
"libhidlbase",
+ "libhidltransport",
"libfmq",
"libpdx_default_transport",
]
diff --git a/opengl/OWNERS b/opengl/OWNERS
index b505712eb5..881f1b8f35 100644
--- a/opengl/OWNERS
+++ b/opengl/OWNERS
@@ -1,7 +1,16 @@
+# alanward@google.com
+chiur@google.com
chrisforbes@google.com
cnorthrop@google.com
courtneygo@google.com
+hliatis@google.com
ianelliott@google.com
jessehall@google.com
lpy@google.com
+marissaw@google.com
+nduca@google.com
+pmuetschard@google.com
+timvp@google.com
+tobine@google.com
+vhau@google.com
zzyiwei@google.com
diff --git a/opengl/libagl/Android.bp b/opengl/libagl/Android.bp
index f5bf015bad..6ec24b3712 100644
--- a/opengl/libagl/Android.bp
+++ b/opengl/libagl/Android.bp
@@ -25,9 +25,8 @@ cc_defaults {
"libnativewindow",
],
- header_libs: [
- "bionic_libc_platform_headers",
- ],
+ // we need to access the private Bionic header <bionic_tls.h>
+ include_dirs: ["bionic/libc/private"],
arch: {
arm: {
diff --git a/opengl/libagl/context.h b/opengl/libagl/context.h
index 6e77a2366f..18ef7d5716 100644
--- a/opengl/libagl/context.h
+++ b/opengl/libagl/context.h
@@ -22,7 +22,7 @@
#include <sys/types.h>
#include <pthread.h>
#ifdef __ANDROID__
-#include <bionic/tls.h>
+#include <bionic_tls.h>
#endif
#include <private/pixelflinger/ggl_context.h>
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index eb90c8b45b..abc7a72716 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -72,13 +72,15 @@ cc_defaults {
"libarect",
],
header_libs: [
- "bionic_libc_platform_headers",
"gl_headers",
"libsystem_headers",
"libhardware_headers",
"libnativebase_headers",
],
export_header_lib_headers: ["gl_headers"],
+
+ // we need to access the private Bionic header <bionic_tls.h>
+ include_dirs: ["bionic/libc/private"],
}
//##############################################################################
@@ -151,6 +153,7 @@ cc_library_shared {
"android.hardware.configstore-utils",
"libbase",
"libhidlbase",
+ "libhidltransport",
"libnativebridge_lazy",
"libnativeloader_lazy",
"libutils",
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index c51a1295e7..29a966d348 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -40,6 +40,7 @@ static inline void clearError() {
EGLDisplay eglGetDisplay(EGLNativeDisplayType display) {
ATRACE_CALL();
+ clearError();
if (egl_init_drivers() == EGL_FALSE) {
return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
@@ -47,7 +48,6 @@ EGLDisplay eglGetDisplay(EGLNativeDisplayType display) {
// Call down the chain, which usually points directly to the impl
// but may also be routed through layers
- clearError();
egl_connection_t* const cnx = &gEGLImpl;
return cnx->platform.eglGetDisplay(display);
}
@@ -55,6 +55,7 @@ EGLDisplay eglGetDisplay(EGLNativeDisplayType display) {
EGLDisplay eglGetPlatformDisplay(EGLenum platform, EGLNativeDisplayType display,
const EGLAttrib* attrib_list) {
ATRACE_CALL();
+ clearError();
if (egl_init_drivers() == EGL_FALSE) {
return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
@@ -62,7 +63,6 @@ EGLDisplay eglGetPlatformDisplay(EGLenum platform, EGLNativeDisplayType display,
// Call down the chain, which usually points directly to the impl
// but may also be routed through layers
- clearError();
egl_connection_t* const cnx = &gEGLImpl;
return cnx->platform.eglGetPlatformDisplay(platform, display, attrib_list);
}
@@ -239,12 +239,13 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char* procname)
// in which case we must make sure we've initialized ourselves, this
// happens the first time egl_get_display() is called.
+ clearError();
+
if (egl_init_drivers() == EGL_FALSE) {
setError(EGL_BAD_PARAMETER, NULL);
return nullptr;
}
- clearError();
egl_connection_t* const cnx = &gEGLImpl;
return cnx->platform.eglGetProcAddress(procname);
}
@@ -323,21 +324,23 @@ EGLBoolean eglWaitClient(void) {
}
EGLBoolean eglBindAPI(EGLenum api) {
+ clearError();
+
if (egl_init_drivers() == EGL_FALSE) {
return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
}
- clearError();
egl_connection_t* const cnx = &gEGLImpl;
return cnx->platform.eglBindAPI(api);
}
EGLenum eglQueryAPI(void) {
+ clearError();
+
if (egl_init_drivers() == EGL_FALSE) {
return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
}
- clearError();
egl_connection_t* const cnx = &gEGLImpl;
return cnx->platform.eglQueryAPI();
}
@@ -592,21 +595,23 @@ EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer* buffer) {
}
EGLuint64NV eglGetSystemTimeFrequencyNV() {
+ clearError();
+
if (egl_init_drivers() == EGL_FALSE) {
return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
}
- clearError();
egl_connection_t* const cnx = &gEGLImpl;
return cnx->platform.eglGetSystemTimeFrequencyNV();
}
EGLuint64NV eglGetSystemTimeNV() {
+ clearError();
+
if (egl_init_drivers() == EGL_FALSE) {
return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
}
- clearError();
egl_connection_t* const cnx = &gEGLImpl;
return cnx->platform.eglGetSystemTimeNV();
}
diff --git a/opengl/libs/EGL/egl_layers.cpp b/opengl/libs/EGL/egl_layers.cpp
index ac01dc8f96..ba7cacdbf2 100644
--- a/opengl/libs/EGL/egl_layers.cpp
+++ b/opengl/libs/EGL/egl_layers.cpp
@@ -337,7 +337,7 @@ void LayerLoader::LoadLayers() {
// Only enable the system search path for non-user builds
std::string system_path;
- if (property_get_bool("ro.debuggable", false) && prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
+ if (android::GraphicsEnv::getInstance().isDebuggable()) {
system_path = kSystemLayerLibraryDir;
}
diff --git a/opengl/libs/ETC1/etc1.cpp b/opengl/libs/ETC1/etc1.cpp
index 19d428a394..97d10851de 100644
--- a/opengl/libs/ETC1/etc1.cpp
+++ b/opengl/libs/ETC1/etc1.cpp
@@ -378,30 +378,34 @@ static void etc_encodeBaseColors(etc1_byte* pBaseColors,
const etc1_byte* pColors, etc_compressed* pCompressed) {
int r1, g1, b1, r2, g2, b2; // 8 bit base colors for sub-blocks
bool differential;
- int r51 = convert8To5(pColors[0]);
- int g51 = convert8To5(pColors[1]);
- int b51 = convert8To5(pColors[2]);
- int r52 = convert8To5(pColors[3]);
- int g52 = convert8To5(pColors[4]);
- int b52 = convert8To5(pColors[5]);
-
- r1 = convert5To8(r51);
- g1 = convert5To8(g51);
- b1 = convert5To8(b51);
-
- int dr = r52 - r51;
- int dg = g52 - g51;
- int db = b52 - b51;
-
- differential = inRange4bitSigned(dr) && inRange4bitSigned(dg)
- && inRange4bitSigned(db);
- if (differential) {
- r2 = convert5To8(r51 + dr);
- g2 = convert5To8(g51 + dg);
- b2 = convert5To8(b51 + db);
- pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19)
- | ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2;
- } else {
+ {
+ int r51 = convert8To5(pColors[0]);
+ int g51 = convert8To5(pColors[1]);
+ int b51 = convert8To5(pColors[2]);
+ int r52 = convert8To5(pColors[3]);
+ int g52 = convert8To5(pColors[4]);
+ int b52 = convert8To5(pColors[5]);
+
+ r1 = convert5To8(r51);
+ g1 = convert5To8(g51);
+ b1 = convert5To8(b51);
+
+ int dr = r52 - r51;
+ int dg = g52 - g51;
+ int db = b52 - b51;
+
+ differential = inRange4bitSigned(dr) && inRange4bitSigned(dg)
+ && inRange4bitSigned(db);
+ if (differential) {
+ r2 = convert5To8(r51 + dr);
+ g2 = convert5To8(g51 + dg);
+ b2 = convert5To8(b51 + db);
+ pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19)
+ | ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2;
+ }
+ }
+
+ if (!differential) {
int r41 = convert8To4(pColors[0]);
int g41 = convert8To4(pColors[1]);
int b41 = convert8To4(pColors[2]);
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 86fec21bae..63a0e140cc 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -46,7 +46,7 @@
#define MAX_NUMBER_OF_GL_EXTENSIONS 256
-#include <bionic/tls.h> /* special private C library header */
+#include <bionic_tls.h> /* special private C library header */
// ----------------------------------------------------------------------------
namespace android {
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index 8bfe517812..a9e873ac43 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -22,17 +22,16 @@ cc_test {
"libbinder",
"libgui",
"libhidlbase",
+ "libhidltransport",
"liblog",
"libutils",
"libnativewindow",
],
include_dirs: [
+ "bionic/libc/private",
"frameworks/native/opengl/libs",
"frameworks/native/opengl/libs/EGL",
],
- header_libs: [
- "bionic_libc_platform_headers",
- ],
}
diff --git a/opengl/tests/gl_perf/fill_common.cpp b/opengl/tests/gl_perf/fill_common.cpp
index 613f1c6aa1..fefedc0939 100644
--- a/opengl/tests/gl_perf/fill_common.cpp
+++ b/opengl/tests/gl_perf/fill_common.cpp
@@ -191,10 +191,10 @@ static void setupVA() {
static void randUniform(int pgm, const char *var) {
GLint loc = glGetUniformLocation(pgm, var);
if (loc >= 0) {
- float x = ((float)rand()) / (float)RAND_MAX;
- float y = ((float)rand()) / (float)RAND_MAX;
- float z = ((float)rand()) / (float)RAND_MAX;
- float w = ((float)rand()) / (float)RAND_MAX;
+ float x = ((float)rand()) / RAND_MAX;
+ float y = ((float)rand()) / RAND_MAX;
+ float z = ((float)rand()) / RAND_MAX;
+ float w = ((float)rand()) / RAND_MAX;
glUniform4f(loc, x, y, z, w);
}
}
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index 2bb6aef3a5..cd03bc2be7 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -37,6 +37,8 @@ cc_library_shared {
"libcrypto",
"libcutils",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"liblog",
"libui",
"libutils",
@@ -62,6 +64,8 @@ cc_binary {
"libcrypto",
"libcutils",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"liblog",
"libui",
"libutils",
diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp
index 4d2d87352b..3442cb2ff7 100644
--- a/services/displayservice/Android.bp
+++ b/services/displayservice/Android.bp
@@ -27,6 +27,7 @@ cc_library_shared {
"liblog",
"libgui",
"libhidlbase",
+ "libhidltransport",
"libutils",
"android.frameworks.displayservice@1.0",
],
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index 7b8e0f835c..dbb6ba6719 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -59,6 +59,9 @@ cc_defaults {
cc_defaults {
name: "gpuservice_binary",
defaults: ["gpuservice_defaults"],
+ whole_static_libs: [
+ "libsigchain",
+ ],
shared_libs: [
"libbinder",
"libcutils",
diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS
deleted file mode 100644
index 5d028393f6..0000000000
--- a/services/gpuservice/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-chrisforbes@google.com
-lpy@google.com
-zzyiwei@google.com
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 11578c393e..576c8d8bb5 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -30,6 +30,7 @@ cc_library_shared {
srcs: [
"InputClassifier.cpp",
"InputClassifierConverter.cpp",
+ "InputDispatcher.cpp",
"InputManager.cpp",
],
@@ -46,11 +47,6 @@ cc_library_shared {
"liblog",
"libutils",
"libui",
- "server_configurable_flags",
- ],
-
- static_libs: [
- "libinputdispatcher",
],
cflags: [
@@ -63,16 +59,44 @@ cc_library_shared {
"include",
],
- export_static_lib_headers: [
- "libinputdispatcher",
- ],
}
cc_library_headers {
name: "libinputflinger_headers",
- header_libs: ["libinputreporter_headers"],
export_include_dirs: ["include"],
- export_header_lib_headers: ["libinputreporter_headers"],
+}
+
+cc_library_shared {
+ name: "libinputreader",
+ defaults: ["inputflinger_defaults"],
+
+ srcs: [
+ "EventHub.cpp",
+ "InputReader.cpp",
+ "InputReaderFactory.cpp",
+ "TouchVideoDevice.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libinputflinger_base",
+ "libcrypto",
+ "libcutils",
+ "libinput",
+ "liblog",
+ "libui",
+ "libutils",
+ "libhardware_legacy",
+ "libstatslog",
+ ],
+
+ header_libs: [
+ "libinputflinger_headers",
+ ],
+
+ export_header_lib_headers: [
+ "libinputflinger_headers",
+ ],
}
cc_library_shared {
@@ -100,6 +124,28 @@ cc_library_shared {
],
}
+cc_library_shared {
+ name: "libinputreporter",
+ defaults: ["inputflinger_defaults"],
+
+ srcs: [
+ "InputReporter.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libutils",
+ ],
+
+ header_libs: [
+ "libinputflinger_headers",
+ ],
+
+ export_header_lib_headers: [
+ "libinputflinger_headers",
+ ],
+}
+
subdirs = [
"host",
"tests",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/EventHub.cpp
index a5e5415dd7..ce5627271a 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -25,9 +25,9 @@
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
+#include <sys/limits.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
-#include <sys/limits.h>
#include <sys/utsname.h>
#include <unistd.h>
@@ -42,13 +42,13 @@
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <openssl/sha.h>
-#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Timers.h>
#include <utils/threads.h>
+#include <utils/Errors.h>
-#include <input/KeyCharacterMap.h>
#include <input/KeyLayoutMap.h>
+#include <input/KeyCharacterMap.h>
#include <input/VirtualKeyMap.h>
/* this macro is used to tell if "bit" is set in "array"
@@ -56,10 +56,10 @@
* operation with a byte that only has the relevant bit set.
* eg. to check for the 12th bit, we do (array[1] & 1<<4)
*/
-#define test_bit(bit, array) ((array)[(bit) / 8] & (1 << ((bit) % 8)))
+#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)%8)))
/* this macro computes the number of bytes needed to represent a bit array of the specified size */
-#define sizeof_bit_array(bits) (((bits) + 7) / 8)
+#define sizeof_bit_array(bits) (((bits) + 7) / 8)
#define INDENT " "
#define INDENT2 " "
@@ -71,10 +71,10 @@ namespace android {
static constexpr bool DEBUG = false;
-static const char* WAKE_LOCK_ID = "KeyEvents";
-static const char* DEVICE_PATH = "/dev/input";
+static const char *WAKE_LOCK_ID = "KeyEvents";
+static const char *DEVICE_PATH = "/dev/input";
// v4l2 devices go directly into /dev
-static const char* VIDEO_DEVICE_PATH = "/dev";
+static const char *VIDEO_DEVICE_PATH = "/dev";
static inline const char* toString(bool value) {
return value ? "true" : "false";
@@ -126,7 +126,7 @@ static bool isV4lTouchNode(const char* name) {
* directly from /dev.
*/
static bool isV4lScanningEnabled() {
- return property_get_bool("ro.input.video_enabled", true /* default_value */);
+ return property_get_bool("ro.input.video_enabled", true /* default_value */);
}
static nsecs_t processEventTimestamp(const struct input_event& event) {
@@ -153,27 +153,27 @@ uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
// Touch devices get dibs on touch-related axes.
if (deviceClasses & INPUT_DEVICE_CLASS_TOUCH) {
switch (axis) {
- case ABS_X:
- case ABS_Y:
- case ABS_PRESSURE:
- case ABS_TOOL_WIDTH:
- case ABS_DISTANCE:
- case ABS_TILT_X:
- case ABS_TILT_Y:
- case ABS_MT_SLOT:
- case ABS_MT_TOUCH_MAJOR:
- case ABS_MT_TOUCH_MINOR:
- case ABS_MT_WIDTH_MAJOR:
- case ABS_MT_WIDTH_MINOR:
- case ABS_MT_ORIENTATION:
- case ABS_MT_POSITION_X:
- case ABS_MT_POSITION_Y:
- case ABS_MT_TOOL_TYPE:
- case ABS_MT_BLOB_ID:
- case ABS_MT_TRACKING_ID:
- case ABS_MT_PRESSURE:
- case ABS_MT_DISTANCE:
- return INPUT_DEVICE_CLASS_TOUCH;
+ case ABS_X:
+ case ABS_Y:
+ case ABS_PRESSURE:
+ case ABS_TOOL_WIDTH:
+ case ABS_DISTANCE:
+ case ABS_TILT_X:
+ case ABS_TILT_Y:
+ case ABS_MT_SLOT:
+ case ABS_MT_TOUCH_MAJOR:
+ case ABS_MT_TOUCH_MINOR:
+ case ABS_MT_WIDTH_MAJOR:
+ case ABS_MT_WIDTH_MINOR:
+ case ABS_MT_ORIENTATION:
+ case ABS_MT_POSITION_X:
+ case ABS_MT_POSITION_Y:
+ case ABS_MT_TOOL_TYPE:
+ case ABS_MT_BLOB_ID:
+ case ABS_MT_TRACKING_ID:
+ case ABS_MT_PRESSURE:
+ case ABS_MT_DISTANCE:
+ return INPUT_DEVICE_CLASS_TOUCH;
}
}
@@ -191,20 +191,12 @@ uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
// --- EventHub::Device ---
EventHub::Device::Device(int fd, int32_t id, const std::string& path,
- const InputDeviceIdentifier& identifier)
- : next(nullptr),
- fd(fd),
- id(id),
- path(path),
- identifier(identifier),
- classes(0),
- configuration(nullptr),
- virtualKeyMap(nullptr),
- ffEffectPlaying(false),
- ffEffectId(-1),
- controllerNumber(0),
- enabled(true),
- isVirtual(fd < 0) {
+ const InputDeviceIdentifier& identifier) :
+ next(nullptr),
+ fd(fd), id(id), path(path), identifier(identifier),
+ classes(0), configuration(nullptr), virtualKeyMap(nullptr),
+ ffEffectPlaying(false), ffEffectId(-1), controllerNumber(0),
+ enabled(true), isVirtual(fd < 0) {
memset(keyBitmask, 0, sizeof(keyBitmask));
memset(absBitmask, 0, sizeof(absBitmask));
memset(relBitmask, 0, sizeof(relBitmask));
@@ -228,7 +220,7 @@ void EventHub::Device::close() {
status_t EventHub::Device::enable() {
fd = open(path.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
- if (fd < 0) {
+ if(fd < 0) {
ALOGE("could not open %s, %s\n", path.c_str(), strerror(errno));
return -errno;
}
@@ -250,18 +242,12 @@ bool EventHub::Device::hasValidFd() {
const int EventHub::EPOLL_MAX_EVENTS;
-EventHub::EventHub(void)
- : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
- mNextDeviceId(1),
- mControllerNumbers(),
- mOpeningDevices(nullptr),
- mClosingDevices(nullptr),
+EventHub::EventHub(void) :
+ mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
+ mOpeningDevices(nullptr), mClosingDevices(nullptr),
mNeedToSendFinishedDeviceScan(false),
- mNeedToReopenDevices(false),
- mNeedToScanDevices(true),
- mPendingEventCount(0),
- mPendingEventIndex(0),
- mPendingINotify(false) {
+ mNeedToReopenDevices(false), mNeedToScanDevices(true),
+ mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
@@ -269,12 +255,12 @@ EventHub::EventHub(void)
mINotifyFd = inotify_init();
mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
- LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s", DEVICE_PATH,
- strerror(errno));
+ LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s",
+ DEVICE_PATH, strerror(errno));
if (isV4lScanningEnabled()) {
mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
- VIDEO_DEVICE_PATH, strerror(errno));
+ VIDEO_DEVICE_PATH, strerror(errno));
} else {
mVideoWd = -1;
ALOGI("Video device scanning disabled");
@@ -296,16 +282,16 @@ EventHub::EventHub(void)
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
- errno);
+ errno);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
- errno);
+ errno);
eventItem.data.fd = mWakeReadPipeFd;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
- errno);
+ errno);
int major, minor;
getLinuxRelease(&major, &minor);
@@ -362,7 +348,7 @@ void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration)
}
status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const {
+ RawAbsoluteAxisInfo* outAxisInfo) const {
outAxisInfo->clear();
if (axis >= 0 && axis <= ABS_MAX) {
@@ -371,9 +357,9 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
Device* device = getDeviceLocked(deviceId);
if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
struct input_absinfo info;
- if (ioctl(device->fd, EVIOCGABS(axis), &info)) {
- ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
- device->identifier.name.c_str(), device->fd, errno);
+ if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
+ ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
+ axis, device->identifier.name.c_str(), device->fd, errno);
return -errno;
}
@@ -480,9 +466,9 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t*
Device* device = getDeviceLocked(deviceId);
if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
struct input_absinfo info;
- if (ioctl(device->fd, EVIOCGABS(axis), &info)) {
- ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
- device->identifier.name.c_str(), device->fd, errno);
+ if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
+ ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
+ axis, device->identifier.name.c_str(), device->fd, errno);
return -errno;
}
@@ -493,8 +479,8 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t*
return -1;
}
-bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) const {
+bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
@@ -503,9 +489,9 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const in
for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
scanCodes.clear();
- status_t err = device->keyMap.keyLayoutMap->findScanCodesForKey(keyCodes[codeIndex],
- &scanCodes);
- if (!err) {
+ status_t err = device->keyMap.keyLayoutMap->findScanCodesForKey(
+ keyCodes[codeIndex], &scanCodes);
+ if (! err) {
// check the possible scan codes identified by the layout map against the
// map of codes actually emitted by the driver
for (size_t sc = 0; sc < scanCodes.size(); sc++) {
@@ -521,8 +507,9 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const in
return false;
}
-status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
- int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
+status_t EventHub::mapKey(int32_t deviceId,
+ int32_t scanCode, int32_t usageCode, int32_t metaState,
+ int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
status_t status = NAME_NOT_FOUND;
@@ -629,7 +616,7 @@ void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) {
}
void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
- std::vector<VirtualKeyDefinition>& outVirtualKeys) const {
+ std::vector<VirtualKeyDefinition>& outVirtualKeys) const {
outVirtualKeys.clear();
AutoMutex _l(mLock);
@@ -650,13 +637,15 @@ sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const {
return nullptr;
}
-bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) {
+bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId,
+ const sp<KeyCharacterMap>& map) {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
if (device) {
if (map != device->overlayKeyMap) {
device->overlayKeyMap = map;
- device->combinedKeyMap = KeyCharacterMap::combine(device->keyMap.keyCharacterMap, map);
+ device->combinedKeyMap = KeyCharacterMap::combine(
+ device->keyMap.keyCharacterMap, map);
return true;
}
}
@@ -665,7 +654,8 @@ bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterM
static std::string generateDescriptor(InputDeviceIdentifier& identifier) {
std::string rawDescriptor;
- rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor, identifier.product);
+ rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
+ identifier.product);
// TODO add handling for USB devices to not uniqueify kbs that show up twice
if (!identifier.uniqueId.empty()) {
rawDescriptor += "uniqueId:";
@@ -704,13 +694,13 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) {
if (identifier.uniqueId.empty()) {
// If it didn't have a unique id check for conflicts and enforce
// uniqueness if necessary.
- while (getDeviceByDescriptorLocked(identifier.descriptor) != nullptr) {
+ while(getDeviceByDescriptorLocked(identifier.descriptor) != nullptr) {
identifier.nonce++;
rawDescriptor = generateDescriptor(identifier);
}
}
ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
- identifier.descriptor.c_str());
+ identifier.descriptor.c_str());
}
void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
@@ -727,7 +717,7 @@ void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
effect.replay.delay = 0;
if (ioctl(device->fd, EVIOCSFF, &effect)) {
ALOGW("Could not upload force feedback effect to device %s due to error %d.",
- device->identifier.name.c_str(), errno);
+ device->identifier.name.c_str(), errno);
return;
}
device->ffEffectId = effect.id;
@@ -740,7 +730,7 @@ void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
ev.value = 1;
if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
ALOGW("Could not start force feedback effect on device %s due to error %d.",
- device->identifier.name.c_str(), errno);
+ device->identifier.name.c_str(), errno);
return;
}
device->ffEffectPlaying = true;
@@ -762,7 +752,7 @@ void EventHub::cancelVibrate(int32_t deviceId) {
ev.value = 0;
if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
ALOGW("Could not stop force feedback effect on device %s due to error %d.",
- device->identifier.name.c_str(), errno);
+ device->identifier.name.c_str(), errno);
return;
}
}
@@ -849,12 +839,12 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
// Report any devices that had last been added/removed.
while (mClosingDevices) {
Device* device = mClosingDevices;
- ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
+ ALOGV("Reporting device closed: id=%d, name=%s\n",
+ device->id, device->path.c_str());
mClosingDevices = device->next;
event->when = now;
- event->deviceId = (device->id == mBuiltInKeyboardId)
- ? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
- : device->id;
+ event->deviceId = (device->id == mBuiltInKeyboardId) ?
+ ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID : device->id;
event->type = DEVICE_REMOVED;
event += 1;
delete device;
@@ -872,7 +862,8 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
while (mOpeningDevices != nullptr) {
Device* device = mOpeningDevices;
- ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
+ ALOGV("Reporting device opened: id=%d, name=%s\n",
+ device->id, device->path.c_str());
mOpeningDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
@@ -918,15 +909,15 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
} else {
ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
- eventItem.events);
+ eventItem.events);
}
continue;
}
Device* device = getDeviceByFdLocked(eventItem.data.fd);
if (!device) {
- ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.", eventItem.events,
- eventItem.data.fd);
+ ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.",
+ eventItem.events, eventItem.data.fd);
ALOG_ASSERT(!DEBUG);
continue;
}
@@ -935,30 +926,30 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
size_t numFrames = device->videoDevice->readAndQueueFrames();
if (numFrames == 0) {
ALOGE("Received epoll event for video device %s, but could not read frame",
- device->videoDevice->getName().c_str());
+ device->videoDevice->getName().c_str());
}
} else if (eventItem.events & EPOLLHUP) {
// TODO(b/121395353) - consider adding EPOLLRDHUP
ALOGI("Removing video device %s due to epoll hang-up event.",
- device->videoDevice->getName().c_str());
+ device->videoDevice->getName().c_str());
unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
device->videoDevice = nullptr;
} else {
- ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
- device->videoDevice->getName().c_str());
+ ALOGW("Received unexpected epoll event 0x%08x for device %s.",
+ eventItem.events, device->videoDevice->getName().c_str());
ALOG_ASSERT(!DEBUG);
}
continue;
}
// This must be an input event
if (eventItem.events & EPOLLIN) {
- int32_t readSize =
- read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
+ int32_t readSize = read(device->fd, readBuffer,
+ sizeof(struct input_event) * capacity);
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// Device was removed before INotify noticed.
ALOGW("could not get event, removed? (fd: %d size: %" PRId32
- " bufferSize: %zu capacity: %zu errno: %d)\n",
- device->fd, readSize, bufferSize, capacity, errno);
+ " bufferSize: %zu capacity: %zu errno: %d)\n",
+ device->fd, readSize, bufferSize, capacity, errno);
deviceChanged = true;
closeDeviceLocked(device);
} else if (readSize < 0) {
@@ -990,12 +981,12 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz
}
} else if (eventItem.events & EPOLLHUP) {
ALOGI("Removing device %s due to epoll hang-up event.",
- device->identifier.name.c_str());
+ device->identifier.name.c_str());
deviceChanged = true;
closeDeviceLocked(device);
} else {
- ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
- device->identifier.name.c_str());
+ ALOGW("Received unexpected epoll event 0x%08x for device %s.",
+ eventItem.events, device->identifier.name.c_str());
}
}
@@ -1090,7 +1081,7 @@ void EventHub::wake() {
void EventHub::scanDevicesLocked() {
status_t result = scanDirLocked(DEVICE_PATH);
- if (result < 0) {
+ if(result < 0) {
ALOGE("scan dir failed for %s", DEVICE_PATH);
}
if (isV4lScanningEnabled()) {
@@ -1118,12 +1109,12 @@ static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint3
}
static const int32_t GAMEPAD_KEYCODES[] = {
- AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C, //
- AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z, //
- AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1, //
- AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2, //
- AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR, //
- AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE, //
+ AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
+ AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
+ AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
+ AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
+ AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
+ AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE,
};
status_t EventHub::registerFdForEpoll(int fd) {
@@ -1190,7 +1181,7 @@ void EventHub::unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& vide
status_t result = unregisterFdFromEpoll(videoDevice.getFd());
if (result != OK) {
ALOGW("Could not remove video device fd from epoll for device: %s",
- videoDevice.getName().c_str());
+ videoDevice.getName().c_str());
}
}
}
@@ -1201,7 +1192,7 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
ALOGV("Opening device: %s", devicePath);
int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
- if (fd < 0) {
+ if(fd < 0) {
ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
return -1;
}
@@ -1209,7 +1200,7 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
InputDeviceIdentifier identifier;
// Get device name.
- if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
+ if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
ALOGE("Could not get device name for %s: %s", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
@@ -1228,7 +1219,7 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
// Get device driver version.
int driverVersion;
- if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
+ if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
close(fd);
return -1;
@@ -1236,7 +1227,7 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
// Get device identifier.
struct input_id inputId;
- if (ioctl(fd, EVIOCGID, &inputId)) {
+ if(ioctl(fd, EVIOCGID, &inputId)) {
ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
close(fd);
return -1;
@@ -1247,16 +1238,16 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
identifier.version = inputId.version;
// Get device physical location.
- if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
- // fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
+ if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
+ //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.location = buffer;
}
// Get device unique id.
- if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
- // fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
+ if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
+ //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.uniqueId = buffer;
@@ -1271,16 +1262,16 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
ALOGV("add device %d: %s\n", deviceId, devicePath);
ALOGV(" bus: %04x\n"
- " vendor %04x\n"
- " product %04x\n"
- " version %04x\n",
- identifier.bus, identifier.vendor, identifier.product, identifier.version);
+ " vendor %04x\n"
+ " product %04x\n"
+ " version %04x\n",
+ identifier.bus, identifier.vendor, identifier.product, identifier.version);
ALOGV(" name: \"%s\"\n", identifier.name.c_str());
ALOGV(" location: \"%s\"\n", identifier.location.c_str());
ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.c_str());
ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.c_str());
- ALOGV(" driver: v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff,
- driverVersion & 0xff);
+ ALOGV(" driver: v%d.%d.%d\n",
+ driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
// Load the configuration file for the device.
loadConfigurationLocked(device);
@@ -1296,21 +1287,21 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
// See if this is a keyboard. Ignore everything in the button range except for
// joystick and gamepad buttons which are handled like keyboards for the most part.
- bool haveKeyboardKeys =
- containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) ||
- containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
- sizeof_bit_array(KEY_MAX + 1));
+ bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))
+ || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
+ sizeof_bit_array(KEY_MAX + 1));
bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
- sizeof_bit_array(BTN_MOUSE)) ||
- containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
- sizeof_bit_array(BTN_DIGI));
+ sizeof_bit_array(BTN_MOUSE))
+ || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
+ sizeof_bit_array(BTN_DIGI));
if (haveKeyboardKeys || haveGamepadButtons) {
device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
}
// See if this is a cursor device such as a trackball or mouse.
- if (test_bit(BTN_MOUSE, device->keyBitmask) && test_bit(REL_X, device->relBitmask) &&
- test_bit(REL_Y, device->relBitmask)) {
+ if (test_bit(BTN_MOUSE, device->keyBitmask)
+ && test_bit(REL_X, device->relBitmask)
+ && test_bit(REL_Y, device->relBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_CURSOR;
}
@@ -1318,29 +1309,31 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
String8 deviceType = String8();
if (device->configuration &&
device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
- if (!deviceType.compare(String8("rotaryEncoder"))) {
- device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
- }
+ if (!deviceType.compare(String8("rotaryEncoder"))) {
+ device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
+ }
}
// See if this is a touch pad.
// Is this a new modern multi-touch driver?
- if (test_bit(ABS_MT_POSITION_X, device->absBitmask) &&
- test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
+ if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
+ && test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
// Some joysticks such as the PS3 controller report axes that conflict
// with the ABS_MT range. Try to confirm that the device really is
// a touch screen.
if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
}
- // Is this an old style single-touch driver?
- } else if (test_bit(BTN_TOUCH, device->keyBitmask) && test_bit(ABS_X, device->absBitmask) &&
- test_bit(ABS_Y, device->absBitmask)) {
+ // Is this an old style single-touch driver?
+ } else if (test_bit(BTN_TOUCH, device->keyBitmask)
+ && test_bit(ABS_X, device->absBitmask)
+ && test_bit(ABS_Y, device->absBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH;
- // Is this a BT stylus?
+ // Is this a BT stylus?
} else if ((test_bit(ABS_PRESSURE, device->absBitmask) ||
- test_bit(BTN_TOUCH, device->keyBitmask)) &&
- !test_bit(ABS_X, device->absBitmask) && !test_bit(ABS_Y, device->absBitmask)) {
+ test_bit(BTN_TOUCH, device->keyBitmask))
+ && !test_bit(ABS_X, device->absBitmask)
+ && !test_bit(ABS_Y, device->absBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
// Keyboard will try to claim some of the buttons but we really want to reserve those so we
// can fuse it with the touch screen data, so just take them back. Note this means an
@@ -1354,8 +1347,8 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
if (haveGamepadButtons) {
uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
for (int i = 0; i <= ABS_MAX; i++) {
- if (test_bit(i, device->absBitmask) &&
- (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
+ if (test_bit(i, device->absBitmask)
+ && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
device->classes = assumedClasses;
break;
}
@@ -1396,8 +1389,10 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
// Configure the keyboard, gamepad or virtual keyboard.
if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
// Register the keyboard as a built-in keyboard if it is eligible.
- if (!keyMapStatus && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD &&
- isEligibleBuiltInKeyboard(device->identifier, device->configuration, &device->keyMap)) {
+ if (!keyMapStatus
+ && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD
+ && isEligibleBuiltInKeyboard(device->identifier,
+ device->configuration, &device->keyMap)) {
mBuiltInKeyboardId = device->id;
}
@@ -1408,15 +1403,15 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
// See if this device has a DPAD.
if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
+ hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
+ hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
+ hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
+ hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
device->classes |= INPUT_DEVICE_CLASS_DPAD;
}
// See if this device has a gamepad.
- for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES) / sizeof(GAMEPAD_KEYCODES[0]); i++) {
+ for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
break;
@@ -1426,8 +1421,8 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
// If the device isn't recognized as something we handle, don't monitor it.
if (device->classes == 0) {
- ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath,
- device->identifier.name.c_str());
+ ALOGV("Dropping device: id=%d, path='%s', name='%s'",
+ deviceId, devicePath, device->identifier.name.c_str());
delete device;
return -1;
}
@@ -1442,8 +1437,8 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
}
- if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD) &&
- device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
+ if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD)
+ && device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
device->controllerNumber = getNextControllerNumberLocked(device);
setLedForControllerLocked(device);
}
@@ -1456,12 +1451,10 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
break;
}
}
- mUnattachedVideoDevices
- .erase(std::remove_if(mUnattachedVideoDevices.begin(), mUnattachedVideoDevices.end(),
- [](const std::unique_ptr<TouchVideoDevice>& videoDevice) {
- return videoDevice == nullptr;
- }),
- mUnattachedVideoDevices.end());
+ mUnattachedVideoDevices.erase(std::remove_if(mUnattachedVideoDevices.begin(),
+ mUnattachedVideoDevices.end(),
+ [](const std::unique_ptr<TouchVideoDevice>& videoDevice){
+ return videoDevice == nullptr; }), mUnattachedVideoDevices.end());
if (registerDeviceForEpollLocked(device) != OK) {
delete device;
@@ -1471,10 +1464,13 @@ status_t EventHub::openDeviceLocked(const char* devicePath) {
configureFd(device);
ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
- "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
- deviceId, fd, devicePath, device->identifier.name.c_str(), device->classes,
- device->configurationFile.c_str(), device->keyMap.keyLayoutFile.c_str(),
- device->keyMap.keyCharacterMapFile.c_str(), toString(mBuiltInKeyboardId == deviceId));
+ "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
+ deviceId, fd, devicePath, device->identifier.name.c_str(),
+ device->classes,
+ device->configurationFile.c_str(),
+ device->keyMap.keyLayoutFile.c_str(),
+ device->keyMap.keyCharacterMapFile.c_str(),
+ toString(mBuiltInKeyboardId == deviceId));
addDeviceLocked(device);
return OK;
@@ -1486,8 +1482,8 @@ void EventHub::configureFd(Device* device) {
// Disable kernel key repeat since we handle it ourselves
unsigned int repeatRate[] = {0, 0};
if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
- ALOGW("Unable to disable kernel key repeat for %s: %s", device->path.c_str(),
- strerror(errno));
+ ALOGW("Unable to disable kernel key repeat for %s: %s",
+ device->path.c_str(), strerror(errno));
}
}
@@ -1511,7 +1507,8 @@ void EventHub::configureFd(Device* device) {
// clock.
int clockId = CLOCK_MONOTONIC;
bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
- ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(), toString(usingClockIoctl));
+ ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(),
+ toString(usingClockIoctl));
}
void EventHub::openVideoDeviceLocked(const std::string& devicePath) {
@@ -1535,7 +1532,7 @@ void EventHub::openVideoDeviceLocked(const std::string& devicePath) {
// Couldn't find a matching input device, so just add it to a temporary holding queue.
// A matching input device may appear later.
ALOGI("Adding video device %s to list of unattached video devices",
- videoDevice->getName().c_str());
+ videoDevice->getName().c_str());
mUnattachedVideoDevices.push_back(std::move(videoDevice));
}
@@ -1592,10 +1589,12 @@ void EventHub::createVirtualKeyboardLocked() {
identifier.uniqueId = "<virtual>";
assignDescriptorLocked(identifier);
- Device* device =
- new Device(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>", identifier);
- device->classes = INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY |
- INPUT_DEVICE_CLASS_DPAD | INPUT_DEVICE_CLASS_VIRTUAL;
+ Device* device = new Device(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>",
+ identifier);
+ device->classes = INPUT_DEVICE_CLASS_KEYBOARD
+ | INPUT_DEVICE_CLASS_ALPHAKEY
+ | INPUT_DEVICE_CLASS_DPAD
+ | INPUT_DEVICE_CLASS_VIRTUAL;
loadKeyMapLocked(device);
addDeviceLocked(device);
}
@@ -1611,14 +1610,14 @@ void EventHub::loadConfigurationLocked(Device* device) {
device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
if (device->configurationFile.empty()) {
ALOGD("No input device configuration file found for device '%s'.",
- device->identifier.name.c_str());
+ device->identifier.name.c_str());
} else {
status_t status = PropertyMap::load(String8(device->configurationFile.c_str()),
- &device->configuration);
+ &device->configuration);
if (status) {
ALOGE("Error loading input device configuration file for device '%s'. "
- "Using default configuration.",
- device->identifier.name.c_str());
+ "Using default configuration.",
+ device->identifier.name.c_str());
}
}
}
@@ -1662,7 +1661,7 @@ bool EventHub::deviceHasMicLocked(Device* device) {
int32_t EventHub::getNextControllerNumberLocked(Device* device) {
if (mControllerNumbers.isFull()) {
ALOGI("Maximum number of controllers reached, assigning controller number 0 to device %s",
- device->identifier.name.c_str());
+ device->identifier.name.c_str());
return 0;
}
// Since the controller number 0 is reserved for non-controllers, translate all numbers up by
@@ -1672,7 +1671,7 @@ int32_t EventHub::getNextControllerNumberLocked(Device* device) {
void EventHub::releaseControllerNumberLocked(Device* device) {
int32_t num = device->controllerNumber;
- device->controllerNumber = 0;
+ device->controllerNumber= 0;
if (num == 0) {
return;
}
@@ -1693,7 +1692,7 @@ bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
std::vector<int32_t> scanCodes;
device->keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
const size_t N = scanCodes.size();
- for (size_t i = 0; i < N && i <= KEY_MAX; i++) {
+ for (size_t i=0; i<N && i<=KEY_MAX; i++) {
int32_t sc = scanCodes[i];
if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
return true;
@@ -1709,8 +1708,8 @@ status_t EventHub::mapLed(Device* device, int32_t led, int32_t* outScanCode) con
}
int32_t scanCode;
- if (device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
- if (scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) {
+ if(device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
+ if(scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) {
*outScanCode = scanCode;
return NO_ERROR;
}
@@ -1718,7 +1717,7 @@ status_t EventHub::mapLed(Device* device, int32_t led, int32_t* outScanCode) con
return NAME_NOT_FOUND;
}
-void EventHub::closeDeviceByPathLocked(const char* devicePath) {
+void EventHub::closeDeviceByPathLocked(const char *devicePath) {
Device* device = getDeviceByPathLocked(devicePath);
if (device) {
closeDeviceLocked(device);
@@ -1743,13 +1742,10 @@ void EventHub::closeVideoDeviceByPathLocked(const std::string& devicePath) {
return;
}
}
- mUnattachedVideoDevices
- .erase(std::remove_if(mUnattachedVideoDevices.begin(), mUnattachedVideoDevices.end(),
- [&devicePath](
- const std::unique_ptr<TouchVideoDevice>& videoDevice) {
- return videoDevice->getPath() == devicePath;
- }),
- mUnattachedVideoDevices.end());
+ mUnattachedVideoDevices.erase(std::remove_if(mUnattachedVideoDevices.begin(),
+ mUnattachedVideoDevices.end(), [&devicePath](
+ const std::unique_ptr<TouchVideoDevice>& videoDevice) {
+ return videoDevice->getPath() == devicePath; }), mUnattachedVideoDevices.end());
}
void EventHub::closeAllDevicesLocked() {
@@ -1760,12 +1756,13 @@ void EventHub::closeAllDevicesLocked() {
}
void EventHub::closeDeviceLocked(Device* device) {
- ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x", device->path.c_str(),
- device->identifier.name.c_str(), device->id, device->fd, device->classes);
+ ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x",
+ device->path.c_str(), device->identifier.name.c_str(), device->id,
+ device->fd, device->classes);
if (device->id == mBuiltInKeyboardId) {
ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
- device->path.c_str(), mBuiltInKeyboardId);
+ device->path.c_str(), mBuiltInKeyboardId);
mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
}
@@ -1783,7 +1780,7 @@ void EventHub::closeDeviceLocked(Device* device) {
// Unlink for opening devices list if it is present.
Device* pred = nullptr;
bool found = false;
- for (Device* entry = mOpeningDevices; entry != nullptr;) {
+ for (Device* entry = mOpeningDevices; entry != nullptr; ) {
if (entry == device) {
found = true;
break;
@@ -1815,28 +1812,30 @@ status_t EventHub::readNotifyLocked() {
char event_buf[512];
int event_size;
int event_pos = 0;
- struct inotify_event* event;
+ struct inotify_event *event;
ALOGV("EventHub::readNotify nfd: %d\n", mINotifyFd);
res = read(mINotifyFd, event_buf, sizeof(event_buf));
- if (res < (int)sizeof(*event)) {
- if (errno == EINTR) return 0;
+ if(res < (int)sizeof(*event)) {
+ if(errno == EINTR)
+ return 0;
ALOGW("could not get event, %s\n", strerror(errno));
return -1;
}
- while (res >= (int)sizeof(*event)) {
- event = (struct inotify_event*)(event_buf + event_pos);
- if (event->len) {
+ while(res >= (int)sizeof(*event)) {
+ event = (struct inotify_event *)(event_buf + event_pos);
+ if(event->len) {
if (event->wd == mInputWd) {
std::string filename = StringPrintf("%s/%s", DEVICE_PATH, event->name);
- if (event->mask & IN_CREATE) {
+ if(event->mask & IN_CREATE) {
openDeviceLocked(filename.c_str());
} else {
ALOGI("Removing device '%s' due to inotify event\n", filename.c_str());
closeDeviceByPathLocked(filename.c_str());
}
- } else if (event->wd == mVideoWd) {
+ }
+ else if (event->wd == mVideoWd) {
if (isV4lTouchNode(event->name)) {
std::string filename = StringPrintf("%s/%s", VIDEO_DEVICE_PATH, event->name);
if (event->mask & IN_CREATE) {
@@ -1846,7 +1845,8 @@ status_t EventHub::readNotifyLocked() {
closeVideoDeviceByPathLocked(filename);
}
}
- } else {
+ }
+ else {
LOG_ALWAYS_FATAL("Unexpected inotify event, wd = %i", event->wd);
}
}
@@ -1857,19 +1857,22 @@ status_t EventHub::readNotifyLocked() {
return 0;
}
-status_t EventHub::scanDirLocked(const char* dirname) {
+status_t EventHub::scanDirLocked(const char *dirname)
+{
char devname[PATH_MAX];
- char* filename;
- DIR* dir;
- struct dirent* de;
+ char *filename;
+ DIR *dir;
+ struct dirent *de;
dir = opendir(dirname);
- if (dir == nullptr) return -1;
+ if(dir == nullptr)
+ return -1;
strcpy(devname, dirname);
filename = devname + strlen(devname);
*filename++ = '/';
- while ((de = readdir(dir))) {
- if (de->d_name[0] == '.' &&
- (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+ while((de = readdir(dir))) {
+ if(de->d_name[0] == '.' &&
+ (de->d_name[1] == '\0' ||
+ (de->d_name[1] == '.' && de->d_name[2] == '\0')))
continue;
strcpy(filename, de->d_name);
openDeviceLocked(devname);
@@ -1881,16 +1884,17 @@ status_t EventHub::scanDirLocked(const char* dirname) {
/**
* Look for all dirname/v4l-touch* devices, and open them.
*/
-status_t EventHub::scanVideoDirLocked(const std::string& dirname) {
+status_t EventHub::scanVideoDirLocked(const std::string& dirname)
+{
DIR* dir;
struct dirent* de;
dir = opendir(dirname.c_str());
- if (!dir) {
+ if(!dir) {
ALOGE("Could not open video directory %s", dirname.c_str());
return BAD_VALUE;
}
- while ((de = readdir(dir))) {
+ while((de = readdir(dir))) {
const char* name = de->d_name;
if (isV4lTouchNode(name)) {
ALOGI("Found touch video device %s", name);
@@ -1922,10 +1926,10 @@ void EventHub::dump(std::string& dump) {
const Device* device = mDevices.valueAt(i);
if (mBuiltInKeyboardId == device->id) {
dump += StringPrintf(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
- device->id, device->identifier.name.c_str());
+ device->id, device->identifier.name.c_str());
} else {
dump += StringPrintf(INDENT2 "%d: %s\n", device->id,
- device->identifier.name.c_str());
+ device->identifier.name.c_str());
}
dump += StringPrintf(INDENT3 "Classes: 0x%08x\n", device->classes);
dump += StringPrintf(INDENT3 "Path: %s\n", device->path.c_str());
@@ -1935,17 +1939,17 @@ void EventHub::dump(std::string& dump) {
dump += StringPrintf(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
dump += StringPrintf(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.c_str());
dump += StringPrintf(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
- "product=0x%04x, version=0x%04x\n",
- device->identifier.bus, device->identifier.vendor,
- device->identifier.product, device->identifier.version);
+ "product=0x%04x, version=0x%04x\n",
+ device->identifier.bus, device->identifier.vendor,
+ device->identifier.product, device->identifier.version);
dump += StringPrintf(INDENT3 "KeyLayoutFile: %s\n",
- device->keyMap.keyLayoutFile.c_str());
+ device->keyMap.keyLayoutFile.c_str());
dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n",
- device->keyMap.keyCharacterMapFile.c_str());
+ device->keyMap.keyCharacterMapFile.c_str());
dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n",
- device->configurationFile.c_str());
+ device->configurationFile.c_str());
dump += StringPrintf(INDENT3 "HaveKeyboardLayoutOverlay: %s\n",
- toString(device->overlayKeyMap != nullptr));
+ toString(device->overlayKeyMap != nullptr));
dump += INDENT3 "VideoDevice: ";
if (device->videoDevice) {
dump += device->videoDevice->dump() + "\n";
@@ -1970,4 +1974,5 @@ void EventHub::monitor() {
mLock.unlock();
}
+
}; // namespace android
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/EventHub.h
index 794396acca..63a20ef3e2 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+//
#ifndef _RUNTIME_EVENT_HUB_H
#define _RUNTIME_EVENT_HUB_H
@@ -21,17 +22,17 @@
#include <input/Input.h>
#include <input/InputDevice.h>
-#include <input/KeyCharacterMap.h>
-#include <input/KeyLayoutMap.h>
#include <input/Keyboard.h>
+#include <input/KeyLayoutMap.h>
+#include <input/KeyCharacterMap.h>
#include <input/VirtualKeyMap.h>
-#include <utils/BitSet.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/List.h>
-#include <utils/Log.h>
#include <utils/Mutex.h>
+#include <utils/Log.h>
+#include <utils/List.h>
+#include <utils/Errors.h>
#include <utils/PropertyMap.h>
+#include <utils/KeyedVector.h>
+#include <utils/BitSet.h>
#include <linux/input.h>
#include <sys/epoll.h>
@@ -40,8 +41,8 @@
/* Convenience constants. */
-#define BTN_FIRST 0x100 // first button code
-#define BTN_LAST 0x15f // last button code
+#define BTN_FIRST 0x100 // first button code
+#define BTN_LAST 0x15f // last button code
namespace android {
@@ -60,10 +61,10 @@ struct RawEvent {
struct RawAbsoluteAxisInfo {
bool valid; // true if the information is valid, false otherwise
- int32_t minValue; // minimum value
- int32_t maxValue; // maximum value
- int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8
- int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
+ int32_t minValue; // minimum value
+ int32_t maxValue; // maximum value
+ int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8
+ int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
int32_t resolution; // resolution in units per mm or radians per mm
inline void clear() {
@@ -81,37 +82,37 @@ struct RawAbsoluteAxisInfo {
*/
enum {
/* The input device is a keyboard or has buttons. */
- INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
+ INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
/* The input device is an alpha-numeric keyboard (not just a dial pad). */
- INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,
+ INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,
/* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */
- INPUT_DEVICE_CLASS_TOUCH = 0x00000004,
+ INPUT_DEVICE_CLASS_TOUCH = 0x00000004,
/* The input device is a cursor device such as a trackball or mouse. */
- INPUT_DEVICE_CLASS_CURSOR = 0x00000008,
+ INPUT_DEVICE_CLASS_CURSOR = 0x00000008,
/* The input device is a multi-touch touchscreen. */
- INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010,
+ INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010,
/* The input device is a directional pad (implies keyboard, has DPAD keys). */
- INPUT_DEVICE_CLASS_DPAD = 0x00000020,
+ INPUT_DEVICE_CLASS_DPAD = 0x00000020,
/* The input device is a gamepad (implies keyboard, has BUTTON keys). */
- INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
+ INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
/* The input device has switches. */
- INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
+ INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
/* The input device is a joystick (implies gamepad, has joystick absolute axes). */
- INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
+ INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
/* The input device has a vibrator (supports FF_RUMBLE). */
- INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,
+ INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,
/* The input device has a microphone. */
- INPUT_DEVICE_CLASS_MIC = 0x00000400,
+ INPUT_DEVICE_CLASS_MIC = 0x00000400,
/* The input device is an external stylus (has data we want to fuse with touch data). */
INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
@@ -120,10 +121,10 @@ enum {
INPUT_DEVICE_CLASS_ROTARY_ENCODER = 0x00001000,
/* The input device is virtual (not a real device, not part of UI configuration). */
- INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,
+ INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,
/* The input device is external (not built-in). */
- INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
+ INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
};
/*
@@ -147,8 +148,8 @@ extern uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses);
*/
class EventHubInterface : public virtual RefBase {
protected:
- EventHubInterface() {}
- virtual ~EventHubInterface() {}
+ EventHubInterface() { }
+ virtual ~EventHubInterface() { }
public:
// Synthetic raw event type codes produced when devices are added or removed.
@@ -173,17 +174,18 @@ public:
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const = 0;
+ RawAbsoluteAxisInfo* outAxisInfo) const = 0;
virtual bool hasRelativeAxis(int32_t deviceId, int axis) const = 0;
virtual bool hasInputProperty(int32_t deviceId, int property) const = 0;
- virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
- int32_t metaState, int32_t* outKeycode, int32_t* outMetaState,
- uint32_t* outFlags) const = 0;
+ virtual status_t mapKey(int32_t deviceId,
+ int32_t scanCode, int32_t usageCode, int32_t metaState,
+ int32_t* outKeycode, int32_t *outMetaState, uint32_t* outFlags) const = 0;
- virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const = 0;
+ virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
+ AxisInfo* outAxisInfo) const = 0;
// Sets devices that are excluded from opening.
// This can be used to ignore input devices for sensors.
@@ -211,13 +213,13 @@ public:
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const = 0;
+ int32_t* outValue) const = 0;
/*
* Examine key input devices for specific framework keycode support
*/
virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) const = 0;
+ uint8_t* outFlags) const = 0;
virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
@@ -225,8 +227,8 @@ public:
virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
- virtual void getVirtualKeyDefinitions(
- int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
+ virtual void getVirtualKeyDefinitions(int32_t deviceId,
+ std::vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const = 0;
virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) = 0;
@@ -257,7 +259,8 @@ public:
virtual status_t disableDevice(int32_t deviceId) = 0;
};
-class EventHub : public EventHubInterface {
+class EventHub : public EventHubInterface
+{
public:
EventHub();
@@ -270,17 +273,18 @@ public:
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const;
+ RawAbsoluteAxisInfo* outAxisInfo) const;
virtual bool hasRelativeAxis(int32_t deviceId, int axis) const;
virtual bool hasInputProperty(int32_t deviceId, int property) const;
- virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
- int32_t metaState, int32_t* outKeycode, int32_t* outMetaState,
- uint32_t* outFlags) const;
+ virtual status_t mapKey(int32_t deviceId,
+ int32_t scanCode, int32_t usageCode, int32_t metaState,
+ int32_t* outKeycode, int32_t *outMetaState, uint32_t* outFlags) const;
- virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const;
+ virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
+ AxisInfo* outAxisInfo) const;
virtual void setExcludedDevices(const std::vector<std::string>& devices);
@@ -289,8 +293,8 @@ public:
virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const;
virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const;
- virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) const;
+ virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags) const;
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId);
@@ -300,7 +304,7 @@ public:
virtual void setLedState(int32_t deviceId, int32_t led, bool on);
virtual void getVirtualKeyDefinitions(int32_t deviceId,
- std::vector<VirtualKeyDefinition>& outVirtualKeys) const;
+ std::vector<VirtualKeyDefinition>& outVirtualKeys) const;
virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const;
virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map);
@@ -353,7 +357,7 @@ private:
int32_t controllerNumber;
Device(int fd, int32_t id, const std::string& path,
- const InputDeviceIdentifier& identifier);
+ const InputDeviceIdentifier& identifier);
~Device();
void close();
@@ -378,7 +382,7 @@ private:
void addDeviceLocked(Device* device);
void assignDescriptorLocked(InputDeviceIdentifier& identifier);
- void closeDeviceByPathLocked(const char* devicePath);
+ void closeDeviceByPathLocked(const char *devicePath);
void closeVideoDeviceByPathLocked(const std::string& devicePath);
void closeDeviceLocked(Device* device);
void closeAllDevicesLocked();
@@ -395,7 +399,7 @@ private:
status_t unregisterDeviceFromEpollLocked(Device* device);
void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice);
- status_t scanDirLocked(const char* dirname);
+ status_t scanDirLocked(const char *dirname);
status_t scanVideoDirLocked(const std::string& dirname);
void scanDevicesLocked();
status_t readNotifyLocked();
@@ -451,8 +455,8 @@ private:
*/
std::vector<std::unique_ptr<TouchVideoDevice>> mUnattachedVideoDevices;
- Device* mOpeningDevices;
- Device* mClosingDevices;
+ Device *mOpeningDevices;
+ Device *mClosingDevices;
bool mNeedToSendFinishedDeviceScan;
bool mNeedToReopenDevices;
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 6a7f2797f4..cda0e0cdcb 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -27,7 +27,6 @@
#if defined(__linux__)
#include <pthread.h>
#endif
-#include <server_configurable_flags/get_flags.h>
#include <unordered_set>
#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
@@ -46,13 +45,6 @@ using namespace android::hardware::input;
namespace android {
-static constexpr bool DEBUG = false;
-
-// Category (=namespace) name for the input settings that are applied at boot time
-static const char* INPUT_NATIVE_BOOT = "input_native_boot";
-// Feature flag name for the deep press feature
-static const char* DEEP_PRESS_ENABLED = "deep_press_enabled";
-
//Max number of elements to store in mEvents.
static constexpr size_t MAX_EVENTS = 5;
@@ -79,20 +71,6 @@ static bool isTouchEvent(const NotifyMotionArgs& args) {
return args.source == AINPUT_SOURCE_TOUCHPAD || args.source == AINPUT_SOURCE_TOUCHSCREEN;
}
-// Check if the "deep touch" feature is on.
-static bool deepPressEnabled() {
- std::string flag_value = server_configurable_flags::GetServerConfigurableFlag(
- INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "false");
- std::transform(flag_value.begin(), flag_value.end(), flag_value.begin(), ::tolower);
- if (flag_value == "1" || flag_value == "true") {
- ALOGI("Deep press feature enabled.");
- return true;
- }
- ALOGI("Deep press feature is not enabled.");
- return false;
-}
-
-
// --- ClassifierEvent ---
ClassifierEvent::ClassifierEvent(std::unique_ptr<NotifyMotionArgs> args) :
@@ -141,53 +119,40 @@ std::optional<int32_t> ClassifierEvent::getDeviceId() const {
// --- MotionClassifier ---
-MotionClassifier::MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient) :
- mDeathRecipient(deathRecipient), mEvents(MAX_EVENTS) {
- mHalThread = std::thread(&MotionClassifier::callInputClassifierHal, this);
+MotionClassifier::MotionClassifier(
+ sp<android::hardware::input::classifier::V1_0::IInputClassifier> service)
+ : mEvents(MAX_EVENTS), mService(service) {
+ // Under normal operation, we do not need to reset the HAL here. But in the case where system
+ // crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
+ // have received events in the past. That means, that HAL could be in an inconsistent state
+ // once it receives events from the newly created MotionClassifier.
+ mEvents.push(ClassifierEvent::createHalResetEvent());
+
+ mHalThread = std::thread(&MotionClassifier::processEvents, this);
#if defined(__linux__)
// Set the thread name for debugging
pthread_setname_np(mHalThread.native_handle(), "InputClassifier");
#endif
}
-/**
- * This function may block for some time to initialize the HAL, so it should only be called
- * from the "InputClassifier HAL" thread.
- */
-bool MotionClassifier::init() {
- ensureHalThread(__func__);
+std::unique_ptr<MotionClassifierInterface> MotionClassifier::create(
+ sp<android::hardware::hidl_death_recipient> deathRecipient) {
sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
classifier::V1_0::IInputClassifier::getService();
if (!service) {
// Not really an error, maybe the device does not have this HAL,
// but somehow the feature flag is flipped
ALOGI("Could not obtain InputClassifier HAL");
- return false;
+ return nullptr;
}
- sp<android::hardware::hidl_death_recipient> recipient = mDeathRecipient.promote();
- if (recipient != nullptr) {
- const bool linked = service->linkToDeath(recipient, 0 /* cookie */).withDefault(false);
- if (!linked) {
- ALOGE("Could not link MotionClassifier to the HAL death");
- return false;
- }
+ const bool linked = service->linkToDeath(deathRecipient, 0 /* cookie */).withDefault(false);
+ if (!linked) {
+ ALOGE("Could not link death recipient to the HAL death");
+ return nullptr;
}
-
- // Under normal operation, we do not need to reset the HAL here. But in the case where system
- // crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
- // have received events in the past. That means, that HAL could be in an inconsistent state
- // once it receives events from the newly created MotionClassifier.
- mEvents.push(ClassifierEvent::createHalResetEvent());
-
- {
- std::scoped_lock lock(mLock);
- if (mService) {
- ALOGE("MotionClassifier::%s should only be called once", __func__);
- }
- mService = service;
- }
- return true;
+ // Using 'new' to access a non-public constructor
+ return std::unique_ptr<MotionClassifier>(new MotionClassifier(service));
}
MotionClassifier::~MotionClassifier() {
@@ -195,14 +160,6 @@ MotionClassifier::~MotionClassifier() {
mHalThread.join();
}
-void MotionClassifier::ensureHalThread(const char* function) {
- if (DEBUG) {
- if (std::this_thread::get_id() != mHalThread.get_id()) {
- LOG_FATAL("Function %s should only be called from InputClassifier thread", function);
- }
- }
-}
-
/**
* Obtain the classification from the HAL for a given MotionEvent.
* Should only be called from the InputClassifier thread (mHalThread).
@@ -213,23 +170,7 @@ void MotionClassifier::ensureHalThread(const char* function) {
* To remove any possibility of negatively affecting the touch latency, the HAL
* is called from a dedicated thread.
*/
-void MotionClassifier::callInputClassifierHal() {
- ensureHalThread(__func__);
- const bool initialized = init();
- if (!initialized) {
- // MotionClassifier no longer useful.
- // Deliver death notification from a separate thread
- // because ~MotionClassifier may be invoked, which calls mHalThread.join()
- std::thread([deathRecipient = mDeathRecipient](){
- sp<android::hardware::hidl_death_recipient> recipient = deathRecipient.promote();
- if (recipient != nullptr) {
- recipient->serviceDied(0 /*cookie*/, nullptr);
- }
- }).detach();
- return;
- }
- // From this point on, mService is guaranteed to be non-null.
-
+void MotionClassifier::processEvents() {
while (true) {
ClassifierEvent event = mEvents.pop();
bool halResponseOk = true;
@@ -383,24 +324,41 @@ void MotionClassifier::dump(std::string& dump) {
}
}
+// --- HalDeathRecipient
-// --- InputClassifier ---
+InputClassifier::HalDeathRecipient::HalDeathRecipient(InputClassifier& parent) : mParent(parent) {}
-InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener) :
- mListener(listener) {
- // The rest of the initialization is done in onFirstRef, because we need to obtain
- // an sp to 'this' in order to register for HAL death notifications
+void InputClassifier::HalDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<android::hidl::base::V1_0::IBase>& who) {
+ sp<android::hidl::base::V1_0::IBase> service = who.promote();
+ if (service) {
+ service->unlinkToDeath(this);
+ }
+ mParent.setMotionClassifier(nullptr);
}
-void InputClassifier::onFirstRef() {
- if (!deepPressEnabled()) {
- // If feature is not enabled, MotionClassifier should stay null to avoid unnecessary work.
- // When MotionClassifier is null, InputClassifier will forward all events
- // to the next InputListener, unmodified.
- return;
+// --- InputClassifier ---
+
+InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
+ : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}
+
+void InputClassifier::setMotionClassifierEnabled(bool enabled) {
+ if (enabled) {
+ ALOGI("Enabling motion classifier");
+ if (mInitializeMotionClassifierThread.joinable()) {
+ mInitializeMotionClassifierThread.join();
+ }
+ mInitializeMotionClassifierThread = std::thread(
+ [this] { setMotionClassifier(MotionClassifier::create(mHalDeathRecipient)); });
+#if defined(__linux__)
+ // Set the thread name for debugging
+ pthread_setname_np(mInitializeMotionClassifierThread.native_handle(),
+ "Create MotionClassifier");
+#endif
+ } else {
+ ALOGI("Disabling motion classifier");
+ setMotionClassifier(nullptr);
}
- std::scoped_lock lock(mLock);
- mMotionClassifier = std::make_unique<MotionClassifier>(this);
}
void InputClassifier::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
@@ -441,15 +399,10 @@ void InputClassifier::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
mListener->notifyDeviceReset(args);
}
-void InputClassifier::serviceDied(uint64_t /*cookie*/,
- const wp<android::hidl::base::V1_0::IBase>& who) {
+void InputClassifier::setMotionClassifier(
+ std::unique_ptr<MotionClassifierInterface> motionClassifier) {
std::scoped_lock lock(mLock);
- ALOGE("InputClassifier HAL has died. Setting mMotionClassifier to null");
- mMotionClassifier = nullptr;
- sp<android::hidl::base::V1_0::IBase> service = who.promote();
- if (service) {
- service->unlinkToDeath(this);
- }
+ mMotionClassifier = std::move(motionClassifier);
}
void InputClassifier::dump(std::string& dump) {
@@ -465,4 +418,10 @@ void InputClassifier::dump(std::string& dump) {
dump += "\n";
}
+InputClassifier::~InputClassifier() {
+ if (mInitializeMotionClassifierThread.joinable()) {
+ mInitializeMotionClassifierThread.join();
+ }
+}
+
} // namespace android
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index 47e20dbf75..9ac8e2db2b 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -19,8 +19,8 @@
#include <android-base/thread_annotations.h>
#include <utils/RefBase.h>
-#include <unordered_map>
#include <thread>
+#include <unordered_map>
#include "BlockingQueue.h"
#include "InputListener.h"
@@ -90,6 +90,7 @@ public:
*/
class InputClassifierInterface : public virtual RefBase, public InputListenerInterface {
public:
+ virtual void setMotionClassifierEnabled(bool enabled) = 0;
/**
* Dump the state of the input classifier.
* This method may be called on any thread (usually by the input manager).
@@ -113,23 +114,23 @@ protected:
*/
class MotionClassifier final : public MotionClassifierInterface {
public:
- /**
- * The deathRecipient will be subscribed to the HAL death. If the death recipient
- * owns MotionClassifier and receives HAL death, it should delete its copy of it.
- * The callback serviceDied will also be sent if the MotionClassifier itself fails
- * to initialize. If the MotionClassifier fails to initialize, it is not useful, and
- * should be deleted.
- * If no death recipient is supplied, then the registration step will be skipped, so there will
- * be no listeners registered for the HAL death. This is useful for testing
- * MotionClassifier in isolation.
+ /*
+ * Create an instance of MotionClassifier.
+ * The death recipient, if provided, will be subscribed to the HAL death.
+ * The death recipient could be used to destroy MotionClassifier.
+ *
+ * This function should be called asynchronously, because getService takes a long time.
*/
- explicit MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient = nullptr);
+ static std::unique_ptr<MotionClassifierInterface> create(
+ sp<android::hardware::hidl_death_recipient> deathRecipient);
+
~MotionClassifier();
/**
* Classifies events asynchronously; that is, it doesn't block events on a classification,
- * but instead sends them over to the classifier HAL and after a classification is
- * determined, it then marks the next event it sees in the stream with it.
+ * but instead sends them over to the classifier HAL. After a classification of a specific
+ * event is determined, MotionClassifier then marks the next event in the stream with this
+ * classification.
*
* Therefore, it is acceptable to have the classifications be delayed by 1-2 events
* in a particular gesture.
@@ -141,15 +142,9 @@ public:
virtual void dump(std::string& dump) override;
private:
- /**
- * Initialize MotionClassifier.
- * Return true if initializaion is successful.
- */
- bool init();
- /**
- * Entity that will be notified of the HAL death (most likely InputClassifier).
- */
- wp<android::hardware::hidl_death_recipient> mDeathRecipient;
+ friend class MotionClassifierTest; // to create MotionClassifier with a test HAL implementation
+ explicit MotionClassifier(
+ sp<android::hardware::input::classifier::V1_0::IInputClassifier> service);
// The events that need to be sent to the HAL.
BlockingQueue<ClassifierEvent> mEvents;
@@ -164,14 +159,9 @@ private:
*/
std::thread mHalThread;
/**
- * Print an error message if the caller is not on the InputClassifier thread.
- * Caller must supply the name of the calling function as __func__
+ * Process events and call the InputClassifier HAL
*/
- void ensureHalThread(const char* function);
- /**
- * Call the InputClassifier HAL
- */
- void callInputClassifierHal();
+ void processEvents();
/**
* Access to the InputClassifier HAL. May be null if init() hasn't completed yet.
* When init() successfully completes, mService is guaranteed to remain non-null and to not
@@ -223,19 +213,15 @@ private:
const char* getServiceStatus() REQUIRES(mLock);
};
-
/**
* Implementation of the InputClassifierInterface.
* Represents a separate stage of input processing. All of the input events go through this stage.
* Acts as a passthrough for all input events except for motion events.
* The events of motion type are sent to MotionClassifier.
*/
-class InputClassifier : public InputClassifierInterface,
- public android::hardware::hidl_death_recipient {
+class InputClassifier : public InputClassifierInterface {
public:
explicit InputClassifier(const sp<InputListenerInterface>& listener);
- // Some of the constructor logic is finished in onFirstRef
- virtual void onFirstRef() override;
virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
virtual void notifyKey(const NotifyKeyArgs* args) override;
@@ -243,17 +229,47 @@ public:
virtual void notifySwitch(const NotifySwitchArgs* args) override;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
- virtual void serviceDied(uint64_t cookie,
- const wp<android::hidl::base::V1_0::IBase>& who) override;
-
virtual void dump(std::string& dump) override;
+ ~InputClassifier();
+
+ // Called from InputManager
+ virtual void setMotionClassifierEnabled(bool enabled) override;
+
private:
// Protect access to mMotionClassifier, since it may become null via a hidl callback
std::mutex mLock;
- std::unique_ptr<MotionClassifierInterface> mMotionClassifier GUARDED_BY(mLock);
// The next stage to pass input events to
sp<InputListenerInterface> mListener;
+
+ std::unique_ptr<MotionClassifierInterface> mMotionClassifier GUARDED_BY(mLock);
+ std::thread mInitializeMotionClassifierThread;
+ /**
+ * Set the value of mMotionClassifier.
+ * This is called from 2 different threads:
+ * 1) mInitializeMotionClassifierThread, when we have constructed a MotionClassifier
+ * 2) A binder thread of the HalDeathRecipient, which is created when HAL dies. This would cause
+ * mMotionClassifier to become nullptr.
+ */
+ void setMotionClassifier(std::unique_ptr<MotionClassifierInterface> motionClassifier);
+
+ /**
+ * The deathRecipient will call setMotionClassifier(null) when the HAL dies.
+ */
+ class HalDeathRecipient : public android::hardware::hidl_death_recipient {
+ public:
+ explicit HalDeathRecipient(InputClassifier& parent);
+ virtual void serviceDied(uint64_t cookie,
+ const wp<android::hidl::base::V1_0::IBase>& who) override;
+
+ private:
+ InputClassifier& mParent;
+ };
+ // We retain a reference to death recipient, because the death recipient will be calling
+ // ~MotionClassifier if the HAL dies.
+ // If we don't retain a reference, and MotionClassifier is the only owner of the death
+ // recipient, the serviceDied call will cause death recipient to call its own destructor.
+ sp<HalDeathRecipient> mHalDeathRecipient;
};
} // namespace android
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 44100086c4..b921d954dc 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -45,22 +45,20 @@
#include "InputDispatcher.h"
-#include "Connection.h"
-
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
+#include <sstream>
#include <stddef.h>
#include <time.h>
#include <unistd.h>
-#include <sstream>
#include <android-base/chrono_utils.h>
#include <android-base/stringprintf.h>
-#include <binder/Binder.h>
#include <log/log.h>
-#include <powermanager/PowerManager.h>
#include <utils/Trace.h>
+#include <powermanager/PowerManager.h>
+#include <binder/Binder.h>
#define INDENT " "
#define INDENT2 " "
@@ -69,7 +67,7 @@
using android::base::StringPrintf;
-namespace android::inputdispatcher {
+namespace android {
// Default input dispatching timeout if there is no focused application or paused window
// from which to determine an appropriate dispatching timeout.
@@ -99,6 +97,10 @@ constexpr std::chrono::milliseconds SLOW_INTERCEPTION_THRESHOLD = 50ms;
// Number of recent events to keep for debugging purposes.
constexpr size_t RECENT_QUEUE_MAX_SIZE = 10;
+// Sequence number for synthesized or injected events.
+constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
+
+
static inline nsecs_t now() {
return systemTime(SYSTEM_TIME_MONOTONIC);
}
@@ -107,23 +109,41 @@ static inline const char* toString(bool value) {
return value ? "true" : "false";
}
+static std::string dispatchModeToString(int32_t dispatchMode) {
+ switch (dispatchMode) {
+ case InputTarget::FLAG_DISPATCH_AS_IS:
+ return "DISPATCH_AS_IS";
+ case InputTarget::FLAG_DISPATCH_AS_OUTSIDE:
+ return "DISPATCH_AS_OUTSIDE";
+ case InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER:
+ return "DISPATCH_AS_HOVER_ENTER";
+ case InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT:
+ return "DISPATCH_AS_HOVER_EXIT";
+ case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT:
+ return "DISPATCH_AS_SLIPPERY_EXIT";
+ case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER:
+ return "DISPATCH_AS_SLIPPERY_ENTER";
+ }
+ return StringPrintf("%" PRId32, dispatchMode);
+}
+
static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
- return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
- AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+ return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
+ >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
}
static bool isValidKeyAction(int32_t action) {
switch (action) {
- case AKEY_EVENT_ACTION_DOWN:
- case AKEY_EVENT_ACTION_UP:
- return true;
- default:
- return false;
+ case AKEY_EVENT_ACTION_DOWN:
+ case AKEY_EVENT_ACTION_UP:
+ return true;
+ default:
+ return false;
}
}
static bool validateKeyEvent(int32_t action) {
- if (!isValidKeyAction(action)) {
+ if (! isValidKeyAction(action)) {
ALOGE("Key event has invalid action code 0x%x", action);
return false;
}
@@ -132,46 +152,46 @@ static bool validateKeyEvent(int32_t action) {
static bool isValidMotionAction(int32_t action, int32_t actionButton, int32_t pointerCount) {
switch (action & AMOTION_EVENT_ACTION_MASK) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL:
- case AMOTION_EVENT_ACTION_MOVE:
- case AMOTION_EVENT_ACTION_OUTSIDE:
- case AMOTION_EVENT_ACTION_HOVER_ENTER:
- case AMOTION_EVENT_ACTION_HOVER_MOVE:
- case AMOTION_EVENT_ACTION_HOVER_EXIT:
- case AMOTION_EVENT_ACTION_SCROLL:
- return true;
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- case AMOTION_EVENT_ACTION_POINTER_UP: {
- int32_t index = getMotionEventActionPointerIndex(action);
- return index >= 0 && index < pointerCount;
- }
- case AMOTION_EVENT_ACTION_BUTTON_PRESS:
- case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
- return actionButton != 0;
- default:
- return false;
+ case AMOTION_EVENT_ACTION_DOWN:
+ case AMOTION_EVENT_ACTION_UP:
+ case AMOTION_EVENT_ACTION_CANCEL:
+ case AMOTION_EVENT_ACTION_MOVE:
+ case AMOTION_EVENT_ACTION_OUTSIDE:
+ case AMOTION_EVENT_ACTION_HOVER_ENTER:
+ case AMOTION_EVENT_ACTION_HOVER_MOVE:
+ case AMOTION_EVENT_ACTION_HOVER_EXIT:
+ case AMOTION_EVENT_ACTION_SCROLL:
+ return true;
+ case AMOTION_EVENT_ACTION_POINTER_DOWN:
+ case AMOTION_EVENT_ACTION_POINTER_UP: {
+ int32_t index = getMotionEventActionPointerIndex(action);
+ return index >= 0 && index < pointerCount;
+ }
+ case AMOTION_EVENT_ACTION_BUTTON_PRESS:
+ case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
+ return actionButton != 0;
+ default:
+ return false;
}
}
static bool validateMotionEvent(int32_t action, int32_t actionButton, size_t pointerCount,
- const PointerProperties* pointerProperties) {
- if (!isValidMotionAction(action, actionButton, pointerCount)) {
+ const PointerProperties* pointerProperties) {
+ if (! isValidMotionAction(action, actionButton, pointerCount)) {
ALOGE("Motion event has invalid action code 0x%x", action);
return false;
}
if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %d.",
- pointerCount, MAX_POINTERS);
+ pointerCount, MAX_POINTERS);
return false;
}
BitSet32 pointerIdBits;
for (size_t i = 0; i < pointerCount; i++) {
int32_t id = pointerProperties[i].id;
if (id < 0 || id > MAX_POINTER_ID) {
- ALOGE("Motion event has invalid pointer id %d; value must be between 0 and %d", id,
- MAX_POINTER_ID);
+ ALOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
+ id, MAX_POINTER_ID);
return false;
}
if (pointerIdBits.hasBit(id)) {
@@ -203,26 +223,23 @@ static void dumpRegion(std::string& dump, const Region& region) {
}
}
-template <typename T, typename U>
+template<typename T, typename U>
static T getValueByKey(std::unordered_map<U, T>& map, U key) {
typename std::unordered_map<U, T>::const_iterator it = map.find(key);
return it != map.end() ? it->second : T{};
}
+
// --- InputDispatcher ---
-InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
- : mPolicy(policy),
- mPendingEvent(nullptr),
- mLastDropReason(DROP_REASON_NOT_DROPPED),
- mAppSwitchSawKeyDown(false),
- mAppSwitchDueTime(LONG_LONG_MAX),
- mNextUnblockedEvent(nullptr),
- mDispatchEnabled(false),
- mDispatchFrozen(false),
- mInputFilterEnabled(false),
- mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
- mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
+InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
+ mPolicy(policy),
+ mPendingEvent(nullptr), mLastDropReason(DROP_REASON_NOT_DROPPED),
+ mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
+ mNextUnblockedEvent(nullptr),
+ mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
+ mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
+ mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
mLooper = new Looper(false);
mReporter = createInputReporter();
@@ -298,7 +315,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
// Ready to start a new event.
// If we don't already have a pending event, go grab one.
- if (!mPendingEvent) {
+ if (! mPendingEvent) {
if (mInboundQueue.isEmpty()) {
if (isAppSwitchDue) {
// The inbound queue is empty so the app switch key we were waiting
@@ -353,59 +370,63 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
}
switch (mPendingEvent->type) {
- case EventEntry::TYPE_CONFIGURATION_CHANGED: {
- ConfigurationChangedEntry* typedEntry =
- static_cast<ConfigurationChangedEntry*>(mPendingEvent);
- done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
- dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
- break;
+ case EventEntry::TYPE_CONFIGURATION_CHANGED: {
+ ConfigurationChangedEntry* typedEntry =
+ static_cast<ConfigurationChangedEntry*>(mPendingEvent);
+ done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
+ dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
+ break;
+ }
+
+ case EventEntry::TYPE_DEVICE_RESET: {
+ DeviceResetEntry* typedEntry =
+ static_cast<DeviceResetEntry*>(mPendingEvent);
+ done = dispatchDeviceResetLocked(currentTime, typedEntry);
+ dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
+ break;
+ }
+
+ case EventEntry::TYPE_KEY: {
+ KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
+ if (isAppSwitchDue) {
+ if (isAppSwitchKeyEvent(typedEntry)) {
+ resetPendingAppSwitchLocked(true);
+ isAppSwitchDue = false;
+ } else if (dropReason == DROP_REASON_NOT_DROPPED) {
+ dropReason = DROP_REASON_APP_SWITCH;
+ }
}
-
- case EventEntry::TYPE_DEVICE_RESET: {
- DeviceResetEntry* typedEntry = static_cast<DeviceResetEntry*>(mPendingEvent);
- done = dispatchDeviceResetLocked(currentTime, typedEntry);
- dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
- break;
+ if (dropReason == DROP_REASON_NOT_DROPPED
+ && isStaleEvent(currentTime, typedEntry)) {
+ dropReason = DROP_REASON_STALE;
}
-
- case EventEntry::TYPE_KEY: {
- KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
- if (isAppSwitchDue) {
- if (isAppSwitchKeyEvent(typedEntry)) {
- resetPendingAppSwitchLocked(true);
- isAppSwitchDue = false;
- } else if (dropReason == DROP_REASON_NOT_DROPPED) {
- dropReason = DROP_REASON_APP_SWITCH;
- }
- }
- if (dropReason == DROP_REASON_NOT_DROPPED && isStaleEvent(currentTime, typedEntry)) {
- dropReason = DROP_REASON_STALE;
- }
- if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
- dropReason = DROP_REASON_BLOCKED;
- }
- done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
- break;
+ if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+ dropReason = DROP_REASON_BLOCKED;
}
+ done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
+ break;
+ }
- case EventEntry::TYPE_MOTION: {
- MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
- if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
- dropReason = DROP_REASON_APP_SWITCH;
- }
- if (dropReason == DROP_REASON_NOT_DROPPED && isStaleEvent(currentTime, typedEntry)) {
- dropReason = DROP_REASON_STALE;
- }
- if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
- dropReason = DROP_REASON_BLOCKED;
- }
- done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
- break;
+ case EventEntry::TYPE_MOTION: {
+ MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
+ if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
+ dropReason = DROP_REASON_APP_SWITCH;
+ }
+ if (dropReason == DROP_REASON_NOT_DROPPED
+ && isStaleEvent(currentTime, typedEntry)) {
+ dropReason = DROP_REASON_STALE;
+ }
+ if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+ dropReason = DROP_REASON_BLOCKED;
}
+ done = dispatchMotionLocked(currentTime, typedEntry,
+ &dropReason, nextWakeupTime);
+ break;
+ }
- default:
- ALOG_ASSERT(false);
- break;
+ default:
+ ALOG_ASSERT(false);
+ break;
}
if (done) {
@@ -415,7 +436,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
mLastDropReason = dropReason;
releasePendingEventLocked();
- *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
+ *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
@@ -425,56 +446,55 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
traceInboundQueueLengthLocked();
switch (entry->type) {
- case EventEntry::TYPE_KEY: {
- // Optimize app switch latency.
- // If the application takes too long to catch up then we drop all events preceding
- // the app switch key.
- KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
- if (isAppSwitchKeyEvent(keyEntry)) {
- if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
- mAppSwitchSawKeyDown = true;
- } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
- if (mAppSwitchSawKeyDown) {
+ case EventEntry::TYPE_KEY: {
+ // Optimize app switch latency.
+ // If the application takes too long to catch up then we drop all events preceding
+ // the app switch key.
+ KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
+ if (isAppSwitchKeyEvent(keyEntry)) {
+ if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
+ mAppSwitchSawKeyDown = true;
+ } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
+ if (mAppSwitchSawKeyDown) {
#if DEBUG_APP_SWITCH
- ALOGD("App switch is pending!");
+ ALOGD("App switch is pending!");
#endif
- mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
- mAppSwitchSawKeyDown = false;
- needWake = true;
- }
+ mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
+ mAppSwitchSawKeyDown = false;
+ needWake = true;
}
}
- break;
}
-
- case EventEntry::TYPE_MOTION: {
- // Optimize case where the current application is unresponsive and the user
- // decides to touch a window in a different application.
- // If the application takes too long to catch up then we drop all events preceding
- // the touch into the other window.
- MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
- if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN &&
- (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) &&
- mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY &&
- mInputTargetWaitApplicationToken != nullptr) {
- int32_t displayId = motionEntry->displayId;
- int32_t x =
- int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
- int32_t y =
- int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
- sp<InputWindowHandle> touchedWindowHandle =
- findTouchedWindowAtLocked(displayId, x, y);
- if (touchedWindowHandle != nullptr &&
- touchedWindowHandle->getApplicationToken() !=
- mInputTargetWaitApplicationToken) {
- // User touched a different application than the one we are waiting on.
- // Flag the event, and start pruning the input queue.
- mNextUnblockedEvent = motionEntry;
- needWake = true;
- }
+ break;
+ }
+
+ case EventEntry::TYPE_MOTION: {
+ // Optimize case where the current application is unresponsive and the user
+ // decides to touch a window in a different application.
+ // If the application takes too long to catch up then we drop all events preceding
+ // the touch into the other window.
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+ if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
+ && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
+ && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
+ && mInputTargetWaitApplicationToken != nullptr) {
+ int32_t displayId = motionEntry->displayId;
+ int32_t x = int32_t(motionEntry->pointerCoords[0].
+ getAxisValue(AMOTION_EVENT_AXIS_X));
+ int32_t y = int32_t(motionEntry->pointerCoords[0].
+ getAxisValue(AMOTION_EVENT_AXIS_Y));
+ sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);
+ if (touchedWindowHandle != nullptr
+ && touchedWindowHandle->getApplicationToken()
+ != mInputTargetWaitApplicationToken) {
+ // User touched a different application than the one we are waiting on.
+ // Flag the event, and start pruning the input queue.
+ mNextUnblockedEvent = motionEntry;
+ needWake = true;
}
- break;
}
+ break;
+ }
}
return needWake;
@@ -488,9 +508,8 @@ void InputDispatcher::addRecentEventLocked(EventEntry* entry) {
}
}
-sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x,
- int32_t y, bool addOutsideTargets,
- bool addPortalWindows) {
+sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
+ int32_t x, int32_t y, bool addOutsideTargets, bool addPortalWindows) {
// Traverse windows from front to back to find touched window.
const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
@@ -500,19 +519,18 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display
if (windowInfo->visible) {
if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
- bool isTouchModal = (flags &
- (InputWindowInfo::FLAG_NOT_FOCUSABLE |
- InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
+ bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
+ | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
int32_t portalToDisplayId = windowInfo->portalToDisplayId;
- if (portalToDisplayId != ADISPLAY_ID_NONE &&
- portalToDisplayId != displayId) {
+ if (portalToDisplayId != ADISPLAY_ID_NONE
+ && portalToDisplayId != displayId) {
if (addPortalWindows) {
// For the monitoring channels of the display.
mTempTouchState.addPortalWindow(windowHandle);
}
- return findTouchedWindowAtLocked(portalToDisplayId, x, y,
- addOutsideTargets, addPortalWindows);
+ return findTouchedWindowAtLocked(
+ portalToDisplayId, x, y, addOutsideTargets, addPortalWindows);
}
// Found window.
return windowHandle;
@@ -520,9 +538,8 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display
}
if (addOutsideTargets && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
- mTempTouchState.addOrUpdateWindow(windowHandle,
- InputTarget::FLAG_DISPATCH_AS_OUTSIDE,
- BitSet32(0));
+ mTempTouchState.addOrUpdateWindow(
+ windowHandle, InputTarget::FLAG_DISPATCH_AS_OUTSIDE, BitSet32(0));
}
}
}
@@ -530,7 +547,7 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display
return nullptr;
}
-std::vector<TouchedMonitor> InputDispatcher::findTouchedGestureMonitorsLocked(
+std::vector<InputDispatcher::TouchedMonitor> InputDispatcher::findTouchedGestureMonitorsLocked(
int32_t displayId, const std::vector<sp<InputWindowHandle>>& portalWindows) {
std::vector<TouchedMonitor> touchedMonitors;
@@ -539,15 +556,14 @@ std::vector<TouchedMonitor> InputDispatcher::findTouchedGestureMonitorsLocked(
for (const sp<InputWindowHandle>& portalWindow : portalWindows) {
const InputWindowInfo* windowInfo = portalWindow->getInfo();
monitors = getValueByKey(mGestureMonitorsByDisplay, windowInfo->portalToDisplayId);
- addGestureMonitors(monitors, touchedMonitors, -windowInfo->frameLeft,
- -windowInfo->frameTop);
+ addGestureMonitors(monitors, touchedMonitors,
+ -windowInfo->frameLeft, -windowInfo->frameTop);
}
return touchedMonitors;
}
void InputDispatcher::addGestureMonitors(const std::vector<Monitor>& monitors,
- std::vector<TouchedMonitor>& outTouchedMonitors,
- float xOffset, float yOffset) {
+ std::vector<TouchedMonitor>& outTouchedMonitors, float xOffset, float yOffset) {
if (monitors.empty()) {
return;
}
@@ -560,66 +576,68 @@ void InputDispatcher::addGestureMonitors(const std::vector<Monitor>& monitors,
void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
const char* reason;
switch (dropReason) {
- case DROP_REASON_POLICY:
+ case DROP_REASON_POLICY:
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("Dropped event because policy consumed it.");
+ ALOGD("Dropped event because policy consumed it.");
#endif
- reason = "inbound event was dropped because the policy consumed it";
- break;
- case DROP_REASON_DISABLED:
- if (mLastDropReason != DROP_REASON_DISABLED) {
- ALOGI("Dropped event because input dispatch is disabled.");
- }
- reason = "inbound event was dropped because input dispatch is disabled";
- break;
- case DROP_REASON_APP_SWITCH:
- ALOGI("Dropped event because of pending overdue app switch.");
- reason = "inbound event was dropped because of pending overdue app switch";
- break;
- case DROP_REASON_BLOCKED:
- ALOGI("Dropped event because the current application is not responding and the user "
- "has started interacting with a different application.");
- reason = "inbound event was dropped because the current application is not responding "
- "and the user has started interacting with a different application";
- break;
- case DROP_REASON_STALE:
- ALOGI("Dropped event because it is stale.");
- reason = "inbound event was dropped because it is stale";
- break;
- default:
- ALOG_ASSERT(false);
- return;
+ reason = "inbound event was dropped because the policy consumed it";
+ break;
+ case DROP_REASON_DISABLED:
+ if (mLastDropReason != DROP_REASON_DISABLED) {
+ ALOGI("Dropped event because input dispatch is disabled.");
+ }
+ reason = "inbound event was dropped because input dispatch is disabled";
+ break;
+ case DROP_REASON_APP_SWITCH:
+ ALOGI("Dropped event because of pending overdue app switch.");
+ reason = "inbound event was dropped because of pending overdue app switch";
+ break;
+ case DROP_REASON_BLOCKED:
+ ALOGI("Dropped event because the current application is not responding and the user "
+ "has started interacting with a different application.");
+ reason = "inbound event was dropped because the current application is not responding "
+ "and the user has started interacting with a different application";
+ break;
+ case DROP_REASON_STALE:
+ ALOGI("Dropped event because it is stale.");
+ reason = "inbound event was dropped because it is stale";
+ break;
+ default:
+ ALOG_ASSERT(false);
+ return;
}
switch (entry->type) {
- case EventEntry::TYPE_KEY: {
+ case EventEntry::TYPE_KEY: {
+ CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
+ synthesizeCancelationEventsForAllConnectionsLocked(options);
+ break;
+ }
+ case EventEntry::TYPE_MOTION: {
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+ if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
+ CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, reason);
+ synthesizeCancelationEventsForAllConnectionsLocked(options);
+ } else {
CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
synthesizeCancelationEventsForAllConnectionsLocked(options);
- break;
- }
- case EventEntry::TYPE_MOTION: {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
- if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
- CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, reason);
- synthesizeCancelationEventsForAllConnectionsLocked(options);
- } else {
- CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
- synthesizeCancelationEventsForAllConnectionsLocked(options);
- }
- break;
}
+ break;
+ }
}
}
static bool isAppSwitchKeyCode(int32_t keyCode) {
- return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL ||
- keyCode == AKEYCODE_APP_SWITCH;
+ return keyCode == AKEYCODE_HOME
+ || keyCode == AKEYCODE_ENDCALL
+ || keyCode == AKEYCODE_APP_SWITCH;
}
bool InputDispatcher::isAppSwitchKeyEvent(KeyEntry* keyEntry) {
- return !(keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) && isAppSwitchKeyCode(keyEntry->keyCode) &&
- (keyEntry->policyFlags & POLICY_FLAG_TRUSTED) &&
- (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
+ return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
+ && isAppSwitchKeyCode(keyEntry->keyCode)
+ && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
+ && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
}
bool InputDispatcher::isAppSwitchPendingLocked() {
@@ -659,18 +677,18 @@ bool InputDispatcher::runCommandsLockedInterruptible() {
commandEntry->connection.clear();
delete commandEntry;
- } while (!mCommandQueue.isEmpty());
+ } while (! mCommandQueue.isEmpty());
return true;
}
-CommandEntry* InputDispatcher::postCommandLocked(Command command) {
+InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
CommandEntry* commandEntry = new CommandEntry(command);
mCommandQueue.enqueueAtTail(commandEntry);
return commandEntry;
}
void InputDispatcher::drainInboundQueueLocked() {
- while (!mInboundQueue.isEmpty()) {
+ while (! mInboundQueue.isEmpty()) {
EventEntry* entry = mInboundQueue.dequeueAtHead();
releaseInboundEventLocked(entry);
}
@@ -707,7 +725,7 @@ void InputDispatcher::resetKeyRepeatLocked() {
}
}
-KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
+InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
// Reuse the repeated key entry if it is otherwise unreferenced.
@@ -719,11 +737,10 @@ KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
entry->policyFlags = policyFlags;
entry->repeatCount += 1;
} else {
- KeyEntry* newEntry =
- new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime, entry->deviceId,
- entry->source, entry->displayId, policyFlags, entry->action,
- entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
- entry->repeatCount + 1, entry->downTime);
+ KeyEntry* newEntry = new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
+ entry->deviceId, entry->source, entry->displayId, policyFlags,
+ entry->action, entry->flags, entry->keyCode, entry->scanCode,
+ entry->metaState, entry->repeatCount + 1, entry->downTime);
mKeyRepeatState.lastKeyEntry = newEntry;
entry->release();
@@ -740,8 +757,8 @@ KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
return entry;
}
-bool InputDispatcher::dispatchConfigurationChangedLocked(nsecs_t currentTime,
- ConfigurationChangedEntry* entry) {
+bool InputDispatcher::dispatchConfigurationChangedLocked(
+ nsecs_t currentTime, ConfigurationChangedEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("dispatchConfigurationChanged - eventTime=%" PRId64, entry->eventTime);
#endif
@@ -750,33 +767,36 @@ bool InputDispatcher::dispatchConfigurationChangedLocked(nsecs_t currentTime,
resetKeyRepeatLocked();
// Enqueue a command to run outside the lock to tell the policy that the configuration changed.
- CommandEntry* commandEntry =
- postCommandLocked(&InputDispatcher::doNotifyConfigurationChangedLockedInterruptible);
+ CommandEntry* commandEntry = postCommandLocked(
+ & InputDispatcher::doNotifyConfigurationChangedLockedInterruptible);
commandEntry->eventTime = entry->eventTime;
return true;
}
-bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime, DeviceResetEntry* entry) {
+bool InputDispatcher::dispatchDeviceResetLocked(
+ nsecs_t currentTime, DeviceResetEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("dispatchDeviceReset - eventTime=%" PRId64 ", deviceId=%d", entry->eventTime,
- entry->deviceId);
+ entry->deviceId);
#endif
- CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, "device was reset");
+ CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
+ "device was reset");
options.deviceId = entry->deviceId;
synthesizeCancelationEventsForAllConnectionsLocked(options);
return true;
}
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
- DropReason* dropReason, nsecs_t* nextWakeupTime) {
+ DropReason* dropReason, nsecs_t* nextWakeupTime) {
// Preprocessing.
- if (!entry->dispatchInProgress) {
- if (entry->repeatCount == 0 && entry->action == AKEY_EVENT_ACTION_DOWN &&
- (entry->policyFlags & POLICY_FLAG_TRUSTED) &&
- (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
- if (mKeyRepeatState.lastKeyEntry &&
- mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
+ if (! entry->dispatchInProgress) {
+ if (entry->repeatCount == 0
+ && entry->action == AKEY_EVENT_ACTION_DOWN
+ && (entry->policyFlags & POLICY_FLAG_TRUSTED)
+ && (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
+ if (mKeyRepeatState.lastKeyEntry
+ && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
// We have seen two identical key downs in a row which indicates that the device
// driver is automatically generating key repeats itself. We take note of the
// repeat here, but we disable our own next key repeat timer since it is clear that
@@ -791,7 +811,7 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
}
mKeyRepeatState.lastKeyEntry = entry;
entry->refCount += 1;
- } else if (!entry->syntheticRepeat) {
+ } else if (! entry->syntheticRepeat) {
resetKeyRepeatLocked();
}
@@ -822,11 +842,12 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
CommandEntry* commandEntry = postCommandLocked(
- &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
+ & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
sp<InputWindowHandle> focusedWindowHandle =
getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
if (focusedWindowHandle != nullptr) {
- commandEntry->inputChannel = getInputChannelLocked(focusedWindowHandle->getToken());
+ commandEntry->inputChannel =
+ getInputChannelLocked(focusedWindowHandle->getToken());
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
@@ -842,17 +863,16 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
// Clean up if dropping the event.
if (*dropReason != DROP_REASON_NOT_DROPPED) {
- setInjectionResult(entry,
- *dropReason == DROP_REASON_POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
- : INPUT_EVENT_INJECTION_FAILED);
+ setInjectionResult(entry, *dropReason == DROP_REASON_POLICY
+ ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
mReporter->reportDroppedKey(entry->sequenceNum);
return true;
}
// Identify targets.
std::vector<InputTarget> inputTargets;
- int32_t injectionResult =
- findFocusedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime);
+ int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
+ entry, inputTargets, nextWakeupTime);
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
@@ -873,19 +893,20 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 ", "
- "policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, "
- "metaState=0x%x, repeatCount=%d, downTime=%" PRId64,
- prefix, entry->eventTime, entry->deviceId, entry->source, entry->displayId,
- entry->policyFlags, entry->action, entry->flags, entry->keyCode, entry->scanCode,
- entry->metaState, entry->repeatCount, entry->downTime);
+ "policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, "
+ "metaState=0x%x, repeatCount=%d, downTime=%" PRId64,
+ prefix,
+ entry->eventTime, entry->deviceId, entry->source, entry->displayId, entry->policyFlags,
+ entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
+ entry->repeatCount, entry->downTime);
#endif
}
-bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry,
- DropReason* dropReason, nsecs_t* nextWakeupTime) {
+bool InputDispatcher::dispatchMotionLocked(
+ nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
ATRACE_CALL();
// Preprocessing.
- if (!entry->dispatchInProgress) {
+ if (! entry->dispatchInProgress) {
entry->dispatchInProgress = true;
logOutboundMotionDetails("dispatchMotion - ", entry);
@@ -893,9 +914,8 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* ent
// Clean up if dropping the event.
if (*dropReason != DROP_REASON_NOT_DROPPED) {
- setInjectionResult(entry,
- *dropReason == DROP_REASON_POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
- : INPUT_EVENT_INJECTION_FAILED);
+ setInjectionResult(entry, *dropReason == DROP_REASON_POLICY
+ ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
return true;
}
@@ -908,13 +928,12 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* ent
int32_t injectionResult;
if (isPointerEvent) {
// Pointer event. (eg. touchscreen)
- injectionResult =
- findTouchedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime,
- &conflictingPointerActions);
+ injectionResult = findTouchedWindowTargetsLocked(currentTime,
+ entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
} else {
// Non touch event. (eg. trackball)
- injectionResult =
- findFocusedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime);
+ injectionResult = findFocusedWindowTargetsLocked(currentTime,
+ entry, inputTargets, nextWakeupTime);
}
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
@@ -923,9 +942,9 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* ent
setInjectionResult(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
- CancelationOptions::Mode mode(isPointerEvent
- ? CancelationOptions::CANCEL_POINTER_EVENTS
- : CancelationOptions::CANCEL_NON_POINTER_EVENTS);
+ CancelationOptions::Mode mode(isPointerEvent ?
+ CancelationOptions::CANCEL_POINTER_EVENTS :
+ CancelationOptions::CANCEL_NON_POINTER_EVENTS);
CancelationOptions options(mode, "input event injection failed");
synthesizeCancelationEventsForMonitorsLocked(options);
}
@@ -945,7 +964,7 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* ent
for (size_t i = 0; i < state.portalWindows.size(); i++) {
const InputWindowInfo* windowInfo = state.portalWindows[i]->getInfo();
addGlobalMonitoringTargetsLocked(inputTargets, windowInfo->portalToDisplayId,
- -windowInfo->frameLeft, -windowInfo->frameTop);
+ -windowInfo->frameLeft, -windowInfo->frameTop);
}
}
}
@@ -954,46 +973,50 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* ent
// Dispatch the motion.
if (conflictingPointerActions) {
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "conflicting pointer actions");
+ "conflicting pointer actions");
synthesizeCancelationEventsForAllConnectionsLocked(options);
}
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
+
void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
- ", policyFlags=0x%x, "
- "action=0x%x, actionButton=0x%x, flags=0x%x, "
- "metaState=0x%x, buttonState=0x%x,"
- "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
- prefix, entry->eventTime, entry->deviceId, entry->source, entry->displayId,
- entry->policyFlags, entry->action, entry->actionButton, entry->flags, entry->metaState,
- entry->buttonState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
- entry->downTime);
+ ", policyFlags=0x%x, "
+ "action=0x%x, actionButton=0x%x, flags=0x%x, "
+ "metaState=0x%x, buttonState=0x%x,"
+ "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
+ prefix,
+ entry->eventTime, entry->deviceId, entry->source, entry->displayId, entry->policyFlags,
+ entry->action, entry->actionButton, entry->flags,
+ entry->metaState, entry->buttonState,
+ entry->edgeFlags, entry->xPrecision, entry->yPrecision,
+ entry->downTime);
for (uint32_t i = 0; i < entry->pointerCount; i++) {
ALOGD(" Pointer %d: id=%d, toolType=%d, "
- "x=%f, y=%f, pressure=%f, size=%f, "
- "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
- "orientation=%f",
- i, entry->pointerProperties[i].id, entry->pointerProperties[i].toolType,
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
+ "x=%f, y=%f, pressure=%f, size=%f, "
+ "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
+ "orientation=%f",
+ i, entry->pointerProperties[i].id,
+ entry->pointerProperties[i].toolType,
+ entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
+ entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
+ entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
+ entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
+ entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
+ entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
+ entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
+ entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
+ entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
}
#endif
}
-void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry,
- const std::vector<InputTarget>& inputTargets) {
+void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
+ EventEntry* eventEntry, const std::vector<InputTarget>& inputTargets) {
ATRACE_CALL();
#if DEBUG_DISPATCH_CYCLE
ALOGD("dispatchEventToCurrentInputTargets");
@@ -1011,17 +1034,18 @@ void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* event
} else {
#if DEBUG_FOCUS
ALOGD("Dropping event delivery to target with channel '%s' because it "
- "is no longer registered with the input dispatcher.",
- inputTarget.inputChannel->getName().c_str());
+ "is no longer registered with the input dispatcher.",
+ inputTarget.inputChannel->getName().c_str());
#endif
}
}
}
-int32_t InputDispatcher::handleTargetsNotReadyLocked(
- nsecs_t currentTime, const EventEntry* entry,
+int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
+ const EventEntry* entry,
const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle, nsecs_t* nextWakeupTime, const char* reason) {
+ const sp<InputWindowHandle>& windowHandle,
+ nsecs_t* nextWakeupTime, const char* reason) {
if (applicationHandle == nullptr && windowHandle == nullptr) {
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
#if DEBUG_FOCUS
@@ -1037,14 +1061,15 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
#if DEBUG_FOCUS
ALOGD("Waiting for application to become ready for input: %s. Reason: %s",
- getApplicationWindowLabel(applicationHandle, windowHandle).c_str(), reason);
+ getApplicationWindowLabel(applicationHandle, windowHandle).c_str(),
+ reason);
#endif
nsecs_t timeout;
if (windowHandle != nullptr) {
timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
} else if (applicationHandle != nullptr) {
- timeout =
- applicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
+ timeout = applicationHandle->getDispatchingTimeout(
+ DEFAULT_INPUT_DISPATCHING_TIMEOUT);
} else {
timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
}
@@ -1069,8 +1094,8 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(
}
if (currentTime >= mInputTargetWaitTimeoutTime) {
- onANRLocked(currentTime, applicationHandle, windowHandle, entry->eventTime,
- mInputTargetWaitStartTime, reason);
+ onANRLocked(currentTime, applicationHandle, windowHandle,
+ entry->eventTime, mInputTargetWaitStartTime, reason);
// Force poll loop to wake up immediately on next iteration once we get the
// ANR response back from the policy.
@@ -1092,8 +1117,8 @@ void InputDispatcher::removeWindowByTokenLocked(const sp<IBinder>& token) {
}
}
-void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(
- nsecs_t newTimeout, const sp<InputChannel>& inputChannel) {
+void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
+ const sp<InputChannel>& inputChannel) {
if (newTimeout > 0) {
// Extend the timeout.
mInputTargetWaitTimeoutTime = now() + newTimeout;
@@ -1114,7 +1139,7 @@ void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(
if (connection->status == Connection::STATUS_NORMAL) {
CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
- "application not responding");
+ "application not responding");
synthesizeCancelationEventsForConnectionLocked(connection, options);
}
}
@@ -1122,7 +1147,8 @@ void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(
}
}
-nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) {
+nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
+ nsecs_t currentTime) {
if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
return currentTime - mInputTargetWaitStartTime;
}
@@ -1131,7 +1157,7 @@ nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(nsecs_t current
void InputDispatcher::resetANRTimeoutsLocked() {
#if DEBUG_FOCUS
- ALOGD("Resetting ANR timeouts.");
+ ALOGD("Resetting ANR timeouts.");
#endif
// Reset input target wait timeout.
@@ -1147,28 +1173,26 @@ void InputDispatcher::resetANRTimeoutsLocked() {
int32_t InputDispatcher::getTargetDisplayId(const EventEntry* entry) {
int32_t displayId;
switch (entry->type) {
- case EventEntry::TYPE_KEY: {
- const KeyEntry* typedEntry = static_cast<const KeyEntry*>(entry);
- displayId = typedEntry->displayId;
- break;
- }
- case EventEntry::TYPE_MOTION: {
- const MotionEntry* typedEntry = static_cast<const MotionEntry*>(entry);
- displayId = typedEntry->displayId;
- break;
- }
- default: {
- ALOGE("Unsupported event type '%" PRId32 "' for target display.", entry->type);
- return ADISPLAY_ID_NONE;
- }
+ case EventEntry::TYPE_KEY: {
+ const KeyEntry* typedEntry = static_cast<const KeyEntry*>(entry);
+ displayId = typedEntry->displayId;
+ break;
+ }
+ case EventEntry::TYPE_MOTION: {
+ const MotionEntry* typedEntry = static_cast<const MotionEntry*>(entry);
+ displayId = typedEntry->displayId;
+ break;
+ }
+ default: {
+ ALOGE("Unsupported event type '%" PRId32 "' for target display.", entry->type);
+ return ADISPLAY_ID_NONE;
+ }
}
return displayId == ADISPLAY_ID_NONE ? mFocusedDisplayId : displayId;
}
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
- const EventEntry* entry,
- std::vector<InputTarget>& inputTargets,
- nsecs_t* nextWakeupTime) {
+ const EventEntry* entry, std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
int32_t injectionResult;
std::string reason;
@@ -1182,20 +1206,16 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
// then drop the event.
if (focusedWindowHandle == nullptr) {
if (focusedApplicationHandle != nullptr) {
- injectionResult =
- handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
- nullptr, nextWakeupTime,
- "Waiting because no window has focus but there is "
- "a "
- "focused application that may eventually add a "
- "window "
- "when it finishes starting up.");
+ injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+ focusedApplicationHandle, nullptr, nextWakeupTime,
+ "Waiting because no window has focus but there is a "
+ "focused application that may eventually add a window "
+ "when it finishes starting up.");
goto Unresponsive;
}
ALOGI("Dropping event because there is no focused window or focused application in display "
- "%" PRId32 ".",
- displayId);
+ "%" PRId32 ".", displayId);
injectionResult = INPUT_EVENT_INJECTION_FAILED;
goto Failed;
}
@@ -1207,19 +1227,19 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
}
// Check whether the window is ready for more input.
- reason = checkWindowReadyForMoreInputLocked(currentTime, focusedWindowHandle, entry, "focused");
+ reason = checkWindowReadyForMoreInputLocked(currentTime,
+ focusedWindowHandle, entry, "focused");
if (!reason.empty()) {
- injectionResult =
- handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
- focusedWindowHandle, nextWakeupTime, reason.c_str());
+ injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+ focusedApplicationHandle, focusedWindowHandle, nextWakeupTime, reason.c_str());
goto Unresponsive;
}
// Success! Output targets.
injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
addWindowTargetLocked(focusedWindowHandle,
- InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
- BitSet32(0), inputTargets);
+ InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
+ inputTargets);
// Done.
Failed:
@@ -1228,17 +1248,15 @@ Unresponsive:
updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
#if DEBUG_FOCUS
ALOGD("findFocusedWindow finished: injectionResult=%d, "
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult, timeSpentWaitingForApplication / 1000000.0);
+ "timeSpentWaitingForApplication=%0.1fms",
+ injectionResult, timeSpentWaitingForApplication / 1000000.0);
#endif
return injectionResult;
}
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
- const MotionEntry* entry,
- std::vector<InputTarget>& inputTargets,
- nsecs_t* nextWakeupTime,
- bool* outConflictingPointerActions) {
+ const MotionEntry* entry, std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
+ bool* outConflictingPointerActions) {
ATRACE_CALL();
enum InjectionPermission {
INJECTION_PERMISSION_UNKNOWN,
@@ -1268,22 +1286,23 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
}
bool isSplit = mTempTouchState.split;
- bool switchedDevice = mTempTouchState.deviceId >= 0 && mTempTouchState.displayId >= 0 &&
- (mTempTouchState.deviceId != entry->deviceId ||
- mTempTouchState.source != entry->source || mTempTouchState.displayId != displayId);
- bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
- maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
- maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
- bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
- maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction);
+ bool switchedDevice = mTempTouchState.deviceId >= 0 && mTempTouchState.displayId >= 0
+ && (mTempTouchState.deviceId != entry->deviceId
+ || mTempTouchState.source != entry->source
+ || mTempTouchState.displayId != displayId);
+ bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
+ || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
+ || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
+ bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN
+ || maskedAction == AMOTION_EVENT_ACTION_SCROLL
+ || isHoverAction);
bool wrongDevice = false;
if (newGesture) {
bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
if (switchedDevice && mTempTouchState.down && !down && !isHoverAction) {
#if DEBUG_FOCUS
ALOGD("Dropping event because a pointer for a different device is already down "
- "in display %" PRId32,
- displayId);
+ "in display %" PRId32, displayId);
#endif
// TODO: test multiple simultaneous input streams.
injectionResult = INPUT_EVENT_INJECTION_FAILED;
@@ -1300,8 +1319,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
} else if (switchedDevice && maskedAction == AMOTION_EVENT_ACTION_MOVE) {
#if DEBUG_FOCUS
ALOGI("Dropping move event because a pointer for a different device is already active "
- "in display %" PRId32,
- displayId);
+ "in display %" PRId32, displayId);
#endif
// TODO: test multiple simultaneous input streams.
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
@@ -1314,20 +1332,21 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
/* Case 1: New splittable pointer going down, or need target for hover or scroll. */
int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- int32_t x = int32_t(entry->pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_X));
- int32_t y = int32_t(entry->pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_Y));
+ int32_t x = int32_t(entry->pointerCoords[pointerIndex].
+ getAxisValue(AMOTION_EVENT_AXIS_X));
+ int32_t y = int32_t(entry->pointerCoords[pointerIndex].
+ getAxisValue(AMOTION_EVENT_AXIS_Y));
bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
- sp<InputWindowHandle> newTouchedWindowHandle =
- findTouchedWindowAtLocked(displayId, x, y, isDown /*addOutsideTargets*/,
- true /*addPortalWindows*/);
+ sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(
+ displayId, x, y, isDown /*addOutsideTargets*/, true /*addPortalWindows*/);
std::vector<TouchedMonitor> newGestureMonitors = isDown
? findTouchedGestureMonitorsLocked(displayId, mTempTouchState.portalWindows)
: std::vector<TouchedMonitor>{};
// Figure out whether splitting will be allowed for this window.
- if (newTouchedWindowHandle != nullptr &&
- newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
+ if (newTouchedWindowHandle != nullptr
+ && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
// New window supports splitting.
isSplit = true;
} else if (isSplit) {
@@ -1344,8 +1363,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
if (newTouchedWindowHandle == nullptr && newGestureMonitors.empty()) {
ALOGI("Dropping event because there is no touchable window or gesture monitor at "
- "(%d, %d) in display %" PRId32 ".",
- x, y, displayId);
+ "(%d, %d) in display %" PRId32 ".", x, y, displayId);
injectionResult = INPUT_EVENT_INJECTION_FAILED;
goto Failed;
}
@@ -1383,19 +1401,19 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
/* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
// If the pointer is not currently down, then ignore the event.
- if (!mTempTouchState.down) {
+ if (! mTempTouchState.down) {
#if DEBUG_FOCUS
ALOGD("Dropping event because the pointer is not down or we previously "
- "dropped the pointer down event in display %" PRId32,
- displayId);
+ "dropped the pointer down event in display %" PRId32, displayId);
#endif
injectionResult = INPUT_EVENT_INJECTION_FAILED;
goto Failed;
}
// Check whether touches should slip outside of the current foreground window.
- if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry->pointerCount == 1 &&
- mTempTouchState.isSlippery()) {
+ if (maskedAction == AMOTION_EVENT_ACTION_MOVE
+ && entry->pointerCount == 1
+ && mTempTouchState.isSlippery()) {
int32_t x = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
int32_t y = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
@@ -1403,25 +1421,26 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
mTempTouchState.getFirstForegroundWindowHandle();
sp<InputWindowHandle> newTouchedWindowHandle =
findTouchedWindowAtLocked(displayId, x, y);
- if (oldTouchedWindowHandle != newTouchedWindowHandle &&
- oldTouchedWindowHandle != nullptr && newTouchedWindowHandle != nullptr) {
+ if (oldTouchedWindowHandle != newTouchedWindowHandle
+ && oldTouchedWindowHandle != nullptr
+ && newTouchedWindowHandle != nullptr) {
#if DEBUG_FOCUS
ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32,
- oldTouchedWindowHandle->getName().c_str(),
- newTouchedWindowHandle->getName().c_str(), displayId);
+ oldTouchedWindowHandle->getName().c_str(),
+ newTouchedWindowHandle->getName().c_str(),
+ displayId);
#endif
// Make a slippery exit from the old window.
mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
- InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT,
- BitSet32(0));
+ InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
// Make a slippery entrance into the new window.
if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
isSplit = true;
}
- int32_t targetFlags =
- InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER;
+ int32_t targetFlags = InputTarget::FLAG_FOREGROUND
+ | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER;
if (isSplit) {
targetFlags |= InputTarget::FLAG_SPLIT;
}
@@ -1443,22 +1462,20 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
if (mLastHoverWindowHandle != nullptr) {
#if DEBUG_HOVER
ALOGD("Sending hover exit event to window %s.",
- mLastHoverWindowHandle->getName().c_str());
+ mLastHoverWindowHandle->getName().c_str());
#endif
mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
- InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT,
- BitSet32(0));
+ InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
}
// Let the new window know that the hover sequence is starting.
if (newHoverWindowHandle != nullptr) {
#if DEBUG_HOVER
ALOGD("Sending hover enter event to window %s.",
- newHoverWindowHandle->getName().c_str());
+ newHoverWindowHandle->getName().c_str());
#endif
mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
- InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER,
- BitSet32(0));
+ InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0));
}
}
@@ -1469,7 +1486,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
haveForegroundWindow = true;
- if (!checkInjectionPermission(touchedWindow.windowHandle, entry->injectionState)) {
+ if (! checkInjectionPermission(touchedWindow.windowHandle,
+ entry->injectionState)) {
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
injectionPermission = INJECTION_PERMISSION_DENIED;
goto Failed;
@@ -1479,9 +1497,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
bool hasGestureMonitor = !mTempTouchState.gestureMonitors.empty();
if (!haveForegroundWindow && !hasGestureMonitor) {
#if DEBUG_FOCUS
- ALOGD("Dropping event because there is no touched foreground window in display %" PRId32
- " or gesture monitor to receive it.",
- displayId);
+ ALOGD("Dropping event because there is no touched foreground window in display %"
+ PRId32 " or gesture monitor to receive it.", displayId);
#endif
injectionResult = INPUT_EVENT_INJECTION_FAILED;
goto Failed;
@@ -1503,8 +1520,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
mTempTouchState.addOrUpdateWindow(inputWindowHandle,
- InputTarget::FLAG_ZERO_COORDS,
- BitSet32(0));
+ InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
}
}
}
@@ -1515,13 +1531,11 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
// Check whether the window is ready for more input.
- std::string reason =
- checkWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle,
- entry, "touched");
+ std::string reason = checkWindowReadyForMoreInputLocked(currentTime,
+ touchedWindow.windowHandle, entry, "touched");
if (!reason.empty()) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry, nullptr,
- touchedWindow.windowHandle,
- nextWakeupTime, reason.c_str());
+ injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+ nullptr, touchedWindow.windowHandle, nextWakeupTime, reason.c_str());
goto Unresponsive;
}
}
@@ -1541,15 +1555,14 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
getWindowHandlesLocked(displayId);
for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
const InputWindowInfo* info = windowHandle->getInfo();
- if (info->displayId == displayId &&
- windowHandle->getInfo()->layoutParamsType == InputWindowInfo::TYPE_WALLPAPER) {
- mTempTouchState
- .addOrUpdateWindow(windowHandle,
- InputTarget::FLAG_WINDOW_IS_OBSCURED |
- InputTarget::
- FLAG_WINDOW_IS_PARTIALLY_OBSCURED |
- InputTarget::FLAG_DISPATCH_AS_IS,
- BitSet32(0));
+ if (info->displayId == displayId
+ && windowHandle->getInfo()->layoutParamsType
+ == InputWindowInfo::TYPE_WALLPAPER) {
+ mTempTouchState.addOrUpdateWindow(windowHandle,
+ InputTarget::FLAG_WINDOW_IS_OBSCURED
+ | InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED
+ | InputTarget::FLAG_DISPATCH_AS_IS,
+ BitSet32(0));
}
}
}
@@ -1560,12 +1573,12 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
- touchedWindow.pointerIds, inputTargets);
+ touchedWindow.pointerIds, inputTargets);
}
for (const TouchedMonitor& touchedMonitor : mTempTouchState.gestureMonitors) {
addMonitoringTargetLocked(touchedMonitor.monitor, touchedMonitor.xOffset,
- touchedMonitor.yOffset, inputTargets);
+ touchedMonitor.yOffset, inputTargets);
}
// Drop the outside or hover touch windows since we will not care about them
@@ -1601,14 +1614,14 @@ Failed:
*outConflictingPointerActions = true;
}
mTempTouchState.reset();
- if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
- maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+ if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
+ || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
mTempTouchState.deviceId = entry->deviceId;
mTempTouchState.source = entry->source;
mTempTouchState.displayId = displayId;
}
- } else if (maskedAction == AMOTION_EVENT_ACTION_UP ||
- maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
+ } else if (maskedAction == AMOTION_EVENT_ACTION_UP
+ || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
// All pointers up or canceled.
mTempTouchState.reset();
} else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
@@ -1625,7 +1638,7 @@ Failed:
int32_t pointerIndex = getMotionEventActionPointerIndex(action);
uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
- for (size_t i = 0; i < mTempTouchState.windows.size();) {
+ for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
TouchedWindow& touchedWindow = mTempTouchState.windows[i];
if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
touchedWindow.pointerIds.clearBit(pointerId);
@@ -1670,15 +1683,14 @@ Unresponsive:
updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
#if DEBUG_FOCUS
ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
+ "timeSpentWaitingForApplication=%0.1fms",
+ injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
#endif
return injectionResult;
}
void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
- int32_t targetFlags, BitSet32 pointerIds,
- std::vector<InputTarget>& inputTargets) {
+ int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) {
sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
if (inputChannel == nullptr) {
ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
@@ -1689,8 +1701,8 @@ void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowH
InputTarget target;
target.inputChannel = inputChannel;
target.flags = targetFlags;
- target.xOffset = -windowInfo->frameLeft;
- target.yOffset = -windowInfo->frameTop;
+ target.xOffset = - windowInfo->frameLeft;
+ target.yOffset = - windowInfo->frameTop;
target.globalScaleFactor = windowInfo->globalScaleFactor;
target.windowXScale = windowInfo->windowXScale;
target.windowYScale = windowInfo->windowYScale;
@@ -1699,8 +1711,8 @@ void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowH
}
void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
- int32_t displayId, float xOffset,
- float yOffset) {
+ int32_t displayId, float xOffset, float yOffset) {
+
std::unordered_map<int32_t, std::vector<Monitor>>::const_iterator it =
mGlobalMonitorsByDisplay.find(displayId);
@@ -1712,9 +1724,8 @@ void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>&
}
}
-void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xOffset,
- float yOffset,
- std::vector<InputTarget>& inputTargets) {
+void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor,
+ float xOffset, float yOffset, std::vector<InputTarget>& inputTargets) {
InputTarget target;
target.inputChannel = monitor.inputChannel;
target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
@@ -1726,27 +1737,28 @@ void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xO
}
bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
- const InjectionState* injectionState) {
- if (injectionState &&
- (windowHandle == nullptr ||
- windowHandle->getInfo()->ownerUid != injectionState->injectorUid) &&
- !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
+ const InjectionState* injectionState) {
+ if (injectionState
+ && (windowHandle == nullptr
+ || windowHandle->getInfo()->ownerUid != injectionState->injectorUid)
+ && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
if (windowHandle != nullptr) {
ALOGW("Permission denied: injecting event from pid %d uid %d to window %s "
- "owned by uid %d",
- injectionState->injectorPid, injectionState->injectorUid,
- windowHandle->getName().c_str(), windowHandle->getInfo()->ownerUid);
+ "owned by uid %d",
+ injectionState->injectorPid, injectionState->injectorUid,
+ windowHandle->getName().c_str(),
+ windowHandle->getInfo()->ownerUid);
} else {
ALOGW("Permission denied: injecting event from pid %d uid %d",
- injectionState->injectorPid, injectionState->injectorUid);
+ injectionState->injectorPid, injectionState->injectorUid);
}
return false;
}
return true;
}
-bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
- int32_t x, int32_t y) const {
+bool InputDispatcher::isWindowObscuredAtPointLocked(
+ const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
int32_t displayId = windowHandle->getInfo()->displayId;
const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
for (const sp<InputWindowHandle>& otherHandle : windowHandles) {
@@ -1755,14 +1767,16 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<InputWindowHandle>&
}
const InputWindowInfo* otherInfo = otherHandle->getInfo();
- if (otherInfo->displayId == displayId && otherInfo->visible &&
- !otherInfo->isTrustedOverlay() && otherInfo->frameContainsPoint(x, y)) {
+ if (otherInfo->displayId == displayId
+ && otherInfo->visible && !otherInfo->isTrustedOverlay()
+ && otherInfo->frameContainsPoint(x, y)) {
return true;
}
}
return false;
}
+
bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
int32_t displayId = windowHandle->getInfo()->displayId;
const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
@@ -1773,47 +1787,45 @@ bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& window
}
const InputWindowInfo* otherInfo = otherHandle->getInfo();
- if (otherInfo->displayId == displayId && otherInfo->visible &&
- !otherInfo->isTrustedOverlay() && otherInfo->overlaps(windowInfo)) {
+ if (otherInfo->displayId == displayId
+ && otherInfo->visible && !otherInfo->isTrustedOverlay()
+ && otherInfo->overlaps(windowInfo)) {
return true;
}
}
return false;
}
-std::string InputDispatcher::checkWindowReadyForMoreInputLocked(
- nsecs_t currentTime, const sp<InputWindowHandle>& windowHandle,
- const EventEntry* eventEntry, const char* targetType) {
+std::string InputDispatcher::checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
+ const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,
+ const char* targetType) {
// If the window is paused then keep waiting.
if (windowHandle->getInfo()->paused) {
return StringPrintf("Waiting because the %s window is paused.", targetType);
}
// If the window's connection is not registered then keep waiting.
- ssize_t connectionIndex =
- getConnectionIndexLocked(getInputChannelLocked(windowHandle->getToken()));
+ ssize_t connectionIndex = getConnectionIndexLocked(
+ getInputChannelLocked(windowHandle->getToken()));
if (connectionIndex < 0) {
return StringPrintf("Waiting because the %s window's input channel is not "
- "registered with the input dispatcher. The window may be in the "
- "process "
- "of being removed.",
- targetType);
+ "registered with the input dispatcher. The window may be in the process "
+ "of being removed.", targetType);
}
// If the connection is dead then keep waiting.
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
if (connection->status != Connection::STATUS_NORMAL) {
return StringPrintf("Waiting because the %s window's input connection is %s."
- "The window may be in the process of being removed.",
- targetType, connection->getStatusLabel());
+ "The window may be in the process of being removed.", targetType,
+ connection->getStatusLabel());
}
// If the connection is backed up then keep waiting.
if (connection->inputPublisherBlocked) {
return StringPrintf("Waiting because the %s window's input channel is full. "
- "Outbound queue length: %d. Wait queue length: %d.",
- targetType, connection->outboundQueue.count(),
- connection->waitQueue.count());
+ "Outbound queue length: %d. Wait queue length: %d.",
+ targetType, connection->outboundQueue.count(), connection->waitQueue.count());
}
// Ensure that the dispatch queues aren't too far backed up for this event.
@@ -1831,11 +1843,9 @@ std::string InputDispatcher::checkWindowReadyForMoreInputLocked(
// prior input events.
if (!connection->outboundQueue.isEmpty() || !connection->waitQueue.isEmpty()) {
return StringPrintf("Waiting to send key event because the %s window has not "
- "finished processing all of the input events that were previously "
- "delivered to it. Outbound queue length: %d. Wait queue length: "
- "%d.",
- targetType, connection->outboundQueue.count(),
- connection->waitQueue.count());
+ "finished processing all of the input events that were previously "
+ "delivered to it. Outbound queue length: %d. Wait queue length: %d.",
+ targetType, connection->outboundQueue.count(), connection->waitQueue.count());
}
} else {
// Touch events can always be sent to a window immediately because the user intended
@@ -1853,17 +1863,15 @@ std::string InputDispatcher::checkWindowReadyForMoreInputLocked(
// The one case where we pause input event delivery is when the wait queue is piling
// up with lots of events because the application is not responding.
// This condition ensures that ANRs are detected reliably.
- if (!connection->waitQueue.isEmpty() &&
- currentTime >= connection->waitQueue.head->deliveryTime + STREAM_AHEAD_EVENT_TIMEOUT) {
+ if (!connection->waitQueue.isEmpty()
+ && currentTime >= connection->waitQueue.head->deliveryTime
+ + STREAM_AHEAD_EVENT_TIMEOUT) {
return StringPrintf("Waiting to send non-key event because the %s window has not "
- "finished processing certain input events that were delivered to "
- "it over "
- "%0.1fms ago. Wait queue length: %d. Wait queue head age: "
- "%0.1fms.",
- targetType, STREAM_AHEAD_EVENT_TIMEOUT * 0.000001f,
- connection->waitQueue.count(),
- (currentTime - connection->waitQueue.head->deliveryTime) *
- 0.000001f);
+ "finished processing certain input events that were delivered to it over "
+ "%0.1fms ago. Wait queue length: %d. Wait queue head age: %0.1fms.",
+ targetType, STREAM_AHEAD_EVENT_TIMEOUT * 0.000001f,
+ connection->waitQueue.count(),
+ (currentTime - connection->waitQueue.head->deliveryTime) * 0.000001f);
}
}
return "";
@@ -1904,50 +1912,50 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
int32_t eventType = USER_ACTIVITY_EVENT_OTHER;
switch (eventEntry->type) {
- case EventEntry::TYPE_MOTION: {
- const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
- if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
- return;
- }
+ case EventEntry::TYPE_MOTION: {
+ const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
+ if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
+ return;
+ }
- if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
- eventType = USER_ACTIVITY_EVENT_TOUCH;
- }
- break;
+ if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
+ eventType = USER_ACTIVITY_EVENT_TOUCH;
}
- case EventEntry::TYPE_KEY: {
- const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
- if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
- return;
- }
- eventType = USER_ACTIVITY_EVENT_BUTTON;
- break;
+ break;
+ }
+ case EventEntry::TYPE_KEY: {
+ const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
+ if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
+ return;
}
+ eventType = USER_ACTIVITY_EVENT_BUTTON;
+ break;
+ }
}
- CommandEntry* commandEntry =
- postCommandLocked(&InputDispatcher::doPokeUserActivityLockedInterruptible);
+ CommandEntry* commandEntry = postCommandLocked(
+ & InputDispatcher::doPokeUserActivityLockedInterruptible);
commandEntry->eventTime = eventEntry->eventTime;
commandEntry->userActivityEventType = eventType;
}
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection,
- EventEntry* eventEntry,
- const InputTarget* inputTarget) {
+ const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
if (ATRACE_ENABLED()) {
- std::string message =
- StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")",
- connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
+ std::string message = StringPrintf(
+ "prepareDispatchCycleLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")",
+ connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
ATRACE_NAME(message.c_str());
}
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
- "xOffset=%f, yOffset=%f, globalScaleFactor=%f, "
- "windowScaleFactor=(%f, %f), pointerIds=0x%x",
- connection->getInputChannelName().c_str(), inputTarget->flags, inputTarget->xOffset,
- inputTarget->yOffset, inputTarget->globalScaleFactor, inputTarget->windowXScale,
- inputTarget->windowYScale, inputTarget->pointerIds.value);
+ "xOffset=%f, yOffset=%f, globalScaleFactor=%f, "
+ "windowScaleFactor=(%f, %f), pointerIds=0x%x",
+ connection->getInputChannelName().c_str(), inputTarget->flags,
+ inputTarget->xOffset, inputTarget->yOffset,
+ inputTarget->globalScaleFactor,
+ inputTarget->windowXScale, inputTarget->windowYScale,
+ inputTarget->pointerIds.value);
#endif
// Skip this event if the connection status is not normal.
@@ -1955,7 +1963,7 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
if (connection->status != Connection::STATUS_NORMAL) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
- connection->getInputChannelName().c_str(), connection->getStatusLabel());
+ connection->getInputChannelName().c_str(), connection->getStatusLabel());
#endif
return;
}
@@ -1966,16 +1974,18 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
- MotionEntry* splitMotionEntry =
- splitMotionEvent(originalMotionEntry, inputTarget->pointerIds);
+ MotionEntry* splitMotionEntry = splitMotionEvent(
+ originalMotionEntry, inputTarget->pointerIds);
if (!splitMotionEntry) {
return; // split event was dropped
}
#if DEBUG_FOCUS
- ALOGD("channel '%s' ~ Split motion event.", connection->getInputChannelName().c_str());
+ ALOGD("channel '%s' ~ Split motion event.",
+ connection->getInputChannelName().c_str());
logOutboundMotionDetails(" ", splitMotionEntry);
#endif
- enqueueDispatchEntriesLocked(currentTime, connection, splitMotionEntry, inputTarget);
+ enqueueDispatchEntriesLocked(currentTime, connection,
+ splitMotionEntry, inputTarget);
splitMotionEntry->release();
return;
}
@@ -1986,14 +1996,11 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
- const sp<Connection>& connection,
- EventEntry* eventEntry,
- const InputTarget* inputTarget) {
+ const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
if (ATRACE_ENABLED()) {
- std::string message =
- StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, sequenceNum=%" PRIu32
- ")",
- connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
+ std::string message = StringPrintf(
+ "enqueueDispatchEntriesLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")",
+ connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
ATRACE_NAME(message.c_str());
}
@@ -2001,17 +2008,17 @@ void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
// Enqueue dispatch entries for the requested modes.
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
+ InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
+ InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
+ InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_IS);
+ InputTarget::FLAG_DISPATCH_AS_IS);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
+ InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
+ InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.isEmpty()) {
@@ -2019,14 +2026,14 @@ void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
}
}
-void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
- EventEntry* eventEntry,
- const InputTarget* inputTarget,
- int32_t dispatchMode) {
+void InputDispatcher::enqueueDispatchEntryLocked(
+ const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
+ int32_t dispatchMode) {
if (ATRACE_ENABLED()) {
- std::string message = StringPrintf("enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)",
- connection->getInputChannelName().c_str(),
- dispatchModeToString(dispatchMode).c_str());
+ std::string message = StringPrintf(
+ "enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)",
+ connection->getInputChannelName().c_str(),
+ dispatchModeToString(dispatchMode).c_str());
ATRACE_NAME(message.c_str());
}
int32_t inputTargetFlags = inputTarget->flags;
@@ -2037,81 +2044,78 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio
// This is a new event.
// Enqueue a new dispatch entry onto the outbound queue for this connection.
- DispatchEntry* dispatchEntry =
- new DispatchEntry(eventEntry, // increments ref
- inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
- inputTarget->globalScaleFactor, inputTarget->windowXScale,
- inputTarget->windowYScale);
+ DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
+ inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
+ inputTarget->globalScaleFactor, inputTarget->windowXScale,
+ inputTarget->windowYScale);
// Apply target flags and update the connection's input state.
switch (eventEntry->type) {
- case EventEntry::TYPE_KEY: {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
- dispatchEntry->resolvedAction = keyEntry->action;
- dispatchEntry->resolvedFlags = keyEntry->flags;
+ case EventEntry::TYPE_KEY: {
+ KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
+ dispatchEntry->resolvedAction = keyEntry->action;
+ dispatchEntry->resolvedFlags = keyEntry->flags;
- if (!connection->inputState.trackKey(keyEntry, dispatchEntry->resolvedAction,
- dispatchEntry->resolvedFlags)) {
+ if (!connection->inputState.trackKey(keyEntry,
+ dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
- connection->getInputChannelName().c_str());
+ ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
+ connection->getInputChannelName().c_str());
#endif
- delete dispatchEntry;
- return; // skip the inconsistent event
- }
- break;
+ delete dispatchEntry;
+ return; // skip the inconsistent event
+ }
+ break;
+ }
+
+ case EventEntry::TYPE_MOTION: {
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
+ if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
+ } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
+ } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+ } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
+ } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
+ } else {
+ dispatchEntry->resolvedAction = motionEntry->action;
}
-
- case EventEntry::TYPE_MOTION: {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
- if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
- } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
- } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
- } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
- } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
- } else {
- dispatchEntry->resolvedAction = motionEntry->action;
- }
- if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
- !connection->inputState.isHovering(motionEntry->deviceId, motionEntry->source,
- motionEntry->displayId)) {
+ if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
+ && !connection->inputState.isHovering(
+ motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) {
#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter "
- "event",
- connection->getInputChannelName().c_str());
+ ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
+ connection->getInputChannelName().c_str());
#endif
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
- }
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+ }
- dispatchEntry->resolvedFlags = motionEntry->flags;
- if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
- dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
- }
- if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
- dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
- }
+ dispatchEntry->resolvedFlags = motionEntry->flags;
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
+ dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+ }
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
+ dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+ }
- if (!connection->inputState.trackMotion(motionEntry, dispatchEntry->resolvedAction,
- dispatchEntry->resolvedFlags)) {
+ if (!connection->inputState.trackMotion(motionEntry,
+ dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion "
- "event",
- connection->getInputChannelName().c_str());
+ ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
+ connection->getInputChannelName().c_str());
#endif
- delete dispatchEntry;
- return; // skip the inconsistent event
- }
+ delete dispatchEntry;
+ return; // skip the inconsistent event
+ }
- dispatchPointerDownOutsideFocus(motionEntry->source, dispatchEntry->resolvedAction,
- inputTarget->inputChannel->getToken());
+ dispatchPointerDownOutsideFocus(motionEntry->source,
+ dispatchEntry->resolvedAction, inputTarget->inputChannel->getToken());
- break;
- }
+ break;
+ }
}
// Remember that we are waiting for this dispatch to complete.
@@ -2122,10 +2126,11 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio
// Enqueue the dispatch entry.
connection->outboundQueue.enqueueAtTail(dispatchEntry);
traceOutboundQueueLength(connection);
+
}
void InputDispatcher::dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
- const sp<IBinder>& newToken) {
+ const sp<IBinder>& newToken) {
int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
uint32_t maskedSource = source & AINPUT_SOURCE_CLASS_MASK;
if (maskedSource != AINPUT_SOURCE_CLASS_POINTER || maskedAction != AMOTION_EVENT_ACTION_DOWN) {
@@ -2146,24 +2151,25 @@ void InputDispatcher::dispatchPointerDownOutsideFocus(uint32_t source, int32_t a
return;
}
- CommandEntry* commandEntry =
- postCommandLocked(&InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible);
+ CommandEntry* commandEntry = postCommandLocked(
+ & InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible);
commandEntry->newToken = newToken;
}
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection) {
+ const sp<Connection>& connection) {
if (ATRACE_ENABLED()) {
std::string message = StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
- connection->getInputChannelName().c_str());
+ connection->getInputChannelName().c_str());
ATRACE_NAME(message.c_str());
}
#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ startDispatchCycle", connection->getInputChannelName().c_str());
+ ALOGD("channel '%s' ~ startDispatchCycle",
+ connection->getInputChannelName().c_str());
#endif
- while (connection->status == Connection::STATUS_NORMAL &&
- !connection->outboundQueue.isEmpty()) {
+ while (connection->status == Connection::STATUS_NORMAL
+ && !connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.head;
dispatchEntry->deliveryTime = currentTime;
@@ -2171,77 +2177,70 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
status_t status;
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type) {
- case EventEntry::TYPE_KEY: {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
-
- // Publish the key event.
- status = connection->inputPublisher
- .publishKeyEvent(dispatchEntry->seq, keyEntry->deviceId,
- keyEntry->source, keyEntry->displayId,
- dispatchEntry->resolvedAction,
- dispatchEntry->resolvedFlags, keyEntry->keyCode,
- keyEntry->scanCode, keyEntry->metaState,
- keyEntry->repeatCount, keyEntry->downTime,
- keyEntry->eventTime);
- break;
- }
+ case EventEntry::TYPE_KEY: {
+ KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
- case EventEntry::TYPE_MOTION: {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
-
- PointerCoords scaledCoords[MAX_POINTERS];
- const PointerCoords* usingCoords = motionEntry->pointerCoords;
-
- // Set the X and Y offset depending on the input source.
- float xOffset, yOffset;
- if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) &&
- !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
- float globalScaleFactor = dispatchEntry->globalScaleFactor;
- float wxs = dispatchEntry->windowXScale;
- float wys = dispatchEntry->windowYScale;
- xOffset = dispatchEntry->xOffset * wxs;
- yOffset = dispatchEntry->yOffset * wys;
- if (wxs != 1.0f || wys != 1.0f || globalScaleFactor != 1.0f) {
- for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
- scaledCoords[i] = motionEntry->pointerCoords[i];
- scaledCoords[i].scale(globalScaleFactor, wxs, wys);
- }
- usingCoords = scaledCoords;
- }
- } else {
- xOffset = 0.0f;
- yOffset = 0.0f;
+ // Publish the key event.
+ status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
+ keyEntry->deviceId, keyEntry->source, keyEntry->displayId,
+ dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
+ keyEntry->keyCode, keyEntry->scanCode,
+ keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
+ keyEntry->eventTime);
+ break;
+ }
- // We don't want the dispatch target to know.
- if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
- for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
- scaledCoords[i].clear();
- }
- usingCoords = scaledCoords;
+ case EventEntry::TYPE_MOTION: {
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
+
+ PointerCoords scaledCoords[MAX_POINTERS];
+ const PointerCoords* usingCoords = motionEntry->pointerCoords;
+
+ // Set the X and Y offset depending on the input source.
+ float xOffset, yOffset;
+ if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
+ && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
+ float globalScaleFactor = dispatchEntry->globalScaleFactor;
+ float wxs = dispatchEntry->windowXScale;
+ float wys = dispatchEntry->windowYScale;
+ xOffset = dispatchEntry->xOffset * wxs;
+ yOffset = dispatchEntry->yOffset * wys;
+ if (wxs != 1.0f || wys != 1.0f || globalScaleFactor != 1.0f) {
+ for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
+ scaledCoords[i] = motionEntry->pointerCoords[i];
+ scaledCoords[i].scale(globalScaleFactor, wxs, wys);
}
+ usingCoords = scaledCoords;
}
+ } else {
+ xOffset = 0.0f;
+ yOffset = 0.0f;
- // Publish the motion event.
- status = connection->inputPublisher
- .publishMotionEvent(dispatchEntry->seq, motionEntry->deviceId,
- motionEntry->source, motionEntry->displayId,
- dispatchEntry->resolvedAction,
- motionEntry->actionButton,
- dispatchEntry->resolvedFlags,
- motionEntry->edgeFlags, motionEntry->metaState,
- motionEntry->buttonState,
- motionEntry->classification, xOffset, yOffset,
- motionEntry->xPrecision,
- motionEntry->yPrecision, motionEntry->downTime,
- motionEntry->eventTime,
- motionEntry->pointerCount,
- motionEntry->pointerProperties, usingCoords);
- break;
+ // We don't want the dispatch target to know.
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
+ for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
+ scaledCoords[i].clear();
+ }
+ usingCoords = scaledCoords;
+ }
}
- default:
- ALOG_ASSERT(false);
- return;
+ // Publish the motion event.
+ status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
+ motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
+ dispatchEntry->resolvedAction, motionEntry->actionButton,
+ dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
+ motionEntry->metaState, motionEntry->buttonState, motionEntry->classification,
+ xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
+ motionEntry->downTime, motionEntry->eventTime,
+ motionEntry->pointerCount, motionEntry->pointerProperties,
+ usingCoords);
+ break;
+ }
+
+ default:
+ ALOG_ASSERT(false);
+ return;
}
// Check the result.
@@ -2249,25 +2248,24 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
if (status == WOULD_BLOCK) {
if (connection->waitQueue.isEmpty()) {
ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
- "This is unexpected because the wait queue is empty, so the pipe "
- "should be empty and we shouldn't have any problems writing an "
- "event to it, status=%d",
- connection->getInputChannelName().c_str(), status);
+ "This is unexpected because the wait queue is empty, so the pipe "
+ "should be empty and we shouldn't have any problems writing an "
+ "event to it, status=%d", connection->getInputChannelName().c_str(),
+ status);
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
} else {
// Pipe is full and we are waiting for the app to finish process some events
// before sending more events to it.
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
- "waiting for the application to catch up",
- connection->getInputChannelName().c_str());
+ "waiting for the application to catch up",
+ connection->getInputChannelName().c_str());
#endif
connection->inputPublisherBlocked = true;
}
} else {
ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
- "status=%d",
- connection->getInputChannelName().c_str(), status);
+ "status=%d", connection->getInputChannelName().c_str(), status);
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
}
return;
@@ -2282,17 +2280,16 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
}
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, uint32_t seq,
- bool handled) {
+ const sp<Connection>& connection, uint32_t seq, bool handled) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
- connection->getInputChannelName().c_str(), seq, toString(handled));
+ connection->getInputChannelName().c_str(), seq, toString(handled));
#endif
connection->inputPublisherBlocked = false;
- if (connection->status == Connection::STATUS_BROKEN ||
- connection->status == Connection::STATUS_ZOMBIE) {
+ if (connection->status == Connection::STATUS_BROKEN
+ || connection->status == Connection::STATUS_ZOMBIE) {
return;
}
@@ -2301,11 +2298,10 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
}
void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection,
- bool notify) {
+ const sp<Connection>& connection, bool notify) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s",
- connection->getInputChannelName().c_str(), toString(notify));
+ connection->getInputChannelName().c_str(), toString(notify));
#endif
// Clear the dispatch queues.
@@ -2349,8 +2345,7 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
if (connectionIndex < 0) {
ALOGE("Received spurious receive callback for unknown input channel. "
- "fd=%d, events=0x%x",
- fd, events);
+ "fd=%d, events=0x%x", fd, events);
return 0; // remove the callback
}
@@ -2359,8 +2354,7 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
if (!(events & ALOOPER_EVENT_INPUT)) {
ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
- "events=0x%x",
- connection->getInputChannelName().c_str(), events);
+ "events=0x%x", connection->getInputChannelName().c_str(), events);
return 1;
}
@@ -2387,7 +2381,7 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
notify = status != DEAD_OBJECT || !connection->monitor;
if (notify) {
ALOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
- connection->getInputChannelName().c_str(), status);
+ connection->getInputChannelName().c_str(), status);
}
} else {
// Monitor channels are never explicitly unregistered.
@@ -2396,25 +2390,25 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
notify = !connection->monitor;
if (notify) {
ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. "
- "events=0x%x",
- connection->getInputChannelName().c_str(), events);
+ "events=0x%x", connection->getInputChannelName().c_str(), events);
}
}
// Unregister the channel.
d->unregisterInputChannelLocked(connection->inputChannel, notify);
return 0; // remove the callback
- } // release lock
+ } // release lock
}
-void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
+void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked (
const CancelationOptions& options) {
for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
- synthesizeCancelationEventsForConnectionLocked(mConnectionsByFd.valueAt(i), options);
+ synthesizeCancelationEventsForConnectionLocked(
+ mConnectionsByFd.valueAt(i), options);
}
}
-void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
+void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked (
const CancelationOptions& options) {
synthesizeCancelationEventsForMonitorsLocked(options, mGlobalMonitorsByDisplay);
synthesizeCancelationEventsForMonitorsLocked(options, mGestureMonitorsByDisplay);
@@ -2435,7 +2429,8 @@ void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
const sp<InputChannel>& channel, const CancelationOptions& options) {
ssize_t index = getConnectionIndexLocked(channel);
if (index >= 0) {
- synthesizeCancelationEventsForConnectionLocked(mConnectionsByFd.valueAt(index), options);
+ synthesizeCancelationEventsForConnectionLocked(
+ mConnectionsByFd.valueAt(index), options);
}
}
@@ -2448,31 +2443,32 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
nsecs_t currentTime = now();
std::vector<EventEntry*> cancelationEvents;
- connection->inputState.synthesizeCancelationEvents(currentTime, cancelationEvents, options);
+ connection->inputState.synthesizeCancelationEvents(currentTime,
+ cancelationEvents, options);
if (!cancelationEvents.empty()) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
- "with reality: %s, mode=%d.",
- connection->getInputChannelName().c_str(), cancelationEvents.size(), options.reason,
- options.mode);
+ "with reality: %s, mode=%d.",
+ connection->getInputChannelName().c_str(), cancelationEvents.size(),
+ options.reason, options.mode);
#endif
for (size_t i = 0; i < cancelationEvents.size(); i++) {
EventEntry* cancelationEventEntry = cancelationEvents[i];
switch (cancelationEventEntry->type) {
- case EventEntry::TYPE_KEY:
- logOutboundKeyDetails("cancel - ",
- static_cast<KeyEntry*>(cancelationEventEntry));
- break;
- case EventEntry::TYPE_MOTION:
- logOutboundMotionDetails("cancel - ",
- static_cast<MotionEntry*>(cancelationEventEntry));
- break;
+ case EventEntry::TYPE_KEY:
+ logOutboundKeyDetails("cancel - ",
+ static_cast<KeyEntry*>(cancelationEventEntry));
+ break;
+ case EventEntry::TYPE_MOTION:
+ logOutboundMotionDetails("cancel - ",
+ static_cast<MotionEntry*>(cancelationEventEntry));
+ break;
}
InputTarget target;
- sp<InputWindowHandle> windowHandle =
- getWindowHandleLocked(connection->inputChannel->getToken());
+ sp<InputWindowHandle> windowHandle = getWindowHandleLocked(
+ connection->inputChannel->getToken());
if (windowHandle != nullptr) {
const InputWindowInfo* windowInfo = windowHandle->getInfo();
target.xOffset = -windowInfo->frameLeft;
@@ -2489,7 +2485,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
- &target, InputTarget::FLAG_DISPATCH_AS_IS);
+ &target, InputTarget::FLAG_DISPATCH_AS_IS);
cancelationEventEntry->release();
}
@@ -2498,8 +2494,8 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
}
}
-MotionEntry* InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry,
- BitSet32 pointerIds) {
+InputDispatcher::MotionEntry*
+InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
ALOG_ASSERT(pointerIds.value != 0);
uint32_t splitPointerIndexMap[MAX_POINTERS];
@@ -2510,7 +2506,7 @@ MotionEntry* InputDispatcher::splitMotionEvent(const MotionEntry* originalMotion
uint32_t splitPointerCount = 0;
for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
- originalPointerIndex++) {
+ originalPointerIndex++) {
const PointerProperties& pointerProperties =
originalMotionEntry->pointerProperties[originalPointerIndex];
uint32_t pointerId = uint32_t(pointerProperties.id);
@@ -2530,16 +2526,16 @@ MotionEntry* InputDispatcher::splitMotionEvent(const MotionEntry* originalMotion
// or ACTION_POINTER_DOWN events that caused us to decide to split the pointers
// in this way.
ALOGW("Dropping split motion event because the pointer count is %d but "
- "we expected there to be %d pointers. This probably means we received "
- "a broken sequence of pointer ids from the input device.",
- splitPointerCount, pointerIds.count());
+ "we expected there to be %d pointers. This probably means we received "
+ "a broken sequence of pointer ids from the input device.",
+ splitPointerCount, pointerIds.count());
return nullptr;
}
int32_t action = originalMotionEntry->action;
int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
- if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN ||
- maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+ if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
+ || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
const PointerProperties& pointerProperties =
originalMotionEntry->pointerProperties[originalPointerIndex];
@@ -2548,16 +2544,15 @@ MotionEntry* InputDispatcher::splitMotionEvent(const MotionEntry* originalMotion
if (pointerIds.count() == 1) {
// The first/last pointer went down/up.
action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
- ? AMOTION_EVENT_ACTION_DOWN
- : AMOTION_EVENT_ACTION_UP;
+ ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
} else {
// A secondary pointer went down/up.
uint32_t splitPointerIndex = 0;
while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) {
splitPointerIndex += 1;
}
- action = maskedAction |
- (splitPointerIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+ action = maskedAction | (splitPointerIndex
+ << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
}
} else {
// An unrelated pointer changed.
@@ -2565,16 +2560,24 @@ MotionEntry* InputDispatcher::splitMotionEvent(const MotionEntry* originalMotion
}
}
- MotionEntry* splitMotionEntry =
- new MotionEntry(originalMotionEntry->sequenceNum, originalMotionEntry->eventTime,
- originalMotionEntry->deviceId, originalMotionEntry->source,
- originalMotionEntry->displayId, originalMotionEntry->policyFlags,
- action, originalMotionEntry->actionButton, originalMotionEntry->flags,
- originalMotionEntry->metaState, originalMotionEntry->buttonState,
- originalMotionEntry->classification, originalMotionEntry->edgeFlags,
- originalMotionEntry->xPrecision, originalMotionEntry->yPrecision,
- originalMotionEntry->downTime, splitPointerCount,
- splitPointerProperties, splitPointerCoords, 0, 0);
+ MotionEntry* splitMotionEntry = new MotionEntry(
+ originalMotionEntry->sequenceNum,
+ originalMotionEntry->eventTime,
+ originalMotionEntry->deviceId,
+ originalMotionEntry->source,
+ originalMotionEntry->displayId,
+ originalMotionEntry->policyFlags,
+ action,
+ originalMotionEntry->actionButton,
+ originalMotionEntry->flags,
+ originalMotionEntry->metaState,
+ originalMotionEntry->buttonState,
+ originalMotionEntry->classification,
+ originalMotionEntry->edgeFlags,
+ originalMotionEntry->xPrecision,
+ originalMotionEntry->yPrecision,
+ originalMotionEntry->downTime,
+ splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
if (originalMotionEntry->injectionState) {
splitMotionEntry->injectionState = originalMotionEntry->injectionState;
@@ -2610,7 +2613,7 @@ void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChange
* This will potentially overwrite keyCode and metaState.
*/
void InputDispatcher::accelerateMetaShortcuts(const int32_t deviceId, const int32_t action,
- int32_t& keyCode, int32_t& metaState) {
+ int32_t& keyCode, int32_t& metaState) {
if (metaState & AMETA_META_ON && action == AKEY_EVENT_ACTION_DOWN) {
int32_t newKeyCode = AKEYCODE_UNKNOWN;
if (keyCode == AKEYCODE_DEL) {
@@ -2642,12 +2645,12 @@ void InputDispatcher::accelerateMetaShortcuts(const int32_t deviceId, const int3
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyKey - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
- "policyFlags=0x%x, action=0x%x, "
- "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64,
- args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
- args->action, args->flags, args->keyCode, args->scanCode, args->metaState,
- args->downTime);
+ ALOGD("notifyKey - eventTime=%" PRId64
+ ", deviceId=%d, source=0x%x, displayId=%" PRId32 "policyFlags=0x%x, action=0x%x, "
+ "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64,
+ args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
+ args->action, args->flags, args->keyCode, args->scanCode,
+ args->metaState, args->downTime);
#endif
if (!validateKeyEvent(args->action)) {
return;
@@ -2673,14 +2676,15 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState);
KeyEvent event;
- event.initialize(args->deviceId, args->source, args->displayId, args->action, flags, keyCode,
- args->scanCode, metaState, repeatCount, args->downTime, args->eventTime);
+ event.initialize(args->deviceId, args->source, args->displayId, args->action,
+ flags, keyCode, args->scanCode, metaState, repeatCount,
+ args->downTime, args->eventTime);
android::base::Timer t;
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
- std::to_string(t.duration().count()).c_str());
+ std::to_string(t.duration().count()).c_str());
}
bool needWake;
@@ -2698,10 +2702,10 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
mLock.lock();
}
- KeyEntry* newEntry =
- new KeyEntry(args->sequenceNum, args->eventTime, args->deviceId, args->source,
- args->displayId, policyFlags, args->action, flags, keyCode,
- args->scanCode, metaState, repeatCount, args->downTime);
+ KeyEntry* newEntry = new KeyEntry(args->sequenceNum, args->eventTime,
+ args->deviceId, args->source, args->displayId, policyFlags,
+ args->action, flags, keyCode, args->scanCode,
+ metaState, repeatCount, args->downTime);
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
@@ -2719,31 +2723,32 @@ bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
- ", policyFlags=0x%x, "
- "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
- "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
- args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
- args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
- args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
+ ", policyFlags=0x%x, "
+ "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
+ "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
+ args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
+ args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
+ args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
for (uint32_t i = 0; i < args->pointerCount; i++) {
ALOGD(" Pointer %d: id=%d, toolType=%d, "
- "x=%f, y=%f, pressure=%f, size=%f, "
- "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
- "orientation=%f",
- i, args->pointerProperties[i].id, args->pointerProperties[i].toolType,
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
+ "x=%f, y=%f, pressure=%f, size=%f, "
+ "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
+ "orientation=%f",
+ i, args->pointerProperties[i].id,
+ args->pointerProperties[i].toolType,
+ args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
+ args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
+ args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
+ args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
+ args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
+ args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
+ args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
+ args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
+ args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
}
#endif
- if (!validateMotionEvent(args->action, args->actionButton, args->pointerCount,
- args->pointerProperties)) {
+ if (!validateMotionEvent(args->action, args->actionButton,
+ args->pointerCount, args->pointerProperties)) {
return;
}
@@ -2754,7 +2759,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
mPolicy->interceptMotionBeforeQueueing(args->displayId, args->eventTime, /*byref*/ policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
- std::to_string(t.duration().count()).c_str());
+ std::to_string(t.duration().count()).c_str());
}
bool needWake;
@@ -2765,11 +2770,12 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
mLock.unlock();
MotionEvent event;
- event.initialize(args->deviceId, args->source, args->displayId, args->action,
- args->actionButton, args->flags, args->edgeFlags, args->metaState,
- args->buttonState, args->classification, 0, 0, args->xPrecision,
- args->yPrecision, args->downTime, args->eventTime, args->pointerCount,
- args->pointerProperties, args->pointerCoords);
+ event.initialize(args->deviceId, args->source, args->displayId,
+ args->action, args->actionButton,
+ args->flags, args->edgeFlags, args->metaState, args->buttonState,
+ args->classification, 0, 0, args->xPrecision, args->yPrecision,
+ args->downTime, args->eventTime,
+ args->pointerCount, args->pointerProperties, args->pointerCoords);
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
@@ -2780,13 +2786,12 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
}
// Just enqueue a new motion event.
- MotionEntry* newEntry =
- new MotionEntry(args->sequenceNum, args->eventTime, args->deviceId, args->source,
- args->displayId, policyFlags, args->action, args->actionButton,
- args->flags, args->metaState, args->buttonState,
- args->classification, args->edgeFlags, args->xPrecision,
- args->yPrecision, args->downTime, args->pointerCount,
- args->pointerProperties, args->pointerCoords, 0, 0);
+ MotionEntry* newEntry = new MotionEntry(args->sequenceNum, args->eventTime,
+ args->deviceId, args->source, args->displayId, policyFlags,
+ args->action, args->actionButton, args->flags,
+ args->metaState, args->buttonState, args->classification,
+ args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
+ args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
@@ -2804,19 +2809,20 @@ bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs
void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, "
- "switchMask=0x%08x",
- args->eventTime, args->policyFlags, args->switchValues, args->switchMask);
+ "switchMask=0x%08x",
+ args->eventTime, args->policyFlags, args->switchValues, args->switchMask);
#endif
uint32_t policyFlags = args->policyFlags;
policyFlags |= POLICY_FLAG_TRUSTED;
- mPolicy->notifySwitch(args->eventTime, args->switchValues, args->switchMask, policyFlags);
+ mPolicy->notifySwitch(args->eventTime,
+ args->switchValues, args->switchMask, policyFlags);
}
void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args->eventTime,
- args->deviceId);
+ ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d",
+ args->eventTime, args->deviceId);
#endif
bool needWake;
@@ -2833,13 +2839,13 @@ void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
}
}
-int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injectorPid,
- int32_t injectorUid, int32_t syncMode,
- int32_t timeoutMillis, uint32_t policyFlags) {
+int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ uint32_t policyFlags) {
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
- "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
- event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
+ "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
+ event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
#endif
nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
@@ -2852,107 +2858,104 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injec
EventEntry* firstInjectedEntry;
EventEntry* lastInjectedEntry;
switch (event->getType()) {
- case AINPUT_EVENT_TYPE_KEY: {
- KeyEvent keyEvent;
- keyEvent.initialize(*static_cast<const KeyEvent*>(event));
- int32_t action = keyEvent.getAction();
- if (!validateKeyEvent(action)) {
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- int32_t flags = keyEvent.getFlags();
- int32_t keyCode = keyEvent.getKeyCode();
- int32_t metaState = keyEvent.getMetaState();
- accelerateMetaShortcuts(keyEvent.getDeviceId(), action,
- /*byref*/ keyCode, /*byref*/ metaState);
- keyEvent.initialize(keyEvent.getDeviceId(), keyEvent.getSource(),
- keyEvent.getDisplayId(), action, flags, keyCode,
- keyEvent.getScanCode(), metaState, keyEvent.getRepeatCount(),
- keyEvent.getDownTime(), keyEvent.getEventTime());
-
- if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
- policyFlags |= POLICY_FLAG_VIRTUAL;
- }
+ case AINPUT_EVENT_TYPE_KEY: {
+ KeyEvent keyEvent;
+ keyEvent.initialize(*static_cast<const KeyEvent*>(event));
+ int32_t action = keyEvent.getAction();
+ if (! validateKeyEvent(action)) {
+ return INPUT_EVENT_INJECTION_FAILED;
+ }
- if (!(policyFlags & POLICY_FLAG_FILTERED)) {
- android::base::Timer t;
- mPolicy->interceptKeyBeforeQueueing(&keyEvent, /*byref*/ policyFlags);
- if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
- ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
- std::to_string(t.duration().count()).c_str());
- }
- }
+ int32_t flags = keyEvent.getFlags();
+ int32_t keyCode = keyEvent.getKeyCode();
+ int32_t metaState = keyEvent.getMetaState();
+ accelerateMetaShortcuts(keyEvent.getDeviceId(), action,
+ /*byref*/ keyCode, /*byref*/ metaState);
+ keyEvent.initialize(keyEvent.getDeviceId(), keyEvent.getSource(), keyEvent.getDisplayId(),
+ action, flags, keyCode, keyEvent.getScanCode(), metaState, keyEvent.getRepeatCount(),
+ keyEvent.getDownTime(), keyEvent.getEventTime());
- mLock.lock();
- firstInjectedEntry = new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM,
- keyEvent.getEventTime(), keyEvent.getDeviceId(),
- keyEvent.getSource(), keyEvent.getDisplayId(),
- policyFlags, action, flags, keyEvent.getKeyCode(),
- keyEvent.getScanCode(), keyEvent.getMetaState(),
- keyEvent.getRepeatCount(), keyEvent.getDownTime());
- lastInjectedEntry = firstInjectedEntry;
- break;
+ if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
+ policyFlags |= POLICY_FLAG_VIRTUAL;
}
- case AINPUT_EVENT_TYPE_MOTION: {
- const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
- int32_t action = motionEvent->getAction();
- size_t pointerCount = motionEvent->getPointerCount();
- const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
- int32_t actionButton = motionEvent->getActionButton();
- int32_t displayId = motionEvent->getDisplayId();
- if (!validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) {
- return INPUT_EVENT_INJECTION_FAILED;
+ if (!(policyFlags & POLICY_FLAG_FILTERED)) {
+ android::base::Timer t;
+ mPolicy->interceptKeyBeforeQueueing(&keyEvent, /*byref*/ policyFlags);
+ if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+ ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
+ std::to_string(t.duration().count()).c_str());
}
+ }
- if (!(policyFlags & POLICY_FLAG_FILTERED)) {
- nsecs_t eventTime = motionEvent->getEventTime();
- android::base::Timer t;
- mPolicy->interceptMotionBeforeQueueing(displayId, eventTime, /*byref*/ policyFlags);
- if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
- ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
- std::to_string(t.duration().count()).c_str());
- }
- }
+ mLock.lock();
+ firstInjectedEntry = new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, keyEvent.getEventTime(),
+ keyEvent.getDeviceId(), keyEvent.getSource(), keyEvent.getDisplayId(),
+ policyFlags, action, flags,
+ keyEvent.getKeyCode(), keyEvent.getScanCode(), keyEvent.getMetaState(),
+ keyEvent.getRepeatCount(), keyEvent.getDownTime());
+ lastInjectedEntry = firstInjectedEntry;
+ break;
+ }
+
+ case AINPUT_EVENT_TYPE_MOTION: {
+ const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
+ int32_t action = motionEvent->getAction();
+ size_t pointerCount = motionEvent->getPointerCount();
+ const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
+ int32_t actionButton = motionEvent->getActionButton();
+ int32_t displayId = motionEvent->getDisplayId();
+ if (! validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) {
+ return INPUT_EVENT_INJECTION_FAILED;
+ }
- mLock.lock();
- const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
- const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
- firstInjectedEntry =
- new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
- motionEvent->getDeviceId(), motionEvent->getSource(),
- motionEvent->getDisplayId(), policyFlags, action, actionButton,
- motionEvent->getFlags(), motionEvent->getMetaState(),
- motionEvent->getButtonState(), motionEvent->getClassification(),
- motionEvent->getEdgeFlags(), motionEvent->getXPrecision(),
- motionEvent->getYPrecision(), motionEvent->getDownTime(),
- uint32_t(pointerCount), pointerProperties, samplePointerCoords,
- motionEvent->getXOffset(), motionEvent->getYOffset());
- lastInjectedEntry = firstInjectedEntry;
- for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
- sampleEventTimes += 1;
- samplePointerCoords += pointerCount;
- MotionEntry* nextInjectedEntry =
- new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
- motionEvent->getDeviceId(), motionEvent->getSource(),
- motionEvent->getDisplayId(), policyFlags, action,
- actionButton, motionEvent->getFlags(),
- motionEvent->getMetaState(), motionEvent->getButtonState(),
- motionEvent->getClassification(),
- motionEvent->getEdgeFlags(), motionEvent->getXPrecision(),
- motionEvent->getYPrecision(), motionEvent->getDownTime(),
- uint32_t(pointerCount), pointerProperties,
- samplePointerCoords, motionEvent->getXOffset(),
- motionEvent->getYOffset());
- lastInjectedEntry->next = nextInjectedEntry;
- lastInjectedEntry = nextInjectedEntry;
+ if (!(policyFlags & POLICY_FLAG_FILTERED)) {
+ nsecs_t eventTime = motionEvent->getEventTime();
+ android::base::Timer t;
+ mPolicy->interceptMotionBeforeQueueing(displayId, eventTime, /*byref*/ policyFlags);
+ if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+ ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
+ std::to_string(t.duration().count()).c_str());
}
- break;
}
- default:
- ALOGW("Cannot inject event of type %d", event->getType());
- return INPUT_EVENT_INJECTION_FAILED;
+ mLock.lock();
+ const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
+ const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
+ firstInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
+ motionEvent->getDeviceId(), motionEvent->getSource(), motionEvent->getDisplayId(),
+ policyFlags,
+ action, actionButton, motionEvent->getFlags(),
+ motionEvent->getMetaState(), motionEvent->getButtonState(),
+ motionEvent->getClassification(), motionEvent->getEdgeFlags(),
+ motionEvent->getXPrecision(), motionEvent->getYPrecision(),
+ motionEvent->getDownTime(),
+ uint32_t(pointerCount), pointerProperties, samplePointerCoords,
+ motionEvent->getXOffset(), motionEvent->getYOffset());
+ lastInjectedEntry = firstInjectedEntry;
+ for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
+ sampleEventTimes += 1;
+ samplePointerCoords += pointerCount;
+ MotionEntry* nextInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM,
+ *sampleEventTimes,
+ motionEvent->getDeviceId(), motionEvent->getSource(),
+ motionEvent->getDisplayId(), policyFlags,
+ action, actionButton, motionEvent->getFlags(),
+ motionEvent->getMetaState(), motionEvent->getButtonState(),
+ motionEvent->getClassification(), motionEvent->getEdgeFlags(),
+ motionEvent->getXPrecision(), motionEvent->getYPrecision(),
+ motionEvent->getDownTime(),
+ uint32_t(pointerCount), pointerProperties, samplePointerCoords,
+ motionEvent->getXOffset(), motionEvent->getYOffset());
+ lastInjectedEntry->next = nextInjectedEntry;
+ lastInjectedEntry = nextInjectedEntry;
+ }
+ break;
+ }
+
+ default:
+ ALOGW("Cannot inject event of type %d", event->getType());
+ return INPUT_EVENT_INJECTION_FAILED;
}
InjectionState* injectionState = new InjectionState(injectorPid, injectorUid);
@@ -2964,7 +2967,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injec
lastInjectedEntry->injectionState = injectionState;
bool needWake = false;
- for (EventEntry* entry = firstInjectedEntry; entry != nullptr;) {
+ for (EventEntry* entry = firstInjectedEntry; entry != nullptr; ) {
EventEntry* nextEntry = entry->next;
needWake |= enqueueInboundEventLocked(entry);
entry = nextEntry;
@@ -2993,7 +2996,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injec
if (remainingTimeout <= 0) {
#if DEBUG_INJECTION
ALOGD("injectInputEvent - Timed out waiting for injection result "
- "to become available.");
+ "to become available.");
#endif
injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
break;
@@ -3002,18 +3005,18 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injec
mInjectionResultAvailable.wait_for(_l, std::chrono::nanoseconds(remainingTimeout));
}
- if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED &&
- syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
+ if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
+ && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
while (injectionState->pendingForegroundDispatches != 0) {
#if DEBUG_INJECTION
ALOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
- injectionState->pendingForegroundDispatches);
+ injectionState->pendingForegroundDispatches);
#endif
nsecs_t remainingTimeout = endTime - now();
if (remainingTimeout <= 0) {
#if DEBUG_INJECTION
- ALOGD("injectInputEvent - Timed out waiting for pending foreground "
- "dispatches to finish.");
+ ALOGD("injectInputEvent - Timed out waiting for pending foreground "
+ "dispatches to finish.");
#endif
injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
break;
@@ -3029,16 +3032,16 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injec
#if DEBUG_INJECTION
ALOGD("injectInputEvent - Finished with result %d. "
- "injectorPid=%d, injectorUid=%d",
- injectionResult, injectorPid, injectorUid);
+ "injectorPid=%d, injectorUid=%d",
+ injectionResult, injectorPid, injectorUid);
#endif
return injectionResult;
}
bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
- return injectorUid == 0 ||
- mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
+ return injectorUid == 0
+ || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
}
void InputDispatcher::setInjectionResult(EventEntry* entry, int32_t injectionResult) {
@@ -3046,25 +3049,26 @@ void InputDispatcher::setInjectionResult(EventEntry* entry, int32_t injectionRes
if (injectionState) {
#if DEBUG_INJECTION
ALOGD("Setting input event injection result to %d. "
- "injectorPid=%d, injectorUid=%d",
- injectionResult, injectionState->injectorPid, injectionState->injectorUid);
+ "injectorPid=%d, injectorUid=%d",
+ injectionResult, injectionState->injectorPid, injectionState->injectorUid);
#endif
- if (injectionState->injectionIsAsync && !(entry->policyFlags & POLICY_FLAG_FILTERED)) {
+ if (injectionState->injectionIsAsync
+ && !(entry->policyFlags & POLICY_FLAG_FILTERED)) {
// Log the outcome since the injector did not wait for the injection result.
switch (injectionResult) {
- case INPUT_EVENT_INJECTION_SUCCEEDED:
- ALOGV("Asynchronous input event injection succeeded.");
- break;
- case INPUT_EVENT_INJECTION_FAILED:
- ALOGW("Asynchronous input event injection failed.");
- break;
- case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
- ALOGW("Asynchronous input event injection permission denied.");
- break;
- case INPUT_EVENT_INJECTION_TIMED_OUT:
- ALOGW("Asynchronous input event injection timed out.");
- break;
+ case INPUT_EVENT_INJECTION_SUCCEEDED:
+ ALOGV("Asynchronous input event injection succeeded.");
+ break;
+ case INPUT_EVENT_INJECTION_FAILED:
+ ALOGW("Asynchronous input event injection failed.");
+ break;
+ case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
+ ALOGW("Asynchronous input event injection permission denied.");
+ break;
+ case INPUT_EVENT_INJECTION_TIMED_OUT:
+ ALOGW("Asynchronous input event injection timed out.");
+ break;
}
}
@@ -3095,7 +3099,7 @@ std::vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(
int32_t displayId) const {
std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>::const_iterator it =
mWindowHandlesByDisplay.find(displayId);
- if (it != mWindowHandlesByDisplay.end()) {
+ if(it != mWindowHandlesByDisplay.end()) {
return it->second;
}
@@ -3123,9 +3127,9 @@ bool InputDispatcher::hasWindowHandleLocked(const sp<InputWindowHandle>& windowH
if (handle->getToken() == windowHandle->getToken()) {
if (windowHandle->getInfo()->displayId != it.first) {
ALOGE("Found window %s in display %" PRId32
- ", but it should belong to display %" PRId32,
- windowHandle->getName().c_str(), it.first,
- windowHandle->getInfo()->displayId);
+ ", but it should belong to display %" PRId32,
+ windowHandle->getName().c_str(), it.first,
+ windowHandle->getInfo()->displayId);
}
return true;
}
@@ -3150,8 +3154,7 @@ sp<InputChannel> InputDispatcher::getInputChannelLocked(const sp<IBinder>& token
* For removed handle, check if need to send a cancel event if already in touch.
*/
void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>& inputWindowHandles,
- int32_t displayId,
- const sp<ISetInputWindowsListener>& setInputWindowsListener) {
+ int32_t displayId, const sp<ISetInputWindowsListener>& setInputWindowsListener) {
#if DEBUG_FOCUS
ALOGD("setInputWindows displayId=%" PRId32, displayId);
#endif
@@ -3218,8 +3221,8 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>&
for (const sp<InputWindowHandle>& windowHandle : newHandles) {
// Set newFocusedWindowHandle to the top most focused window instead of the last one
- if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus &&
- windowHandle->getInfo()->visible) {
+ if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus
+ && windowHandle->getInfo()->visible) {
newFocusedWindowHandle = windowHandle;
}
if (windowHandle == mLastHoverWindowHandle) {
@@ -3242,21 +3245,22 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>&
if (oldFocusedWindowHandle != nullptr) {
#if DEBUG_FOCUS
ALOGD("Focus left window: %s in display %" PRId32,
- oldFocusedWindowHandle->getName().c_str(), displayId);
+ oldFocusedWindowHandle->getName().c_str(), displayId);
#endif
- sp<InputChannel> focusedInputChannel =
- getInputChannelLocked(oldFocusedWindowHandle->getToken());
+ sp<InputChannel> focusedInputChannel = getInputChannelLocked(
+ oldFocusedWindowHandle->getToken());
if (focusedInputChannel != nullptr) {
CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
- "focus left window");
- synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options);
+ "focus left window");
+ synthesizeCancelationEventsForInputChannelLocked(
+ focusedInputChannel, options);
}
mFocusedWindowHandlesByDisplay.erase(displayId);
}
if (newFocusedWindowHandle != nullptr) {
#if DEBUG_FOCUS
ALOGD("Focus entered window: %s in display %" PRId32,
- newFocusedWindowHandle->getName().c_str(), displayId);
+ newFocusedWindowHandle->getName().c_str(), displayId);
#endif
mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
}
@@ -3264,29 +3268,30 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>&
if (mFocusedDisplayId == displayId) {
onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
}
+
}
ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
if (stateIndex >= 0) {
TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
- for (size_t i = 0; i < state.windows.size();) {
+ for (size_t i = 0; i < state.windows.size(); ) {
TouchedWindow& touchedWindow = state.windows[i];
if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
#if DEBUG_FOCUS
ALOGD("Touched window was removed: %s in display %" PRId32,
- touchedWindow.windowHandle->getName().c_str(), displayId);
+ touchedWindow.windowHandle->getName().c_str(), displayId);
#endif
sp<InputChannel> touchedInputChannel =
getInputChannelLocked(touchedWindow.windowHandle->getToken());
if (touchedInputChannel != nullptr) {
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "touched window was removed");
- synthesizeCancelationEventsForInputChannelLocked(touchedInputChannel,
- options);
+ "touched window was removed");
+ synthesizeCancelationEventsForInputChannelLocked(
+ touchedInputChannel, options);
}
state.windows.erase(state.windows.begin() + i);
} else {
- ++i;
+ ++i;
}
}
}
@@ -3337,7 +3342,7 @@ void InputDispatcher::setFocusedApplication(
}
#if DEBUG_FOCUS
- // logDispatchStateLocked();
+ //logDispatchStateLocked();
#endif
} // release lock
@@ -3366,11 +3371,11 @@ void InputDispatcher::setFocusedDisplay(int32_t displayId) {
getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
if (oldFocusedWindowHandle != nullptr) {
sp<InputChannel> inputChannel =
- getInputChannelLocked(oldFocusedWindowHandle->getToken());
+ getInputChannelLocked(oldFocusedWindowHandle->getToken());
if (inputChannel != nullptr) {
- CancelationOptions
- options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
- "The display which contains this window no longer has focus.");
+ CancelationOptions options(
+ CancelationOptions::CANCEL_NON_POINTER_EVENTS,
+ "The display which contains this window no longer has focus.");
options.displayId = ADISPLAY_ID_NONE;
synthesizeCancelationEventsForInputChannelLocked(inputChannel, options);
}
@@ -3389,8 +3394,8 @@ void InputDispatcher::setFocusedDisplay(int32_t displayId) {
for (auto& it : mFocusedWindowHandlesByDisplay) {
const int32_t displayId = it.first;
const sp<InputWindowHandle>& windowHandle = it.second;
- ALOGE("Display #%" PRId32 " has focused window: '%s'\n", displayId,
- windowHandle->getName().c_str());
+ ALOGE("Display #%" PRId32 " has focused window: '%s'\n",
+ displayId, windowHandle->getName().c_str());
}
}
}
@@ -3480,7 +3485,7 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<
}
#if DEBUG_FOCUS
ALOGD("transferTouchFocus: fromWindowHandle=%s, toWindowHandle=%s",
- fromWindowHandle->getName().c_str(), toWindowHandle->getName().c_str());
+ fromWindowHandle->getName().c_str(), toWindowHandle->getName().c_str());
#endif
if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) {
#if DEBUG_FOCUS
@@ -3500,9 +3505,9 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<
state.windows.erase(state.windows.begin() + i);
- int32_t newTargetFlags = oldTargetFlags &
- (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT |
- InputTarget::FLAG_DISPATCH_AS_IS);
+ int32_t newTargetFlags = oldTargetFlags
+ & (InputTarget::FLAG_FOREGROUND
+ | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
state.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
found = true;
@@ -3510,15 +3515,16 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<
}
}
}
- Found:
+Found:
- if (!found) {
+ if (! found) {
#if DEBUG_FOCUS
ALOGD("Focus transfer failed because from window did not have focus.");
#endif
return false;
}
+
sp<InputChannel> fromChannel = getInputChannelLocked(fromToken);
sp<InputChannel> toChannel = getInputChannelLocked(toToken);
ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
@@ -3528,9 +3534,8 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<
sp<Connection> toConnection = mConnectionsByFd.valueAt(toConnectionIndex);
fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
- CancelationOptions
- options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "transferring touch focus from this window to another window");
+ CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+ "transferring touch focus from this window to another window");
synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
}
@@ -3585,12 +3590,12 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
for (auto& it : mFocusedApplicationHandlesByDisplay) {
const int32_t displayId = it.first;
const sp<InputApplicationHandle>& applicationHandle = it.second;
- dump += StringPrintf(INDENT2 "displayId=%" PRId32
- ", name='%s', dispatchingTimeout=%0.3fms\n",
- displayId, applicationHandle->getName().c_str(),
- applicationHandle->getDispatchingTimeout(
- DEFAULT_INPUT_DISPATCHING_TIMEOUT) /
- 1000000.0);
+ dump += StringPrintf(
+ INDENT2 "displayId=%" PRId32 ", name='%s', dispatchingTimeout=%0.3fms\n",
+ displayId,
+ applicationHandle->getName().c_str(),
+ applicationHandle->getDispatchingTimeout(
+ DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
}
} else {
dump += StringPrintf(INDENT "FocusedApplications: <none>\n");
@@ -3601,8 +3606,8 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
for (auto& it : mFocusedWindowHandlesByDisplay) {
const int32_t displayId = it.first;
const sp<InputWindowHandle>& windowHandle = it.second;
- dump += StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s'\n", displayId,
- windowHandle->getName().c_str());
+ dump += StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s'\n",
+ displayId, windowHandle->getName().c_str());
}
} else {
dump += StringPrintf(INDENT "FocusedWindows: <none>\n");
@@ -3613,16 +3618,16 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
for (size_t i = 0; i < mTouchStatesByDisplay.size(); i++) {
const TouchState& state = mTouchStatesByDisplay.valueAt(i);
dump += StringPrintf(INDENT2 "%d: down=%s, split=%s, deviceId=%d, source=0x%08x\n",
- state.displayId, toString(state.down), toString(state.split),
- state.deviceId, state.source);
+ state.displayId, toString(state.down), toString(state.split),
+ state.deviceId, state.source);
if (!state.windows.empty()) {
dump += INDENT3 "Windows:\n";
for (size_t i = 0; i < state.windows.size(); i++) {
const TouchedWindow& touchedWindow = state.windows[i];
- dump += StringPrintf(INDENT4
- "%zu: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
- i, touchedWindow.windowHandle->getName().c_str(),
- touchedWindow.pointerIds.value, touchedWindow.targetFlags);
+ dump += StringPrintf(INDENT4 "%zu: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
+ i, touchedWindow.windowHandle->getName().c_str(),
+ touchedWindow.pointerIds.value,
+ touchedWindow.targetFlags);
}
} else {
dump += INDENT3 "Windows: <none>\n";
@@ -3631,8 +3636,8 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
dump += INDENT3 "Portal windows:\n";
for (size_t i = 0; i < state.portalWindows.size(); i++) {
const sp<InputWindowHandle> portalWindowHandle = state.portalWindows[i];
- dump += StringPrintf(INDENT4 "%zu: name='%s'\n", i,
- portalWindowHandle->getName().c_str());
+ dump += StringPrintf(INDENT4 "%zu: name='%s'\n",
+ i, portalWindowHandle->getName().c_str());
}
}
}
@@ -3641,7 +3646,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
}
if (!mWindowHandlesByDisplay.empty()) {
- for (auto& it : mWindowHandlesByDisplay) {
+ for (auto& it : mWindowHandlesByDisplay) {
const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
dump += StringPrintf(INDENT "Display: %" PRId32 "\n", it.first);
if (!windowHandles.empty()) {
@@ -3651,31 +3656,28 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
const InputWindowInfo* windowInfo = windowHandle->getInfo();
dump += StringPrintf(INDENT3 "%zu: name='%s', displayId=%d, "
- "portalToDisplayId=%d, paused=%s, hasFocus=%s, "
- "hasWallpaper=%s, "
- "visible=%s, canReceiveKeys=%s, flags=0x%08x, "
- "type=0x%08x, layer=%d, "
- "frame=[%d,%d][%d,%d], globalScale=%f, "
- "windowScale=(%f,%f), "
- "touchableRegion=",
- i, windowInfo->name.c_str(), windowInfo->displayId,
- windowInfo->portalToDisplayId,
- toString(windowInfo->paused),
- toString(windowInfo->hasFocus),
- toString(windowInfo->hasWallpaper),
- toString(windowInfo->visible),
- toString(windowInfo->canReceiveKeys),
- windowInfo->layoutParamsFlags,
- windowInfo->layoutParamsType, windowInfo->layer,
- windowInfo->frameLeft, windowInfo->frameTop,
- windowInfo->frameRight, windowInfo->frameBottom,
- windowInfo->globalScaleFactor, windowInfo->windowXScale,
- windowInfo->windowYScale);
+ "portalToDisplayId=%d, paused=%s, hasFocus=%s, hasWallpaper=%s, "
+ "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
+ "frame=[%d,%d][%d,%d], globalScale=%f, windowScale=(%f,%f), "
+ "touchableRegion=",
+ i, windowInfo->name.c_str(), windowInfo->displayId,
+ windowInfo->portalToDisplayId,
+ toString(windowInfo->paused),
+ toString(windowInfo->hasFocus),
+ toString(windowInfo->hasWallpaper),
+ toString(windowInfo->visible),
+ toString(windowInfo->canReceiveKeys),
+ windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
+ windowInfo->layer,
+ windowInfo->frameLeft, windowInfo->frameTop,
+ windowInfo->frameRight, windowInfo->frameBottom,
+ windowInfo->globalScaleFactor,
+ windowInfo->windowXScale, windowInfo->windowYScale);
dumpRegion(dump, windowInfo->touchableRegion);
dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
- windowInfo->ownerPid, windowInfo->ownerUid,
- windowInfo->dispatchingTimeout / 1000000.0);
+ windowInfo->ownerPid, windowInfo->ownerUid,
+ windowInfo->dispatchingTimeout / 1000000.0);
}
} else {
dump += INDENT2 "Windows: <none>\n";
@@ -3686,16 +3688,16 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
}
if (!mGlobalMonitorsByDisplay.empty() || !mGestureMonitorsByDisplay.empty()) {
- for (auto& it : mGlobalMonitorsByDisplay) {
+ for (auto& it : mGlobalMonitorsByDisplay) {
const std::vector<Monitor>& monitors = it.second;
dump += StringPrintf(INDENT "Global monitors in display %" PRId32 ":\n", it.first);
dumpMonitors(dump, monitors);
- }
- for (auto& it : mGestureMonitorsByDisplay) {
+ }
+ for (auto& it : mGestureMonitorsByDisplay) {
const std::vector<Monitor>& monitors = it.second;
dump += StringPrintf(INDENT "Gesture monitors in display %" PRId32 ":\n", it.first);
dumpMonitors(dump, monitors);
- }
+ }
} else {
dump += INDENT "Monitors: <none>\n";
}
@@ -3708,7 +3710,8 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
for (EventEntry* entry = mRecentQueue.head; entry; entry = entry->next) {
dump += INDENT2;
entry->appendDescription(dump);
- dump += StringPrintf(", age=%0.1fms\n", (currentTime - entry->eventTime) * 0.000001f);
+ dump += StringPrintf(", age=%0.1fms\n",
+ (currentTime - entry->eventTime) * 0.000001f);
}
} else {
dump += INDENT "RecentQueue: <empty>\n";
@@ -3720,7 +3723,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
dump += INDENT2;
mPendingEvent->appendDescription(dump);
dump += StringPrintf(", age=%0.1fms\n",
- (currentTime - mPendingEvent->eventTime) * 0.000001f);
+ (currentTime - mPendingEvent->eventTime) * 0.000001f);
} else {
dump += INDENT "PendingEvent: <none>\n";
}
@@ -3731,7 +3734,8 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) {
dump += INDENT2;
entry->appendDescription(dump);
- dump += StringPrintf(", age=%0.1fms\n", (currentTime - entry->eventTime) * 0.000001f);
+ dump += StringPrintf(", age=%0.1fms\n",
+ (currentTime - entry->eventTime) * 0.000001f);
}
} else {
dump += INDENT "InboundQueue: <empty>\n";
@@ -3742,8 +3746,8 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
for (size_t i = 0; i < mReplacedKeys.size(); i++) {
const KeyReplacement& replacement = mReplacedKeys.keyAt(i);
int32_t newKeyCode = mReplacedKeys.valueAt(i);
- dump += StringPrintf(INDENT2 "%zu: originalKeyCode=%d, deviceId=%d, newKeyCode=%d\n", i,
- replacement.keyCode, replacement.deviceId, newKeyCode);
+ dump += StringPrintf(INDENT2 "%zu: originalKeyCode=%d, deviceId=%d, newKeyCode=%d\n",
+ i, replacement.keyCode, replacement.deviceId, newKeyCode);
}
} else {
dump += INDENT "ReplacedKeys: <empty>\n";
@@ -3754,22 +3758,22 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
dump += StringPrintf(INDENT2 "%zu: channelName='%s', windowName='%s', "
- "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
- i, connection->getInputChannelName().c_str(),
- connection->getWindowName().c_str(), connection->getStatusLabel(),
- toString(connection->monitor),
- toString(connection->inputPublisherBlocked));
+ "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
+ i, connection->getInputChannelName().c_str(),
+ connection->getWindowName().c_str(),
+ connection->getStatusLabel(), toString(connection->monitor),
+ toString(connection->inputPublisherBlocked));
if (!connection->outboundQueue.isEmpty()) {
dump += StringPrintf(INDENT3 "OutboundQueue: length=%u\n",
- connection->outboundQueue.count());
+ connection->outboundQueue.count());
for (DispatchEntry* entry = connection->outboundQueue.head; entry;
- entry = entry->next) {
+ entry = entry->next) {
dump.append(INDENT4);
entry->eventEntry->appendDescription(dump);
dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, age=%0.1fms\n",
- entry->targetFlags, entry->resolvedAction,
- (currentTime - entry->eventEntry->eventTime) * 0.000001f);
+ entry->targetFlags, entry->resolvedAction,
+ (currentTime - entry->eventEntry->eventTime) * 0.000001f);
}
} else {
dump += INDENT3 "OutboundQueue: <empty>\n";
@@ -3777,16 +3781,16 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
if (!connection->waitQueue.isEmpty()) {
dump += StringPrintf(INDENT3 "WaitQueue: length=%u\n",
- connection->waitQueue.count());
+ connection->waitQueue.count());
for (DispatchEntry* entry = connection->waitQueue.head; entry;
- entry = entry->next) {
+ entry = entry->next) {
dump += INDENT4;
entry->eventEntry->appendDescription(dump);
dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, "
- "age=%0.1fms, wait=%0.1fms\n",
- entry->targetFlags, entry->resolvedAction,
- (currentTime - entry->eventEntry->eventTime) * 0.000001f,
- (currentTime - entry->deliveryTime) * 0.000001f);
+ "age=%0.1fms, wait=%0.1fms\n",
+ entry->targetFlags, entry->resolvedAction,
+ (currentTime - entry->eventEntry->eventTime) * 0.000001f,
+ (currentTime - entry->deliveryTime) * 0.000001f);
}
} else {
dump += INDENT3 "WaitQueue: <empty>\n";
@@ -3798,15 +3802,16 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
if (isAppSwitchPendingLocked()) {
dump += StringPrintf(INDENT "AppSwitch: pending, due in %0.1fms\n",
- (mAppSwitchDueTime - now()) / 1000000.0);
+ (mAppSwitchDueTime - now()) / 1000000.0);
} else {
dump += INDENT "AppSwitch: not pending\n";
}
dump += INDENT "Configuration:\n";
- dump += StringPrintf(INDENT2 "KeyRepeatDelay: %0.1fms\n", mConfig.keyRepeatDelay * 0.000001f);
+ dump += StringPrintf(INDENT2 "KeyRepeatDelay: %0.1fms\n",
+ mConfig.keyRepeatDelay * 0.000001f);
dump += StringPrintf(INDENT2 "KeyRepeatTimeout: %0.1fms\n",
- mConfig.keyRepeatTimeout * 0.000001f);
+ mConfig.keyRepeatTimeout * 0.000001f);
}
void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) {
@@ -3820,10 +3825,10 @@ void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>
}
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
- int32_t displayId) {
+ int32_t displayId) {
#if DEBUG_REGISTRATION
ALOGD("channel '%s' ~ registerInputChannel - displayId=%" PRId32,
- inputChannel->getName().c_str(), displayId);
+ inputChannel->getName().c_str(), displayId);
#endif
{ // acquire lock
@@ -3831,7 +3836,7 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
if (getConnectionIndexLocked(inputChannel) >= 0) {
ALOGW("Attempted to register already registered input channel '%s'",
- inputChannel->getName().c_str());
+ inputChannel->getName().c_str());
return BAD_VALUE;
}
@@ -3850,7 +3855,7 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
}
status_t InputDispatcher::registerInputMonitor(const sp<InputChannel>& inputChannel,
- int32_t displayId, bool isGestureMonitor) {
+ int32_t displayId, bool isGestureMonitor) {
{ // acquire lock
std::scoped_lock _l(mLock);
@@ -3870,11 +3875,13 @@ status_t InputDispatcher::registerInputMonitor(const sp<InputChannel>& inputChan
mConnectionsByFd.add(fd, connection);
mInputChannelsByToken[inputChannel->getToken()] = inputChannel;
- auto& monitorsByDisplay =
- isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay;
+ auto& monitorsByDisplay = isGestureMonitor
+ ? mGestureMonitorsByDisplay
+ : mGlobalMonitorsByDisplay;
monitorsByDisplay[displayId].emplace_back(inputChannel);
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
+
}
// Wake the looper because some connections have changed.
mLooper->wake();
@@ -3902,11 +3909,11 @@ status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputCh
}
status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,
- bool notify) {
+ bool notify) {
ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
if (connectionIndex < 0) {
ALOGW("Attempted to unregister already unregistered input channel '%s'",
- inputChannel->getName().c_str());
+ inputChannel->getName().c_str());
return BAD_VALUE;
}
@@ -3933,17 +3940,16 @@ void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputCh
removeMonitorChannelLocked(inputChannel, mGestureMonitorsByDisplay);
}
-void InputDispatcher::removeMonitorChannelLocked(
- const sp<InputChannel>& inputChannel,
+void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel,
std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) {
- for (auto it = monitorsByDisplay.begin(); it != monitorsByDisplay.end();) {
+ for (auto it = monitorsByDisplay.begin(); it != monitorsByDisplay.end(); ) {
std::vector<Monitor>& monitors = it->second;
const size_t numMonitors = monitors.size();
for (size_t i = 0; i < numMonitors; i++) {
- if (monitors[i].inputChannel == inputChannel) {
- monitors.erase(monitors.begin() + i);
- break;
- }
+ if (monitors[i].inputChannel == inputChannel) {
+ monitors.erase(monitors.begin() + i);
+ break;
+ }
}
if (monitors.empty()) {
it = monitorsByDisplay.erase(it);
@@ -3979,14 +3985,14 @@ status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) {
}
if (!foundDeviceId || !state.down) {
ALOGW("Attempted to pilfer points from a monitor without any on-going pointer streams."
- " Ignoring.");
+ " Ignoring.");
return BAD_VALUE;
}
int32_t deviceId = foundDeviceId.value();
// Send cancel events to all the input channels we're stealing from.
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "gesture monitor stole pointer stream");
+ "gesture monitor stole pointer stream");
options.deviceId = deviceId;
options.displayId = displayId;
for (const TouchedWindow& window : state.windows) {
@@ -3999,6 +4005,7 @@ status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) {
return OK;
}
+
std::optional<int32_t> InputDispatcher::findGestureMonitorDisplayByTokenLocked(
const sp<IBinder>& token) {
for (const auto& it : mGestureMonitorsByDisplay) {
@@ -4027,47 +4034,46 @@ ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputC
return -1;
}
-void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime,
- const sp<Connection>& connection, uint32_t seq,
- bool handled) {
- CommandEntry* commandEntry =
- postCommandLocked(&InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
+void InputDispatcher::onDispatchCycleFinishedLocked(
+ nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
+ CommandEntry* commandEntry = postCommandLocked(
+ & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
commandEntry->connection = connection;
commandEntry->eventTime = currentTime;
commandEntry->seq = seq;
commandEntry->handled = handled;
}
-void InputDispatcher::onDispatchCycleBrokenLocked(nsecs_t currentTime,
- const sp<Connection>& connection) {
+void InputDispatcher::onDispatchCycleBrokenLocked(
+ nsecs_t currentTime, const sp<Connection>& connection) {
ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
- connection->getInputChannelName().c_str());
+ connection->getInputChannelName().c_str());
- CommandEntry* commandEntry =
- postCommandLocked(&InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
+ CommandEntry* commandEntry = postCommandLocked(
+ & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
commandEntry->connection = connection;
}
void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
- const sp<InputWindowHandle>& newFocus) {
+ const sp<InputWindowHandle>& newFocus) {
sp<IBinder> oldToken = oldFocus != nullptr ? oldFocus->getToken() : nullptr;
sp<IBinder> newToken = newFocus != nullptr ? newFocus->getToken() : nullptr;
- CommandEntry* commandEntry =
- postCommandLocked(&InputDispatcher::doNotifyFocusChangedLockedInterruptible);
+ CommandEntry* commandEntry = postCommandLocked(
+ & InputDispatcher::doNotifyFocusChangedLockedInterruptible);
commandEntry->oldToken = oldToken;
commandEntry->newToken = newToken;
}
-void InputDispatcher::onANRLocked(nsecs_t currentTime,
- const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime,
- nsecs_t waitStartTime, const char* reason) {
+void InputDispatcher::onANRLocked(
+ nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle,
+ nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) {
float dispatchLatency = (currentTime - eventTime) * 0.000001f;
float waitDuration = (currentTime - waitStartTime) * 0.000001f;
ALOGI("Application is not responding: %s. "
- "It has been %0.1fms since event, %0.1fms since wait started. Reason: %s",
- getApplicationWindowLabel(applicationHandle, windowHandle).c_str(), dispatchLatency,
- waitDuration, reason);
+ "It has been %0.1fms since event, %0.1fms since wait started. Reason: %s",
+ getApplicationWindowLabel(applicationHandle, windowHandle).c_str(),
+ dispatchLatency, waitDuration, reason);
// Capture a record of the InputDispatcher state at the time of the ANR.
time_t t = time(nullptr);
@@ -4078,23 +4084,23 @@ void InputDispatcher::onANRLocked(nsecs_t currentTime,
mLastANRState.clear();
mLastANRState += INDENT "ANR:\n";
mLastANRState += StringPrintf(INDENT2 "Time: %s\n", timestr);
- mLastANRState +=
- StringPrintf(INDENT2 "Window: %s\n",
- getApplicationWindowLabel(applicationHandle, windowHandle).c_str());
+ mLastANRState += StringPrintf(INDENT2 "Window: %s\n",
+ getApplicationWindowLabel(applicationHandle, windowHandle).c_str());
mLastANRState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
mLastANRState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
mLastANRState += StringPrintf(INDENT2 "Reason: %s\n", reason);
dumpDispatchStateLocked(mLastANRState);
- CommandEntry* commandEntry =
- postCommandLocked(&InputDispatcher::doNotifyANRLockedInterruptible);
+ CommandEntry* commandEntry = postCommandLocked(
+ & InputDispatcher::doNotifyANRLockedInterruptible);
commandEntry->inputApplicationHandle = applicationHandle;
- commandEntry->inputChannel =
- windowHandle != nullptr ? getInputChannelLocked(windowHandle->getToken()) : nullptr;
+ commandEntry->inputChannel = windowHandle != nullptr ?
+ getInputChannelLocked(windowHandle->getToken()) : nullptr;
commandEntry->reason = reason;
}
-void InputDispatcher::doNotifyConfigurationChangedLockedInterruptible(CommandEntry* commandEntry) {
+void InputDispatcher::doNotifyConfigurationChangedLockedInterruptible (
+ CommandEntry* commandEntry) {
mLock.unlock();
mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
@@ -4102,7 +4108,8 @@ void InputDispatcher::doNotifyConfigurationChangedLockedInterruptible(CommandEnt
mLock.lock();
}
-void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) {
+void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
+ CommandEntry* commandEntry) {
sp<Connection> connection = commandEntry->connection;
if (connection->status != Connection::STATUS_ZOMBIE) {
@@ -4114,7 +4121,8 @@ void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(CommandEntry
}
}
-void InputDispatcher::doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) {
+void InputDispatcher::doNotifyFocusChangedLockedInterruptible(
+ CommandEntry* commandEntry) {
sp<IBinder> oldToken = commandEntry->oldToken;
sp<IBinder> newToken = commandEntry->newToken;
mLock.unlock();
@@ -4122,18 +4130,19 @@ void InputDispatcher::doNotifyFocusChangedLockedInterruptible(CommandEntry* comm
mLock.lock();
}
-void InputDispatcher::doNotifyANRLockedInterruptible(CommandEntry* commandEntry) {
+void InputDispatcher::doNotifyANRLockedInterruptible(
+ CommandEntry* commandEntry) {
mLock.unlock();
- nsecs_t newTimeout =
- mPolicy->notifyANR(commandEntry->inputApplicationHandle,
- commandEntry->inputChannel ? commandEntry->inputChannel->getToken()
- : nullptr,
- commandEntry->reason);
+ nsecs_t newTimeout = mPolicy->notifyANR(
+ commandEntry->inputApplicationHandle,
+ commandEntry->inputChannel ? commandEntry->inputChannel->getToken() : nullptr,
+ commandEntry->reason);
mLock.lock();
- resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
+ resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
+ commandEntry->inputChannel);
}
void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
@@ -4146,13 +4155,13 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
mLock.unlock();
android::base::Timer t;
- sp<IBinder> token = commandEntry->inputChannel != nullptr
- ? commandEntry->inputChannel->getToken()
- : nullptr;
- nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token, &event, entry->policyFlags);
+ sp<IBinder> token = commandEntry->inputChannel != nullptr ?
+ commandEntry->inputChannel->getToken() : nullptr;
+ nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token,
+ &event, entry->policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
- std::to_string(t.duration().count()).c_str());
+ std::to_string(t.duration().count()).c_str());
}
mLock.lock();
@@ -4174,7 +4183,8 @@ void InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible(CommandEntr
mLock.lock();
}
-void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) {
+void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
+ CommandEntry* commandEntry) {
sp<Connection> connection = commandEntry->connection;
nsecs_t finishTime = commandEntry->eventTime;
uint32_t seq = commandEntry->seq;
@@ -4187,7 +4197,7 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c
if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
std::string msg =
StringPrintf("Window '%s' spent %0.1fms processing the last input event: ",
- connection->getWindowName().c_str(), eventDuration * 0.000001f);
+ connection->getWindowName().c_str(), eventDuration * 0.000001f);
dispatchEntry->eventEntry->appendDescription(msg);
ALOGI("%s", msg.c_str());
}
@@ -4195,12 +4205,12 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c
bool restartEvent;
if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
- restartEvent =
- afterKeyEventLockedInterruptible(connection, dispatchEntry, keyEntry, handled);
+ restartEvent = afterKeyEventLockedInterruptible(connection,
+ dispatchEntry, keyEntry, handled);
} else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
- restartEvent = afterMotionEventLockedInterruptible(connection, dispatchEntry,
- motionEntry, handled);
+ restartEvent = afterMotionEventLockedInterruptible(connection,
+ dispatchEntry, motionEntry, handled);
} else {
restartEvent = false;
}
@@ -4226,8 +4236,7 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c
}
bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry,
- KeyEntry* keyEntry, bool handled) {
+ DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
if (keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK) {
if (!handled) {
// Report the key as unhandled, since the fallback was not handled.
@@ -4252,9 +4261,9 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con
// Dispatch the unhandled key to the policy with the cancel flag.
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: Asking policy to cancel fallback action. "
- "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
- keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
- keyEntry->policyFlags);
+ "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
+ keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
+ keyEntry->policyFlags);
#endif
KeyEvent event;
initializeKeyEvent(&event, keyEntry);
@@ -4262,8 +4271,8 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con
mLock.unlock();
- mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(), &event,
- keyEntry->policyFlags, &event);
+ mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
+ &event, keyEntry->policyFlags, &event);
mLock.lock();
@@ -4282,13 +4291,15 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con
// If the application did not handle a non-fallback key, first check
// that we are in a good state to perform unhandled key event processing
// Then ask the policy what to do with it.
- bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN && keyEntry->repeatCount == 0;
+ bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN
+ && keyEntry->repeatCount == 0;
if (fallbackKeyCode == -1 && !initialDown) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: Skipping unhandled key event processing "
- "since this is not an initial down. "
- "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
- originalKeyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags);
+ "since this is not an initial down. "
+ "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
+ originalKeyCode, keyEntry->action, keyEntry->repeatCount,
+ keyEntry->policyFlags);
#endif
return false;
}
@@ -4296,16 +4307,17 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con
// Dispatch the unhandled key to the policy.
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: Asking policy to perform fallback action. "
- "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
- keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags);
+ "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
+ keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
+ keyEntry->policyFlags);
#endif
KeyEvent event;
initializeKeyEvent(&event, keyEntry);
mLock.unlock();
- bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(), &event,
- keyEntry->policyFlags, &event);
+ bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
+ &event, keyEntry->policyFlags, &event);
mLock.lock();
@@ -4330,19 +4342,19 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con
// Cancel the fallback key if the policy decides not to send it anymore.
// We will continue to dispatch the key to the policy but we will no
// longer dispatch a fallback key to the application.
- if (fallbackKeyCode != AKEYCODE_UNKNOWN &&
- (!fallback || fallbackKeyCode != event.getKeyCode())) {
+ if (fallbackKeyCode != AKEYCODE_UNKNOWN
+ && (!fallback || fallbackKeyCode != event.getKeyCode())) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
if (fallback) {
ALOGD("Unhandled key event: Policy requested to send key %d"
- "as a fallback for %d, but on the DOWN it had requested "
- "to send %d instead. Fallback canceled.",
- event.getKeyCode(), originalKeyCode, fallbackKeyCode);
+ "as a fallback for %d, but on the DOWN it had requested "
+ "to send %d instead. Fallback canceled.",
+ event.getKeyCode(), originalKeyCode, fallbackKeyCode);
} else {
ALOGD("Unhandled key event: Policy did not request fallback for %d, "
- "but on the DOWN it had requested to send %d. "
- "Fallback canceled.",
- originalKeyCode, fallbackKeyCode);
+ "but on the DOWN it had requested to send %d. "
+ "Fallback canceled.",
+ originalKeyCode, fallbackKeyCode);
}
#endif
@@ -4354,7 +4366,8 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con
fallback = false;
fallbackKeyCode = AKEYCODE_UNKNOWN;
if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
- connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
+ connection->inputState.setFallbackKey(originalKeyCode,
+ fallbackKeyCode);
}
}
@@ -4364,10 +4377,11 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con
const KeyedVector<int32_t, int32_t>& fallbackKeys =
connection->inputState.getFallbackKeys();
for (size_t i = 0; i < fallbackKeys.size(); i++) {
- msg += StringPrintf(", %d->%d", fallbackKeys.keyAt(i), fallbackKeys.valueAt(i));
+ msg += StringPrintf(", %d->%d", fallbackKeys.keyAt(i),
+ fallbackKeys.valueAt(i));
}
ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
- fallbackKeys.size(), msg.c_str());
+ fallbackKeys.size(), msg.c_str());
}
#endif
@@ -4387,8 +4401,8 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: Dispatching fallback key. "
- "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
- originalKeyCode, fallbackKeyCode, keyEntry->metaState);
+ "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
+ originalKeyCode, fallbackKeyCode, keyEntry->metaState);
#endif
return true; // restart the event
} else {
@@ -4404,8 +4418,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con
}
bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry,
- MotionEntry* motionEntry, bool handled) {
+ DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) {
return false;
}
@@ -4419,13 +4432,12 @@ void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* comman
void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
event->initialize(entry->deviceId, entry->source, entry->displayId, entry->action, entry->flags,
- entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
- entry->downTime, entry->eventTime);
+ entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
+ entry->downTime, entry->eventTime);
}
void InputDispatcher::updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
- int32_t injectionResult,
- nsecs_t timeSpentWaitingForApplication) {
+ int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
// TODO Write some statistics about how long we spend waiting.
}
@@ -4470,4 +4482,762 @@ void InputDispatcher::monitor() {
mDispatcherIsAlive.wait(_l);
}
-} // namespace android::inputdispatcher
+
+// --- InputDispatcher::InjectionState ---
+
+InputDispatcher::InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid) :
+ refCount(1),
+ injectorPid(injectorPid), injectorUid(injectorUid),
+ injectionResult(INPUT_EVENT_INJECTION_PENDING), injectionIsAsync(false),
+ pendingForegroundDispatches(0) {
+}
+
+InputDispatcher::InjectionState::~InjectionState() {
+}
+
+void InputDispatcher::InjectionState::release() {
+ refCount -= 1;
+ if (refCount == 0) {
+ delete this;
+ } else {
+ ALOG_ASSERT(refCount > 0);
+ }
+}
+
+
+// --- InputDispatcher::EventEntry ---
+
+InputDispatcher::EventEntry::EventEntry(uint32_t sequenceNum, int32_t type,
+ nsecs_t eventTime, uint32_t policyFlags) :
+ sequenceNum(sequenceNum), refCount(1), type(type), eventTime(eventTime),
+ policyFlags(policyFlags), injectionState(nullptr), dispatchInProgress(false) {
+}
+
+InputDispatcher::EventEntry::~EventEntry() {
+ releaseInjectionState();
+}
+
+void InputDispatcher::EventEntry::release() {
+ refCount -= 1;
+ if (refCount == 0) {
+ delete this;
+ } else {
+ ALOG_ASSERT(refCount > 0);
+ }
+}
+
+void InputDispatcher::EventEntry::releaseInjectionState() {
+ if (injectionState) {
+ injectionState->release();
+ injectionState = nullptr;
+ }
+}
+
+
+// --- InputDispatcher::ConfigurationChangedEntry ---
+
+InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(
+ uint32_t sequenceNum, nsecs_t eventTime) :
+ EventEntry(sequenceNum, TYPE_CONFIGURATION_CHANGED, eventTime, 0) {
+}
+
+InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
+}
+
+void InputDispatcher::ConfigurationChangedEntry::appendDescription(std::string& msg) const {
+ msg += StringPrintf("ConfigurationChangedEvent(), policyFlags=0x%08x", policyFlags);
+}
+
+
+// --- InputDispatcher::DeviceResetEntry ---
+
+InputDispatcher::DeviceResetEntry::DeviceResetEntry(
+ uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId) :
+ EventEntry(sequenceNum, TYPE_DEVICE_RESET, eventTime, 0),
+ deviceId(deviceId) {
+}
+
+InputDispatcher::DeviceResetEntry::~DeviceResetEntry() {
+}
+
+void InputDispatcher::DeviceResetEntry::appendDescription(std::string& msg) const {
+ msg += StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x",
+ deviceId, policyFlags);
+}
+
+
+// --- InputDispatcher::KeyEntry ---
+
+InputDispatcher::KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime,
+ int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
+ int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
+ int32_t repeatCount, nsecs_t downTime) :
+ EventEntry(sequenceNum, TYPE_KEY, eventTime, policyFlags),
+ deviceId(deviceId), source(source), displayId(displayId), action(action), flags(flags),
+ keyCode(keyCode), scanCode(scanCode), metaState(metaState),
+ repeatCount(repeatCount), downTime(downTime),
+ syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN),
+ interceptKeyWakeupTime(0) {
+}
+
+InputDispatcher::KeyEntry::~KeyEntry() {
+}
+
+void InputDispatcher::KeyEntry::appendDescription(std::string& msg) const {
+ msg += StringPrintf("KeyEvent");
+}
+
+void InputDispatcher::KeyEntry::recycle() {
+ releaseInjectionState();
+
+ dispatchInProgress = false;
+ syntheticRepeat = false;
+ interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
+ interceptKeyWakeupTime = 0;
+}
+
+
+// --- InputDispatcher::MotionEntry ---
+
+InputDispatcher::MotionEntry::MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
+ uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
+ int32_t actionButton,
+ int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
+ int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime,
+ uint32_t pointerCount,
+ const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+ float xOffset, float yOffset) :
+ EventEntry(sequenceNum, TYPE_MOTION, eventTime, policyFlags),
+ eventTime(eventTime),
+ deviceId(deviceId), source(source), displayId(displayId), action(action),
+ actionButton(actionButton), flags(flags), metaState(metaState), buttonState(buttonState),
+ classification(classification), edgeFlags(edgeFlags),
+ xPrecision(xPrecision), yPrecision(yPrecision),
+ downTime(downTime), pointerCount(pointerCount) {
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ this->pointerProperties[i].copyFrom(pointerProperties[i]);
+ this->pointerCoords[i].copyFrom(pointerCoords[i]);
+ if (xOffset || yOffset) {
+ this->pointerCoords[i].applyOffset(xOffset, yOffset);
+ }
+ }
+}
+
+InputDispatcher::MotionEntry::~MotionEntry() {
+}
+
+void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const {
+ msg += StringPrintf("MotionEvent");
+}
+
+
+// --- InputDispatcher::DispatchEntry ---
+
+volatile int32_t InputDispatcher::DispatchEntry::sNextSeqAtomic;
+
+InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry,
+ int32_t targetFlags, float xOffset, float yOffset, float globalScaleFactor,
+ float windowXScale, float windowYScale) :
+ seq(nextSeq()),
+ eventEntry(eventEntry), targetFlags(targetFlags),
+ xOffset(xOffset), yOffset(yOffset), globalScaleFactor(globalScaleFactor),
+ windowXScale(windowXScale), windowYScale(windowYScale),
+ deliveryTime(0), resolvedAction(0), resolvedFlags(0) {
+ eventEntry->refCount += 1;
+}
+
+InputDispatcher::DispatchEntry::~DispatchEntry() {
+ eventEntry->release();
+}
+
+uint32_t InputDispatcher::DispatchEntry::nextSeq() {
+ // Sequence number 0 is reserved and will never be returned.
+ uint32_t seq;
+ do {
+ seq = android_atomic_inc(&sNextSeqAtomic);
+ } while (!seq);
+ return seq;
+}
+
+
+// --- InputDispatcher::InputState ---
+
+InputDispatcher::InputState::InputState() {
+}
+
+InputDispatcher::InputState::~InputState() {
+}
+
+bool InputDispatcher::InputState::isNeutral() const {
+ return mKeyMementos.empty() && mMotionMementos.empty();
+}
+
+bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source,
+ int32_t displayId) const {
+ for (const MotionMemento& memento : mMotionMementos) {
+ if (memento.deviceId == deviceId
+ && memento.source == source
+ && memento.displayId == displayId
+ && memento.hovering) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool InputDispatcher::InputState::trackKey(const KeyEntry* entry,
+ int32_t action, int32_t flags) {
+ switch (action) {
+ case AKEY_EVENT_ACTION_UP: {
+ if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+ for (size_t i = 0; i < mFallbackKeys.size(); ) {
+ if (mFallbackKeys.valueAt(i) == entry->keyCode) {
+ mFallbackKeys.removeItemsAt(i);
+ } else {
+ i += 1;
+ }
+ }
+ }
+ ssize_t index = findKeyMemento(entry);
+ if (index >= 0) {
+ mKeyMementos.erase(mKeyMementos.begin() + index);
+ return true;
+ }
+ /* FIXME: We can't just drop the key up event because that prevents creating
+ * popup windows that are automatically shown when a key is held and then
+ * dismissed when the key is released. The problem is that the popup will
+ * not have received the original key down, so the key up will be considered
+ * to be inconsistent with its observed state. We could perhaps handle this
+ * by synthesizing a key down but that will cause other problems.
+ *
+ * So for now, allow inconsistent key up events to be dispatched.
+ *
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
+ "keyCode=%d, scanCode=%d",
+ entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
+#endif
+ return false;
+ */
+ return true;
+ }
+
+ case AKEY_EVENT_ACTION_DOWN: {
+ ssize_t index = findKeyMemento(entry);
+ if (index >= 0) {
+ mKeyMementos.erase(mKeyMementos.begin() + index);
+ }
+ addKeyMemento(entry, flags);
+ return true;
+ }
+
+ default:
+ return true;
+ }
+}
+
+bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
+ int32_t action, int32_t flags) {
+ int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
+ switch (actionMasked) {
+ case AMOTION_EVENT_ACTION_UP:
+ case AMOTION_EVENT_ACTION_CANCEL: {
+ ssize_t index = findMotionMemento(entry, false /*hovering*/);
+ if (index >= 0) {
+ mMotionMementos.erase(mMotionMementos.begin() + index);
+ return true;
+ }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
+ "displayId=%" PRId32 ", actionMasked=%d",
+ entry->deviceId, entry->source, entry->displayId, actionMasked);
+#endif
+ return false;
+ }
+
+ case AMOTION_EVENT_ACTION_DOWN: {
+ ssize_t index = findMotionMemento(entry, false /*hovering*/);
+ if (index >= 0) {
+ mMotionMementos.erase(mMotionMementos.begin() + index);
+ }
+ addMotionMemento(entry, flags, false /*hovering*/);
+ return true;
+ }
+
+ case AMOTION_EVENT_ACTION_POINTER_UP:
+ case AMOTION_EVENT_ACTION_POINTER_DOWN:
+ case AMOTION_EVENT_ACTION_MOVE: {
+ if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) {
+ // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need to
+ // generate cancellation events for these since they're based in relative rather than
+ // absolute units.
+ return true;
+ }
+
+ ssize_t index = findMotionMemento(entry, false /*hovering*/);
+
+ if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) {
+ // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
+ // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral. Any
+ // other value and we need to track the motion so we can send cancellation events for
+ // anything generating fallback events (e.g. DPad keys for joystick movements).
+ if (index >= 0) {
+ if (entry->pointerCoords[0].isEmpty()) {
+ mMotionMementos.erase(mMotionMementos.begin() + index);
+ } else {
+ MotionMemento& memento = mMotionMementos[index];
+ memento.setPointers(entry);
+ }
+ } else if (!entry->pointerCoords[0].isEmpty()) {
+ addMotionMemento(entry, flags, false /*hovering*/);
+ }
+
+ // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
+ return true;
+ }
+ if (index >= 0) {
+ MotionMemento& memento = mMotionMementos[index];
+ memento.setPointers(entry);
+ return true;
+ }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ ALOGD("Dropping inconsistent motion pointer up/down or move event: "
+ "deviceId=%d, source=%08x, displayId=%" PRId32 ", actionMasked=%d",
+ entry->deviceId, entry->source, entry->displayId, actionMasked);
+#endif
+ return false;
+ }
+
+ case AMOTION_EVENT_ACTION_HOVER_EXIT: {
+ ssize_t index = findMotionMemento(entry, true /*hovering*/);
+ if (index >= 0) {
+ mMotionMementos.erase(mMotionMementos.begin() + index);
+ return true;
+ }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x, "
+ "displayId=%" PRId32,
+ entry->deviceId, entry->source, entry->displayId);
+#endif
+ return false;
+ }
+
+ case AMOTION_EVENT_ACTION_HOVER_ENTER:
+ case AMOTION_EVENT_ACTION_HOVER_MOVE: {
+ ssize_t index = findMotionMemento(entry, true /*hovering*/);
+ if (index >= 0) {
+ mMotionMementos.erase(mMotionMementos.begin() + index);
+ }
+ addMotionMemento(entry, flags, true /*hovering*/);
+ return true;
+ }
+
+ default:
+ return true;
+ }
+}
+
+ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const {
+ for (size_t i = 0; i < mKeyMementos.size(); i++) {
+ const KeyMemento& memento = mKeyMementos[i];
+ if (memento.deviceId == entry->deviceId
+ && memento.source == entry->source
+ && memento.displayId == entry->displayId
+ && memento.keyCode == entry->keyCode
+ && memento.scanCode == entry->scanCode) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry,
+ bool hovering) const {
+ for (size_t i = 0; i < mMotionMementos.size(); i++) {
+ const MotionMemento& memento = mMotionMementos[i];
+ if (memento.deviceId == entry->deviceId
+ && memento.source == entry->source
+ && memento.displayId == entry->displayId
+ && memento.hovering == hovering) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) {
+ KeyMemento memento;
+ memento.deviceId = entry->deviceId;
+ memento.source = entry->source;
+ memento.displayId = entry->displayId;
+ memento.keyCode = entry->keyCode;
+ memento.scanCode = entry->scanCode;
+ memento.metaState = entry->metaState;
+ memento.flags = flags;
+ memento.downTime = entry->downTime;
+ memento.policyFlags = entry->policyFlags;
+ mKeyMementos.push_back(memento);
+}
+
+void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry,
+ int32_t flags, bool hovering) {
+ MotionMemento memento;
+ memento.deviceId = entry->deviceId;
+ memento.source = entry->source;
+ memento.displayId = entry->displayId;
+ memento.flags = flags;
+ memento.xPrecision = entry->xPrecision;
+ memento.yPrecision = entry->yPrecision;
+ memento.downTime = entry->downTime;
+ memento.setPointers(entry);
+ memento.hovering = hovering;
+ memento.policyFlags = entry->policyFlags;
+ mMotionMementos.push_back(memento);
+}
+
+void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
+ pointerCount = entry->pointerCount;
+ for (uint32_t i = 0; i < entry->pointerCount; i++) {
+ pointerProperties[i].copyFrom(entry->pointerProperties[i]);
+ pointerCoords[i].copyFrom(entry->pointerCoords[i]);
+ }
+}
+
+void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
+ std::vector<EventEntry*>& outEvents, const CancelationOptions& options) {
+ for (KeyMemento& memento : mKeyMementos) {
+ if (shouldCancelKey(memento, options)) {
+ outEvents.push_back(new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
+ memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
+ AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
+ memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime));
+ }
+ }
+
+ for (const MotionMemento& memento : mMotionMementos) {
+ if (shouldCancelMotion(memento, options)) {
+ const int32_t action = memento.hovering ?
+ AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
+ outEvents.push_back(new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
+ memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
+ action, 0 /*actionButton*/, memento.flags, AMETA_NONE, 0 /*buttonState*/,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ memento.xPrecision, memento.yPrecision, memento.downTime,
+ memento.pointerCount, memento.pointerProperties, memento.pointerCoords,
+ 0 /*xOffset*/, 0 /*yOffset*/));
+ }
+ }
+}
+
+void InputDispatcher::InputState::clear() {
+ mKeyMementos.clear();
+ mMotionMementos.clear();
+ mFallbackKeys.clear();
+}
+
+void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
+ for (size_t i = 0; i < mMotionMementos.size(); i++) {
+ const MotionMemento& memento = mMotionMementos[i];
+ if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
+ for (size_t j = 0; j < other.mMotionMementos.size(); ) {
+ const MotionMemento& otherMemento = other.mMotionMementos[j];
+ if (memento.deviceId == otherMemento.deviceId
+ && memento.source == otherMemento.source
+ && memento.displayId == otherMemento.displayId) {
+ other.mMotionMementos.erase(other.mMotionMementos.begin() + j);
+ } else {
+ j += 1;
+ }
+ }
+ other.mMotionMementos.push_back(memento);
+ }
+ }
+}
+
+int32_t InputDispatcher::InputState::getFallbackKey(int32_t originalKeyCode) {
+ ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
+ return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
+}
+
+void InputDispatcher::InputState::setFallbackKey(int32_t originalKeyCode,
+ int32_t fallbackKeyCode) {
+ ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
+ if (index >= 0) {
+ mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
+ } else {
+ mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
+ }
+}
+
+void InputDispatcher::InputState::removeFallbackKey(int32_t originalKeyCode) {
+ mFallbackKeys.removeItem(originalKeyCode);
+}
+
+bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
+ const CancelationOptions& options) {
+ if (options.keyCode && memento.keyCode != options.keyCode.value()) {
+ return false;
+ }
+
+ if (options.deviceId && memento.deviceId != options.deviceId.value()) {
+ return false;
+ }
+
+ if (options.displayId && memento.displayId != options.displayId.value()) {
+ return false;
+ }
+
+ switch (options.mode) {
+ case CancelationOptions::CANCEL_ALL_EVENTS:
+ case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
+ return true;
+ case CancelationOptions::CANCEL_FALLBACK_EVENTS:
+ return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
+ default:
+ return false;
+ }
+}
+
+bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
+ const CancelationOptions& options) {
+ if (options.deviceId && memento.deviceId != options.deviceId.value()) {
+ return false;
+ }
+
+ if (options.displayId && memento.displayId != options.displayId.value()) {
+ return false;
+ }
+
+ switch (options.mode) {
+ case CancelationOptions::CANCEL_ALL_EVENTS:
+ return true;
+ case CancelationOptions::CANCEL_POINTER_EVENTS:
+ return memento.source & AINPUT_SOURCE_CLASS_POINTER;
+ case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
+ return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
+ default:
+ return false;
+ }
+}
+
+
+// --- InputDispatcher::Connection ---
+
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor) :
+ status(STATUS_NORMAL), inputChannel(inputChannel),
+ monitor(monitor),
+ inputPublisher(inputChannel), inputPublisherBlocked(false) {
+}
+
+InputDispatcher::Connection::~Connection() {
+}
+
+const std::string InputDispatcher::Connection::getWindowName() const {
+ if (inputChannel != nullptr) {
+ return inputChannel->getName();
+ }
+ if (monitor) {
+ return "monitor";
+ }
+ return "?";
+}
+
+const char* InputDispatcher::Connection::getStatusLabel() const {
+ switch (status) {
+ case STATUS_NORMAL:
+ return "NORMAL";
+
+ case STATUS_BROKEN:
+ return "BROKEN";
+
+ case STATUS_ZOMBIE:
+ return "ZOMBIE";
+
+ default:
+ return "UNKNOWN";
+ }
+}
+
+InputDispatcher::DispatchEntry* InputDispatcher::Connection::findWaitQueueEntry(uint32_t seq) {
+ for (DispatchEntry* entry = waitQueue.head; entry != nullptr; entry = entry->next) {
+ if (entry->seq == seq) {
+ return entry;
+ }
+ }
+ return nullptr;
+}
+
+// --- InputDispatcher::Monitor
+InputDispatcher::Monitor::Monitor(const sp<InputChannel>& inputChannel) :
+ inputChannel(inputChannel) {
+}
+
+
+// --- InputDispatcher::CommandEntry ---
+//
+InputDispatcher::CommandEntry::CommandEntry(Command command) :
+ command(command), eventTime(0), keyEntry(nullptr), userActivityEventType(0),
+ seq(0), handled(false) {
+}
+
+InputDispatcher::CommandEntry::~CommandEntry() {
+}
+
+// --- InputDispatcher::TouchedMonitor ---
+InputDispatcher::TouchedMonitor::TouchedMonitor(const Monitor& monitor, float xOffset,
+ float yOffset) : monitor(monitor), xOffset(xOffset), yOffset(yOffset) {
+}
+
+// --- InputDispatcher::TouchState ---
+
+InputDispatcher::TouchState::TouchState() :
+ down(false), split(false), deviceId(-1), source(0), displayId(ADISPLAY_ID_NONE) {
+}
+
+InputDispatcher::TouchState::~TouchState() {
+}
+
+void InputDispatcher::TouchState::reset() {
+ down = false;
+ split = false;
+ deviceId = -1;
+ source = 0;
+ displayId = ADISPLAY_ID_NONE;
+ windows.clear();
+ portalWindows.clear();
+ gestureMonitors.clear();
+}
+
+void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
+ down = other.down;
+ split = other.split;
+ deviceId = other.deviceId;
+ source = other.source;
+ displayId = other.displayId;
+ windows = other.windows;
+ portalWindows = other.portalWindows;
+ gestureMonitors = other.gestureMonitors;
+}
+
+void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
+ int32_t targetFlags, BitSet32 pointerIds) {
+ if (targetFlags & InputTarget::FLAG_SPLIT) {
+ split = true;
+ }
+
+ for (size_t i = 0; i < windows.size(); i++) {
+ TouchedWindow& touchedWindow = windows[i];
+ if (touchedWindow.windowHandle == windowHandle) {
+ touchedWindow.targetFlags |= targetFlags;
+ if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+ touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
+ }
+ touchedWindow.pointerIds.value |= pointerIds.value;
+ return;
+ }
+ }
+
+ TouchedWindow touchedWindow;
+ touchedWindow.windowHandle = windowHandle;
+ touchedWindow.targetFlags = targetFlags;
+ touchedWindow.pointerIds = pointerIds;
+ windows.push_back(touchedWindow);
+}
+
+void InputDispatcher::TouchState::addPortalWindow(const sp<InputWindowHandle>& windowHandle) {
+ size_t numWindows = portalWindows.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ if (portalWindows[i] == windowHandle) {
+ return;
+ }
+ }
+ portalWindows.push_back(windowHandle);
+}
+
+void InputDispatcher::TouchState::addGestureMonitors(
+ const std::vector<TouchedMonitor>& newMonitors) {
+ const size_t newSize = gestureMonitors.size() + newMonitors.size();
+ gestureMonitors.reserve(newSize);
+ gestureMonitors.insert(std::end(gestureMonitors),
+ std::begin(newMonitors), std::end(newMonitors));
+}
+
+void InputDispatcher::TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
+ for (size_t i = 0; i < windows.size(); i++) {
+ if (windows[i].windowHandle == windowHandle) {
+ windows.erase(windows.begin() + i);
+ return;
+ }
+ }
+}
+
+void InputDispatcher::TouchState::removeWindowByToken(const sp<IBinder>& token) {
+ for (size_t i = 0; i < windows.size(); i++) {
+ if (windows[i].windowHandle->getToken() == token) {
+ windows.erase(windows.begin() + i);
+ return;
+ }
+ }
+}
+
+void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
+ for (size_t i = 0 ; i < windows.size(); ) {
+ TouchedWindow& window = windows[i];
+ if (window.targetFlags & (InputTarget::FLAG_DISPATCH_AS_IS
+ | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
+ window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
+ window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
+ i += 1;
+ } else {
+ windows.erase(windows.begin() + i);
+ }
+ }
+}
+
+void InputDispatcher::TouchState::filterNonMonitors() {
+ windows.clear();
+ portalWindows.clear();
+}
+
+sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const {
+ for (size_t i = 0; i < windows.size(); i++) {
+ const TouchedWindow& window = windows[i];
+ if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
+ return window.windowHandle;
+ }
+ }
+ return nullptr;
+}
+
+bool InputDispatcher::TouchState::isSlippery() const {
+ // Must have exactly one foreground window.
+ bool haveSlipperyForegroundWindow = false;
+ for (const TouchedWindow& window : windows) {
+ if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
+ if (haveSlipperyForegroundWindow
+ || !(window.windowHandle->getInfo()->layoutParamsFlags
+ & InputWindowInfo::FLAG_SLIPPERY)) {
+ return false;
+ }
+ haveSlipperyForegroundWindow = true;
+ }
+ }
+ return haveSlipperyForegroundWindow;
+}
+
+
+// --- InputDispatcherThread ---
+
+InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
+ Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
+}
+
+InputDispatcherThread::~InputDispatcherThread() {
+}
+
+bool InputDispatcherThread::threadLoop() {
+ mDispatcher->dispatchOnce();
+ return true;
+}
+
+} // namespace android
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
new file mode 100644
index 0000000000..753b748884
--- /dev/null
+++ b/services/inputflinger/InputDispatcher.h
@@ -0,0 +1,1305 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _UI_INPUT_DISPATCHER_H
+#define _UI_INPUT_DISPATCHER_H
+
+#include <condition_variable>
+#include <input/Input.h>
+#include <input/InputApplication.h>
+#include <input/InputTransport.h>
+#include <input/InputWindow.h>
+#include <input/ISetInputWindowsListener.h>
+#include <optional>
+#include <ui/Region.h>
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/Looper.h>
+#include <utils/BitSet.h>
+#include <cutils/atomic.h>
+#include <unordered_map>
+
+#include <stddef.h>
+#include <unistd.h>
+#include <limits.h>
+#include <unordered_map>
+
+#include "InputListener.h"
+#include "InputReporterInterface.h"
+
+namespace android {
+
+/*
+ * Constants used to report the outcome of input event injection.
+ */
+enum {
+ /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */
+ INPUT_EVENT_INJECTION_PENDING = -1,
+
+ /* Injection succeeded. */
+ INPUT_EVENT_INJECTION_SUCCEEDED = 0,
+
+ /* Injection failed because the injector did not have permission to inject
+ * into the application with input focus. */
+ INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,
+
+ /* Injection failed because there were no available input targets. */
+ INPUT_EVENT_INJECTION_FAILED = 2,
+
+ /* Injection failed due to a timeout. */
+ INPUT_EVENT_INJECTION_TIMED_OUT = 3
+};
+
+/*
+ * Constants used to determine the input event injection synchronization mode.
+ */
+enum {
+ /* Injection is asynchronous and is assumed always to be successful. */
+ INPUT_EVENT_INJECTION_SYNC_NONE = 0,
+
+ /* Waits for previous events to be dispatched so that the input dispatcher can determine
+ * whether input event injection willbe permitted based on the current input focus.
+ * Does not wait for the input event to finish processing. */
+ INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1,
+
+ /* Waits for the input event to be completely processed. */
+ INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2,
+};
+
+
+/*
+ * An input target specifies how an input event is to be dispatched to a particular window
+ * including the window's input channel, control flags, a timeout, and an X / Y offset to
+ * be added to input event coordinates to compensate for the absolute position of the
+ * window area.
+ */
+struct InputTarget {
+ enum {
+ /* This flag indicates that the event is being delivered to a foreground application. */
+ FLAG_FOREGROUND = 1 << 0,
+
+ /* This flag indicates that the MotionEvent falls within the area of the target
+ * obscured by another visible window above it. The motion event should be
+ * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
+ FLAG_WINDOW_IS_OBSCURED = 1 << 1,
+
+ /* This flag indicates that a motion event is being split across multiple windows. */
+ FLAG_SPLIT = 1 << 2,
+
+ /* This flag indicates that the pointer coordinates dispatched to the application
+ * will be zeroed out to avoid revealing information to an application. This is
+ * used in conjunction with FLAG_DISPATCH_AS_OUTSIDE to prevent apps not sharing
+ * the same UID from watching all touches. */
+ FLAG_ZERO_COORDS = 1 << 3,
+
+ /* This flag indicates that the event should be sent as is.
+ * Should always be set unless the event is to be transmuted. */
+ FLAG_DISPATCH_AS_IS = 1 << 8,
+
+ /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
+ * of the area of this target and so should instead be delivered as an
+ * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
+ FLAG_DISPATCH_AS_OUTSIDE = 1 << 9,
+
+ /* This flag indicates that a hover sequence is starting in the given window.
+ * The event is transmuted into ACTION_HOVER_ENTER. */
+ FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10,
+
+ /* This flag indicates that a hover event happened outside of a window which handled
+ * previous hover events, signifying the end of the current hover sequence for that
+ * window.
+ * The event is transmuted into ACTION_HOVER_ENTER. */
+ FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11,
+
+ /* This flag indicates that the event should be canceled.
+ * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
+ * outside of a window. */
+ FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,
+
+ /* This flag indicates that the event should be dispatched as an initial down.
+ * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
+ * into a new window. */
+ FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
+
+ /* Mask for all dispatch modes. */
+ FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS
+ | FLAG_DISPATCH_AS_OUTSIDE
+ | FLAG_DISPATCH_AS_HOVER_ENTER
+ | FLAG_DISPATCH_AS_HOVER_EXIT
+ | FLAG_DISPATCH_AS_SLIPPERY_EXIT
+ | FLAG_DISPATCH_AS_SLIPPERY_ENTER,
+
+ /* This flag indicates that the target of a MotionEvent is partly or wholly
+ * obscured by another visible window above it. The motion event should be
+ * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
+ FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
+
+ };
+
+ // The input channel to be targeted.
+ sp<InputChannel> inputChannel;
+
+ // Flags for the input target.
+ int32_t flags;
+
+ // The x and y offset to add to a MotionEvent as it is delivered.
+ // (ignored for KeyEvents)
+ float xOffset, yOffset;
+
+ // Scaling factor to apply to MotionEvent as it is delivered.
+ // (ignored for KeyEvents)
+ float globalScaleFactor;
+ float windowXScale = 1.0f;
+ float windowYScale = 1.0f;
+
+ // The subset of pointer ids to include in motion events dispatched to this input target
+ // if FLAG_SPLIT is set.
+ BitSet32 pointerIds;
+};
+
+
+/*
+ * Input dispatcher configuration.
+ *
+ * Specifies various options that modify the behavior of the input dispatcher.
+ * The values provided here are merely defaults. The actual values will come from ViewConfiguration
+ * and are passed into the dispatcher during initialization.
+ */
+struct InputDispatcherConfiguration {
+ // The key repeat initial timeout.
+ nsecs_t keyRepeatTimeout;
+
+ // The key repeat inter-key delay.
+ nsecs_t keyRepeatDelay;
+
+ InputDispatcherConfiguration() :
+ keyRepeatTimeout(500 * 1000000LL),
+ keyRepeatDelay(50 * 1000000LL) { }
+};
+
+
+/*
+ * Input dispatcher policy interface.
+ *
+ * The input reader policy is used by the input reader to interact with the Window Manager
+ * and other system components.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI. This interface is also mocked in the unit tests.
+ */
+class InputDispatcherPolicyInterface : public virtual RefBase {
+protected:
+ InputDispatcherPolicyInterface() { }
+ virtual ~InputDispatcherPolicyInterface() { }
+
+public:
+ /* Notifies the system that a configuration change has occurred. */
+ virtual void notifyConfigurationChanged(nsecs_t when) = 0;
+
+ /* Notifies the system that an application is not responding.
+ * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
+ virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
+ const sp<IBinder>& token,
+ const std::string& reason) = 0;
+
+ /* Notifies the system that an input channel is unrecoverably broken. */
+ virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
+ virtual void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) = 0;
+
+ /* Gets the input dispatcher configuration. */
+ virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
+
+ /* Filters an input event.
+ * Return true to dispatch the event unmodified, false to consume the event.
+ * A filter can also transform and inject events later by passing POLICY_FLAG_FILTERED
+ * to injectInputEvent.
+ */
+ virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;
+
+ /* Intercepts a key event immediately before queueing it.
+ * The policy can use this method as an opportunity to perform power management functions
+ * and early event preprocessing such as updating policy flags.
+ *
+ * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
+ * should be dispatched to applications.
+ */
+ virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
+
+ /* Intercepts a touch, trackball or other motion event before queueing it.
+ * The policy can use this method as an opportunity to perform power management functions
+ * and early event preprocessing such as updating policy flags.
+ *
+ * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
+ * should be dispatched to applications.
+ */
+ virtual void interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
+ uint32_t& policyFlags) = 0;
+
+ /* Allows the policy a chance to intercept a key before dispatching. */
+ virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token,
+ const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
+
+ /* Allows the policy a chance to perform default processing for an unhandled key.
+ * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
+ virtual bool dispatchUnhandledKey(const sp<IBinder>& token,
+ const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
+
+ /* Notifies the policy about switch events.
+ */
+ virtual void notifySwitch(nsecs_t when,
+ uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) = 0;
+
+ /* Poke user activity for an event dispatched to a window. */
+ virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
+
+ /* Checks whether a given application pid/uid has permission to inject input events
+ * into other applications.
+ *
+ * This method is special in that its implementation promises to be non-reentrant and
+ * is safe to call while holding other locks. (Most other methods make no such guarantees!)
+ */
+ virtual bool checkInjectEventsPermissionNonReentrant(
+ int32_t injectorPid, int32_t injectorUid) = 0;
+
+ /* Notifies the policy that a pointer down event has occurred outside the current focused
+ * window.
+ *
+ * The touchedToken passed as an argument is the window that received the input event.
+ */
+ virtual void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) = 0;
+};
+
+
+/* Notifies the system about input events generated by the input reader.
+ * The dispatcher is expected to be mostly asynchronous. */
+class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface {
+protected:
+ InputDispatcherInterface() { }
+ virtual ~InputDispatcherInterface() { }
+
+public:
+ /* Dumps the state of the input dispatcher.
+ *
+ * This method may be called on any thread (usually by the input manager). */
+ virtual void dump(std::string& dump) = 0;
+
+ /* Called by the heatbeat to ensures that the dispatcher has not deadlocked. */
+ virtual void monitor() = 0;
+
+ /* Runs a single iteration of the dispatch loop.
+ * Nominally processes one queued event, a timeout, or a response from an input consumer.
+ *
+ * This method should only be called on the input dispatcher thread.
+ */
+ virtual void dispatchOnce() = 0;
+
+ /* Injects an input event and optionally waits for sync.
+ * The synchronization mode determines whether the method blocks while waiting for
+ * input injection to proceed.
+ * Returns one of the INPUT_EVENT_INJECTION_XXX constants.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual int32_t injectInputEvent(const InputEvent* event,
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ uint32_t policyFlags) = 0;
+
+ /* Sets the list of input windows.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual void setInputWindows(const std::vector<sp<InputWindowHandle> >& inputWindowHandles,
+ int32_t displayId,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) = 0;
+
+ /* Sets the focused application on the given display.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual void setFocusedApplication(
+ int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
+
+ /* Sets the focused display.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual void setFocusedDisplay(int32_t displayId) = 0;
+
+ /* Sets the input dispatching mode.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
+
+ /* Sets whether input event filtering is enabled.
+ * When enabled, incoming input events are sent to the policy's filterInputEvent
+ * method instead of being dispatched. The filter is expected to use
+ * injectInputEvent to inject the events it would like to have dispatched.
+ * It should include POLICY_FLAG_FILTERED in the policy flags during injection.
+ */
+ virtual void setInputFilterEnabled(bool enabled) = 0;
+
+ /* Transfers touch focus from one window to another window.
+ *
+ * Returns true on success. False if the window did not actually have touch focus.
+ */
+ virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
+
+ /* Registers input channels that may be used as targets for input events.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual status_t registerInputChannel(
+ const sp<InputChannel>& inputChannel, int32_t displayId) = 0;
+
+ /* Registers input channels to be used to monitor input events.
+ *
+ * Each monitor must target a specific display and will only receive input events sent to that
+ * display. If the monitor is a gesture monitor, it will only receive pointer events on the
+ * targeted display.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual status_t registerInputMonitor(
+ const sp<InputChannel>& inputChannel, int32_t displayId, bool gestureMonitor) = 0;
+
+ /* Unregister input channels that will no longer receive input events.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
+
+ /* Allows an input monitor steal the current pointer stream away from normal input windows.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual status_t pilferPointers(const sp<IBinder>& token) = 0;
+
+};
+
+/* Dispatches events to input targets. Some functions of the input dispatcher, such as
+ * identifying input targets, are controlled by a separate policy object.
+ *
+ * IMPORTANT INVARIANT:
+ * Because the policy can potentially block or cause re-entrance into the input dispatcher,
+ * the input dispatcher never calls into the policy while holding its internal locks.
+ * The implementation is also carefully designed to recover from scenarios such as an
+ * input channel becoming unregistered while identifying input targets or processing timeouts.
+ *
+ * Methods marked 'Locked' must be called with the lock acquired.
+ *
+ * Methods marked 'LockedInterruptible' must be called with the lock acquired but
+ * may during the course of their execution release the lock, call into the policy, and
+ * then reacquire the lock. The caller is responsible for recovering gracefully.
+ *
+ * A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.
+ */
+class InputDispatcher : public InputDispatcherInterface {
+protected:
+ virtual ~InputDispatcher();
+
+public:
+ explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
+
+ virtual void dump(std::string& dump) override;
+ virtual void monitor() override;
+
+ virtual void dispatchOnce() override;
+
+ virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+ virtual void notifyKey(const NotifyKeyArgs* args) override;
+ virtual void notifyMotion(const NotifyMotionArgs* args) override;
+ virtual void notifySwitch(const NotifySwitchArgs* args) override;
+ virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+
+ virtual int32_t injectInputEvent(const InputEvent* event,
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ uint32_t policyFlags) override;
+
+ virtual void setInputWindows(const std::vector<sp<InputWindowHandle> >& inputWindowHandles,
+ int32_t displayId,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) override;
+ virtual void setFocusedApplication(int32_t displayId,
+ const sp<InputApplicationHandle>& inputApplicationHandle) override;
+ virtual void setFocusedDisplay(int32_t displayId) override;
+ virtual void setInputDispatchMode(bool enabled, bool frozen) override;
+ virtual void setInputFilterEnabled(bool enabled) override;
+
+ virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken)
+ override;
+
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+ int32_t displayId) override;
+ virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel,
+ int32_t displayId, bool isGestureMonitor) override;
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) override;
+ virtual status_t pilferPointers(const sp<IBinder>& token) override;
+
+private:
+ template <typename T>
+ struct Link {
+ T* next;
+ T* prev;
+
+ protected:
+ inline Link() : next(nullptr), prev(nullptr) { }
+ };
+
+ struct InjectionState {
+ mutable int32_t refCount;
+
+ int32_t injectorPid;
+ int32_t injectorUid;
+ int32_t injectionResult; // initially INPUT_EVENT_INJECTION_PENDING
+ bool injectionIsAsync; // set to true if injection is not waiting for the result
+ int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
+
+ InjectionState(int32_t injectorPid, int32_t injectorUid);
+ void release();
+
+ private:
+ ~InjectionState();
+ };
+
+ struct EventEntry : Link<EventEntry> {
+ enum {
+ TYPE_CONFIGURATION_CHANGED,
+ TYPE_DEVICE_RESET,
+ TYPE_KEY,
+ TYPE_MOTION
+ };
+
+ uint32_t sequenceNum;
+ mutable int32_t refCount;
+ int32_t type;
+ nsecs_t eventTime;
+ uint32_t policyFlags;
+ InjectionState* injectionState;
+
+ bool dispatchInProgress; // initially false, set to true while dispatching
+
+ inline bool isInjected() const { return injectionState != nullptr; }
+
+ void release();
+
+ virtual void appendDescription(std::string& msg) const = 0;
+
+ protected:
+ EventEntry(uint32_t sequenceNum, int32_t type, nsecs_t eventTime, uint32_t policyFlags);
+ virtual ~EventEntry();
+ void releaseInjectionState();
+ };
+
+ struct ConfigurationChangedEntry : EventEntry {
+ explicit ConfigurationChangedEntry(uint32_t sequenceNum, nsecs_t eventTime);
+ virtual void appendDescription(std::string& msg) const;
+
+ protected:
+ virtual ~ConfigurationChangedEntry();
+ };
+
+ struct DeviceResetEntry : EventEntry {
+ int32_t deviceId;
+
+ DeviceResetEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId);
+ virtual void appendDescription(std::string& msg) const;
+
+ protected:
+ virtual ~DeviceResetEntry();
+ };
+
+ struct KeyEntry : EventEntry {
+ int32_t deviceId;
+ uint32_t source;
+ int32_t displayId;
+ int32_t action;
+ int32_t flags;
+ int32_t keyCode;
+ int32_t scanCode;
+ int32_t metaState;
+ int32_t repeatCount;
+ nsecs_t downTime;
+
+ bool syntheticRepeat; // set to true for synthetic key repeats
+
+ enum InterceptKeyResult {
+ INTERCEPT_KEY_RESULT_UNKNOWN,
+ INTERCEPT_KEY_RESULT_SKIP,
+ INTERCEPT_KEY_RESULT_CONTINUE,
+ INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER,
+ };
+ InterceptKeyResult interceptKeyResult; // set based on the interception result
+ nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
+
+ KeyEntry(uint32_t sequenceNum, nsecs_t eventTime,
+ int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
+ int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
+ int32_t repeatCount, nsecs_t downTime);
+ virtual void appendDescription(std::string& msg) const;
+ void recycle();
+
+ protected:
+ virtual ~KeyEntry();
+ };
+
+ struct MotionEntry : EventEntry {
+ nsecs_t eventTime;
+ int32_t deviceId;
+ uint32_t source;
+ int32_t displayId;
+ int32_t action;
+ int32_t actionButton;
+ int32_t flags;
+ int32_t metaState;
+ int32_t buttonState;
+ MotionClassification classification;
+ int32_t edgeFlags;
+ float xPrecision;
+ float yPrecision;
+ nsecs_t downTime;
+ uint32_t pointerCount;
+ PointerProperties pointerProperties[MAX_POINTERS];
+ PointerCoords pointerCoords[MAX_POINTERS];
+
+ MotionEntry(uint32_t sequenceNum, nsecs_t eventTime,
+ int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
+ int32_t action, int32_t actionButton, int32_t flags,
+ int32_t metaState, int32_t buttonState, MotionClassification classification,
+ int32_t edgeFlags, float xPrecision, float yPrecision,
+ nsecs_t downTime, uint32_t pointerCount,
+ const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+ float xOffset, float yOffset);
+ virtual void appendDescription(std::string& msg) const;
+
+ protected:
+ virtual ~MotionEntry();
+ };
+
+ // Tracks the progress of dispatching a particular event to a particular connection.
+ struct DispatchEntry : Link<DispatchEntry> {
+ const uint32_t seq; // unique sequence number, never 0
+
+ EventEntry* eventEntry; // the event to dispatch
+ int32_t targetFlags;
+ float xOffset;
+ float yOffset;
+ float globalScaleFactor;
+ float windowXScale = 1.0f;
+ float windowYScale = 1.0f;
+ nsecs_t deliveryTime; // time when the event was actually delivered
+
+ // Set to the resolved action and flags when the event is enqueued.
+ int32_t resolvedAction;
+ int32_t resolvedFlags;
+
+ DispatchEntry(EventEntry* eventEntry,
+ int32_t targetFlags, float xOffset, float yOffset,
+ float globalScaleFactor, float windowXScale, float windowYScale);
+ ~DispatchEntry();
+
+ inline bool hasForegroundTarget() const {
+ return targetFlags & InputTarget::FLAG_FOREGROUND;
+ }
+
+ inline bool isSplit() const {
+ return targetFlags & InputTarget::FLAG_SPLIT;
+ }
+
+ private:
+ static volatile int32_t sNextSeqAtomic;
+
+ static uint32_t nextSeq();
+ };
+
+ // A command entry captures state and behavior for an action to be performed in the
+ // dispatch loop after the initial processing has taken place. It is essentially
+ // a kind of continuation used to postpone sensitive policy interactions to a point
+ // in the dispatch loop where it is safe to release the lock (generally after finishing
+ // the critical parts of the dispatch cycle).
+ //
+ // The special thing about commands is that they can voluntarily release and reacquire
+ // the dispatcher lock at will. Initially when the command starts running, the
+ // dispatcher lock is held. However, if the command needs to call into the policy to
+ // do some work, it can release the lock, do the work, then reacquire the lock again
+ // before returning.
+ //
+ // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
+ // never calls into the policy while holding its lock.
+ //
+ // Commands are implicitly 'LockedInterruptible'.
+ struct CommandEntry;
+ typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
+
+ class Connection;
+ struct CommandEntry : Link<CommandEntry> {
+ explicit CommandEntry(Command command);
+ ~CommandEntry();
+
+ Command command;
+
+ // parameters for the command (usage varies by command)
+ sp<Connection> connection;
+ nsecs_t eventTime;
+ KeyEntry* keyEntry;
+ sp<InputApplicationHandle> inputApplicationHandle;
+ std::string reason;
+ int32_t userActivityEventType;
+ uint32_t seq;
+ bool handled;
+ sp<InputChannel> inputChannel;
+ sp<IBinder> oldToken;
+ sp<IBinder> newToken;
+ };
+
+ // Generic queue implementation.
+ template <typename T>
+ struct Queue {
+ T* head;
+ T* tail;
+ uint32_t entryCount;
+
+ inline Queue() : head(nullptr), tail(nullptr), entryCount(0) {
+ }
+
+ inline bool isEmpty() const {
+ return !head;
+ }
+
+ inline void enqueueAtTail(T* entry) {
+ entryCount++;
+ entry->prev = tail;
+ if (tail) {
+ tail->next = entry;
+ } else {
+ head = entry;
+ }
+ entry->next = nullptr;
+ tail = entry;
+ }
+
+ inline void enqueueAtHead(T* entry) {
+ entryCount++;
+ entry->next = head;
+ if (head) {
+ head->prev = entry;
+ } else {
+ tail = entry;
+ }
+ entry->prev = nullptr;
+ head = entry;
+ }
+
+ inline void dequeue(T* entry) {
+ entryCount--;
+ if (entry->prev) {
+ entry->prev->next = entry->next;
+ } else {
+ head = entry->next;
+ }
+ if (entry->next) {
+ entry->next->prev = entry->prev;
+ } else {
+ tail = entry->prev;
+ }
+ }
+
+ inline T* dequeueAtHead() {
+ entryCount--;
+ T* entry = head;
+ head = entry->next;
+ if (head) {
+ head->prev = nullptr;
+ } else {
+ tail = nullptr;
+ }
+ return entry;
+ }
+
+ uint32_t count() const {
+ return entryCount;
+ }
+ };
+
+ /* Specifies which events are to be canceled and why. */
+ struct CancelationOptions {
+ enum Mode {
+ CANCEL_ALL_EVENTS = 0,
+ CANCEL_POINTER_EVENTS = 1,
+ CANCEL_NON_POINTER_EVENTS = 2,
+ CANCEL_FALLBACK_EVENTS = 3,
+ };
+
+ // The criterion to use to determine which events should be canceled.
+ Mode mode;
+
+ // Descriptive reason for the cancelation.
+ const char* reason;
+
+ // The specific keycode of the key event to cancel, or nullopt to cancel any key event.
+ std::optional<int32_t> keyCode = std::nullopt;
+
+ // The specific device id of events to cancel, or nullopt to cancel events from any device.
+ std::optional<int32_t> deviceId = std::nullopt;
+
+ // The specific display id of events to cancel, or nullopt to cancel events on any display.
+ std::optional<int32_t> displayId = std::nullopt;
+
+ CancelationOptions(Mode mode, const char* reason) : mode(mode), reason(reason) { }
+ };
+
+ /* Tracks dispatched key and motion event state so that cancelation events can be
+ * synthesized when events are dropped. */
+ class InputState {
+ public:
+ InputState();
+ ~InputState();
+
+ // Returns true if there is no state to be canceled.
+ bool isNeutral() const;
+
+ // Returns true if the specified source is known to have received a hover enter
+ // motion event.
+ bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const;
+
+ // Records tracking information for a key event that has just been published.
+ // Returns true if the event should be delivered, false if it is inconsistent
+ // and should be skipped.
+ bool trackKey(const KeyEntry* entry, int32_t action, int32_t flags);
+
+ // Records tracking information for a motion event that has just been published.
+ // Returns true if the event should be delivered, false if it is inconsistent
+ // and should be skipped.
+ bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags);
+
+ // Synthesizes cancelation events for the current state and resets the tracked state.
+ void synthesizeCancelationEvents(nsecs_t currentTime,
+ std::vector<EventEntry*>& outEvents, const CancelationOptions& options);
+
+ // Clears the current state.
+ void clear();
+
+ // Copies pointer-related parts of the input state to another instance.
+ void copyPointerStateTo(InputState& other) const;
+
+ // Gets the fallback key associated with a keycode.
+ // Returns -1 if none.
+ // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy.
+ int32_t getFallbackKey(int32_t originalKeyCode);
+
+ // Sets the fallback key for a particular keycode.
+ void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode);
+
+ // Removes the fallback key for a particular keycode.
+ void removeFallbackKey(int32_t originalKeyCode);
+
+ inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const {
+ return mFallbackKeys;
+ }
+
+ private:
+ struct KeyMemento {
+ int32_t deviceId;
+ uint32_t source;
+ int32_t displayId;
+ int32_t keyCode;
+ int32_t scanCode;
+ int32_t metaState;
+ int32_t flags;
+ nsecs_t downTime;
+ uint32_t policyFlags;
+ };
+
+ struct MotionMemento {
+ int32_t deviceId;
+ uint32_t source;
+ int32_t displayId;
+ int32_t flags;
+ float xPrecision;
+ float yPrecision;
+ nsecs_t downTime;
+ uint32_t pointerCount;
+ PointerProperties pointerProperties[MAX_POINTERS];
+ PointerCoords pointerCoords[MAX_POINTERS];
+ bool hovering;
+ uint32_t policyFlags;
+
+ void setPointers(const MotionEntry* entry);
+ };
+
+ std::vector<KeyMemento> mKeyMementos;
+ std::vector<MotionMemento> mMotionMementos;
+ KeyedVector<int32_t, int32_t> mFallbackKeys;
+
+ ssize_t findKeyMemento(const KeyEntry* entry) const;
+ ssize_t findMotionMemento(const MotionEntry* entry, bool hovering) const;
+
+ void addKeyMemento(const KeyEntry* entry, int32_t flags);
+ void addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering);
+
+ static bool shouldCancelKey(const KeyMemento& memento,
+ const CancelationOptions& options);
+ static bool shouldCancelMotion(const MotionMemento& memento,
+ const CancelationOptions& options);
+ };
+
+ /* Manages the dispatch state associated with a single input channel. */
+ class Connection : public RefBase {
+ protected:
+ virtual ~Connection();
+
+ public:
+ enum Status {
+ // Everything is peachy.
+ STATUS_NORMAL,
+ // An unrecoverable communication error has occurred.
+ STATUS_BROKEN,
+ // The input channel has been unregistered.
+ STATUS_ZOMBIE
+ };
+
+ Status status;
+ sp<InputChannel> inputChannel; // never null
+ bool monitor;
+ InputPublisher inputPublisher;
+ InputState inputState;
+
+ // True if the socket is full and no further events can be published until
+ // the application consumes some of the input.
+ bool inputPublisherBlocked;
+
+ // Queue of events that need to be published to the connection.
+ Queue<DispatchEntry> outboundQueue;
+
+ // Queue of events that have been published to the connection but that have not
+ // yet received a "finished" response from the application.
+ Queue<DispatchEntry> waitQueue;
+
+ explicit Connection(const sp<InputChannel>& inputChannel, bool monitor);
+
+ inline const std::string getInputChannelName() const { return inputChannel->getName(); }
+
+ const std::string getWindowName() const;
+ const char* getStatusLabel() const;
+
+ DispatchEntry* findWaitQueueEntry(uint32_t seq);
+ };
+
+ struct Monitor {
+ sp<InputChannel> inputChannel; // never null
+
+ explicit Monitor(const sp<InputChannel>& inputChannel);
+ };
+
+ enum DropReason {
+ DROP_REASON_NOT_DROPPED = 0,
+ DROP_REASON_POLICY = 1,
+ DROP_REASON_APP_SWITCH = 2,
+ DROP_REASON_DISABLED = 3,
+ DROP_REASON_BLOCKED = 4,
+ DROP_REASON_STALE = 5,
+ };
+
+ sp<InputDispatcherPolicyInterface> mPolicy;
+ InputDispatcherConfiguration mConfig;
+
+ std::mutex mLock;
+
+ std::condition_variable mDispatcherIsAlive;
+
+ sp<Looper> mLooper;
+
+ EventEntry* mPendingEvent GUARDED_BY(mLock);
+ Queue<EventEntry> mInboundQueue GUARDED_BY(mLock);
+ Queue<EventEntry> mRecentQueue GUARDED_BY(mLock);
+ Queue<CommandEntry> mCommandQueue GUARDED_BY(mLock);
+
+ DropReason mLastDropReason GUARDED_BY(mLock);
+
+ void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) REQUIRES(mLock);
+
+ // Enqueues an inbound event. Returns true if mLooper->wake() should be called.
+ bool enqueueInboundEventLocked(EventEntry* entry) REQUIRES(mLock);
+
+ // Cleans up input state when dropping an inbound event.
+ void dropInboundEventLocked(EventEntry* entry, DropReason dropReason) REQUIRES(mLock);
+
+ // Adds an event to a queue of recent events for debugging purposes.
+ void addRecentEventLocked(EventEntry* entry) REQUIRES(mLock);
+
+ // App switch latency optimization.
+ bool mAppSwitchSawKeyDown GUARDED_BY(mLock);
+ nsecs_t mAppSwitchDueTime GUARDED_BY(mLock);
+
+ bool isAppSwitchKeyEvent(KeyEntry* keyEntry);
+ bool isAppSwitchPendingLocked() REQUIRES(mLock);
+ void resetPendingAppSwitchLocked(bool handled) REQUIRES(mLock);
+
+ // Stale event latency optimization.
+ static bool isStaleEvent(nsecs_t currentTime, EventEntry* entry);
+
+ // Blocked event latency optimization. Drops old events when the user intends
+ // to transfer focus to a new application.
+ EventEntry* mNextUnblockedEvent GUARDED_BY(mLock);
+
+ sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y,
+ bool addOutsideTargets = false, bool addPortalWindows = false) REQUIRES(mLock);
+
+ // All registered connections mapped by channel file descriptor.
+ KeyedVector<int, sp<Connection> > mConnectionsByFd GUARDED_BY(mLock);
+
+ struct IBinderHash {
+ std::size_t operator()(const sp<IBinder>& b) const {
+ return std::hash<IBinder *>{}(b.get());
+ }
+ };
+ std::unordered_map<sp<IBinder>, sp<InputChannel>, IBinderHash> mInputChannelsByToken
+ GUARDED_BY(mLock);
+
+ // Finds the display ID of the gesture monitor identified by the provided token.
+ std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token)
+ REQUIRES(mLock);
+
+ ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
+
+ // Input channels that will receive a copy of all input events sent to the provided display.
+ std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay
+ GUARDED_BY(mLock);
+
+ // Input channels that will receive pointer events that start within the corresponding display.
+ // These are a bit special when compared to global monitors since they'll cause gesture streams
+ // to continue even when there isn't a touched window,and have the ability to steal the rest of
+ // the pointer stream in order to claim it for a system gesture.
+ std::unordered_map<int32_t, std::vector<Monitor>> mGestureMonitorsByDisplay
+ GUARDED_BY(mLock);
+
+
+ // Event injection and synchronization.
+ std::condition_variable mInjectionResultAvailable;
+ bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
+ void setInjectionResult(EventEntry* entry, int32_t injectionResult);
+
+ std::condition_variable mInjectionSyncFinished;
+ void incrementPendingForegroundDispatches(EventEntry* entry);
+ void decrementPendingForegroundDispatches(EventEntry* entry);
+
+ // Key repeat tracking.
+ struct KeyRepeatState {
+ KeyEntry* lastKeyEntry; // or null if no repeat
+ nsecs_t nextRepeatTime;
+ } mKeyRepeatState GUARDED_BY(mLock);
+
+ void resetKeyRepeatLocked() REQUIRES(mLock);
+ KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime) REQUIRES(mLock);
+
+ // Key replacement tracking
+ struct KeyReplacement {
+ int32_t keyCode;
+ int32_t deviceId;
+ bool operator==(const KeyReplacement& rhs) const {
+ return keyCode == rhs.keyCode && deviceId == rhs.deviceId;
+ }
+ bool operator<(const KeyReplacement& rhs) const {
+ return keyCode != rhs.keyCode ? keyCode < rhs.keyCode : deviceId < rhs.deviceId;
+ }
+ };
+ // Maps the key code replaced, device id tuple to the key code it was replaced with
+ KeyedVector<KeyReplacement, int32_t> mReplacedKeys GUARDED_BY(mLock);
+ // Process certain Meta + Key combinations
+ void accelerateMetaShortcuts(const int32_t deviceId, const int32_t action,
+ int32_t& keyCode, int32_t& metaState);
+
+ // Deferred command processing.
+ bool haveCommandsLocked() const REQUIRES(mLock);
+ bool runCommandsLockedInterruptible() REQUIRES(mLock);
+ CommandEntry* postCommandLocked(Command command) REQUIRES(mLock);
+
+ // Input filter processing.
+ bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) REQUIRES(mLock);
+ bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) REQUIRES(mLock);
+
+ // Inbound event processing.
+ void drainInboundQueueLocked() REQUIRES(mLock);
+ void releasePendingEventLocked() REQUIRES(mLock);
+ void releaseInboundEventLocked(EventEntry* entry) REQUIRES(mLock);
+
+ // Dispatch state.
+ bool mDispatchEnabled GUARDED_BY(mLock);
+ bool mDispatchFrozen GUARDED_BY(mLock);
+ bool mInputFilterEnabled GUARDED_BY(mLock);
+
+ std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay
+ GUARDED_BY(mLock);
+ // Get window handles by display, return an empty vector if not found.
+ std::vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const
+ REQUIRES(mLock);
+ sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken) const
+ REQUIRES(mLock);
+ sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const REQUIRES(mLock);
+ bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
+
+ // Focus tracking for keys, trackball, etc.
+ std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
+ GUARDED_BY(mLock);
+
+ // Focus tracking for touch.
+ struct TouchedWindow {
+ sp<InputWindowHandle> windowHandle;
+ int32_t targetFlags;
+ BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set
+ };
+
+ // For tracking the offsets we need to apply when adding gesture monitor targets.
+ struct TouchedMonitor {
+ Monitor monitor;
+ float xOffset = 0.f;
+ float yOffset = 0.f;
+
+ explicit TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset);
+ };
+
+ struct TouchState {
+ bool down;
+ bool split;
+ int32_t deviceId; // id of the device that is currently down, others are rejected
+ uint32_t source; // source of the device that is current down, others are rejected
+ int32_t displayId; // id to the display that currently has a touch, others are rejected
+ std::vector<TouchedWindow> windows;
+
+ // This collects the portal windows that the touch has gone through. Each portal window
+ // targets a display (embedded display for most cases). With this info, we can add the
+ // monitoring channels of the displays touched.
+ std::vector<sp<InputWindowHandle>> portalWindows;
+
+ std::vector<TouchedMonitor> gestureMonitors;
+
+ TouchState();
+ ~TouchState();
+ void reset();
+ void copyFrom(const TouchState& other);
+ void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
+ int32_t targetFlags, BitSet32 pointerIds);
+ void addPortalWindow(const sp<InputWindowHandle>& windowHandle);
+ void addGestureMonitors(const std::vector<TouchedMonitor>& monitors);
+ void removeWindow(const sp<InputWindowHandle>& windowHandle);
+ void removeWindowByToken(const sp<IBinder>& token);
+ void filterNonAsIsTouchWindows();
+ void filterNonMonitors();
+ sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
+ bool isSlippery() const;
+ };
+
+ KeyedVector<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock);
+ TouchState mTempTouchState GUARDED_BY(mLock);
+
+ // Focused applications.
+ std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay
+ GUARDED_BY(mLock);
+
+ // Top focused display.
+ int32_t mFocusedDisplayId GUARDED_BY(mLock);
+
+ // Dispatcher state at time of last ANR.
+ std::string mLastANRState GUARDED_BY(mLock);
+
+ // Dispatch inbound events.
+ bool dispatchConfigurationChangedLocked(
+ nsecs_t currentTime, ConfigurationChangedEntry* entry) REQUIRES(mLock);
+ bool dispatchDeviceResetLocked(
+ nsecs_t currentTime, DeviceResetEntry* entry) REQUIRES(mLock);
+ bool dispatchKeyLocked(
+ nsecs_t currentTime, KeyEntry* entry,
+ DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock);
+ bool dispatchMotionLocked(
+ nsecs_t currentTime, MotionEntry* entry,
+ DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock);
+ void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry,
+ const std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
+
+ void logOutboundKeyDetails(const char* prefix, const KeyEntry* entry);
+ void logOutboundMotionDetails(const char* prefix, const MotionEntry* entry);
+
+ // Keeping track of ANR timeouts.
+ enum InputTargetWaitCause {
+ INPUT_TARGET_WAIT_CAUSE_NONE,
+ INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
+ INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
+ };
+
+ InputTargetWaitCause mInputTargetWaitCause GUARDED_BY(mLock);
+ nsecs_t mInputTargetWaitStartTime GUARDED_BY(mLock);
+ nsecs_t mInputTargetWaitTimeoutTime GUARDED_BY(mLock);
+ bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock);
+ sp<IBinder> mInputTargetWaitApplicationToken GUARDED_BY(mLock);
+
+ // Contains the last window which received a hover event.
+ sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock);
+
+ // Finding targets for input events.
+ int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
+ const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle,
+ nsecs_t* nextWakeupTime, const char* reason) REQUIRES(mLock);
+
+ void removeWindowByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock);
+
+ void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
+ const sp<InputChannel>& inputChannel) REQUIRES(mLock);
+ nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) REQUIRES(mLock);
+ void resetANRTimeoutsLocked() REQUIRES(mLock);
+
+ int32_t getTargetDisplayId(const EventEntry* entry);
+ int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
+ std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) REQUIRES(mLock);
+ int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
+ std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
+ bool* outConflictingPointerActions) REQUIRES(mLock);
+ std::vector<TouchedMonitor> findTouchedGestureMonitorsLocked(int32_t displayId,
+ const std::vector<sp<InputWindowHandle>>& portalWindows) REQUIRES(mLock);
+ void addGestureMonitors(const std::vector<Monitor>& monitors,
+ std::vector<TouchedMonitor>& outTouchedMonitors, float xOffset = 0, float yOffset = 0);
+
+ void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
+ int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets)
+ REQUIRES(mLock);
+ void addMonitoringTargetLocked(const Monitor& monitor, float xOffset, float yOffset,
+ std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
+ void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
+ int32_t displayId, float xOffset = 0, float yOffset = 0) REQUIRES(mLock);
+
+ void pokeUserActivityLocked(const EventEntry* eventEntry) REQUIRES(mLock);
+ bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
+ const InjectionState* injectionState);
+ bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
+ int32_t x, int32_t y) const REQUIRES(mLock);
+ bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
+ std::string getApplicationWindowLabel(const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle);
+
+ std::string checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
+ const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,
+ const char* targetType) REQUIRES(mLock);
+
+ // Manage the dispatch cycle for a single connection.
+ // These methods are deliberately not Interruptible because doing all of the work
+ // with the mutex held makes it easier to ensure that connection invariants are maintained.
+ // If needed, the methods post commands to run later once the critical bits are done.
+ void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+ EventEntry* eventEntry, const InputTarget* inputTarget) REQUIRES(mLock);
+ void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection,
+ EventEntry* eventEntry, const InputTarget* inputTarget) REQUIRES(mLock);
+ void enqueueDispatchEntryLocked(const sp<Connection>& connection,
+ EventEntry* eventEntry, const InputTarget* inputTarget, int32_t dispatchMode)
+ REQUIRES(mLock);
+ void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection)
+ REQUIRES(mLock);
+ void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+ uint32_t seq, bool handled) REQUIRES(mLock);
+ void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+ bool notify) REQUIRES(mLock);
+ void drainDispatchQueue(Queue<DispatchEntry>* queue);
+ void releaseDispatchEntry(DispatchEntry* dispatchEntry);
+ static int handleReceiveCallback(int fd, int events, void* data);
+ // The action sent should only be of type AMOTION_EVENT_*
+ void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
+ const sp<IBinder>& newToken) REQUIRES(mLock);
+
+ void synthesizeCancelationEventsForAllConnectionsLocked(
+ const CancelationOptions& options) REQUIRES(mLock);
+ void synthesizeCancelationEventsForMonitorsLocked(
+ const CancelationOptions& options) REQUIRES(mLock);
+ void synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions& options,
+ std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
+ void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
+ const CancelationOptions& options) REQUIRES(mLock);
+ void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
+ const CancelationOptions& options) REQUIRES(mLock);
+
+ // Splitting motion events across windows.
+ MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
+
+ // Reset and drop everything the dispatcher is doing.
+ void resetAndDropEverythingLocked(const char* reason) REQUIRES(mLock);
+
+ // Dump state.
+ void dumpDispatchStateLocked(std::string& dump) REQUIRES(mLock);
+ void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors);
+ void logDispatchStateLocked() REQUIRES(mLock);
+
+ // Registration.
+ void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
+ void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel,
+ std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay)
+ REQUIRES(mLock);
+ status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify)
+ REQUIRES(mLock);
+
+ // Interesting events that we might like to log or tell the framework about.
+ void onDispatchCycleFinishedLocked(
+ nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled)
+ REQUIRES(mLock);
+ void onDispatchCycleBrokenLocked(
+ nsecs_t currentTime, const sp<Connection>& connection) REQUIRES(mLock);
+ void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
+ const sp<InputWindowHandle>& newFocus) REQUIRES(mLock);
+ void onANRLocked(
+ nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle,
+ nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) REQUIRES(mLock);
+
+ // Outbound policy interactions.
+ void doNotifyConfigurationChangedLockedInterruptible(CommandEntry* commandEntry)
+ REQUIRES(mLock);
+ void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+ void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+ void doNotifyANRLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+ void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry)
+ REQUIRES(mLock);
+ void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+ bool afterKeyEventLockedInterruptible(const sp<Connection>& connection,
+ DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) REQUIRES(mLock);
+ bool afterMotionEventLockedInterruptible(const sp<Connection>& connection,
+ DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) REQUIRES(mLock);
+ void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+ void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
+ void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry)
+ REQUIRES(mLock);
+
+ // Statistics gathering.
+ void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
+ int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
+ void traceInboundQueueLengthLocked() REQUIRES(mLock);
+ void traceOutboundQueueLength(const sp<Connection>& connection);
+ void traceWaitQueueLength(const sp<Connection>& connection);
+
+ sp<InputReporterInterface> mReporter;
+};
+
+/* Enqueues and dispatches input events, endlessly. */
+class InputDispatcherThread : public Thread {
+public:
+ explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
+ ~InputDispatcherThread();
+
+private:
+ virtual bool threadLoop();
+
+ sp<InputDispatcherInterface> mDispatcher;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_DISPATCHER_H
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 359325faed..52e908066e 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -19,8 +19,6 @@
//#define LOG_NDEBUG 0
#include "InputManager.h"
-#include "InputDispatcherFactory.h"
-#include "InputDispatcherThread.h"
#include "InputReaderFactory.h"
#include <binder/IPCThreadState.h>
@@ -35,7 +33,7 @@ namespace android {
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
- mDispatcher = createInputDispatcher(dispatcherPolicy);
+ mDispatcher = new InputDispatcher(dispatcherPolicy);
mClassifier = new InputClassifier(mDispatcher);
mReader = createInputReader(readerPolicy, mClassifier);
initialize();
@@ -119,10 +117,6 @@ void InputManager::setInputWindows(const std::vector<InputWindowInfo>& infos,
}
}
-void InputManager::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
- mDispatcher->transferTouchFocus(fromToken, toToken);
-}
-
// Used by tests only.
void InputManager::registerInputChannel(const sp<InputChannel>& channel) {
IPCThreadState* ipc = IPCThreadState::self();
@@ -139,4 +133,8 @@ void InputManager::unregisterInputChannel(const sp<InputChannel>& channel) {
mDispatcher->unregisterInputChannel(channel);
}
+void InputManager::setMotionClassifierEnabled(bool enabled) {
+ mClassifier->setMotionClassifierEnabled(enabled);
+}
+
} // namespace android
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index f3da324ba4..c75611f083 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -21,14 +21,15 @@
* Native input manager.
*/
-#include "InputClassifier.h"
+#include "EventHub.h"
#include "InputReaderBase.h"
+#include "InputClassifier.h"
+#include "InputDispatcher.h"
+#include "InputReader.h"
-#include <InputDispatcherInterface.h>
-#include <InputDispatcherPolicyInterface.h>
-#include <input/ISetInputWindowsListener.h>
#include <input/Input.h>
#include <input/InputTransport.h>
+#include <input/ISetInputWindowsListener.h>
#include <input/IInputFlinger.h>
#include <utils/Errors.h>
@@ -38,7 +39,6 @@
namespace android {
class InputChannel;
-class InputDispatcherThread;
/*
* The input manager is the core of the system event processing.
@@ -96,11 +96,12 @@ public:
virtual void setInputWindows(const std::vector<InputWindowInfo>& handles,
const sp<ISetInputWindowsListener>& setInputWindowsListener);
- virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
virtual void registerInputChannel(const sp<InputChannel>& channel);
virtual void unregisterInputChannel(const sp<InputChannel>& channel);
+ void setMotionClassifierEnabled(bool enabled);
+
private:
sp<InputReaderInterface> mReader;
sp<InputReaderThread> mReaderThread;
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
new file mode 100644
index 0000000000..a45b8a56ce
--- /dev/null
+++ b/services/inputflinger/InputReader.cpp
@@ -0,0 +1,7534 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "InputReader"
+
+//#define LOG_NDEBUG 0
+
+// Log debug messages for each raw event received from the EventHub.
+#define DEBUG_RAW_EVENTS 0
+
+// Log debug messages about touch screen filtering hacks.
+#define DEBUG_HACKS 0
+
+// Log debug messages about virtual key processing.
+#define DEBUG_VIRTUAL_KEYS 0
+
+// Log debug messages about pointers.
+#define DEBUG_POINTERS 0
+
+// Log debug messages about pointer assignment calculations.
+#define DEBUG_POINTER_ASSIGNMENT 0
+
+// Log debug messages about gesture detection.
+#define DEBUG_GESTURES 0
+
+// Log debug messages about the vibrator.
+#define DEBUG_VIBRATOR 0
+
+// Log debug messages about fusing stylus data.
+#define DEBUG_STYLUS_FUSION 0
+
+#include "InputReader.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <log/log.h>
+
+#include <android-base/stringprintf.h>
+#include <input/Keyboard.h>
+#include <input/VirtualKeyMap.h>
+#include <statslog.h>
+
+#define INDENT " "
+#define INDENT2 " "
+#define INDENT3 " "
+#define INDENT4 " "
+#define INDENT5 " "
+
+using android::base::StringPrintf;
+
+namespace android {
+
+// --- Constants ---
+
+// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
+static constexpr size_t MAX_SLOTS = 32;
+
+// Maximum amount of latency to add to touch events while waiting for data from an
+// external stylus.
+static constexpr nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72);
+
+// Maximum amount of time to wait on touch data before pushing out new pressure data.
+static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20);
+
+// Artificial latency on synthetic events created from stylus data without corresponding touch
+// data.
+static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
+
+// How often to report input event statistics
+static constexpr nsecs_t STATISTICS_REPORT_FREQUENCY = seconds_to_nanoseconds(5 * 60);
+
+// --- Static Functions ---
+
+template<typename T>
+inline static T abs(const T& value) {
+ return value < 0 ? - value : value;
+}
+
+template<typename T>
+inline static T min(const T& a, const T& b) {
+ return a < b ? a : b;
+}
+
+template<typename T>
+inline static void swap(T& a, T& b) {
+ T temp = a;
+ a = b;
+ b = temp;
+}
+
+inline static float avg(float x, float y) {
+ return (x + y) / 2;
+}
+
+inline static float distance(float x1, float y1, float x2, float y2) {
+ return hypotf(x1 - x2, y1 - y2);
+}
+
+inline static int32_t signExtendNybble(int32_t value) {
+ return value >= 8 ? value - 16 : value;
+}
+
+static inline const char* toString(bool value) {
+ return value ? "true" : "false";
+}
+
+static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
+ const int32_t map[][4], size_t mapSize) {
+ if (orientation != DISPLAY_ORIENTATION_0) {
+ for (size_t i = 0; i < mapSize; i++) {
+ if (value == map[i][0]) {
+ return map[i][orientation];
+ }
+ }
+ }
+ return value;
+}
+
+static const int32_t keyCodeRotationMap[][4] = {
+ // key codes enumerated counter-clockwise with the original (unrotated) key first
+ // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
+ { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
+ { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
+ { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
+ { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
+ { AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
+ AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT },
+ { AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
+ AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN },
+ { AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
+ AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT },
+ { AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
+ AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP },
+};
+static const size_t keyCodeRotationMapSize =
+ sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
+
+static int32_t rotateStemKey(int32_t value, int32_t orientation,
+ const int32_t map[][2], size_t mapSize) {
+ if (orientation == DISPLAY_ORIENTATION_180) {
+ for (size_t i = 0; i < mapSize; i++) {
+ if (value == map[i][0]) {
+ return map[i][1];
+ }
+ }
+ }
+ return value;
+}
+
+// The mapping can be defined using input device configuration properties keyboard.rotated.stem_X
+static int32_t stemKeyRotationMap[][2] = {
+ // key codes enumerated with the original (unrotated) key first
+ // no rotation, 180 degree rotation
+ { AKEYCODE_STEM_PRIMARY, AKEYCODE_STEM_PRIMARY },
+ { AKEYCODE_STEM_1, AKEYCODE_STEM_1 },
+ { AKEYCODE_STEM_2, AKEYCODE_STEM_2 },
+ { AKEYCODE_STEM_3, AKEYCODE_STEM_3 },
+};
+static const size_t stemKeyRotationMapSize =
+ sizeof(stemKeyRotationMap) / sizeof(stemKeyRotationMap[0]);
+
+static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
+ keyCode = rotateStemKey(keyCode, orientation,
+ stemKeyRotationMap, stemKeyRotationMapSize);
+ return rotateValueUsingRotationMap(keyCode, orientation,
+ keyCodeRotationMap, keyCodeRotationMapSize);
+}
+
+static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
+ float temp;
+ switch (orientation) {
+ case DISPLAY_ORIENTATION_90:
+ temp = *deltaX;
+ *deltaX = *deltaY;
+ *deltaY = -temp;
+ break;
+
+ case DISPLAY_ORIENTATION_180:
+ *deltaX = -*deltaX;
+ *deltaY = -*deltaY;
+ break;
+
+ case DISPLAY_ORIENTATION_270:
+ temp = *deltaX;
+ *deltaX = -*deltaY;
+ *deltaY = temp;
+ break;
+ }
+}
+
+static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
+ return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
+}
+
+// Returns true if the pointer should be reported as being down given the specified
+// button states. This determines whether the event is reported as a touch event.
+static bool isPointerDown(int32_t buttonState) {
+ return buttonState &
+ (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
+ | AMOTION_EVENT_BUTTON_TERTIARY);
+}
+
+static float calculateCommonVector(float a, float b) {
+ if (a > 0 && b > 0) {
+ return a < b ? a : b;
+ } else if (a < 0 && b < 0) {
+ return a > b ? a : b;
+ } else {
+ return 0;
+ }
+}
+
+static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
+ nsecs_t when, int32_t deviceId, uint32_t source, int32_t displayId,
+ uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
+ int32_t buttonState, int32_t keyCode) {
+ if (
+ (action == AKEY_EVENT_ACTION_DOWN
+ && !(lastButtonState & buttonState)
+ && (currentButtonState & buttonState))
+ || (action == AKEY_EVENT_ACTION_UP
+ && (lastButtonState & buttonState)
+ && !(currentButtonState & buttonState))) {
+ NotifyKeyArgs args(context->getNextSequenceNum(), when, deviceId, source, displayId,
+ policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when);
+ context->getListener()->notifyKey(&args);
+ }
+}
+
+static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
+ nsecs_t when, int32_t deviceId, uint32_t source, int32_t displayId,
+ uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
+ synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
+ lastButtonState, currentButtonState,
+ AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
+ synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
+ lastButtonState, currentButtonState,
+ AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
+}
+
+
+// --- InputReader ---
+
+InputReader::InputReader(const sp<EventHubInterface>& eventHub,
+ const sp<InputReaderPolicyInterface>& policy,
+ const sp<InputListenerInterface>& listener) :
+ mContext(this), mEventHub(eventHub), mPolicy(policy),
+ mNextSequenceNum(1), mGlobalMetaState(0), mGeneration(1),
+ mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
+ mConfigurationChangesToRefresh(0) {
+ mQueuedListener = new QueuedInputListener(listener);
+
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ refreshConfigurationLocked(0);
+ updateGlobalMetaStateLocked();
+ } // release lock
+}
+
+InputReader::~InputReader() {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ delete mDevices.valueAt(i);
+ }
+}
+
+void InputReader::loopOnce() {
+ int32_t oldGeneration;
+ int32_t timeoutMillis;
+ bool inputDevicesChanged = false;
+ std::vector<InputDeviceInfo> inputDevices;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ oldGeneration = mGeneration;
+ timeoutMillis = -1;
+
+ uint32_t changes = mConfigurationChangesToRefresh;
+ if (changes) {
+ mConfigurationChangesToRefresh = 0;
+ timeoutMillis = 0;
+ refreshConfigurationLocked(changes);
+ } else if (mNextTimeout != LLONG_MAX) {
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
+ }
+ } // release lock
+
+ size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
+
+ { // acquire lock
+ AutoMutex _l(mLock);
+ mReaderIsAliveCondition.broadcast();
+
+ if (count) {
+ processEventsLocked(mEventBuffer, count);
+ }
+
+ if (mNextTimeout != LLONG_MAX) {
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ if (now >= mNextTimeout) {
+#if DEBUG_RAW_EVENTS
+ ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
+#endif
+ mNextTimeout = LLONG_MAX;
+ timeoutExpiredLocked(now);
+ }
+ }
+
+ if (oldGeneration != mGeneration) {
+ inputDevicesChanged = true;
+ getInputDevicesLocked(inputDevices);
+ }
+ } // release lock
+
+ // Send out a message that the describes the changed input devices.
+ if (inputDevicesChanged) {
+ mPolicy->notifyInputDevicesChanged(inputDevices);
+ }
+
+ // Flush queued events out to the listener.
+ // This must happen outside of the lock because the listener could potentially call
+ // back into the InputReader's methods, such as getScanCodeState, or become blocked
+ // on another thread similarly waiting to acquire the InputReader lock thereby
+ // resulting in a deadlock. This situation is actually quite plausible because the
+ // listener is actually the input dispatcher, which calls into the window manager,
+ // which occasionally calls into the input reader.
+ mQueuedListener->flush();
+}
+
+void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
+ for (const RawEvent* rawEvent = rawEvents; count;) {
+ int32_t type = rawEvent->type;
+ size_t batchSize = 1;
+ if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
+ int32_t deviceId = rawEvent->deviceId;
+ while (batchSize < count) {
+ if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
+ || rawEvent[batchSize].deviceId != deviceId) {
+ break;
+ }
+ batchSize += 1;
+ }
+#if DEBUG_RAW_EVENTS
+ ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
+#endif
+ processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
+ } else {
+ switch (rawEvent->type) {
+ case EventHubInterface::DEVICE_ADDED:
+ addDeviceLocked(rawEvent->when, rawEvent->deviceId);
+ break;
+ case EventHubInterface::DEVICE_REMOVED:
+ removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
+ break;
+ case EventHubInterface::FINISHED_DEVICE_SCAN:
+ handleConfigurationChangedLocked(rawEvent->when);
+ break;
+ default:
+ ALOG_ASSERT(false); // can't happen
+ break;
+ }
+ }
+ count -= batchSize;
+ rawEvent += batchSize;
+ }
+}
+
+void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex >= 0) {
+ ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
+ return;
+ }
+
+ InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
+ uint32_t classes = mEventHub->getDeviceClasses(deviceId);
+ int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
+
+ InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
+ device->configure(when, &mConfig, 0);
+ device->reset(when);
+
+ if (device->isIgnored()) {
+ ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
+ identifier.name.c_str());
+ } else {
+ ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
+ identifier.name.c_str(), device->getSources());
+ }
+
+ mDevices.add(deviceId, device);
+ bumpGenerationLocked();
+
+ if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ notifyExternalStylusPresenceChanged();
+ }
+}
+
+void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
+ InputDevice* device = nullptr;
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex < 0) {
+ ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
+ return;
+ }
+
+ device = mDevices.valueAt(deviceIndex);
+ mDevices.removeItemsAt(deviceIndex, 1);
+ bumpGenerationLocked();
+
+ if (device->isIgnored()) {
+ ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
+ device->getId(), device->getName().c_str());
+ } else {
+ ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
+ device->getId(), device->getName().c_str(), device->getSources());
+ }
+
+ if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ notifyExternalStylusPresenceChanged();
+ }
+
+ device->reset(when);
+ delete device;
+}
+
+InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
+ const InputDeviceIdentifier& identifier, uint32_t classes) {
+ InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
+ controllerNumber, identifier, classes);
+
+ // External devices.
+ if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
+ device->setExternal(true);
+ }
+
+ // Devices with mics.
+ if (classes & INPUT_DEVICE_CLASS_MIC) {
+ device->setMic(true);
+ }
+
+ // Switch-like devices.
+ if (classes & INPUT_DEVICE_CLASS_SWITCH) {
+ device->addMapper(new SwitchInputMapper(device));
+ }
+
+ // Scroll wheel-like devices.
+ if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
+ device->addMapper(new RotaryEncoderInputMapper(device));
+ }
+
+ // Vibrator-like devices.
+ if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
+ device->addMapper(new VibratorInputMapper(device));
+ }
+
+ // Keyboard-like devices.
+ uint32_t keyboardSource = 0;
+ int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
+ if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
+ keyboardSource |= AINPUT_SOURCE_KEYBOARD;
+ }
+ if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
+ keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
+ }
+ if (classes & INPUT_DEVICE_CLASS_DPAD) {
+ keyboardSource |= AINPUT_SOURCE_DPAD;
+ }
+ if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
+ keyboardSource |= AINPUT_SOURCE_GAMEPAD;
+ }
+
+ if (keyboardSource != 0) {
+ device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
+ }
+
+ // Cursor-like devices.
+ if (classes & INPUT_DEVICE_CLASS_CURSOR) {
+ device->addMapper(new CursorInputMapper(device));
+ }
+
+ // Touchscreens and touchpad devices.
+ if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
+ device->addMapper(new MultiTouchInputMapper(device));
+ } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
+ device->addMapper(new SingleTouchInputMapper(device));
+ }
+
+ // Joystick-like devices.
+ if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
+ device->addMapper(new JoystickInputMapper(device));
+ }
+
+ // External stylus-like devices.
+ if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ device->addMapper(new ExternalStylusInputMapper(device));
+ }
+
+ return device;
+}
+
+void InputReader::processEventsForDeviceLocked(int32_t deviceId,
+ const RawEvent* rawEvents, size_t count) {
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex < 0) {
+ ALOGW("Discarding event for unknown deviceId %d.", deviceId);
+ return;
+ }
+
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ if (device->isIgnored()) {
+ //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
+ return;
+ }
+
+ device->process(rawEvents, count);
+}
+
+void InputReader::timeoutExpiredLocked(nsecs_t when) {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ if (!device->isIgnored()) {
+ device->timeoutExpired(when);
+ }
+ }
+}
+
+void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
+ // Reset global meta state because it depends on the list of all configured devices.
+ updateGlobalMetaStateLocked();
+
+ // Enqueue configuration changed.
+ NotifyConfigurationChangedArgs args(mContext.getNextSequenceNum(), when);
+ mQueuedListener->notifyConfigurationChanged(&args);
+}
+
+void InputReader::refreshConfigurationLocked(uint32_t changes) {
+ mPolicy->getReaderConfiguration(&mConfig);
+ mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
+
+ if (changes) {
+ ALOGI("Reconfiguring input devices. changes=0x%08x", changes);
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
+ mEventHub->requestReopenDevices();
+ } else {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ device->configure(now, &mConfig, changes);
+ }
+ }
+ }
+}
+
+void InputReader::updateGlobalMetaStateLocked() {
+ mGlobalMetaState = 0;
+
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ mGlobalMetaState |= device->getMetaState();
+ }
+}
+
+int32_t InputReader::getGlobalMetaStateLocked() {
+ return mGlobalMetaState;
+}
+
+void InputReader::notifyExternalStylusPresenceChanged() {
+ refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
+}
+
+void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
+ InputDeviceInfo info;
+ device->getDeviceInfo(&info);
+ outDevices.push_back(info);
+ }
+ }
+}
+
+void InputReader::dispatchExternalStylusState(const StylusState& state) {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ device->updateExternalStylusState(state);
+ }
+}
+
+void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
+ mDisableVirtualKeysTimeout = time;
+}
+
+bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
+ InputDevice* device, int32_t keyCode, int32_t scanCode) {
+ if (now < mDisableVirtualKeysTimeout) {
+ ALOGI("Dropping virtual key from device %s because virtual keys are "
+ "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
+ device->getName().c_str(),
+ (mDisableVirtualKeysTimeout - now) * 0.000001,
+ keyCode, scanCode);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void InputReader::fadePointerLocked() {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ device->fadePointer();
+ }
+}
+
+void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
+ if (when < mNextTimeout) {
+ mNextTimeout = when;
+ mEventHub->wake();
+ }
+}
+
+int32_t InputReader::bumpGenerationLocked() {
+ return ++mGeneration;
+}
+
+void InputReader::getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) {
+ AutoMutex _l(mLock);
+ getInputDevicesLocked(outInputDevices);
+}
+
+void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) {
+ outInputDevices.clear();
+
+ size_t numDevices = mDevices.size();
+ for (size_t i = 0; i < numDevices; i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ if (!device->isIgnored()) {
+ InputDeviceInfo info;
+ device->getDeviceInfo(&info);
+ outInputDevices.push_back(info);
+ }
+ }
+}
+
+int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+ int32_t keyCode) {
+ AutoMutex _l(mLock);
+
+ return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
+}
+
+int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+ int32_t scanCode) {
+ AutoMutex _l(mLock);
+
+ return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
+}
+
+int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
+ AutoMutex _l(mLock);
+
+ return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
+}
+
+int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
+ GetStateFunc getStateFunc) {
+ int32_t result = AKEY_STATE_UNKNOWN;
+ if (deviceId >= 0) {
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex >= 0) {
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+ result = (device->*getStateFunc)(sourceMask, code);
+ }
+ }
+ } else {
+ size_t numDevices = mDevices.size();
+ for (size_t i = 0; i < numDevices; i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+ // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
+ // value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
+ int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
+ if (currentResult >= AKEY_STATE_DOWN) {
+ return currentResult;
+ } else if (currentResult == AKEY_STATE_UP) {
+ result = currentResult;
+ }
+ }
+ }
+ }
+ return result;
+}
+
+void InputReader::toggleCapsLockState(int32_t deviceId) {
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex < 0) {
+ ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
+ return;
+ }
+
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ if (device->isIgnored()) {
+ return;
+ }
+
+ device->updateMetaState(AKEYCODE_CAPS_LOCK);
+}
+
+bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
+ size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
+ AutoMutex _l(mLock);
+
+ memset(outFlags, 0, numCodes);
+ return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
+}
+
+bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
+ size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
+ bool result = false;
+ if (deviceId >= 0) {
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex >= 0) {
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+ result = device->markSupportedKeyCodes(sourceMask,
+ numCodes, keyCodes, outFlags);
+ }
+ }
+ } else {
+ size_t numDevices = mDevices.size();
+ for (size_t i = 0; i < numDevices; i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+ result |= device->markSupportedKeyCodes(sourceMask,
+ numCodes, keyCodes, outFlags);
+ }
+ }
+ }
+ return result;
+}
+
+void InputReader::requestRefreshConfiguration(uint32_t changes) {
+ AutoMutex _l(mLock);
+
+ if (changes) {
+ bool needWake = !mConfigurationChangesToRefresh;
+ mConfigurationChangesToRefresh |= changes;
+
+ if (needWake) {
+ mEventHub->wake();
+ }
+ }
+}
+
+void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
+ ssize_t repeat, int32_t token) {
+ AutoMutex _l(mLock);
+
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex >= 0) {
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ device->vibrate(pattern, patternSize, repeat, token);
+ }
+}
+
+void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
+ AutoMutex _l(mLock);
+
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex >= 0) {
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ device->cancelVibrate(token);
+ }
+}
+
+bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
+ AutoMutex _l(mLock);
+
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex >= 0) {
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ return device->isEnabled();
+ }
+ ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
+ return false;
+}
+
+bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) {
+ AutoMutex _l(mLock);
+
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex < 0) {
+ ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
+ return false;
+ }
+
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplay();
+ // No associated display. By default, can dispatch to all displays.
+ if (!associatedDisplayId) {
+ return true;
+ }
+
+ if (*associatedDisplayId == ADISPLAY_ID_NONE) {
+ ALOGW("Device has associated, but no associated display id.");
+ return true;
+ }
+
+ return *associatedDisplayId == displayId;
+}
+
+void InputReader::dump(std::string& dump) {
+ AutoMutex _l(mLock);
+
+ mEventHub->dump(dump);
+ dump += "\n";
+
+ dump += "Input Reader State:\n";
+
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ mDevices.valueAt(i)->dump(dump);
+ }
+
+ dump += INDENT "Configuration:\n";
+ dump += INDENT2 "ExcludedDeviceNames: [";
+ for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
+ if (i != 0) {
+ dump += ", ";
+ }
+ dump += mConfig.excludedDeviceNames[i];
+ }
+ dump += "]\n";
+ dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
+ mConfig.virtualKeyQuietTime * 0.000001f);
+
+ dump += StringPrintf(INDENT2 "PointerVelocityControlParameters: "
+ "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
+ mConfig.pointerVelocityControlParameters.scale,
+ mConfig.pointerVelocityControlParameters.lowThreshold,
+ mConfig.pointerVelocityControlParameters.highThreshold,
+ mConfig.pointerVelocityControlParameters.acceleration);
+
+ dump += StringPrintf(INDENT2 "WheelVelocityControlParameters: "
+ "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
+ mConfig.wheelVelocityControlParameters.scale,
+ mConfig.wheelVelocityControlParameters.lowThreshold,
+ mConfig.wheelVelocityControlParameters.highThreshold,
+ mConfig.wheelVelocityControlParameters.acceleration);
+
+ dump += StringPrintf(INDENT2 "PointerGesture:\n");
+ dump += StringPrintf(INDENT3 "Enabled: %s\n",
+ toString(mConfig.pointerGesturesEnabled));
+ dump += StringPrintf(INDENT3 "QuietInterval: %0.1fms\n",
+ mConfig.pointerGestureQuietInterval * 0.000001f);
+ dump += StringPrintf(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
+ mConfig.pointerGestureDragMinSwitchSpeed);
+ dump += StringPrintf(INDENT3 "TapInterval: %0.1fms\n",
+ mConfig.pointerGestureTapInterval * 0.000001f);
+ dump += StringPrintf(INDENT3 "TapDragInterval: %0.1fms\n",
+ mConfig.pointerGestureTapDragInterval * 0.000001f);
+ dump += StringPrintf(INDENT3 "TapSlop: %0.1fpx\n",
+ mConfig.pointerGestureTapSlop);
+ dump += StringPrintf(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
+ mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
+ dump += StringPrintf(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
+ mConfig.pointerGestureMultitouchMinDistance);
+ dump += StringPrintf(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
+ mConfig.pointerGestureSwipeTransitionAngleCosine);
+ dump += StringPrintf(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
+ mConfig.pointerGestureSwipeMaxWidthRatio);
+ dump += StringPrintf(INDENT3 "MovementSpeedRatio: %0.1f\n",
+ mConfig.pointerGestureMovementSpeedRatio);
+ dump += StringPrintf(INDENT3 "ZoomSpeedRatio: %0.1f\n",
+ mConfig.pointerGestureZoomSpeedRatio);
+
+ dump += INDENT3 "Viewports:\n";
+ mConfig.dump(dump);
+}
+
+void InputReader::monitor() {
+ // Acquire and release the lock to ensure that the reader has not deadlocked.
+ mLock.lock();
+ mEventHub->wake();
+ mReaderIsAliveCondition.wait(mLock);
+ mLock.unlock();
+
+ // Check the EventHub
+ mEventHub->monitor();
+}
+
+
+// --- InputReader::ContextImpl ---
+
+InputReader::ContextImpl::ContextImpl(InputReader* reader) :
+ mReader(reader) {
+}
+
+void InputReader::ContextImpl::updateGlobalMetaState() {
+ // lock is already held by the input loop
+ mReader->updateGlobalMetaStateLocked();
+}
+
+int32_t InputReader::ContextImpl::getGlobalMetaState() {
+ // lock is already held by the input loop
+ return mReader->getGlobalMetaStateLocked();
+}
+
+void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
+ // lock is already held by the input loop
+ mReader->disableVirtualKeysUntilLocked(time);
+}
+
+bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
+ InputDevice* device, int32_t keyCode, int32_t scanCode) {
+ // lock is already held by the input loop
+ return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
+}
+
+void InputReader::ContextImpl::fadePointer() {
+ // lock is already held by the input loop
+ mReader->fadePointerLocked();
+}
+
+void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
+ // lock is already held by the input loop
+ mReader->requestTimeoutAtTimeLocked(when);
+}
+
+int32_t InputReader::ContextImpl::bumpGeneration() {
+ // lock is already held by the input loop
+ return mReader->bumpGenerationLocked();
+}
+
+void InputReader::ContextImpl::getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) {
+ // lock is already held by whatever called refreshConfigurationLocked
+ mReader->getExternalStylusDevicesLocked(outDevices);
+}
+
+void InputReader::ContextImpl::dispatchExternalStylusState(const StylusState& state) {
+ mReader->dispatchExternalStylusState(state);
+}
+
+InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
+ return mReader->mPolicy.get();
+}
+
+InputListenerInterface* InputReader::ContextImpl::getListener() {
+ return mReader->mQueuedListener.get();
+}
+
+EventHubInterface* InputReader::ContextImpl::getEventHub() {
+ return mReader->mEventHub.get();
+}
+
+uint32_t InputReader::ContextImpl::getNextSequenceNum() {
+ return (mReader->mNextSequenceNum)++;
+}
+
+// --- InputDevice ---
+
+InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
+ int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) :
+ mContext(context), mId(id), mGeneration(generation), mControllerNumber(controllerNumber),
+ mIdentifier(identifier), mClasses(classes),
+ mSources(0), mIsExternal(false), mHasMic(false), mDropUntilNextSync(false) {
+}
+
+InputDevice::~InputDevice() {
+ size_t numMappers = mMappers.size();
+ for (size_t i = 0; i < numMappers; i++) {
+ delete mMappers[i];
+ }
+ mMappers.clear();
+}
+
+bool InputDevice::isEnabled() {
+ return getEventHub()->isDeviceEnabled(mId);
+}
+
+void InputDevice::setEnabled(bool enabled, nsecs_t when) {
+ if (isEnabled() == enabled) {
+ return;
+ }
+
+ if (enabled) {
+ getEventHub()->enableDevice(mId);
+ reset(when);
+ } else {
+ reset(when);
+ getEventHub()->disableDevice(mId);
+ }
+ // Must change generation to flag this device as changed
+ bumpGeneration();
+}
+
+void InputDevice::dump(std::string& dump) {
+ InputDeviceInfo deviceInfo;
+ getDeviceInfo(&deviceInfo);
+
+ dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
+ deviceInfo.getDisplayName().c_str());
+ dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
+ dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
+ dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
+ if (mAssociatedDisplayPort) {
+ dump += StringPrintf("%" PRIu8 "\n", *mAssociatedDisplayPort);
+ } else {
+ dump += "<none>\n";
+ }
+ dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
+ dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
+ dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
+
+ const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
+ if (!ranges.empty()) {
+ dump += INDENT2 "Motion Ranges:\n";
+ for (size_t i = 0; i < ranges.size(); i++) {
+ const InputDeviceInfo::MotionRange& range = ranges[i];
+ const char* label = getAxisLabel(range.axis);
+ char name[32];
+ if (label) {
+ strncpy(name, label, sizeof(name));
+ name[sizeof(name) - 1] = '\0';
+ } else {
+ snprintf(name, sizeof(name), "%d", range.axis);
+ }
+ dump += StringPrintf(INDENT3 "%s: source=0x%08x, "
+ "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
+ name, range.source, range.min, range.max, range.flat, range.fuzz,
+ range.resolution);
+ }
+ }
+
+ size_t numMappers = mMappers.size();
+ for (size_t i = 0; i < numMappers; i++) {
+ InputMapper* mapper = mMappers[i];
+ mapper->dump(dump);
+ }
+}
+
+void InputDevice::addMapper(InputMapper* mapper) {
+ mMappers.push_back(mapper);
+}
+
+void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
+ mSources = 0;
+
+ if (!isIgnored()) {
+ if (!changes) { // first time only
+ mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
+ }
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
+ if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
+ sp<KeyCharacterMap> keyboardLayout =
+ mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
+ if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
+ bumpGeneration();
+ }
+ }
+ }
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
+ if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
+ std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
+ if (mAlias != alias) {
+ mAlias = alias;
+ bumpGeneration();
+ }
+ }
+ }
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
+ ssize_t index = config->disabledDevices.indexOf(mId);
+ bool enabled = index < 0;
+ setEnabled(enabled, when);
+ }
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ // In most situations, no port will be specified.
+ mAssociatedDisplayPort = std::nullopt;
+ // Find the display port that corresponds to the current input port.
+ const std::string& inputPort = mIdentifier.location;
+ if (!inputPort.empty()) {
+ const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
+ const auto& displayPort = ports.find(inputPort);
+ if (displayPort != ports.end()) {
+ mAssociatedDisplayPort = std::make_optional(displayPort->second);
+ }
+ }
+ }
+
+ for (InputMapper* mapper : mMappers) {
+ mapper->configure(when, config, changes);
+ mSources |= mapper->getSources();
+ }
+ }
+}
+
+void InputDevice::reset(nsecs_t when) {
+ for (InputMapper* mapper : mMappers) {
+ mapper->reset(when);
+ }
+
+ mContext->updateGlobalMetaState();
+
+ notifyReset(when);
+}
+
+void InputDevice::process(const RawEvent* rawEvents, size_t count) {
+ // Process all of the events in order for each mapper.
+ // We cannot simply ask each mapper to process them in bulk because mappers may
+ // have side-effects that must be interleaved. For example, joystick movement events and
+ // gamepad button presses are handled by different mappers but they should be dispatched
+ // in the order received.
+ for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
+#if DEBUG_RAW_EVENTS
+ ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
+ rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
+ rawEvent->when);
+#endif
+
+ if (mDropUntilNextSync) {
+ if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+ mDropUntilNextSync = false;
+#if DEBUG_RAW_EVENTS
+ ALOGD("Recovered from input event buffer overrun.");
+#endif
+ } else {
+#if DEBUG_RAW_EVENTS
+ ALOGD("Dropped input event while waiting for next input sync.");
+#endif
+ }
+ } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
+ ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
+ mDropUntilNextSync = true;
+ reset(rawEvent->when);
+ } else {
+ for (InputMapper* mapper : mMappers) {
+ mapper->process(rawEvent);
+ }
+ }
+ --count;
+ }
+}
+
+void InputDevice::timeoutExpired(nsecs_t when) {
+ for (InputMapper* mapper : mMappers) {
+ mapper->timeoutExpired(when);
+ }
+}
+
+void InputDevice::updateExternalStylusState(const StylusState& state) {
+ for (InputMapper* mapper : mMappers) {
+ mapper->updateExternalStylusState(state);
+ }
+}
+
+void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
+ outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias,
+ mIsExternal, mHasMic);
+ for (InputMapper* mapper : mMappers) {
+ mapper->populateDeviceInfo(outDeviceInfo);
+ }
+}
+
+int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+ return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
+}
+
+int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+ return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
+}
+
+int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+ return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
+}
+
+int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
+ int32_t result = AKEY_STATE_UNKNOWN;
+ for (InputMapper* mapper : mMappers) {
+ if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
+ // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
+ // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
+ int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
+ if (currentResult >= AKEY_STATE_DOWN) {
+ return currentResult;
+ } else if (currentResult == AKEY_STATE_UP) {
+ result = currentResult;
+ }
+ }
+ }
+ return result;
+}
+
+bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags) {
+ bool result = false;
+ for (InputMapper* mapper : mMappers) {
+ if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
+ result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
+ }
+ }
+ return result;
+}
+
+void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+ int32_t token) {
+ for (InputMapper* mapper : mMappers) {
+ mapper->vibrate(pattern, patternSize, repeat, token);
+ }
+}
+
+void InputDevice::cancelVibrate(int32_t token) {
+ for (InputMapper* mapper : mMappers) {
+ mapper->cancelVibrate(token);
+ }
+}
+
+void InputDevice::cancelTouch(nsecs_t when) {
+ for (InputMapper* mapper : mMappers) {
+ mapper->cancelTouch(when);
+ }
+}
+
+int32_t InputDevice::getMetaState() {
+ int32_t result = 0;
+ for (InputMapper* mapper : mMappers) {
+ result |= mapper->getMetaState();
+ }
+ return result;
+}
+
+void InputDevice::updateMetaState(int32_t keyCode) {
+ for (InputMapper* mapper : mMappers) {
+ mapper->updateMetaState(keyCode);
+ }
+}
+
+void InputDevice::fadePointer() {
+ for (InputMapper* mapper : mMappers) {
+ mapper->fadePointer();
+ }
+}
+
+void InputDevice::bumpGeneration() {
+ mGeneration = mContext->bumpGeneration();
+}
+
+void InputDevice::notifyReset(nsecs_t when) {
+ NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
+ mContext->getListener()->notifyDeviceReset(&args);
+}
+
+std::optional<int32_t> InputDevice::getAssociatedDisplay() {
+ for (InputMapper* mapper : mMappers) {
+ std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay();
+ if (associatedDisplayId) {
+ return associatedDisplayId;
+ }
+ }
+
+ return std::nullopt;
+}
+
+// --- CursorButtonAccumulator ---
+
+CursorButtonAccumulator::CursorButtonAccumulator() {
+ clearButtons();
+}
+
+void CursorButtonAccumulator::reset(InputDevice* device) {
+ mBtnLeft = device->isKeyPressed(BTN_LEFT);
+ mBtnRight = device->isKeyPressed(BTN_RIGHT);
+ mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
+ mBtnBack = device->isKeyPressed(BTN_BACK);
+ mBtnSide = device->isKeyPressed(BTN_SIDE);
+ mBtnForward = device->isKeyPressed(BTN_FORWARD);
+ mBtnExtra = device->isKeyPressed(BTN_EXTRA);
+ mBtnTask = device->isKeyPressed(BTN_TASK);
+}
+
+void CursorButtonAccumulator::clearButtons() {
+ mBtnLeft = 0;
+ mBtnRight = 0;
+ mBtnMiddle = 0;
+ mBtnBack = 0;
+ mBtnSide = 0;
+ mBtnForward = 0;
+ mBtnExtra = 0;
+ mBtnTask = 0;
+}
+
+void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_KEY) {
+ switch (rawEvent->code) {
+ case BTN_LEFT:
+ mBtnLeft = rawEvent->value;
+ break;
+ case BTN_RIGHT:
+ mBtnRight = rawEvent->value;
+ break;
+ case BTN_MIDDLE:
+ mBtnMiddle = rawEvent->value;
+ break;
+ case BTN_BACK:
+ mBtnBack = rawEvent->value;
+ break;
+ case BTN_SIDE:
+ mBtnSide = rawEvent->value;
+ break;
+ case BTN_FORWARD:
+ mBtnForward = rawEvent->value;
+ break;
+ case BTN_EXTRA:
+ mBtnExtra = rawEvent->value;
+ break;
+ case BTN_TASK:
+ mBtnTask = rawEvent->value;
+ break;
+ }
+ }
+}
+
+uint32_t CursorButtonAccumulator::getButtonState() const {
+ uint32_t result = 0;
+ if (mBtnLeft) {
+ result |= AMOTION_EVENT_BUTTON_PRIMARY;
+ }
+ if (mBtnRight) {
+ result |= AMOTION_EVENT_BUTTON_SECONDARY;
+ }
+ if (mBtnMiddle) {
+ result |= AMOTION_EVENT_BUTTON_TERTIARY;
+ }
+ if (mBtnBack || mBtnSide) {
+ result |= AMOTION_EVENT_BUTTON_BACK;
+ }
+ if (mBtnForward || mBtnExtra) {
+ result |= AMOTION_EVENT_BUTTON_FORWARD;
+ }
+ return result;
+}
+
+
+// --- CursorMotionAccumulator ---
+
+CursorMotionAccumulator::CursorMotionAccumulator() {
+ clearRelativeAxes();
+}
+
+void CursorMotionAccumulator::reset(InputDevice* device) {
+ clearRelativeAxes();
+}
+
+void CursorMotionAccumulator::clearRelativeAxes() {
+ mRelX = 0;
+ mRelY = 0;
+}
+
+void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_REL) {
+ switch (rawEvent->code) {
+ case REL_X:
+ mRelX = rawEvent->value;
+ break;
+ case REL_Y:
+ mRelY = rawEvent->value;
+ break;
+ }
+ }
+}
+
+void CursorMotionAccumulator::finishSync() {
+ clearRelativeAxes();
+}
+
+
+// --- CursorScrollAccumulator ---
+
+CursorScrollAccumulator::CursorScrollAccumulator() :
+ mHaveRelWheel(false), mHaveRelHWheel(false) {
+ clearRelativeAxes();
+}
+
+void CursorScrollAccumulator::configure(InputDevice* device) {
+ mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
+ mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
+}
+
+void CursorScrollAccumulator::reset(InputDevice* device) {
+ clearRelativeAxes();
+}
+
+void CursorScrollAccumulator::clearRelativeAxes() {
+ mRelWheel = 0;
+ mRelHWheel = 0;
+}
+
+void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_REL) {
+ switch (rawEvent->code) {
+ case REL_WHEEL:
+ mRelWheel = rawEvent->value;
+ break;
+ case REL_HWHEEL:
+ mRelHWheel = rawEvent->value;
+ break;
+ }
+ }
+}
+
+void CursorScrollAccumulator::finishSync() {
+ clearRelativeAxes();
+}
+
+
+// --- TouchButtonAccumulator ---
+
+TouchButtonAccumulator::TouchButtonAccumulator() :
+ mHaveBtnTouch(false), mHaveStylus(false) {
+ clearButtons();
+}
+
+void TouchButtonAccumulator::configure(InputDevice* device) {
+ mHaveBtnTouch = device->hasKey(BTN_TOUCH);
+ mHaveStylus = device->hasKey(BTN_TOOL_PEN)
+ || device->hasKey(BTN_TOOL_RUBBER)
+ || device->hasKey(BTN_TOOL_BRUSH)
+ || device->hasKey(BTN_TOOL_PENCIL)
+ || device->hasKey(BTN_TOOL_AIRBRUSH);
+}
+
+void TouchButtonAccumulator::reset(InputDevice* device) {
+ mBtnTouch = device->isKeyPressed(BTN_TOUCH);
+ mBtnStylus = device->isKeyPressed(BTN_STYLUS);
+ // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
+ mBtnStylus2 =
+ device->isKeyPressed(BTN_STYLUS2) || device->isKeyPressed(BTN_0);
+ mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
+ mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
+ mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
+ mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
+ mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
+ mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
+ mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
+ mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
+ mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
+ mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
+ mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
+}
+
+void TouchButtonAccumulator::clearButtons() {
+ mBtnTouch = 0;
+ mBtnStylus = 0;
+ mBtnStylus2 = 0;
+ mBtnToolFinger = 0;
+ mBtnToolPen = 0;
+ mBtnToolRubber = 0;
+ mBtnToolBrush = 0;
+ mBtnToolPencil = 0;
+ mBtnToolAirbrush = 0;
+ mBtnToolMouse = 0;
+ mBtnToolLens = 0;
+ mBtnToolDoubleTap = 0;
+ mBtnToolTripleTap = 0;
+ mBtnToolQuadTap = 0;
+}
+
+void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_KEY) {
+ switch (rawEvent->code) {
+ case BTN_TOUCH:
+ mBtnTouch = rawEvent->value;
+ break;
+ case BTN_STYLUS:
+ mBtnStylus = rawEvent->value;
+ break;
+ case BTN_STYLUS2:
+ case BTN_0:// BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
+ mBtnStylus2 = rawEvent->value;
+ break;
+ case BTN_TOOL_FINGER:
+ mBtnToolFinger = rawEvent->value;
+ break;
+ case BTN_TOOL_PEN:
+ mBtnToolPen = rawEvent->value;
+ break;
+ case BTN_TOOL_RUBBER:
+ mBtnToolRubber = rawEvent->value;
+ break;
+ case BTN_TOOL_BRUSH:
+ mBtnToolBrush = rawEvent->value;
+ break;
+ case BTN_TOOL_PENCIL:
+ mBtnToolPencil = rawEvent->value;
+ break;
+ case BTN_TOOL_AIRBRUSH:
+ mBtnToolAirbrush = rawEvent->value;
+ break;
+ case BTN_TOOL_MOUSE:
+ mBtnToolMouse = rawEvent->value;
+ break;
+ case BTN_TOOL_LENS:
+ mBtnToolLens = rawEvent->value;
+ break;
+ case BTN_TOOL_DOUBLETAP:
+ mBtnToolDoubleTap = rawEvent->value;
+ break;
+ case BTN_TOOL_TRIPLETAP:
+ mBtnToolTripleTap = rawEvent->value;
+ break;
+ case BTN_TOOL_QUADTAP:
+ mBtnToolQuadTap = rawEvent->value;
+ break;
+ }
+ }
+}
+
+uint32_t TouchButtonAccumulator::getButtonState() const {
+ uint32_t result = 0;
+ if (mBtnStylus) {
+ result |= AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
+ }
+ if (mBtnStylus2) {
+ result |= AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
+ }
+ return result;
+}
+
+int32_t TouchButtonAccumulator::getToolType() const {
+ if (mBtnToolMouse || mBtnToolLens) {
+ return AMOTION_EVENT_TOOL_TYPE_MOUSE;
+ }
+ if (mBtnToolRubber) {
+ return AMOTION_EVENT_TOOL_TYPE_ERASER;
+ }
+ if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
+ return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ }
+ if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
+ return AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
+ return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+bool TouchButtonAccumulator::isToolActive() const {
+ return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
+ || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
+ || mBtnToolMouse || mBtnToolLens
+ || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
+}
+
+bool TouchButtonAccumulator::isHovering() const {
+ return mHaveBtnTouch && !mBtnTouch;
+}
+
+bool TouchButtonAccumulator::hasStylus() const {
+ return mHaveStylus;
+}
+
+
+// --- RawPointerAxes ---
+
+RawPointerAxes::RawPointerAxes() {
+ clear();
+}
+
+void RawPointerAxes::clear() {
+ x.clear();
+ y.clear();
+ pressure.clear();
+ touchMajor.clear();
+ touchMinor.clear();
+ toolMajor.clear();
+ toolMinor.clear();
+ orientation.clear();
+ distance.clear();
+ tiltX.clear();
+ tiltY.clear();
+ trackingId.clear();
+ slot.clear();
+}
+
+
+// --- RawPointerData ---
+
+RawPointerData::RawPointerData() {
+ clear();
+}
+
+void RawPointerData::clear() {
+ pointerCount = 0;
+ clearIdBits();
+}
+
+void RawPointerData::copyFrom(const RawPointerData& other) {
+ pointerCount = other.pointerCount;
+ hoveringIdBits = other.hoveringIdBits;
+ touchingIdBits = other.touchingIdBits;
+
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ pointers[i] = other.pointers[i];
+
+ int id = pointers[i].id;
+ idToIndex[id] = other.idToIndex[id];
+ }
+}
+
+void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
+ float x = 0, y = 0;
+ uint32_t count = touchingIdBits.count();
+ if (count) {
+ for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const Pointer& pointer = pointerForId(id);
+ x += pointer.x;
+ y += pointer.y;
+ }
+ x /= count;
+ y /= count;
+ }
+ *outX = x;
+ *outY = y;
+}
+
+
+// --- CookedPointerData ---
+
+CookedPointerData::CookedPointerData() {
+ clear();
+}
+
+void CookedPointerData::clear() {
+ pointerCount = 0;
+ hoveringIdBits.clear();
+ touchingIdBits.clear();
+}
+
+void CookedPointerData::copyFrom(const CookedPointerData& other) {
+ pointerCount = other.pointerCount;
+ hoveringIdBits = other.hoveringIdBits;
+ touchingIdBits = other.touchingIdBits;
+
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].copyFrom(other.pointerProperties[i]);
+ pointerCoords[i].copyFrom(other.pointerCoords[i]);
+
+ int id = pointerProperties[i].id;
+ idToIndex[id] = other.idToIndex[id];
+ }
+}
+
+
+// --- SingleTouchMotionAccumulator ---
+
+SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
+ clearAbsoluteAxes();
+}
+
+void SingleTouchMotionAccumulator::reset(InputDevice* device) {
+ mAbsX = device->getAbsoluteAxisValue(ABS_X);
+ mAbsY = device->getAbsoluteAxisValue(ABS_Y);
+ mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
+ mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
+ mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
+ mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
+ mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
+}
+
+void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
+ mAbsX = 0;
+ mAbsY = 0;
+ mAbsPressure = 0;
+ mAbsToolWidth = 0;
+ mAbsDistance = 0;
+ mAbsTiltX = 0;
+ mAbsTiltY = 0;
+}
+
+void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_ABS) {
+ switch (rawEvent->code) {
+ case ABS_X:
+ mAbsX = rawEvent->value;
+ break;
+ case ABS_Y:
+ mAbsY = rawEvent->value;
+ break;
+ case ABS_PRESSURE:
+ mAbsPressure = rawEvent->value;
+ break;
+ case ABS_TOOL_WIDTH:
+ mAbsToolWidth = rawEvent->value;
+ break;
+ case ABS_DISTANCE:
+ mAbsDistance = rawEvent->value;
+ break;
+ case ABS_TILT_X:
+ mAbsTiltX = rawEvent->value;
+ break;
+ case ABS_TILT_Y:
+ mAbsTiltY = rawEvent->value;
+ break;
+ }
+ }
+}
+
+
+// --- MultiTouchMotionAccumulator ---
+
+MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
+ mCurrentSlot(-1), mSlots(nullptr), mSlotCount(0), mUsingSlotsProtocol(false),
+ mHaveStylus(false), mDeviceTimestamp(0) {
+}
+
+MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
+ delete[] mSlots;
+}
+
+void MultiTouchMotionAccumulator::configure(InputDevice* device,
+ size_t slotCount, bool usingSlotsProtocol) {
+ mSlotCount = slotCount;
+ mUsingSlotsProtocol = usingSlotsProtocol;
+ mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
+
+ delete[] mSlots;
+ mSlots = new Slot[slotCount];
+}
+
+void MultiTouchMotionAccumulator::reset(InputDevice* device) {
+ // Unfortunately there is no way to read the initial contents of the slots.
+ // So when we reset the accumulator, we must assume they are all zeroes.
+ if (mUsingSlotsProtocol) {
+ // Query the driver for the current slot index and use it as the initial slot
+ // before we start reading events from the device. It is possible that the
+ // current slot index will not be the same as it was when the first event was
+ // written into the evdev buffer, which means the input mapper could start
+ // out of sync with the initial state of the events in the evdev buffer.
+ // In the extremely unlikely case that this happens, the data from
+ // two slots will be confused until the next ABS_MT_SLOT event is received.
+ // This can cause the touch point to "jump", but at least there will be
+ // no stuck touches.
+ int32_t initialSlot;
+ status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
+ ABS_MT_SLOT, &initialSlot);
+ if (status) {
+ ALOGD("Could not retrieve current multitouch slot index. status=%d", status);
+ initialSlot = -1;
+ }
+ clearSlots(initialSlot);
+ } else {
+ clearSlots(-1);
+ }
+ mDeviceTimestamp = 0;
+}
+
+void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
+ if (mSlots) {
+ for (size_t i = 0; i < mSlotCount; i++) {
+ mSlots[i].clear();
+ }
+ }
+ mCurrentSlot = initialSlot;
+}
+
+void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_ABS) {
+ bool newSlot = false;
+ if (mUsingSlotsProtocol) {
+ if (rawEvent->code == ABS_MT_SLOT) {
+ mCurrentSlot = rawEvent->value;
+ newSlot = true;
+ }
+ } else if (mCurrentSlot < 0) {
+ mCurrentSlot = 0;
+ }
+
+ if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
+#if DEBUG_POINTERS
+ if (newSlot) {
+ ALOGW("MultiTouch device emitted invalid slot index %d but it "
+ "should be between 0 and %zd; ignoring this slot.",
+ mCurrentSlot, mSlotCount - 1);
+ }
+#endif
+ } else {
+ Slot* slot = &mSlots[mCurrentSlot];
+
+ switch (rawEvent->code) {
+ case ABS_MT_POSITION_X:
+ slot->mInUse = true;
+ slot->mAbsMTPositionX = rawEvent->value;
+ break;
+ case ABS_MT_POSITION_Y:
+ slot->mInUse = true;
+ slot->mAbsMTPositionY = rawEvent->value;
+ break;
+ case ABS_MT_TOUCH_MAJOR:
+ slot->mInUse = true;
+ slot->mAbsMTTouchMajor = rawEvent->value;
+ break;
+ case ABS_MT_TOUCH_MINOR:
+ slot->mInUse = true;
+ slot->mAbsMTTouchMinor = rawEvent->value;
+ slot->mHaveAbsMTTouchMinor = true;
+ break;
+ case ABS_MT_WIDTH_MAJOR:
+ slot->mInUse = true;
+ slot->mAbsMTWidthMajor = rawEvent->value;
+ break;
+ case ABS_MT_WIDTH_MINOR:
+ slot->mInUse = true;
+ slot->mAbsMTWidthMinor = rawEvent->value;
+ slot->mHaveAbsMTWidthMinor = true;
+ break;
+ case ABS_MT_ORIENTATION:
+ slot->mInUse = true;
+ slot->mAbsMTOrientation = rawEvent->value;
+ break;
+ case ABS_MT_TRACKING_ID:
+ if (mUsingSlotsProtocol && rawEvent->value < 0) {
+ // The slot is no longer in use but it retains its previous contents,
+ // which may be reused for subsequent touches.
+ slot->mInUse = false;
+ } else {
+ slot->mInUse = true;
+ slot->mAbsMTTrackingId = rawEvent->value;
+ }
+ break;
+ case ABS_MT_PRESSURE:
+ slot->mInUse = true;
+ slot->mAbsMTPressure = rawEvent->value;
+ break;
+ case ABS_MT_DISTANCE:
+ slot->mInUse = true;
+ slot->mAbsMTDistance = rawEvent->value;
+ break;
+ case ABS_MT_TOOL_TYPE:
+ slot->mInUse = true;
+ slot->mAbsMTToolType = rawEvent->value;
+ slot->mHaveAbsMTToolType = true;
+ break;
+ }
+ }
+ } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
+ // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
+ mCurrentSlot += 1;
+ } else if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
+ mDeviceTimestamp = rawEvent->value;
+ }
+}
+
+void MultiTouchMotionAccumulator::finishSync() {
+ if (!mUsingSlotsProtocol) {
+ clearSlots(-1);
+ }
+}
+
+bool MultiTouchMotionAccumulator::hasStylus() const {
+ return mHaveStylus;
+}
+
+
+// --- MultiTouchMotionAccumulator::Slot ---
+
+MultiTouchMotionAccumulator::Slot::Slot() {
+ clear();
+}
+
+void MultiTouchMotionAccumulator::Slot::clear() {
+ mInUse = false;
+ mHaveAbsMTTouchMinor = false;
+ mHaveAbsMTWidthMinor = false;
+ mHaveAbsMTToolType = false;
+ mAbsMTPositionX = 0;
+ mAbsMTPositionY = 0;
+ mAbsMTTouchMajor = 0;
+ mAbsMTTouchMinor = 0;
+ mAbsMTWidthMajor = 0;
+ mAbsMTWidthMinor = 0;
+ mAbsMTOrientation = 0;
+ mAbsMTTrackingId = -1;
+ mAbsMTPressure = 0;
+ mAbsMTDistance = 0;
+ mAbsMTToolType = 0;
+}
+
+int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
+ if (mHaveAbsMTToolType) {
+ switch (mAbsMTToolType) {
+ case MT_TOOL_FINGER:
+ return AMOTION_EVENT_TOOL_TYPE_FINGER;
+ case MT_TOOL_PEN:
+ return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ }
+ }
+ return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+
+// --- InputMapper ---
+
+InputMapper::InputMapper(InputDevice* device) :
+ mDevice(device), mContext(device->getContext()) {
+}
+
+InputMapper::~InputMapper() {
+}
+
+void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ info->addSource(getSources());
+}
+
+void InputMapper::dump(std::string& dump) {
+}
+
+void InputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+}
+
+void InputMapper::reset(nsecs_t when) {
+}
+
+void InputMapper::timeoutExpired(nsecs_t when) {
+}
+
+int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+ return AKEY_STATE_UNKNOWN;
+}
+
+int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+ return AKEY_STATE_UNKNOWN;
+}
+
+int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+ return AKEY_STATE_UNKNOWN;
+}
+
+bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags) {
+ return false;
+}
+
+void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+ int32_t token) {
+}
+
+void InputMapper::cancelVibrate(int32_t token) {
+}
+
+void InputMapper::cancelTouch(nsecs_t when) {
+}
+
+int32_t InputMapper::getMetaState() {
+ return 0;
+}
+
+void InputMapper::updateMetaState(int32_t keyCode) {
+}
+
+void InputMapper::updateExternalStylusState(const StylusState& state) {
+
+}
+
+void InputMapper::fadePointer() {
+}
+
+status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
+ return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
+}
+
+void InputMapper::bumpGeneration() {
+ mDevice->bumpGeneration();
+}
+
+void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump,
+ const RawAbsoluteAxisInfo& axis, const char* name) {
+ if (axis.valid) {
+ dump += StringPrintf(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
+ name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
+ } else {
+ dump += StringPrintf(INDENT4 "%s: unknown range\n", name);
+ }
+}
+
+void InputMapper::dumpStylusState(std::string& dump, const StylusState& state) {
+ dump += StringPrintf(INDENT4 "When: %" PRId64 "\n", state.when);
+ dump += StringPrintf(INDENT4 "Pressure: %f\n", state.pressure);
+ dump += StringPrintf(INDENT4 "Button State: 0x%08x\n", state.buttons);
+ dump += StringPrintf(INDENT4 "Tool Type: %" PRId32 "\n", state.toolType);
+}
+
+// --- SwitchInputMapper ---
+
+SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
+ InputMapper(device), mSwitchValues(0), mUpdatedSwitchMask(0) {
+}
+
+SwitchInputMapper::~SwitchInputMapper() {
+}
+
+uint32_t SwitchInputMapper::getSources() {
+ return AINPUT_SOURCE_SWITCH;
+}
+
+void SwitchInputMapper::process(const RawEvent* rawEvent) {
+ switch (rawEvent->type) {
+ case EV_SW:
+ processSwitch(rawEvent->code, rawEvent->value);
+ break;
+
+ case EV_SYN:
+ if (rawEvent->code == SYN_REPORT) {
+ sync(rawEvent->when);
+ }
+ }
+}
+
+void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
+ if (switchCode >= 0 && switchCode < 32) {
+ if (switchValue) {
+ mSwitchValues |= 1 << switchCode;
+ } else {
+ mSwitchValues &= ~(1 << switchCode);
+ }
+ mUpdatedSwitchMask |= 1 << switchCode;
+ }
+}
+
+void SwitchInputMapper::sync(nsecs_t when) {
+ if (mUpdatedSwitchMask) {
+ uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
+ NotifySwitchArgs args(mContext->getNextSequenceNum(), when, 0, updatedSwitchValues,
+ mUpdatedSwitchMask);
+ getListener()->notifySwitch(&args);
+
+ mUpdatedSwitchMask = 0;
+ }
+}
+
+int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+ return getEventHub()->getSwitchState(getDeviceId(), switchCode);
+}
+
+void SwitchInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Switch Input Mapper:\n";
+ dump += StringPrintf(INDENT3 "SwitchValues: %x\n", mSwitchValues);
+}
+
+// --- VibratorInputMapper ---
+
+VibratorInputMapper::VibratorInputMapper(InputDevice* device) :
+ InputMapper(device), mVibrating(false) {
+}
+
+VibratorInputMapper::~VibratorInputMapper() {
+}
+
+uint32_t VibratorInputMapper::getSources() {
+ return 0;
+}
+
+void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ info->setVibrator(true);
+}
+
+void VibratorInputMapper::process(const RawEvent* rawEvent) {
+ // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
+}
+
+void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+ int32_t token) {
+#if DEBUG_VIBRATOR
+ std::string patternStr;
+ for (size_t i = 0; i < patternSize; i++) {
+ if (i != 0) {
+ patternStr += ", ";
+ }
+ patternStr += StringPrintf("%" PRId64, pattern[i]);
+ }
+ ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d",
+ getDeviceId(), patternStr.c_str(), repeat, token);
+#endif
+
+ mVibrating = true;
+ memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
+ mPatternSize = patternSize;
+ mRepeat = repeat;
+ mToken = token;
+ mIndex = -1;
+
+ nextStep();
+}
+
+void VibratorInputMapper::cancelVibrate(int32_t token) {
+#if DEBUG_VIBRATOR
+ ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
+#endif
+
+ if (mVibrating && mToken == token) {
+ stopVibrating();
+ }
+}
+
+void VibratorInputMapper::timeoutExpired(nsecs_t when) {
+ if (mVibrating) {
+ if (when >= mNextStepTime) {
+ nextStep();
+ } else {
+ getContext()->requestTimeoutAtTime(mNextStepTime);
+ }
+ }
+}
+
+void VibratorInputMapper::nextStep() {
+ mIndex += 1;
+ if (size_t(mIndex) >= mPatternSize) {
+ if (mRepeat < 0) {
+ // We are done.
+ stopVibrating();
+ return;
+ }
+ mIndex = mRepeat;
+ }
+
+ bool vibratorOn = mIndex & 1;
+ nsecs_t duration = mPattern[mIndex];
+ if (vibratorOn) {
+#if DEBUG_VIBRATOR
+ ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
+#endif
+ getEventHub()->vibrate(getDeviceId(), duration);
+ } else {
+#if DEBUG_VIBRATOR
+ ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
+#endif
+ getEventHub()->cancelVibrate(getDeviceId());
+ }
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ mNextStepTime = now + duration;
+ getContext()->requestTimeoutAtTime(mNextStepTime);
+#if DEBUG_VIBRATOR
+ ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
+#endif
+}
+
+void VibratorInputMapper::stopVibrating() {
+ mVibrating = false;
+#if DEBUG_VIBRATOR
+ ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
+#endif
+ getEventHub()->cancelVibrate(getDeviceId());
+}
+
+void VibratorInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Vibrator Input Mapper:\n";
+ dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
+}
+
+
+// --- KeyboardInputMapper ---
+
+KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
+ uint32_t source, int32_t keyboardType) :
+ InputMapper(device), mSource(source), mKeyboardType(keyboardType) {
+}
+
+KeyboardInputMapper::~KeyboardInputMapper() {
+}
+
+uint32_t KeyboardInputMapper::getSources() {
+ return mSource;
+}
+
+int32_t KeyboardInputMapper::getOrientation() {
+ if (mViewport) {
+ return mViewport->orientation;
+ }
+ return DISPLAY_ORIENTATION_0;
+}
+
+int32_t KeyboardInputMapper::getDisplayId() {
+ if (mViewport) {
+ return mViewport->displayId;
+ }
+ return ADISPLAY_ID_NONE;
+}
+
+void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ info->setKeyboardType(mKeyboardType);
+ info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
+}
+
+void KeyboardInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Keyboard Input Mapper:\n";
+ dumpParameters(dump);
+ dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
+ dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
+ dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
+ dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
+ dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
+}
+
+void KeyboardInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ InputMapper::configure(when, config, changes);
+
+ if (!changes) { // first time only
+ // Configure basic parameters.
+ configureParameters();
+ }
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ if (mParameters.orientationAware) {
+ mViewport = config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ }
+ }
+}
+
+static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const *property) {
+ int32_t mapped = 0;
+ if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
+ for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
+ if (stemKeyRotationMap[i][0] == keyCode) {
+ stemKeyRotationMap[i][1] = mapped;
+ return;
+ }
+ }
+ }
+}
+
+void KeyboardInputMapper::configureParameters() {
+ mParameters.orientationAware = false;
+ const PropertyMap& config = getDevice()->getConfiguration();
+ config.tryGetProperty(String8("keyboard.orientationAware"),
+ mParameters.orientationAware);
+
+ if (mParameters.orientationAware) {
+ mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
+ mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
+ mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
+ mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
+ }
+
+ mParameters.handlesKeyRepeat = false;
+ config.tryGetProperty(String8("keyboard.handlesKeyRepeat"),
+ mParameters.handlesKeyRepeat);
+}
+
+void KeyboardInputMapper::dumpParameters(std::string& dump) {
+ dump += INDENT3 "Parameters:\n";
+ dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
+ toString(mParameters.orientationAware));
+ dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n",
+ toString(mParameters.handlesKeyRepeat));
+}
+
+void KeyboardInputMapper::reset(nsecs_t when) {
+ mMetaState = AMETA_NONE;
+ mDownTime = 0;
+ mKeyDowns.clear();
+ mCurrentHidUsage = 0;
+
+ resetLedState();
+
+ InputMapper::reset(when);
+}
+
+void KeyboardInputMapper::process(const RawEvent* rawEvent) {
+ switch (rawEvent->type) {
+ case EV_KEY: {
+ int32_t scanCode = rawEvent->code;
+ int32_t usageCode = mCurrentHidUsage;
+ mCurrentHidUsage = 0;
+
+ if (isKeyboardOrGamepadKey(scanCode)) {
+ processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
+ }
+ break;
+ }
+ case EV_MSC: {
+ if (rawEvent->code == MSC_SCAN) {
+ mCurrentHidUsage = rawEvent->value;
+ }
+ break;
+ }
+ case EV_SYN: {
+ if (rawEvent->code == SYN_REPORT) {
+ mCurrentHidUsage = 0;
+ }
+ }
+ }
+}
+
+bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
+ return scanCode < BTN_MOUSE
+ || scanCode >= KEY_OK
+ || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
+ || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
+}
+
+bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
+ switch (keyCode) {
+ case AKEYCODE_MEDIA_PLAY:
+ case AKEYCODE_MEDIA_PAUSE:
+ case AKEYCODE_MEDIA_PLAY_PAUSE:
+ case AKEYCODE_MUTE:
+ case AKEYCODE_HEADSETHOOK:
+ case AKEYCODE_MEDIA_STOP:
+ case AKEYCODE_MEDIA_NEXT:
+ case AKEYCODE_MEDIA_PREVIOUS:
+ case AKEYCODE_MEDIA_REWIND:
+ case AKEYCODE_MEDIA_RECORD:
+ case AKEYCODE_MEDIA_FAST_FORWARD:
+ case AKEYCODE_MEDIA_SKIP_FORWARD:
+ case AKEYCODE_MEDIA_SKIP_BACKWARD:
+ case AKEYCODE_MEDIA_STEP_FORWARD:
+ case AKEYCODE_MEDIA_STEP_BACKWARD:
+ case AKEYCODE_MEDIA_AUDIO_TRACK:
+ case AKEYCODE_VOLUME_UP:
+ case AKEYCODE_VOLUME_DOWN:
+ case AKEYCODE_VOLUME_MUTE:
+ case AKEYCODE_TV_AUDIO_DESCRIPTION:
+ case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
+ case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
+ return true;
+ }
+ return false;
+}
+
+void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
+ int32_t usageCode) {
+ int32_t keyCode;
+ int32_t keyMetaState;
+ uint32_t policyFlags;
+
+ if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState,
+ &keyCode, &keyMetaState, &policyFlags)) {
+ keyCode = AKEYCODE_UNKNOWN;
+ keyMetaState = mMetaState;
+ policyFlags = 0;
+ }
+
+ if (down) {
+ // Rotate key codes according to orientation if needed.
+ if (mParameters.orientationAware) {
+ keyCode = rotateKeyCode(keyCode, getOrientation());
+ }
+
+ // Add key down.
+ ssize_t keyDownIndex = findKeyDown(scanCode);
+ if (keyDownIndex >= 0) {
+ // key repeat, be sure to use same keycode as before in case of rotation
+ keyCode = mKeyDowns[keyDownIndex].keyCode;
+ } else {
+ // key down
+ if ((policyFlags & POLICY_FLAG_VIRTUAL)
+ && mContext->shouldDropVirtualKey(when,
+ getDevice(), keyCode, scanCode)) {
+ return;
+ }
+ if (policyFlags & POLICY_FLAG_GESTURE) {
+ mDevice->cancelTouch(when);
+ }
+
+ KeyDown keyDown;
+ keyDown.keyCode = keyCode;
+ keyDown.scanCode = scanCode;
+ mKeyDowns.push_back(keyDown);
+ }
+
+ mDownTime = when;
+ } else {
+ // Remove key down.
+ ssize_t keyDownIndex = findKeyDown(scanCode);
+ if (keyDownIndex >= 0) {
+ // key up, be sure to use same keycode as before in case of rotation
+ keyCode = mKeyDowns[keyDownIndex].keyCode;
+ mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
+ } else {
+ // key was not actually down
+ ALOGI("Dropping key up from device %s because the key was not down. "
+ "keyCode=%d, scanCode=%d",
+ getDeviceName().c_str(), keyCode, scanCode);
+ return;
+ }
+ }
+
+ if (updateMetaStateIfNeeded(keyCode, down)) {
+ // If global meta state changed send it along with the key.
+ // If it has not changed then we'll use what keymap gave us,
+ // since key replacement logic might temporarily reset a few
+ // meta bits for given key.
+ keyMetaState = mMetaState;
+ }
+
+ nsecs_t downTime = mDownTime;
+
+ // Key down on external an keyboard should wake the device.
+ // We don't do this for internal keyboards to prevent them from waking up in your pocket.
+ // For internal keyboards, the key layout file should specify the policy flags for
+ // each wake key individually.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) {
+ policyFlags |= POLICY_FLAG_WAKE;
+ }
+
+ if (mParameters.handlesKeyRepeat) {
+ policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
+ }
+
+ NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+ getDisplayId(), policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+ AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
+ getListener()->notifyKey(&args);
+}
+
+ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
+ size_t n = mKeyDowns.size();
+ for (size_t i = 0; i < n; i++) {
+ if (mKeyDowns[i].scanCode == scanCode) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+ return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
+}
+
+int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+ return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
+}
+
+bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags) {
+ return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
+}
+
+int32_t KeyboardInputMapper::getMetaState() {
+ return mMetaState;
+}
+
+void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
+ updateMetaStateIfNeeded(keyCode, false);
+}
+
+bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
+ int32_t oldMetaState = mMetaState;
+ int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
+ bool metaStateChanged = oldMetaState != newMetaState;
+ if (metaStateChanged) {
+ mMetaState = newMetaState;
+ updateLedState(false);
+
+ getContext()->updateGlobalMetaState();
+ }
+
+ return metaStateChanged;
+}
+
+void KeyboardInputMapper::resetLedState() {
+ initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
+ initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
+ initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
+
+ updateLedState(true);
+}
+
+void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
+ ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
+ ledState.on = false;
+}
+
+void KeyboardInputMapper::updateLedState(bool reset) {
+ updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK,
+ AMETA_CAPS_LOCK_ON, reset);
+ updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK,
+ AMETA_NUM_LOCK_ON, reset);
+ updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK,
+ AMETA_SCROLL_LOCK_ON, reset);
+}
+
+void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
+ int32_t led, int32_t modifier, bool reset) {
+ if (ledState.avail) {
+ bool desiredState = (mMetaState & modifier) != 0;
+ if (reset || ledState.on != desiredState) {
+ getEventHub()->setLedState(getDeviceId(), led, desiredState);
+ ledState.on = desiredState;
+ }
+ }
+}
+
+
+// --- CursorInputMapper ---
+
+CursorInputMapper::CursorInputMapper(InputDevice* device) :
+ InputMapper(device) {
+}
+
+CursorInputMapper::~CursorInputMapper() {
+}
+
+uint32_t CursorInputMapper::getSources() {
+ return mSource;
+}
+
+void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ if (mParameters.mode == Parameters::MODE_POINTER) {
+ float minX, minY, maxX, maxY;
+ if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
+ info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
+ }
+ } else {
+ info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
+ info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
+ }
+ info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+
+ if (mCursorScrollAccumulator.haveRelativeVWheel()) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+ }
+ if (mCursorScrollAccumulator.haveRelativeHWheel()) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+ }
+}
+
+void CursorInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Cursor Input Mapper:\n";
+ dumpParameters(dump);
+ dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
+ dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
+ dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
+ dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
+ dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
+ toString(mCursorScrollAccumulator.haveRelativeVWheel()));
+ dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
+ toString(mCursorScrollAccumulator.haveRelativeHWheel()));
+ dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
+ dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
+ dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
+ dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
+ dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
+ dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
+}
+
+void CursorInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ InputMapper::configure(when, config, changes);
+
+ if (!changes) { // first time only
+ mCursorScrollAccumulator.configure(getDevice());
+
+ // Configure basic parameters.
+ configureParameters();
+
+ // Configure device mode.
+ switch (mParameters.mode) {
+ case Parameters::MODE_POINTER_RELATIVE:
+ // Should not happen during first time configuration.
+ ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
+ mParameters.mode = Parameters::MODE_POINTER;
+ [[fallthrough]];
+ case Parameters::MODE_POINTER:
+ mSource = AINPUT_SOURCE_MOUSE;
+ mXPrecision = 1.0f;
+ mYPrecision = 1.0f;
+ mXScale = 1.0f;
+ mYScale = 1.0f;
+ mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+ break;
+ case Parameters::MODE_NAVIGATION:
+ mSource = AINPUT_SOURCE_TRACKBALL;
+ mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+ mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+ mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+ mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+ break;
+ }
+
+ mVWheelScale = 1.0f;
+ mHWheelScale = 1.0f;
+ }
+
+ if ((!changes && config->pointerCapture)
+ || (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE)) {
+ if (config->pointerCapture) {
+ if (mParameters.mode == Parameters::MODE_POINTER) {
+ mParameters.mode = Parameters::MODE_POINTER_RELATIVE;
+ mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
+ // Keep PointerController around in order to preserve the pointer position.
+ mPointerController->fade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+ } else {
+ ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
+ }
+ } else {
+ if (mParameters.mode == Parameters::MODE_POINTER_RELATIVE) {
+ mParameters.mode = Parameters::MODE_POINTER;
+ mSource = AINPUT_SOURCE_MOUSE;
+ } else {
+ ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
+ }
+ }
+ bumpGeneration();
+ if (changes) {
+ getDevice()->notifyReset(when);
+ }
+ }
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
+ mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
+ mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
+ mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
+ }
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ mOrientation = DISPLAY_ORIENTATION_0;
+ if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
+ std::optional<DisplayViewport> internalViewport =
+ config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ if (internalViewport) {
+ mOrientation = internalViewport->orientation;
+ }
+ }
+
+ // Update the PointerController if viewports changed.
+ if (mParameters.mode == Parameters::MODE_POINTER) {
+ getPolicy()->obtainPointerController(getDeviceId());
+ }
+ bumpGeneration();
+ }
+}
+
+void CursorInputMapper::configureParameters() {
+ mParameters.mode = Parameters::MODE_POINTER;
+ String8 cursorModeString;
+ if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
+ if (cursorModeString == "navigation") {
+ mParameters.mode = Parameters::MODE_NAVIGATION;
+ } else if (cursorModeString != "pointer" && cursorModeString != "default") {
+ ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
+ }
+ }
+
+ mParameters.orientationAware = false;
+ getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
+ mParameters.orientationAware);
+
+ mParameters.hasAssociatedDisplay = false;
+ if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
+ mParameters.hasAssociatedDisplay = true;
+ }
+}
+
+void CursorInputMapper::dumpParameters(std::string& dump) {
+ dump += INDENT3 "Parameters:\n";
+ dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
+ toString(mParameters.hasAssociatedDisplay));
+
+ switch (mParameters.mode) {
+ case Parameters::MODE_POINTER:
+ dump += INDENT4 "Mode: pointer\n";
+ break;
+ case Parameters::MODE_POINTER_RELATIVE:
+ dump += INDENT4 "Mode: relative pointer\n";
+ break;
+ case Parameters::MODE_NAVIGATION:
+ dump += INDENT4 "Mode: navigation\n";
+ break;
+ default:
+ ALOG_ASSERT(false);
+ }
+
+ dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
+ toString(mParameters.orientationAware));
+}
+
+void CursorInputMapper::reset(nsecs_t when) {
+ mButtonState = 0;
+ mDownTime = 0;
+
+ mPointerVelocityControl.reset();
+ mWheelXVelocityControl.reset();
+ mWheelYVelocityControl.reset();
+
+ mCursorButtonAccumulator.reset(getDevice());
+ mCursorMotionAccumulator.reset(getDevice());
+ mCursorScrollAccumulator.reset(getDevice());
+
+ InputMapper::reset(when);
+}
+
+void CursorInputMapper::process(const RawEvent* rawEvent) {
+ mCursorButtonAccumulator.process(rawEvent);
+ mCursorMotionAccumulator.process(rawEvent);
+ mCursorScrollAccumulator.process(rawEvent);
+
+ if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+ sync(rawEvent->when);
+ }
+}
+
+void CursorInputMapper::sync(nsecs_t when) {
+ int32_t lastButtonState = mButtonState;
+ int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
+ mButtonState = currentButtonState;
+
+ bool wasDown = isPointerDown(lastButtonState);
+ bool down = isPointerDown(currentButtonState);
+ bool downChanged;
+ if (!wasDown && down) {
+ mDownTime = when;
+ downChanged = true;
+ } else if (wasDown && !down) {
+ downChanged = true;
+ } else {
+ downChanged = false;
+ }
+ nsecs_t downTime = mDownTime;
+ bool buttonsChanged = currentButtonState != lastButtonState;
+ int32_t buttonsPressed = currentButtonState & ~lastButtonState;
+ int32_t buttonsReleased = lastButtonState & ~currentButtonState;
+
+ float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
+ float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
+ bool moved = deltaX != 0 || deltaY != 0;
+
+ // Rotate delta according to orientation if needed.
+ if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
+ && (deltaX != 0.0f || deltaY != 0.0f)) {
+ rotateDelta(mOrientation, &deltaX, &deltaY);
+ }
+
+ // Move the pointer.
+ PointerProperties pointerProperties;
+ pointerProperties.clear();
+ pointerProperties.id = 0;
+ pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
+
+ PointerCoords pointerCoords;
+ pointerCoords.clear();
+
+ float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
+ float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
+ bool scrolled = vscroll != 0 || hscroll != 0;
+
+ mWheelYVelocityControl.move(when, nullptr, &vscroll);
+ mWheelXVelocityControl.move(when, &hscroll, nullptr);
+
+ mPointerVelocityControl.move(when, &deltaX, &deltaY);
+
+ int32_t displayId;
+ if (mSource == AINPUT_SOURCE_MOUSE) {
+ if (moved || scrolled || buttonsChanged) {
+ mPointerController->setPresentation(
+ PointerControllerInterface::PRESENTATION_POINTER);
+
+ if (moved) {
+ mPointerController->move(deltaX, deltaY);
+ }
+
+ if (buttonsChanged) {
+ mPointerController->setButtonState(currentButtonState);
+ }
+
+ mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+ }
+
+ float x, y;
+ mPointerController->getPosition(&x, &y);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
+ displayId = mPointerController->getDisplayId();
+ } else {
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
+ displayId = ADISPLAY_ID_NONE;
+ }
+
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
+
+ // Moving an external trackball or mouse should wake the device.
+ // We don't do this for internal cursor devices to prevent them from waking up
+ // the device in your pocket.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ uint32_t policyFlags = 0;
+ if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
+ policyFlags |= POLICY_FLAG_WAKE;
+ }
+
+ // Synthesize key down from buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
+ displayId, policyFlags, lastButtonState, currentButtonState);
+
+ // Send motion event.
+ if (downChanged || moved || scrolled || buttonsChanged) {
+ int32_t metaState = mContext->getGlobalMetaState();
+ int32_t buttonState = lastButtonState;
+ int32_t motionEventAction;
+ if (downChanged) {
+ motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
+ } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
+ motionEventAction = AMOTION_EVENT_ACTION_MOVE;
+ } else {
+ motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
+ }
+
+ if (buttonsReleased) {
+ BitSet32 released(buttonsReleased);
+ while (!released.isEmpty()) {
+ int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
+ buttonState &= ~actionButton;
+ NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
+ metaState, buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&releaseArgs);
+ }
+ }
+
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+ displayId, policyFlags, motionEventAction, 0, 0, metaState, currentButtonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+
+ if (buttonsPressed) {
+ BitSet32 pressed(buttonsPressed);
+ while (!pressed.isEmpty()) {
+ int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
+ buttonState |= actionButton;
+ NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_PRESS,
+ actionButton, 0, metaState, buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&pressArgs);
+ }
+ }
+
+ ALOG_ASSERT(buttonState == currentButtonState);
+
+ // Send hover move after UP to tell the application that the mouse is hovering now.
+ if (motionEventAction == AMOTION_EVENT_ACTION_UP
+ && (mSource == AINPUT_SOURCE_MOUSE)) {
+ NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+ metaState, currentButtonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&hoverArgs);
+ }
+
+ // Send scroll events.
+ if (scrolled) {
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
+
+ NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&scrollArgs);
+ }
+ }
+
+ // Synthesize key up from buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
+ displayId, policyFlags, lastButtonState, currentButtonState);
+
+ mCursorMotionAccumulator.finishSync();
+ mCursorScrollAccumulator.finishSync();
+}
+
+int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+ if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
+ return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
+ } else {
+ return AKEY_STATE_UNKNOWN;
+ }
+}
+
+void CursorInputMapper::fadePointer() {
+ if (mPointerController != nullptr) {
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+ }
+}
+
+std::optional<int32_t> CursorInputMapper::getAssociatedDisplay() {
+ if (mParameters.hasAssociatedDisplay) {
+ if (mParameters.mode == Parameters::MODE_POINTER) {
+ return std::make_optional(mPointerController->getDisplayId());
+ } else {
+ // If the device is orientationAware and not a mouse,
+ // it expects to dispatch events to any display
+ return std::make_optional(ADISPLAY_ID_NONE);
+ }
+ }
+ return std::nullopt;
+}
+
+// --- RotaryEncoderInputMapper ---
+
+RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
+ InputMapper(device), mOrientation(DISPLAY_ORIENTATION_0) {
+ mSource = AINPUT_SOURCE_ROTARY_ENCODER;
+}
+
+RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {
+}
+
+uint32_t RotaryEncoderInputMapper::getSources() {
+ return mSource;
+}
+
+void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
+ float res = 0.0f;
+ if (!mDevice->getConfiguration().tryGetProperty(String8("device.res"), res)) {
+ ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
+ }
+ if (!mDevice->getConfiguration().tryGetProperty(String8("device.scalingFactor"),
+ mScalingFactor)) {
+ ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
+ "default to 1.0!\n");
+ mScalingFactor = 1.0f;
+ }
+ info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
+ res * mScalingFactor);
+ }
+}
+
+void RotaryEncoderInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Rotary Encoder Input Mapper:\n";
+ dump += StringPrintf(INDENT3 "HaveWheel: %s\n",
+ toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
+}
+
+void RotaryEncoderInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ InputMapper::configure(when, config, changes);
+ if (!changes) {
+ mRotaryEncoderScrollAccumulator.configure(getDevice());
+ }
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ std::optional<DisplayViewport> internalViewport =
+ config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ if (internalViewport) {
+ mOrientation = internalViewport->orientation;
+ } else {
+ mOrientation = DISPLAY_ORIENTATION_0;
+ }
+ }
+}
+
+void RotaryEncoderInputMapper::reset(nsecs_t when) {
+ mRotaryEncoderScrollAccumulator.reset(getDevice());
+
+ InputMapper::reset(when);
+}
+
+void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
+ mRotaryEncoderScrollAccumulator.process(rawEvent);
+
+ if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+ sync(rawEvent->when);
+ }
+}
+
+void RotaryEncoderInputMapper::sync(nsecs_t when) {
+ PointerCoords pointerCoords;
+ pointerCoords.clear();
+
+ PointerProperties pointerProperties;
+ pointerProperties.clear();
+ pointerProperties.id = 0;
+ pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+
+ float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
+ bool scrolled = scroll != 0;
+
+ // This is not a pointer, so it's not associated with a display.
+ int32_t displayId = ADISPLAY_ID_NONE;
+
+ // Moving the rotary encoder should wake the device (if specified).
+ uint32_t policyFlags = 0;
+ if (scrolled && getDevice()->isExternal()) {
+ policyFlags |= POLICY_FLAG_WAKE;
+ }
+
+ if (mOrientation == DISPLAY_ORIENTATION_180) {
+ scroll = -scroll;
+ }
+
+ // Send motion event.
+ if (scrolled) {
+ int32_t metaState = mContext->getGlobalMetaState();
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
+
+ NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, /* buttonState */ 0,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ 0, 0, 0, /* videoFrames */ {});
+ getListener()->notifyMotion(&scrollArgs);
+ }
+
+ mRotaryEncoderScrollAccumulator.finishSync();
+}
+
+// --- TouchInputMapper ---
+
+TouchInputMapper::TouchInputMapper(InputDevice* device) :
+ InputMapper(device),
+ mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
+ mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
+ mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0),
+ mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
+}
+
+TouchInputMapper::~TouchInputMapper() {
+}
+
+uint32_t TouchInputMapper::getSources() {
+ return mSource;
+}
+
+void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ if (mDeviceMode != DEVICE_MODE_DISABLED) {
+ info->addMotionRange(mOrientedRanges.x);
+ info->addMotionRange(mOrientedRanges.y);
+ info->addMotionRange(mOrientedRanges.pressure);
+
+ if (mOrientedRanges.haveSize) {
+ info->addMotionRange(mOrientedRanges.size);
+ }
+
+ if (mOrientedRanges.haveTouchSize) {
+ info->addMotionRange(mOrientedRanges.touchMajor);
+ info->addMotionRange(mOrientedRanges.touchMinor);
+ }
+
+ if (mOrientedRanges.haveToolSize) {
+ info->addMotionRange(mOrientedRanges.toolMajor);
+ info->addMotionRange(mOrientedRanges.toolMinor);
+ }
+
+ if (mOrientedRanges.haveOrientation) {
+ info->addMotionRange(mOrientedRanges.orientation);
+ }
+
+ if (mOrientedRanges.haveDistance) {
+ info->addMotionRange(mOrientedRanges.distance);
+ }
+
+ if (mOrientedRanges.haveTilt) {
+ info->addMotionRange(mOrientedRanges.tilt);
+ }
+
+ if (mCursorScrollAccumulator.haveRelativeVWheel()) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f);
+ }
+ if (mCursorScrollAccumulator.haveRelativeHWheel()) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f);
+ }
+ if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+ const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
+ const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
+ x.fuzz, x.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
+ y.fuzz, y.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
+ x.fuzz, x.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
+ y.fuzz, y.resolution);
+ }
+ info->setButtonUnderPad(mParameters.hasButtonUnderPad);
+ }
+}
+
+void TouchInputMapper::dump(std::string& dump) {
+ dump += StringPrintf(INDENT2 "Touch Input Mapper (mode - %s):\n", modeToString(mDeviceMode));
+ dumpParameters(dump);
+ dumpVirtualKeys(dump);
+ dumpRawPointerAxes(dump);
+ dumpCalibration(dump);
+ dumpAffineTransformation(dump);
+ dumpSurface(dump);
+
+ dump += StringPrintf(INDENT3 "Translation and Scaling Factors:\n");
+ dump += StringPrintf(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
+ dump += StringPrintf(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
+ dump += StringPrintf(INDENT4 "XScale: %0.3f\n", mXScale);
+ dump += StringPrintf(INDENT4 "YScale: %0.3f\n", mYScale);
+ dump += StringPrintf(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
+ dump += StringPrintf(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
+ dump += StringPrintf(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
+ dump += StringPrintf(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
+ dump += StringPrintf(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
+ dump += StringPrintf(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
+ dump += StringPrintf(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
+ dump += StringPrintf(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
+ dump += StringPrintf(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
+ dump += StringPrintf(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
+ dump += StringPrintf(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
+ dump += StringPrintf(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
+
+ dump += StringPrintf(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState);
+ dump += StringPrintf(INDENT3 "Last Raw Touch: pointerCount=%d\n",
+ mLastRawState.rawPointerData.pointerCount);
+ for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
+ const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
+ dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
+ "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
+ "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
+ "toolType=%d, isHovering=%s\n", i,
+ pointer.id, pointer.x, pointer.y, pointer.pressure,
+ pointer.touchMajor, pointer.touchMinor,
+ pointer.toolMajor, pointer.toolMinor,
+ pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
+ pointer.toolType, toString(pointer.isHovering));
+ }
+
+ dump += StringPrintf(INDENT3 "Last Cooked Button State: 0x%08x\n", mLastCookedState.buttonState);
+ dump += StringPrintf(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
+ mLastCookedState.cookedPointerData.pointerCount);
+ for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
+ const PointerProperties& pointerProperties =
+ mLastCookedState.cookedPointerData.pointerProperties[i];
+ const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
+ dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
+ "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
+ "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
+ "toolType=%d, isHovering=%s\n", i,
+ pointerProperties.id,
+ pointerCoords.getX(),
+ pointerCoords.getY(),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
+ pointerProperties.toolType,
+ toString(mLastCookedState.cookedPointerData.isHovering(i)));
+ }
+
+ dump += INDENT3 "Stylus Fusion:\n";
+ dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n",
+ toString(mExternalStylusConnected));
+ dump += StringPrintf(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
+ dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
+ mExternalStylusFusionTimeout);
+ dump += INDENT3 "External Stylus State:\n";
+ dumpStylusState(dump, mExternalStylusState);
+
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
+ dump += StringPrintf(INDENT3 "Pointer Gesture Detector:\n");
+ dump += StringPrintf(INDENT4 "XMovementScale: %0.3f\n",
+ mPointerXMovementScale);
+ dump += StringPrintf(INDENT4 "YMovementScale: %0.3f\n",
+ mPointerYMovementScale);
+ dump += StringPrintf(INDENT4 "XZoomScale: %0.3f\n",
+ mPointerXZoomScale);
+ dump += StringPrintf(INDENT4 "YZoomScale: %0.3f\n",
+ mPointerYZoomScale);
+ dump += StringPrintf(INDENT4 "MaxSwipeWidth: %f\n",
+ mPointerGestureMaxSwipeWidth);
+ }
+}
+
+const char* TouchInputMapper::modeToString(DeviceMode deviceMode) {
+ switch (deviceMode) {
+ case DEVICE_MODE_DISABLED:
+ return "disabled";
+ case DEVICE_MODE_DIRECT:
+ return "direct";
+ case DEVICE_MODE_UNSCALED:
+ return "unscaled";
+ case DEVICE_MODE_NAVIGATION:
+ return "navigation";
+ case DEVICE_MODE_POINTER:
+ return "pointer";
+ }
+ return "unknown";
+}
+
+void TouchInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ InputMapper::configure(when, config, changes);
+
+ mConfig = *config;
+
+ if (!changes) { // first time only
+ // Configure basic parameters.
+ configureParameters();
+
+ // Configure common accumulators.
+ mCursorScrollAccumulator.configure(getDevice());
+ mTouchButtonAccumulator.configure(getDevice());
+
+ // Configure absolute axis information.
+ configureRawPointerAxes();
+
+ // Prepare input device calibration.
+ parseCalibration();
+ resolveCalibration();
+ }
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) {
+ // Update location calibration to reflect current settings
+ updateAffineTransformation();
+ }
+
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
+ // Update pointer speed.
+ mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
+ mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
+ mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
+ }
+
+ bool resetNeeded = false;
+ if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
+ | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
+ | InputReaderConfiguration::CHANGE_SHOW_TOUCHES
+ | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
+ // Configure device sources, surface dimensions, orientation and
+ // scaling factors.
+ configureSurface(when, &resetNeeded);
+ }
+
+ if (changes && resetNeeded) {
+ // Send reset, unless this is the first time the device has been configured,
+ // in which case the reader will call reset itself after all mappers are ready.
+ getDevice()->notifyReset(when);
+ }
+}
+
+void TouchInputMapper::resolveExternalStylusPresence() {
+ std::vector<InputDeviceInfo> devices;
+ mContext->getExternalStylusDevices(devices);
+ mExternalStylusConnected = !devices.empty();
+
+ if (!mExternalStylusConnected) {
+ resetExternalStylus();
+ }
+}
+
+void TouchInputMapper::configureParameters() {
+ // Use the pointer presentation mode for devices that do not support distinct
+ // multitouch. The spot-based presentation relies on being able to accurately
+ // locate two or more fingers on the touch pad.
+ mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
+ ? Parameters::GESTURE_MODE_SINGLE_TOUCH : Parameters::GESTURE_MODE_MULTI_TOUCH;
+
+ String8 gestureModeString;
+ if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
+ gestureModeString)) {
+ if (gestureModeString == "single-touch") {
+ mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
+ } else if (gestureModeString == "multi-touch") {
+ mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
+ } else if (gestureModeString != "default") {
+ ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
+ }
+ }
+
+ if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
+ // The device is a touch screen.
+ mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+ } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
+ // The device is a pointing device like a track pad.
+ mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+ } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
+ || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
+ // The device is a cursor device with a touch pad attached.
+ // By default don't use the touch pad to move the pointer.
+ mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
+ } else {
+ // The device is a touch pad of unknown purpose.
+ mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+ }
+
+ mParameters.hasButtonUnderPad=
+ getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_BUTTONPAD);
+
+ String8 deviceTypeString;
+ if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
+ deviceTypeString)) {
+ if (deviceTypeString == "touchScreen") {
+ mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+ } else if (deviceTypeString == "touchPad") {
+ mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
+ } else if (deviceTypeString == "touchNavigation") {
+ mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
+ } else if (deviceTypeString == "pointer") {
+ mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+ } else if (deviceTypeString != "default") {
+ ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
+ }
+ }
+
+ mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+ getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
+ mParameters.orientationAware);
+
+ mParameters.hasAssociatedDisplay = false;
+ mParameters.associatedDisplayIsExternal = false;
+ if (mParameters.orientationAware
+ || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
+ || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
+ mParameters.hasAssociatedDisplay = true;
+ if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
+ mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
+ String8 uniqueDisplayId;
+ getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
+ uniqueDisplayId);
+ mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
+ }
+ }
+ if (getDevice()->getAssociatedDisplayPort()) {
+ mParameters.hasAssociatedDisplay = true;
+ }
+
+ // Initial downs on external touch devices should wake the device.
+ // Normally we don't do this for internal touch screens to prevent them from waking
+ // up in your pocket but you can enable it using the input device configuration.
+ mParameters.wake = getDevice()->isExternal();
+ getDevice()->getConfiguration().tryGetProperty(String8("touch.wake"),
+ mParameters.wake);
+}
+
+void TouchInputMapper::dumpParameters(std::string& dump) {
+ dump += INDENT3 "Parameters:\n";
+
+ switch (mParameters.gestureMode) {
+ case Parameters::GESTURE_MODE_SINGLE_TOUCH:
+ dump += INDENT4 "GestureMode: single-touch\n";
+ break;
+ case Parameters::GESTURE_MODE_MULTI_TOUCH:
+ dump += INDENT4 "GestureMode: multi-touch\n";
+ break;
+ default:
+ assert(false);
+ }
+
+ switch (mParameters.deviceType) {
+ case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
+ dump += INDENT4 "DeviceType: touchScreen\n";
+ break;
+ case Parameters::DEVICE_TYPE_TOUCH_PAD:
+ dump += INDENT4 "DeviceType: touchPad\n";
+ break;
+ case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
+ dump += INDENT4 "DeviceType: touchNavigation\n";
+ break;
+ case Parameters::DEVICE_TYPE_POINTER:
+ dump += INDENT4 "DeviceType: pointer\n";
+ break;
+ default:
+ ALOG_ASSERT(false);
+ }
+
+ dump += StringPrintf(
+ INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, displayId='%s'\n",
+ toString(mParameters.hasAssociatedDisplay),
+ toString(mParameters.associatedDisplayIsExternal),
+ mParameters.uniqueDisplayId.c_str());
+ dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
+ toString(mParameters.orientationAware));
+}
+
+void TouchInputMapper::configureRawPointerAxes() {
+ mRawPointerAxes.clear();
+}
+
+void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
+ dump += INDENT3 "Raw Touch Axes:\n";
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
+ dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
+}
+
+bool TouchInputMapper::hasExternalStylus() const {
+ return mExternalStylusConnected;
+}
+
+/**
+ * Determine which DisplayViewport to use.
+ * 1. If display port is specified, return the matching viewport. If matching viewport not
+ * found, then return.
+ * 2. If a device has associated display, get the matching viewport by either unique id or by
+ * the display type (internal or external).
+ * 3. Otherwise, use a non-display viewport.
+ */
+std::optional<DisplayViewport> TouchInputMapper::findViewport() {
+ if (mParameters.hasAssociatedDisplay) {
+ const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
+ if (displayPort) {
+ // Find the viewport that contains the same port
+ std::optional<DisplayViewport> v = mConfig.getDisplayViewportByPort(*displayPort);
+ if (!v) {
+ ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
+ "but the corresponding viewport is not found.",
+ getDeviceName().c_str(), *displayPort);
+ }
+ return v;
+ }
+
+ if (!mParameters.uniqueDisplayId.empty()) {
+ return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
+ }
+
+ ViewportType viewportTypeToUse;
+ if (mParameters.associatedDisplayIsExternal) {
+ viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
+ } else {
+ viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
+ }
+
+ std::optional<DisplayViewport> viewport =
+ mConfig.getDisplayViewportByType(viewportTypeToUse);
+ if (!viewport && viewportTypeToUse == ViewportType::VIEWPORT_EXTERNAL) {
+ ALOGW("Input device %s should be associated with external display, "
+ "fallback to internal one for the external viewport is not found.",
+ getDeviceName().c_str());
+ viewport = mConfig.getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ }
+
+ return viewport;
+ }
+
+ DisplayViewport newViewport;
+ // Raw width and height in the natural orientation.
+ int32_t rawWidth = mRawPointerAxes.getRawWidth();
+ int32_t rawHeight = mRawPointerAxes.getRawHeight();
+ newViewport.setNonDisplayViewport(rawWidth, rawHeight);
+ return std::make_optional(newViewport);
+}
+
+void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
+ int32_t oldDeviceMode = mDeviceMode;
+
+ resolveExternalStylusPresence();
+
+ // Determine device mode.
+ if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
+ && mConfig.pointerGesturesEnabled) {
+ mSource = AINPUT_SOURCE_MOUSE;
+ mDeviceMode = DEVICE_MODE_POINTER;
+ if (hasStylus()) {
+ mSource |= AINPUT_SOURCE_STYLUS;
+ }
+ } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
+ && mParameters.hasAssociatedDisplay) {
+ mSource = AINPUT_SOURCE_TOUCHSCREEN;
+ mDeviceMode = DEVICE_MODE_DIRECT;
+ if (hasStylus()) {
+ mSource |= AINPUT_SOURCE_STYLUS;
+ }
+ if (hasExternalStylus()) {
+ mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
+ }
+ } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
+ mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
+ mDeviceMode = DEVICE_MODE_NAVIGATION;
+ } else {
+ mSource = AINPUT_SOURCE_TOUCHPAD;
+ mDeviceMode = DEVICE_MODE_UNSCALED;
+ }
+
+ // Ensure we have valid X and Y axes.
+ if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
+ ALOGW("Touch device '%s' did not report support for X or Y axis! "
+ "The device will be inoperable.", getDeviceName().c_str());
+ mDeviceMode = DEVICE_MODE_DISABLED;
+ return;
+ }
+
+ // Get associated display dimensions.
+ std::optional<DisplayViewport> newViewport = findViewport();
+ if (!newViewport) {
+ ALOGI("Touch device '%s' could not query the properties of its associated "
+ "display. The device will be inoperable until the display size "
+ "becomes available.",
+ getDeviceName().c_str());
+ mDeviceMode = DEVICE_MODE_DISABLED;
+ return;
+ }
+
+ // Raw width and height in the natural orientation.
+ int32_t rawWidth = mRawPointerAxes.getRawWidth();
+ int32_t rawHeight = mRawPointerAxes.getRawHeight();
+
+ bool viewportChanged = mViewport != *newViewport;
+ if (viewportChanged) {
+ mViewport = *newViewport;
+
+ if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
+ // Convert rotated viewport to natural surface coordinates.
+ int32_t naturalLogicalWidth, naturalLogicalHeight;
+ int32_t naturalPhysicalWidth, naturalPhysicalHeight;
+ int32_t naturalPhysicalLeft, naturalPhysicalTop;
+ int32_t naturalDeviceWidth, naturalDeviceHeight;
+ switch (mViewport.orientation) {
+ case DISPLAY_ORIENTATION_90:
+ naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
+ naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
+ naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
+ naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
+ naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
+ naturalPhysicalTop = mViewport.physicalLeft;
+ naturalDeviceWidth = mViewport.deviceHeight;
+ naturalDeviceHeight = mViewport.deviceWidth;
+ break;
+ case DISPLAY_ORIENTATION_180:
+ naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
+ naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
+ naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
+ naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
+ naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
+ naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
+ naturalDeviceWidth = mViewport.deviceWidth;
+ naturalDeviceHeight = mViewport.deviceHeight;
+ break;
+ case DISPLAY_ORIENTATION_270:
+ naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
+ naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
+ naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
+ naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
+ naturalPhysicalLeft = mViewport.physicalTop;
+ naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
+ naturalDeviceWidth = mViewport.deviceHeight;
+ naturalDeviceHeight = mViewport.deviceWidth;
+ break;
+ case DISPLAY_ORIENTATION_0:
+ default:
+ naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
+ naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
+ naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
+ naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
+ naturalPhysicalLeft = mViewport.physicalLeft;
+ naturalPhysicalTop = mViewport.physicalTop;
+ naturalDeviceWidth = mViewport.deviceWidth;
+ naturalDeviceHeight = mViewport.deviceHeight;
+ break;
+ }
+
+ if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
+ ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
+ naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
+ naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
+ }
+
+ mPhysicalWidth = naturalPhysicalWidth;
+ mPhysicalHeight = naturalPhysicalHeight;
+ mPhysicalLeft = naturalPhysicalLeft;
+ mPhysicalTop = naturalPhysicalTop;
+
+ mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
+ mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
+ mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
+ mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
+
+ mSurfaceOrientation = mParameters.orientationAware ?
+ mViewport.orientation : DISPLAY_ORIENTATION_0;
+ } else {
+ mPhysicalWidth = rawWidth;
+ mPhysicalHeight = rawHeight;
+ mPhysicalLeft = 0;
+ mPhysicalTop = 0;
+
+ mSurfaceWidth = rawWidth;
+ mSurfaceHeight = rawHeight;
+ mSurfaceLeft = 0;
+ mSurfaceTop = 0;
+ mSurfaceOrientation = DISPLAY_ORIENTATION_0;
+ }
+ }
+
+ // If moving between pointer modes, need to reset some state.
+ bool deviceModeChanged = mDeviceMode != oldDeviceMode;
+ if (deviceModeChanged) {
+ mOrientedRanges.clear();
+ }
+
+ // Create or update pointer controller if needed.
+ if (mDeviceMode == DEVICE_MODE_POINTER ||
+ (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
+ if (mPointerController == nullptr || viewportChanged) {
+ mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+ }
+ } else {
+ mPointerController.clear();
+ }
+
+ if (viewportChanged || deviceModeChanged) {
+ ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
+ "display id %d",
+ getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
+ mSurfaceOrientation, mDeviceMode, mViewport.displayId);
+
+ // Configure X and Y factors.
+ mXScale = float(mSurfaceWidth) / rawWidth;
+ mYScale = float(mSurfaceHeight) / rawHeight;
+ mXTranslate = -mSurfaceLeft;
+ mYTranslate = -mSurfaceTop;
+ mXPrecision = 1.0f / mXScale;
+ mYPrecision = 1.0f / mYScale;
+
+ mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
+ mOrientedRanges.x.source = mSource;
+ mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
+ mOrientedRanges.y.source = mSource;
+
+ configureVirtualKeys();
+
+ // Scale factor for terms that are not oriented in a particular axis.
+ // If the pixels are square then xScale == yScale otherwise we fake it
+ // by choosing an average.
+ mGeometricScale = avg(mXScale, mYScale);
+
+ // Size of diagonal axis.
+ float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
+
+ // Size factors.
+ if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
+ if (mRawPointerAxes.touchMajor.valid
+ && mRawPointerAxes.touchMajor.maxValue != 0) {
+ mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
+ } else if (mRawPointerAxes.toolMajor.valid
+ && mRawPointerAxes.toolMajor.maxValue != 0) {
+ mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
+ } else {
+ mSizeScale = 0.0f;
+ }
+
+ mOrientedRanges.haveTouchSize = true;
+ mOrientedRanges.haveToolSize = true;
+ mOrientedRanges.haveSize = true;
+
+ mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
+ mOrientedRanges.touchMajor.source = mSource;
+ mOrientedRanges.touchMajor.min = 0;
+ mOrientedRanges.touchMajor.max = diagonalSize;
+ mOrientedRanges.touchMajor.flat = 0;
+ mOrientedRanges.touchMajor.fuzz = 0;
+ mOrientedRanges.touchMajor.resolution = 0;
+
+ mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
+ mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
+
+ mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
+ mOrientedRanges.toolMajor.source = mSource;
+ mOrientedRanges.toolMajor.min = 0;
+ mOrientedRanges.toolMajor.max = diagonalSize;
+ mOrientedRanges.toolMajor.flat = 0;
+ mOrientedRanges.toolMajor.fuzz = 0;
+ mOrientedRanges.toolMajor.resolution = 0;
+
+ mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
+ mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
+
+ mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
+ mOrientedRanges.size.source = mSource;
+ mOrientedRanges.size.min = 0;
+ mOrientedRanges.size.max = 1.0;
+ mOrientedRanges.size.flat = 0;
+ mOrientedRanges.size.fuzz = 0;
+ mOrientedRanges.size.resolution = 0;
+ } else {
+ mSizeScale = 0.0f;
+ }
+
+ // Pressure factors.
+ mPressureScale = 0;
+ float pressureMax = 1.0;
+ if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
+ || mCalibration.pressureCalibration
+ == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
+ if (mCalibration.havePressureScale) {
+ mPressureScale = mCalibration.pressureScale;
+ pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
+ } else if (mRawPointerAxes.pressure.valid
+ && mRawPointerAxes.pressure.maxValue != 0) {
+ mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
+ }
+ }
+
+ mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
+ mOrientedRanges.pressure.source = mSource;
+ mOrientedRanges.pressure.min = 0;
+ mOrientedRanges.pressure.max = pressureMax;
+ mOrientedRanges.pressure.flat = 0;
+ mOrientedRanges.pressure.fuzz = 0;
+ mOrientedRanges.pressure.resolution = 0;
+
+ // Tilt
+ mTiltXCenter = 0;
+ mTiltXScale = 0;
+ mTiltYCenter = 0;
+ mTiltYScale = 0;
+ mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
+ if (mHaveTilt) {
+ mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
+ mRawPointerAxes.tiltX.maxValue);
+ mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
+ mRawPointerAxes.tiltY.maxValue);
+ mTiltXScale = M_PI / 180;
+ mTiltYScale = M_PI / 180;
+
+ mOrientedRanges.haveTilt = true;
+
+ mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
+ mOrientedRanges.tilt.source = mSource;
+ mOrientedRanges.tilt.min = 0;
+ mOrientedRanges.tilt.max = M_PI_2;
+ mOrientedRanges.tilt.flat = 0;
+ mOrientedRanges.tilt.fuzz = 0;
+ mOrientedRanges.tilt.resolution = 0;
+ }
+
+ // Orientation
+ mOrientationScale = 0;
+ if (mHaveTilt) {
+ mOrientedRanges.haveOrientation = true;
+
+ mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
+ mOrientedRanges.orientation.source = mSource;
+ mOrientedRanges.orientation.min = -M_PI;
+ mOrientedRanges.orientation.max = M_PI;
+ mOrientedRanges.orientation.flat = 0;
+ mOrientedRanges.orientation.fuzz = 0;
+ mOrientedRanges.orientation.resolution = 0;
+ } else if (mCalibration.orientationCalibration !=
+ Calibration::ORIENTATION_CALIBRATION_NONE) {
+ if (mCalibration.orientationCalibration
+ == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
+ if (mRawPointerAxes.orientation.valid) {
+ if (mRawPointerAxes.orientation.maxValue > 0) {
+ mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
+ } else if (mRawPointerAxes.orientation.minValue < 0) {
+ mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
+ } else {
+ mOrientationScale = 0;
+ }
+ }
+ }
+
+ mOrientedRanges.haveOrientation = true;
+
+ mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
+ mOrientedRanges.orientation.source = mSource;
+ mOrientedRanges.orientation.min = -M_PI_2;
+ mOrientedRanges.orientation.max = M_PI_2;
+ mOrientedRanges.orientation.flat = 0;
+ mOrientedRanges.orientation.fuzz = 0;
+ mOrientedRanges.orientation.resolution = 0;
+ }
+
+ // Distance
+ mDistanceScale = 0;
+ if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
+ if (mCalibration.distanceCalibration
+ == Calibration::DISTANCE_CALIBRATION_SCALED) {
+ if (mCalibration.haveDistanceScale) {
+ mDistanceScale = mCalibration.distanceScale;
+ } else {
+ mDistanceScale = 1.0f;
+ }
+ }
+
+ mOrientedRanges.haveDistance = true;
+
+ mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
+ mOrientedRanges.distance.source = mSource;
+ mOrientedRanges.distance.min =
+ mRawPointerAxes.distance.minValue * mDistanceScale;
+ mOrientedRanges.distance.max =
+ mRawPointerAxes.distance.maxValue * mDistanceScale;
+ mOrientedRanges.distance.flat = 0;
+ mOrientedRanges.distance.fuzz =
+ mRawPointerAxes.distance.fuzz * mDistanceScale;
+ mOrientedRanges.distance.resolution = 0;
+ }
+
+ // Compute oriented precision, scales and ranges.
+ // Note that the maximum value reported is an inclusive maximum value so it is one
+ // unit less than the total width or height of surface.
+ switch (mSurfaceOrientation) {
+ case DISPLAY_ORIENTATION_90:
+ case DISPLAY_ORIENTATION_270:
+ mOrientedXPrecision = mYPrecision;
+ mOrientedYPrecision = mXPrecision;
+
+ mOrientedRanges.x.min = mYTranslate;
+ mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
+ mOrientedRanges.x.flat = 0;
+ mOrientedRanges.x.fuzz = 0;
+ mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
+
+ mOrientedRanges.y.min = mXTranslate;
+ mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
+ mOrientedRanges.y.flat = 0;
+ mOrientedRanges.y.fuzz = 0;
+ mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
+ break;
+
+ default:
+ mOrientedXPrecision = mXPrecision;
+ mOrientedYPrecision = mYPrecision;
+
+ mOrientedRanges.x.min = mXTranslate;
+ mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
+ mOrientedRanges.x.flat = 0;
+ mOrientedRanges.x.fuzz = 0;
+ mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
+
+ mOrientedRanges.y.min = mYTranslate;
+ mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
+ mOrientedRanges.y.flat = 0;
+ mOrientedRanges.y.fuzz = 0;
+ mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
+ break;
+ }
+
+ // Location
+ updateAffineTransformation();
+
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
+ // Compute pointer gesture detection parameters.
+ float rawDiagonal = hypotf(rawWidth, rawHeight);
+ float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
+
+ // Scale movements such that one whole swipe of the touch pad covers a
+ // given area relative to the diagonal size of the display when no acceleration
+ // is applied.
+ // Assume that the touch pad has a square aspect ratio such that movements in
+ // X and Y of the same number of raw units cover the same physical distance.
+ mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
+ * displayDiagonal / rawDiagonal;
+ mPointerYMovementScale = mPointerXMovementScale;
+
+ // Scale zooms to cover a smaller range of the display than movements do.
+ // This value determines the area around the pointer that is affected by freeform
+ // pointer gestures.
+ mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
+ * displayDiagonal / rawDiagonal;
+ mPointerYZoomScale = mPointerXZoomScale;
+
+ // Max width between pointers to detect a swipe gesture is more than some fraction
+ // of the diagonal axis of the touch pad. Touches that are wider than this are
+ // translated into freeform gestures.
+ mPointerGestureMaxSwipeWidth =
+ mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
+
+ // Abort current pointer usages because the state has changed.
+ abortPointerUsage(when, 0 /*policyFlags*/);
+ }
+
+ // Inform the dispatcher about the changes.
+ *outResetNeeded = true;
+ bumpGeneration();
+ }
+}
+
+void TouchInputMapper::dumpSurface(std::string& dump) {
+ dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
+ dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
+ dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
+ dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
+ dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
+ dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
+ dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
+ dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
+ dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
+ dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
+}
+
+void TouchInputMapper::configureVirtualKeys() {
+ std::vector<VirtualKeyDefinition> virtualKeyDefinitions;
+ getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
+
+ mVirtualKeys.clear();
+
+ if (virtualKeyDefinitions.size() == 0) {
+ return;
+ }
+
+ int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
+ int32_t touchScreenTop = mRawPointerAxes.y.minValue;
+ int32_t touchScreenWidth = mRawPointerAxes.getRawWidth();
+ int32_t touchScreenHeight = mRawPointerAxes.getRawHeight();
+
+ for (const VirtualKeyDefinition& virtualKeyDefinition : virtualKeyDefinitions) {
+ VirtualKey virtualKey;
+
+ virtualKey.scanCode = virtualKeyDefinition.scanCode;
+ int32_t keyCode;
+ int32_t dummyKeyMetaState;
+ uint32_t flags;
+ if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, 0,
+ &keyCode, &dummyKeyMetaState, &flags)) {
+ ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
+ virtualKey.scanCode);
+ continue; // drop the key
+ }
+
+ virtualKey.keyCode = keyCode;
+ virtualKey.flags = flags;
+
+ // convert the key definition's display coordinates into touch coordinates for a hit box
+ int32_t halfWidth = virtualKeyDefinition.width / 2;
+ int32_t halfHeight = virtualKeyDefinition.height / 2;
+
+ virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
+ * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
+ virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
+ * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
+ virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
+ * touchScreenHeight / mSurfaceHeight + touchScreenTop;
+ virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
+ * touchScreenHeight / mSurfaceHeight + touchScreenTop;
+ mVirtualKeys.push_back(virtualKey);
+ }
+}
+
+void TouchInputMapper::dumpVirtualKeys(std::string& dump) {
+ if (!mVirtualKeys.empty()) {
+ dump += INDENT3 "Virtual Keys:\n";
+
+ for (size_t i = 0; i < mVirtualKeys.size(); i++) {
+ const VirtualKey& virtualKey = mVirtualKeys[i];
+ dump += StringPrintf(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
+ "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
+ i, virtualKey.scanCode, virtualKey.keyCode,
+ virtualKey.hitLeft, virtualKey.hitRight,
+ virtualKey.hitTop, virtualKey.hitBottom);
+ }
+ }
+}
+
+void TouchInputMapper::parseCalibration() {
+ const PropertyMap& in = getDevice()->getConfiguration();
+ Calibration& out = mCalibration;
+
+ // Size
+ out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
+ String8 sizeCalibrationString;
+ if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
+ if (sizeCalibrationString == "none") {
+ out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
+ } else if (sizeCalibrationString == "geometric") {
+ out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
+ } else if (sizeCalibrationString == "diameter") {
+ out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
+ } else if (sizeCalibrationString == "box") {
+ out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
+ } else if (sizeCalibrationString == "area") {
+ out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
+ } else if (sizeCalibrationString != "default") {
+ ALOGW("Invalid value for touch.size.calibration: '%s'",
+ sizeCalibrationString.string());
+ }
+ }
+
+ out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
+ out.sizeScale);
+ out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
+ out.sizeBias);
+ out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
+ out.sizeIsSummed);
+
+ // Pressure
+ out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
+ String8 pressureCalibrationString;
+ if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
+ if (pressureCalibrationString == "none") {
+ out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
+ } else if (pressureCalibrationString == "physical") {
+ out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
+ } else if (pressureCalibrationString == "amplitude") {
+ out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
+ } else if (pressureCalibrationString != "default") {
+ ALOGW("Invalid value for touch.pressure.calibration: '%s'",
+ pressureCalibrationString.string());
+ }
+ }
+
+ out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
+ out.pressureScale);
+
+ // Orientation
+ out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
+ String8 orientationCalibrationString;
+ if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
+ if (orientationCalibrationString == "none") {
+ out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
+ } else if (orientationCalibrationString == "interpolated") {
+ out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
+ } else if (orientationCalibrationString == "vector") {
+ out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
+ } else if (orientationCalibrationString != "default") {
+ ALOGW("Invalid value for touch.orientation.calibration: '%s'",
+ orientationCalibrationString.string());
+ }
+ }
+
+ // Distance
+ out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
+ String8 distanceCalibrationString;
+ if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
+ if (distanceCalibrationString == "none") {
+ out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
+ } else if (distanceCalibrationString == "scaled") {
+ out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
+ } else if (distanceCalibrationString != "default") {
+ ALOGW("Invalid value for touch.distance.calibration: '%s'",
+ distanceCalibrationString.string());
+ }
+ }
+
+ out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
+ out.distanceScale);
+
+ out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
+ String8 coverageCalibrationString;
+ if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
+ if (coverageCalibrationString == "none") {
+ out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+ } else if (coverageCalibrationString == "box") {
+ out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
+ } else if (coverageCalibrationString != "default") {
+ ALOGW("Invalid value for touch.coverage.calibration: '%s'",
+ coverageCalibrationString.string());
+ }
+ }
+}
+
+void TouchInputMapper::resolveCalibration() {
+ // Size
+ if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
+ if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
+ mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
+ }
+ } else {
+ mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
+ }
+
+ // Pressure
+ if (mRawPointerAxes.pressure.valid) {
+ if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
+ mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
+ }
+ } else {
+ mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
+ }
+
+ // Orientation
+ if (mRawPointerAxes.orientation.valid) {
+ if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
+ mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
+ }
+ } else {
+ mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
+ }
+
+ // Distance
+ if (mRawPointerAxes.distance.valid) {
+ if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
+ mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
+ }
+ } else {
+ mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
+ }
+
+ // Coverage
+ if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
+ mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+ }
+}
+
+void TouchInputMapper::dumpCalibration(std::string& dump) {
+ dump += INDENT3 "Calibration:\n";
+
+ // Size
+ switch (mCalibration.sizeCalibration) {
+ case Calibration::SIZE_CALIBRATION_NONE:
+ dump += INDENT4 "touch.size.calibration: none\n";
+ break;
+ case Calibration::SIZE_CALIBRATION_GEOMETRIC:
+ dump += INDENT4 "touch.size.calibration: geometric\n";
+ break;
+ case Calibration::SIZE_CALIBRATION_DIAMETER:
+ dump += INDENT4 "touch.size.calibration: diameter\n";
+ break;
+ case Calibration::SIZE_CALIBRATION_BOX:
+ dump += INDENT4 "touch.size.calibration: box\n";
+ break;
+ case Calibration::SIZE_CALIBRATION_AREA:
+ dump += INDENT4 "touch.size.calibration: area\n";
+ break;
+ default:
+ ALOG_ASSERT(false);
+ }
+
+ if (mCalibration.haveSizeScale) {
+ dump += StringPrintf(INDENT4 "touch.size.scale: %0.3f\n",
+ mCalibration.sizeScale);
+ }
+
+ if (mCalibration.haveSizeBias) {
+ dump += StringPrintf(INDENT4 "touch.size.bias: %0.3f\n",
+ mCalibration.sizeBias);
+ }
+
+ if (mCalibration.haveSizeIsSummed) {
+ dump += StringPrintf(INDENT4 "touch.size.isSummed: %s\n",
+ toString(mCalibration.sizeIsSummed));
+ }
+
+ // Pressure
+ switch (mCalibration.pressureCalibration) {
+ case Calibration::PRESSURE_CALIBRATION_NONE:
+ dump += INDENT4 "touch.pressure.calibration: none\n";
+ break;
+ case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
+ dump += INDENT4 "touch.pressure.calibration: physical\n";
+ break;
+ case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
+ dump += INDENT4 "touch.pressure.calibration: amplitude\n";
+ break;
+ default:
+ ALOG_ASSERT(false);
+ }
+
+ if (mCalibration.havePressureScale) {
+ dump += StringPrintf(INDENT4 "touch.pressure.scale: %0.3f\n",
+ mCalibration.pressureScale);
+ }
+
+ // Orientation
+ switch (mCalibration.orientationCalibration) {
+ case Calibration::ORIENTATION_CALIBRATION_NONE:
+ dump += INDENT4 "touch.orientation.calibration: none\n";
+ break;
+ case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
+ dump += INDENT4 "touch.orientation.calibration: interpolated\n";
+ break;
+ case Calibration::ORIENTATION_CALIBRATION_VECTOR:
+ dump += INDENT4 "touch.orientation.calibration: vector\n";
+ break;
+ default:
+ ALOG_ASSERT(false);
+ }
+
+ // Distance
+ switch (mCalibration.distanceCalibration) {
+ case Calibration::DISTANCE_CALIBRATION_NONE:
+ dump += INDENT4 "touch.distance.calibration: none\n";
+ break;
+ case Calibration::DISTANCE_CALIBRATION_SCALED:
+ dump += INDENT4 "touch.distance.calibration: scaled\n";
+ break;
+ default:
+ ALOG_ASSERT(false);
+ }
+
+ if (mCalibration.haveDistanceScale) {
+ dump += StringPrintf(INDENT4 "touch.distance.scale: %0.3f\n",
+ mCalibration.distanceScale);
+ }
+
+ switch (mCalibration.coverageCalibration) {
+ case Calibration::COVERAGE_CALIBRATION_NONE:
+ dump += INDENT4 "touch.coverage.calibration: none\n";
+ break;
+ case Calibration::COVERAGE_CALIBRATION_BOX:
+ dump += INDENT4 "touch.coverage.calibration: box\n";
+ break;
+ default:
+ ALOG_ASSERT(false);
+ }
+}
+
+void TouchInputMapper::dumpAffineTransformation(std::string& dump) {
+ dump += INDENT3 "Affine Transformation:\n";
+
+ dump += StringPrintf(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
+ dump += StringPrintf(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
+ dump += StringPrintf(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
+ dump += StringPrintf(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
+ dump += StringPrintf(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
+ dump += StringPrintf(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
+}
+
+void TouchInputMapper::updateAffineTransformation() {
+ mAffineTransform = getPolicy()->getTouchAffineTransformation(mDevice->getDescriptor(),
+ mSurfaceOrientation);
+}
+
+void TouchInputMapper::reset(nsecs_t when) {
+ mCursorButtonAccumulator.reset(getDevice());
+ mCursorScrollAccumulator.reset(getDevice());
+ mTouchButtonAccumulator.reset(getDevice());
+
+ mPointerVelocityControl.reset();
+ mWheelXVelocityControl.reset();
+ mWheelYVelocityControl.reset();
+
+ mRawStatesPending.clear();
+ mCurrentRawState.clear();
+ mCurrentCookedState.clear();
+ mLastRawState.clear();
+ mLastCookedState.clear();
+ mPointerUsage = POINTER_USAGE_NONE;
+ mSentHoverEnter = false;
+ mHavePointerIds = false;
+ mCurrentMotionAborted = false;
+ mDownTime = 0;
+
+ mCurrentVirtualKey.down = false;
+
+ mPointerGesture.reset();
+ mPointerSimple.reset();
+ resetExternalStylus();
+
+ if (mPointerController != nullptr) {
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+ mPointerController->clearSpots();
+ }
+
+ InputMapper::reset(when);
+}
+
+void TouchInputMapper::resetExternalStylus() {
+ mExternalStylusState.clear();
+ mExternalStylusId = -1;
+ mExternalStylusFusionTimeout = LLONG_MAX;
+ mExternalStylusDataPending = false;
+}
+
+void TouchInputMapper::clearStylusDataPendingFlags() {
+ mExternalStylusDataPending = false;
+ mExternalStylusFusionTimeout = LLONG_MAX;
+}
+
+void TouchInputMapper::reportEventForStatistics(nsecs_t evdevTime) {
+ nsecs_t now = systemTime(CLOCK_MONOTONIC);
+ nsecs_t latency = now - evdevTime;
+ mStatistics.addValue(nanoseconds_to_microseconds(latency));
+ nsecs_t timeSinceLastReport = now - mStatistics.lastReportTime;
+ if (timeSinceLastReport > STATISTICS_REPORT_FREQUENCY) {
+ android::util::stats_write(android::util::TOUCH_EVENT_REPORTED,
+ mStatistics.min, mStatistics.max,
+ mStatistics.mean(), mStatistics.stdev(), mStatistics.count);
+ mStatistics.reset(now);
+ }
+}
+
+void TouchInputMapper::process(const RawEvent* rawEvent) {
+ mCursorButtonAccumulator.process(rawEvent);
+ mCursorScrollAccumulator.process(rawEvent);
+ mTouchButtonAccumulator.process(rawEvent);
+
+ if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+ reportEventForStatistics(rawEvent->when);
+ sync(rawEvent->when);
+ }
+}
+
+void TouchInputMapper::sync(nsecs_t when) {
+ const RawState* last = mRawStatesPending.empty() ?
+ &mCurrentRawState : &mRawStatesPending.back();
+
+ // Push a new state.
+ mRawStatesPending.emplace_back();
+
+ RawState* next = &mRawStatesPending.back();
+ next->clear();
+ next->when = when;
+
+ // Sync button state.
+ next->buttonState = mTouchButtonAccumulator.getButtonState()
+ | mCursorButtonAccumulator.getButtonState();
+
+ // Sync scroll
+ next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
+ next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
+ mCursorScrollAccumulator.finishSync();
+
+ // Sync touch
+ syncTouch(when, next);
+
+ // Assign pointer ids.
+ if (!mHavePointerIds) {
+ assignPointerIds(last, next);
+ }
+
+#if DEBUG_RAW_EVENTS
+ ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
+ "hovering ids 0x%08x -> 0x%08x",
+ last->rawPointerData.pointerCount,
+ next->rawPointerData.pointerCount,
+ last->rawPointerData.touchingIdBits.value,
+ next->rawPointerData.touchingIdBits.value,
+ last->rawPointerData.hoveringIdBits.value,
+ next->rawPointerData.hoveringIdBits.value);
+#endif
+
+ processRawTouches(false /*timeout*/);
+}
+
+void TouchInputMapper::processRawTouches(bool timeout) {
+ if (mDeviceMode == DEVICE_MODE_DISABLED) {
+ // Drop all input if the device is disabled.
+ mCurrentRawState.clear();
+ mRawStatesPending.clear();
+ return;
+ }
+
+ // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
+ // valid and must go through the full cook and dispatch cycle. This ensures that anything
+ // touching the current state will only observe the events that have been dispatched to the
+ // rest of the pipeline.
+ const size_t N = mRawStatesPending.size();
+ size_t count;
+ for(count = 0; count < N; count++) {
+ const RawState& next = mRawStatesPending[count];
+
+ // A failure to assign the stylus id means that we're waiting on stylus data
+ // and so should defer the rest of the pipeline.
+ if (assignExternalStylusId(next, timeout)) {
+ break;
+ }
+
+ // All ready to go.
+ clearStylusDataPendingFlags();
+ mCurrentRawState.copyFrom(next);
+ if (mCurrentRawState.when < mLastRawState.when) {
+ mCurrentRawState.when = mLastRawState.when;
+ }
+ cookAndDispatch(mCurrentRawState.when);
+ }
+ if (count != 0) {
+ mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count);
+ }
+
+ if (mExternalStylusDataPending) {
+ if (timeout) {
+ nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
+ clearStylusDataPendingFlags();
+ mCurrentRawState.copyFrom(mLastRawState);
+#if DEBUG_STYLUS_FUSION
+ ALOGD("Timeout expired, synthesizing event with new stylus data");
+#endif
+ cookAndDispatch(when);
+ } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
+ mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
+ getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+ }
+ }
+}
+
+void TouchInputMapper::cookAndDispatch(nsecs_t when) {
+ // Always start with a clean state.
+ mCurrentCookedState.clear();
+
+ // Apply stylus buttons to current raw state.
+ applyExternalStylusButtonState(when);
+
+ // Handle policy on initial down or hover events.
+ bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
+ && mCurrentRawState.rawPointerData.pointerCount != 0;
+
+ uint32_t policyFlags = 0;
+ bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
+ if (initialDown || buttonsPressed) {
+ // If this is a touch screen, hide the pointer on an initial down.
+ if (mDeviceMode == DEVICE_MODE_DIRECT) {
+ getContext()->fadePointer();
+ }
+
+ if (mParameters.wake) {
+ policyFlags |= POLICY_FLAG_WAKE;
+ }
+ }
+
+ // Consume raw off-screen touches before cooking pointer data.
+ // If touches are consumed, subsequent code will not receive any pointer data.
+ if (consumeRawTouches(when, policyFlags)) {
+ mCurrentRawState.rawPointerData.clear();
+ }
+
+ // Cook pointer data. This call populates the mCurrentCookedState.cookedPointerData structure
+ // with cooked pointer data that has the same ids and indices as the raw data.
+ // The following code can use either the raw or cooked data, as needed.
+ cookPointerData();
+
+ // Apply stylus pressure to current cooked state.
+ applyExternalStylusTouchState(when);
+
+ // Synthesize key down from raw buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
+ mViewport.displayId, policyFlags,
+ mLastCookedState.buttonState, mCurrentCookedState.buttonState);
+
+ // Dispatch the touches either directly or by translation through a pointer on screen.
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
+ for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
+ !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const RawPointerData::Pointer& pointer =
+ mCurrentRawState.rawPointerData.pointerForId(id);
+ if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
+ || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
+ mCurrentCookedState.stylusIdBits.markBit(id);
+ } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
+ || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ mCurrentCookedState.fingerIdBits.markBit(id);
+ } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
+ mCurrentCookedState.mouseIdBits.markBit(id);
+ }
+ }
+ for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
+ !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const RawPointerData::Pointer& pointer =
+ mCurrentRawState.rawPointerData.pointerForId(id);
+ if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
+ || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
+ mCurrentCookedState.stylusIdBits.markBit(id);
+ }
+ }
+
+ // Stylus takes precedence over all tools, then mouse, then finger.
+ PointerUsage pointerUsage = mPointerUsage;
+ if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
+ mCurrentCookedState.mouseIdBits.clear();
+ mCurrentCookedState.fingerIdBits.clear();
+ pointerUsage = POINTER_USAGE_STYLUS;
+ } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
+ mCurrentCookedState.fingerIdBits.clear();
+ pointerUsage = POINTER_USAGE_MOUSE;
+ } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
+ isPointerDown(mCurrentRawState.buttonState)) {
+ pointerUsage = POINTER_USAGE_GESTURES;
+ }
+
+ dispatchPointerUsage(when, policyFlags, pointerUsage);
+ } else {
+ if (mDeviceMode == DEVICE_MODE_DIRECT
+ && mConfig.showTouches && mPointerController != nullptr) {
+ mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+
+ mPointerController->setButtonState(mCurrentRawState.buttonState);
+ mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.touchingIdBits,
+ mViewport.displayId);
+ }
+
+ if (!mCurrentMotionAborted) {
+ dispatchButtonRelease(when, policyFlags);
+ dispatchHoverExit(when, policyFlags);
+ dispatchTouches(when, policyFlags);
+ dispatchHoverEnterAndMove(when, policyFlags);
+ dispatchButtonPress(when, policyFlags);
+ }
+
+ if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
+ mCurrentMotionAborted = false;
+ }
+ }
+
+ // Synthesize key up from raw buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
+ mViewport.displayId, policyFlags,
+ mLastCookedState.buttonState, mCurrentCookedState.buttonState);
+
+ // Clear some transient state.
+ mCurrentRawState.rawVScroll = 0;
+ mCurrentRawState.rawHScroll = 0;
+
+ // Copy current touch to last touch in preparation for the next cycle.
+ mLastRawState.copyFrom(mCurrentRawState);
+ mLastCookedState.copyFrom(mCurrentCookedState);
+}
+
+void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
+ if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
+ mCurrentRawState.buttonState |= mExternalStylusState.buttons;
+ }
+}
+
+void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
+ CookedPointerData& currentPointerData = mCurrentCookedState.cookedPointerData;
+ const CookedPointerData& lastPointerData = mLastCookedState.cookedPointerData;
+
+ if (mExternalStylusId != -1 && currentPointerData.isTouching(mExternalStylusId)) {
+ float pressure = mExternalStylusState.pressure;
+ if (pressure == 0.0f && lastPointerData.isTouching(mExternalStylusId)) {
+ const PointerCoords& coords = lastPointerData.pointerCoordsForId(mExternalStylusId);
+ pressure = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
+ }
+ PointerCoords& coords = currentPointerData.editPointerCoordsWithId(mExternalStylusId);
+ coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
+
+ PointerProperties& properties =
+ currentPointerData.editPointerPropertiesWithId(mExternalStylusId);
+ if (mExternalStylusState.toolType != AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ properties.toolType = mExternalStylusState.toolType;
+ }
+ }
+}
+
+bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
+ if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
+ return false;
+ }
+
+ const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
+ && state.rawPointerData.pointerCount != 0;
+ if (initialDown) {
+ if (mExternalStylusState.pressure != 0.0f) {
+#if DEBUG_STYLUS_FUSION
+ ALOGD("Have both stylus and touch data, beginning fusion");
+#endif
+ mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
+ } else if (timeout) {
+#if DEBUG_STYLUS_FUSION
+ ALOGD("Timeout expired, assuming touch is not a stylus.");
+#endif
+ resetExternalStylus();
+ } else {
+ if (mExternalStylusFusionTimeout == LLONG_MAX) {
+ mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
+ }
+#if DEBUG_STYLUS_FUSION
+ ALOGD("No stylus data but stylus is connected, requesting timeout "
+ "(%" PRId64 "ms)", mExternalStylusFusionTimeout);
+#endif
+ getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+ return true;
+ }
+ }
+
+ // Check if the stylus pointer has gone up.
+ if (mExternalStylusId != -1 &&
+ !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
+#if DEBUG_STYLUS_FUSION
+ ALOGD("Stylus pointer is going up");
+#endif
+ mExternalStylusId = -1;
+ }
+
+ return false;
+}
+
+void TouchInputMapper::timeoutExpired(nsecs_t when) {
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
+ if (mPointerUsage == POINTER_USAGE_GESTURES) {
+ dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
+ }
+ } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
+ if (mExternalStylusFusionTimeout < when) {
+ processRawTouches(true /*timeout*/);
+ } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
+ getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+ }
+ }
+}
+
+void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
+ mExternalStylusState.copyFrom(state);
+ if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
+ // We're either in the middle of a fused stream of data or we're waiting on data before
+ // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
+ // data.
+ mExternalStylusDataPending = true;
+ processRawTouches(false /*timeout*/);
+ }
+}
+
+bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
+ // Check for release of a virtual key.
+ if (mCurrentVirtualKey.down) {
+ if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
+ // Pointer went up while virtual key was down.
+ mCurrentVirtualKey.down = false;
+ if (!mCurrentVirtualKey.ignored) {
+#if DEBUG_VIRTUAL_KEYS
+ ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
+ mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+#endif
+ dispatchVirtualKey(when, policyFlags,
+ AKEY_EVENT_ACTION_UP,
+ AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
+ }
+ return true;
+ }
+
+ if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
+ uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
+ const RawPointerData::Pointer& pointer =
+ mCurrentRawState.rawPointerData.pointerForId(id);
+ const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
+ if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
+ // Pointer is still within the space of the virtual key.
+ return true;
+ }
+ }
+
+ // Pointer left virtual key area or another pointer also went down.
+ // Send key cancellation but do not consume the touch yet.
+ // This is useful when the user swipes through from the virtual key area
+ // into the main display surface.
+ mCurrentVirtualKey.down = false;
+ if (!mCurrentVirtualKey.ignored) {
+#if DEBUG_VIRTUAL_KEYS
+ ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
+ mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+#endif
+ dispatchVirtualKey(when, policyFlags,
+ AKEY_EVENT_ACTION_UP,
+ AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
+ | AKEY_EVENT_FLAG_CANCELED);
+ }
+ }
+
+ if (mLastRawState.rawPointerData.touchingIdBits.isEmpty()
+ && !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
+ // Pointer just went down. Check for virtual key press or off-screen touches.
+ uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
+ const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
+ if (!isPointInsideSurface(pointer.x, pointer.y)) {
+ // If exactly one pointer went down, check for virtual key hit.
+ // Otherwise we will drop the entire stroke.
+ if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
+ const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
+ if (virtualKey) {
+ mCurrentVirtualKey.down = true;
+ mCurrentVirtualKey.downTime = when;
+ mCurrentVirtualKey.keyCode = virtualKey->keyCode;
+ mCurrentVirtualKey.scanCode = virtualKey->scanCode;
+ mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
+ when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
+
+ if (!mCurrentVirtualKey.ignored) {
+#if DEBUG_VIRTUAL_KEYS
+ ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
+ mCurrentVirtualKey.keyCode,
+ mCurrentVirtualKey.scanCode);
+#endif
+ dispatchVirtualKey(when, policyFlags,
+ AKEY_EVENT_ACTION_DOWN,
+ AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
+ }
+ }
+ }
+ return true;
+ }
+ }
+
+ // Disable all virtual key touches that happen within a short time interval of the
+ // most recent touch within the screen area. The idea is to filter out stray
+ // virtual key presses when interacting with the touch screen.
+ //
+ // Problems we're trying to solve:
+ //
+ // 1. While scrolling a list or dragging the window shade, the user swipes down into a
+ // virtual key area that is implemented by a separate touch panel and accidentally
+ // triggers a virtual key.
+ //
+ // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
+ // area and accidentally triggers a virtual key. This often happens when virtual keys
+ // are layed out below the screen near to where the on screen keyboard's space bar
+ // is displayed.
+ if (mConfig.virtualKeyQuietTime > 0 &&
+ !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
+ mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
+ }
+ return false;
+}
+
+void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
+ int32_t keyEventAction, int32_t keyEventFlags) {
+ int32_t keyCode = mCurrentVirtualKey.keyCode;
+ int32_t scanCode = mCurrentVirtualKey.scanCode;
+ nsecs_t downTime = mCurrentVirtualKey.downTime;
+ int32_t metaState = mContext->getGlobalMetaState();
+ policyFlags |= POLICY_FLAG_VIRTUAL;
+
+ NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
+ mViewport.displayId,
+ policyFlags, keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
+ getListener()->notifyKey(&args);
+}
+
+void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
+ BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
+ if (!currentIdBits.isEmpty()) {
+ int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mCurrentCookedState.buttonState;
+ dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ mCurrentCookedState.deviceTimestamp,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ currentIdBits, -1,
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mCurrentMotionAborted = true;
+ }
+}
+
+void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
+ BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
+ BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
+ int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mCurrentCookedState.buttonState;
+
+ if (currentIdBits == lastIdBits) {
+ if (!currentIdBits.isEmpty()) {
+ // No pointer id changes so this is a move event.
+ // The listener takes care of batching moves so we don't have to deal with that here.
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
+ mCurrentCookedState.deviceTimestamp,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ currentIdBits, -1,
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ }
+ } else {
+ // There may be pointers going up and pointers going down and pointers moving
+ // all at the same time.
+ BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
+ BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
+ BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
+ BitSet32 dispatchedIdBits(lastIdBits.value);
+
+ // Update last coordinates of pointers that have moved so that we observe the new
+ // pointer positions at the same time as other pointers that have just gone up.
+ bool moveNeeded = updateMovedPointers(
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ mLastCookedState.cookedPointerData.pointerProperties,
+ mLastCookedState.cookedPointerData.pointerCoords,
+ mLastCookedState.cookedPointerData.idToIndex,
+ moveIdBits);
+ if (buttonState != mLastCookedState.buttonState) {
+ moveNeeded = true;
+ }
+
+ // Dispatch pointer up events.
+ while (!upIdBits.isEmpty()) {
+ uint32_t upId = upIdBits.clearFirstMarkedBit();
+
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
+ mCurrentCookedState.deviceTimestamp,
+ mLastCookedState.cookedPointerData.pointerProperties,
+ mLastCookedState.cookedPointerData.pointerCoords,
+ mLastCookedState.cookedPointerData.idToIndex,
+ dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ dispatchedIdBits.clearBit(upId);
+ }
+
+ // Dispatch move events if any of the remaining pointers moved from their old locations.
+ // Although applications receive new locations as part of individual pointer up
+ // events, they do not generally handle them except when presented in a move event.
+ if (moveNeeded && !moveIdBits.isEmpty()) {
+ ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
+ mCurrentCookedState.deviceTimestamp,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ }
+
+ // Dispatch pointer down events using the new pointer locations.
+ while (!downIdBits.isEmpty()) {
+ uint32_t downId = downIdBits.clearFirstMarkedBit();
+ dispatchedIdBits.markBit(downId);
+
+ if (dispatchedIdBits.count() == 1) {
+ // First pointer is going down. Set down time.
+ mDownTime = when;
+ }
+
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
+ mCurrentCookedState.deviceTimestamp,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ }
+ }
+}
+
+void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
+ if (mSentHoverEnter &&
+ (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()
+ || !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
+ int32_t metaState = getContext()->getGlobalMetaState();
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastCookedState.buttonState, 0,
+ mLastCookedState.deviceTimestamp,
+ mLastCookedState.cookedPointerData.pointerProperties,
+ mLastCookedState.cookedPointerData.pointerCoords,
+ mLastCookedState.cookedPointerData.idToIndex,
+ mLastCookedState.cookedPointerData.hoveringIdBits, -1,
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mSentHoverEnter = false;
+ }
+}
+
+void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
+ if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty()
+ && !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
+ int32_t metaState = getContext()->getGlobalMetaState();
+ if (!mSentHoverEnter) {
+ dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER,
+ 0, 0, metaState, mCurrentRawState.buttonState, 0,
+ mCurrentCookedState.deviceTimestamp,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mSentHoverEnter = true;
+ }
+
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+ mCurrentRawState.buttonState, 0,
+ mCurrentCookedState.deviceTimestamp,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ }
+}
+
+void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) {
+ BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
+ const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData);
+ const int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mLastCookedState.buttonState;
+ while (!releasedButtons.isEmpty()) {
+ int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
+ buttonState &= ~actionButton;
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton,
+ 0, metaState, buttonState, 0,
+ mCurrentCookedState.deviceTimestamp,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ }
+}
+
+void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) {
+ BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
+ const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData);
+ const int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mLastCookedState.buttonState;
+ while (!pressedButtons.isEmpty()) {
+ int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
+ buttonState |= actionButton;
+ dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
+ 0, metaState, buttonState, 0,
+ mCurrentCookedState.deviceTimestamp,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ }
+}
+
+const BitSet32& TouchInputMapper::findActiveIdBits(const CookedPointerData& cookedPointerData) {
+ if (!cookedPointerData.touchingIdBits.isEmpty()) {
+ return cookedPointerData.touchingIdBits;
+ }
+ return cookedPointerData.hoveringIdBits;
+}
+
+void TouchInputMapper::cookPointerData() {
+ uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
+
+ mCurrentCookedState.cookedPointerData.clear();
+ mCurrentCookedState.deviceTimestamp =
+ mCurrentRawState.deviceTimestamp;
+ mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
+ mCurrentCookedState.cookedPointerData.hoveringIdBits =
+ mCurrentRawState.rawPointerData.hoveringIdBits;
+ mCurrentCookedState.cookedPointerData.touchingIdBits =
+ mCurrentRawState.rawPointerData.touchingIdBits;
+
+ if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
+ mCurrentCookedState.buttonState = 0;
+ } else {
+ mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
+ }
+
+ // Walk through the the active pointers and map device coordinates onto
+ // surface coordinates and adjust for display orientation.
+ for (uint32_t i = 0; i < currentPointerCount; i++) {
+ const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
+
+ // Size
+ float touchMajor, touchMinor, toolMajor, toolMinor, size;
+ switch (mCalibration.sizeCalibration) {
+ case Calibration::SIZE_CALIBRATION_GEOMETRIC:
+ case Calibration::SIZE_CALIBRATION_DIAMETER:
+ case Calibration::SIZE_CALIBRATION_BOX:
+ case Calibration::SIZE_CALIBRATION_AREA:
+ if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
+ touchMajor = in.touchMajor;
+ touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
+ toolMajor = in.toolMajor;
+ toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
+ size = mRawPointerAxes.touchMinor.valid
+ ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
+ } else if (mRawPointerAxes.touchMajor.valid) {
+ toolMajor = touchMajor = in.touchMajor;
+ toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
+ ? in.touchMinor : in.touchMajor;
+ size = mRawPointerAxes.touchMinor.valid
+ ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
+ } else if (mRawPointerAxes.toolMajor.valid) {
+ touchMajor = toolMajor = in.toolMajor;
+ touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
+ ? in.toolMinor : in.toolMajor;
+ size = mRawPointerAxes.toolMinor.valid
+ ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
+ } else {
+ ALOG_ASSERT(false, "No touch or tool axes. "
+ "Size calibration should have been resolved to NONE.");
+ touchMajor = 0;
+ touchMinor = 0;
+ toolMajor = 0;
+ toolMinor = 0;
+ size = 0;
+ }
+
+ if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
+ uint32_t touchingCount =
+ mCurrentRawState.rawPointerData.touchingIdBits.count();
+ if (touchingCount > 1) {
+ touchMajor /= touchingCount;
+ touchMinor /= touchingCount;
+ toolMajor /= touchingCount;
+ toolMinor /= touchingCount;
+ size /= touchingCount;
+ }
+ }
+
+ if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
+ touchMajor *= mGeometricScale;
+ touchMinor *= mGeometricScale;
+ toolMajor *= mGeometricScale;
+ toolMinor *= mGeometricScale;
+ } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
+ touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
+ touchMinor = touchMajor;
+ toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
+ toolMinor = toolMajor;
+ } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
+ touchMinor = touchMajor;
+ toolMinor = toolMajor;
+ }
+
+ mCalibration.applySizeScaleAndBias(&touchMajor);
+ mCalibration.applySizeScaleAndBias(&touchMinor);
+ mCalibration.applySizeScaleAndBias(&toolMajor);
+ mCalibration.applySizeScaleAndBias(&toolMinor);
+ size *= mSizeScale;
+ break;
+ default:
+ touchMajor = 0;
+ touchMinor = 0;
+ toolMajor = 0;
+ toolMinor = 0;
+ size = 0;
+ break;
+ }
+
+ // Pressure
+ float pressure;
+ switch (mCalibration.pressureCalibration) {
+ case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
+ case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
+ pressure = in.pressure * mPressureScale;
+ break;
+ default:
+ pressure = in.isHovering ? 0 : 1;
+ break;
+ }
+
+ // Tilt and Orientation
+ float tilt;
+ float orientation;
+ if (mHaveTilt) {
+ float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
+ float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
+ orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
+ tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
+ } else {
+ tilt = 0;
+
+ switch (mCalibration.orientationCalibration) {
+ case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
+ orientation = in.orientation * mOrientationScale;
+ break;
+ case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
+ int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
+ int32_t c2 = signExtendNybble(in.orientation & 0x0f);
+ if (c1 != 0 || c2 != 0) {
+ orientation = atan2f(c1, c2) * 0.5f;
+ float confidence = hypotf(c1, c2);
+ float scale = 1.0f + confidence / 16.0f;
+ touchMajor *= scale;
+ touchMinor /= scale;
+ toolMajor *= scale;
+ toolMinor /= scale;
+ } else {
+ orientation = 0;
+ }
+ break;
+ }
+ default:
+ orientation = 0;
+ }
+ }
+
+ // Distance
+ float distance;
+ switch (mCalibration.distanceCalibration) {
+ case Calibration::DISTANCE_CALIBRATION_SCALED:
+ distance = in.distance * mDistanceScale;
+ break;
+ default:
+ distance = 0;
+ }
+
+ // Coverage
+ int32_t rawLeft, rawTop, rawRight, rawBottom;
+ switch (mCalibration.coverageCalibration) {
+ case Calibration::COVERAGE_CALIBRATION_BOX:
+ rawLeft = (in.toolMinor & 0xffff0000) >> 16;
+ rawRight = in.toolMinor & 0x0000ffff;
+ rawBottom = in.toolMajor & 0x0000ffff;
+ rawTop = (in.toolMajor & 0xffff0000) >> 16;
+ break;
+ default:
+ rawLeft = rawTop = rawRight = rawBottom = 0;
+ break;
+ }
+
+ // Adjust X,Y coords for device calibration
+ // TODO: Adjust coverage coords?
+ float xTransformed = in.x, yTransformed = in.y;
+ mAffineTransform.applyTo(xTransformed, yTransformed);
+
+ // Adjust X, Y, and coverage coords for surface orientation.
+ float x, y;
+ float left, top, right, bottom;
+
+ switch (mSurfaceOrientation) {
+ case DISPLAY_ORIENTATION_90:
+ x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
+ left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
+ top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
+ orientation -= M_PI_2;
+ if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
+ orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
+ }
+ break;
+ case DISPLAY_ORIENTATION_180:
+ x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
+ y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
+ left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
+ right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
+ bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
+ top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
+ orientation -= M_PI;
+ if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
+ orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
+ }
+ break;
+ case DISPLAY_ORIENTATION_270:
+ x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
+ y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
+ right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
+ bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ orientation += M_PI_2;
+ if (mOrientedRanges.haveOrientation && orientation > mOrientedRanges.orientation.max) {
+ orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
+ }
+ break;
+ default:
+ x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ break;
+ }
+
+ // Write output coords.
+ PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
+ out.clear();
+ out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
+ out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
+ out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
+ out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
+ out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
+ out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
+ out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
+ if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+ out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
+ out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
+ out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
+ out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
+ } else {
+ out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
+ out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
+ }
+
+ // Write output properties.
+ PointerProperties& properties =
+ mCurrentCookedState.cookedPointerData.pointerProperties[i];
+ uint32_t id = in.id;
+ properties.clear();
+ properties.id = id;
+ properties.toolType = in.toolType;
+
+ // Write id index.
+ mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
+ }
+}
+
+void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
+ PointerUsage pointerUsage) {
+ if (pointerUsage != mPointerUsage) {
+ abortPointerUsage(when, policyFlags);
+ mPointerUsage = pointerUsage;
+ }
+
+ switch (mPointerUsage) {
+ case POINTER_USAGE_GESTURES:
+ dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
+ break;
+ case POINTER_USAGE_STYLUS:
+ dispatchPointerStylus(when, policyFlags);
+ break;
+ case POINTER_USAGE_MOUSE:
+ dispatchPointerMouse(when, policyFlags);
+ break;
+ default:
+ break;
+ }
+}
+
+void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
+ switch (mPointerUsage) {
+ case POINTER_USAGE_GESTURES:
+ abortPointerGestures(when, policyFlags);
+ break;
+ case POINTER_USAGE_STYLUS:
+ abortPointerStylus(when, policyFlags);
+ break;
+ case POINTER_USAGE_MOUSE:
+ abortPointerMouse(when, policyFlags);
+ break;
+ default:
+ break;
+ }
+
+ mPointerUsage = POINTER_USAGE_NONE;
+}
+
+void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
+ bool isTimeout) {
+ // Update current gesture coordinates.
+ bool cancelPreviousGesture, finishPreviousGesture;
+ bool sendEvents = preparePointerGestures(when,
+ &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
+ if (!sendEvents) {
+ return;
+ }
+ if (finishPreviousGesture) {
+ cancelPreviousGesture = false;
+ }
+
+ // Update the pointer presentation and spots.
+ if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
+ mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+ if (finishPreviousGesture || cancelPreviousGesture) {
+ mPointerController->clearSpots();
+ }
+
+ if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
+ mPointerController->setSpots(mPointerGesture.currentGestureCoords,
+ mPointerGesture.currentGestureIdToIndex,
+ mPointerGesture.currentGestureIdBits,
+ mPointerController->getDisplayId());
+ }
+ } else {
+ mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+ }
+
+ // Show or hide the pointer if needed.
+ switch (mPointerGesture.currentGestureMode) {
+ case PointerGesture::NEUTRAL:
+ case PointerGesture::QUIET:
+ if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH
+ && mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
+ // Remind the user of where the pointer is after finishing a gesture with spots.
+ mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
+ }
+ break;
+ case PointerGesture::TAP:
+ case PointerGesture::TAP_DRAG:
+ case PointerGesture::BUTTON_CLICK_OR_DRAG:
+ case PointerGesture::HOVER:
+ case PointerGesture::PRESS:
+ case PointerGesture::SWIPE:
+ // Unfade the pointer when the current gesture manipulates the
+ // area directly under the pointer.
+ mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+ break;
+ case PointerGesture::FREEFORM:
+ // Fade the pointer when the current gesture manipulates a different
+ // area and there are spots to guide the user experience.
+ if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+ } else {
+ mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+ }
+ break;
+ }
+
+ // Send events!
+ int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mCurrentCookedState.buttonState;
+
+ // Update last coordinates of pointers that have moved so that we observe the new
+ // pointer positions at the same time as other pointers that have just gone up.
+ bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
+ || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
+ || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
+ || mPointerGesture.currentGestureMode == PointerGesture::PRESS
+ || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
+ || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
+ bool moveNeeded = false;
+ if (down && !cancelPreviousGesture && !finishPreviousGesture
+ && !mPointerGesture.lastGestureIdBits.isEmpty()
+ && !mPointerGesture.currentGestureIdBits.isEmpty()) {
+ BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
+ & mPointerGesture.lastGestureIdBits.value);
+ moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
+ mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
+ mPointerGesture.lastGestureProperties,
+ mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
+ movedGestureIdBits);
+ if (buttonState != mLastCookedState.buttonState) {
+ moveNeeded = true;
+ }
+ }
+
+ // Send motion events for all pointers that went up or were canceled.
+ BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
+ if (!dispatchedGestureIdBits.isEmpty()) {
+ if (cancelPreviousGesture) {
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ mPointerGesture.lastGestureProperties,
+ mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
+ dispatchedGestureIdBits, -1, 0,
+ 0, mPointerGesture.downTime);
+
+ dispatchedGestureIdBits.clear();
+ } else {
+ BitSet32 upGestureIdBits;
+ if (finishPreviousGesture) {
+ upGestureIdBits = dispatchedGestureIdBits;
+ } else {
+ upGestureIdBits.value = dispatchedGestureIdBits.value
+ & ~mPointerGesture.currentGestureIdBits.value;
+ }
+ while (!upGestureIdBits.isEmpty()) {
+ uint32_t id = upGestureIdBits.clearFirstMarkedBit();
+
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ /* deviceTimestamp */ 0,
+ mPointerGesture.lastGestureProperties,
+ mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
+ dispatchedGestureIdBits, id,
+ 0, 0, mPointerGesture.downTime);
+
+ dispatchedGestureIdBits.clearBit(id);
+ }
+ }
+ }
+
+ // Send motion events for all pointers that moved.
+ if (moveNeeded) {
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ mPointerGesture.currentGestureProperties,
+ mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
+ dispatchedGestureIdBits, -1,
+ 0, 0, mPointerGesture.downTime);
+ }
+
+ // Send motion events for all pointers that went down.
+ if (down) {
+ BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
+ & ~dispatchedGestureIdBits.value);
+ while (!downGestureIdBits.isEmpty()) {
+ uint32_t id = downGestureIdBits.clearFirstMarkedBit();
+ dispatchedGestureIdBits.markBit(id);
+
+ if (dispatchedGestureIdBits.count() == 1) {
+ mPointerGesture.downTime = when;
+ }
+
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
+ /* deviceTimestamp */ 0,
+ mPointerGesture.currentGestureProperties,
+ mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
+ dispatchedGestureIdBits, id,
+ 0, 0, mPointerGesture.downTime);
+ }
+ }
+
+ // Send motion events for hover.
+ if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ mPointerGesture.currentGestureProperties,
+ mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
+ mPointerGesture.currentGestureIdBits, -1,
+ 0, 0, mPointerGesture.downTime);
+ } else if (dispatchedGestureIdBits.isEmpty()
+ && !mPointerGesture.lastGestureIdBits.isEmpty()) {
+ // Synthesize a hover move event after all pointers go up to indicate that
+ // the pointer is hovering again even if the user is not currently touching
+ // the touch pad. This ensures that a view will receive a fresh hover enter
+ // event after a tap.
+ float x, y;
+ mPointerController->getPosition(&x, &y);
+
+ PointerProperties pointerProperties;
+ pointerProperties.clear();
+ pointerProperties.id = 0;
+ pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+
+ PointerCoords pointerCoords;
+ pointerCoords.clear();
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+
+ const int32_t displayId = mPointerController->getDisplayId();
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+ metaState, buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ 0, 0, mPointerGesture.downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+ }
+
+ // Update state.
+ mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
+ if (!down) {
+ mPointerGesture.lastGestureIdBits.clear();
+ } else {
+ mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
+ for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
+ mPointerGesture.lastGestureProperties[index].copyFrom(
+ mPointerGesture.currentGestureProperties[index]);
+ mPointerGesture.lastGestureCoords[index].copyFrom(
+ mPointerGesture.currentGestureCoords[index]);
+ mPointerGesture.lastGestureIdToIndex[id] = index;
+ }
+ }
+}
+
+void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
+ // Cancel previously dispatches pointers.
+ if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
+ int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mCurrentRawState.buttonState;
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ mPointerGesture.lastGestureProperties,
+ mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
+ mPointerGesture.lastGestureIdBits, -1,
+ 0, 0, mPointerGesture.downTime);
+ }
+
+ // Reset the current pointer gesture.
+ mPointerGesture.reset();
+ mPointerVelocityControl.reset();
+
+ // Remove any current spots.
+ if (mPointerController != nullptr) {
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+ mPointerController->clearSpots();
+ }
+}
+
+bool TouchInputMapper::preparePointerGestures(nsecs_t when,
+ bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
+ *outCancelPreviousGesture = false;
+ *outFinishPreviousGesture = false;
+
+ // Handle TAP timeout.
+ if (isTimeout) {
+#if DEBUG_GESTURES
+ ALOGD("Gestures: Processing timeout");
+#endif
+
+ if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
+ if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
+ // The tap/drag timeout has not yet expired.
+ getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
+ + mConfig.pointerGestureTapDragInterval);
+ } else {
+ // The tap is finished.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: TAP finished");
+#endif
+ *outFinishPreviousGesture = true;
+
+ mPointerGesture.activeGestureId = -1;
+ mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
+ mPointerGesture.currentGestureIdBits.clear();
+
+ mPointerVelocityControl.reset();
+ return true;
+ }
+ }
+
+ // We did not handle this timeout.
+ return false;
+ }
+
+ const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
+ const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
+
+ // Update the velocity tracker.
+ {
+ VelocityTracker::Position positions[MAX_POINTERS];
+ uint32_t count = 0;
+ for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); count++) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const RawPointerData::Pointer& pointer =
+ mCurrentRawState.rawPointerData.pointerForId(id);
+ positions[count].x = pointer.x * mPointerXMovementScale;
+ positions[count].y = pointer.y * mPointerYMovementScale;
+ }
+ mPointerGesture.velocityTracker.addMovement(when,
+ mCurrentCookedState.fingerIdBits, positions);
+ }
+
+ // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
+ // to NEUTRAL, then we should not generate tap event.
+ if (mPointerGesture.lastGestureMode != PointerGesture::HOVER
+ && mPointerGesture.lastGestureMode != PointerGesture::TAP
+ && mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
+ mPointerGesture.resetTap();
+ }
+
+ // Pick a new active touch id if needed.
+ // Choose an arbitrary pointer that just went down, if there is one.
+ // Otherwise choose an arbitrary remaining pointer.
+ // This guarantees we always have an active touch id when there is at least one pointer.
+ // We keep the same active touch id for as long as possible.
+ int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
+ int32_t activeTouchId = lastActiveTouchId;
+ if (activeTouchId < 0) {
+ if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
+ activeTouchId = mPointerGesture.activeTouchId =
+ mCurrentCookedState.fingerIdBits.firstMarkedBit();
+ mPointerGesture.firstTouchTime = when;
+ }
+ } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
+ if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
+ activeTouchId = mPointerGesture.activeTouchId =
+ mCurrentCookedState.fingerIdBits.firstMarkedBit();
+ } else {
+ activeTouchId = mPointerGesture.activeTouchId = -1;
+ }
+ }
+
+ // Determine whether we are in quiet time.
+ bool isQuietTime = false;
+ if (activeTouchId < 0) {
+ mPointerGesture.resetQuietTime();
+ } else {
+ isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
+ if (!isQuietTime) {
+ if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
+ || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
+ || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
+ && currentFingerCount < 2) {
+ // Enter quiet time when exiting swipe or freeform state.
+ // This is to prevent accidentally entering the hover state and flinging the
+ // pointer when finishing a swipe and there is still one pointer left onscreen.
+ isQuietTime = true;
+ } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
+ && currentFingerCount >= 2
+ && !isPointerDown(mCurrentRawState.buttonState)) {
+ // Enter quiet time when releasing the button and there are still two or more
+ // fingers down. This may indicate that one finger was used to press the button
+ // but it has not gone up yet.
+ isQuietTime = true;
+ }
+ if (isQuietTime) {
+ mPointerGesture.quietTime = when;
+ }
+ }
+ }
+
+ // Switch states based on button and pointer state.
+ if (isQuietTime) {
+ // Case 1: Quiet time. (QUIET)
+#if DEBUG_GESTURES
+ ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
+ + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
+#endif
+ if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
+ *outFinishPreviousGesture = true;
+ }
+
+ mPointerGesture.activeGestureId = -1;
+ mPointerGesture.currentGestureMode = PointerGesture::QUIET;
+ mPointerGesture.currentGestureIdBits.clear();
+
+ mPointerVelocityControl.reset();
+ } else if (isPointerDown(mCurrentRawState.buttonState)) {
+ // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
+ // The pointer follows the active touch point.
+ // Emit DOWN, MOVE, UP events at the pointer location.
+ //
+ // Only the active touch matters; other fingers are ignored. This policy helps
+ // to handle the case where the user places a second finger on the touch pad
+ // to apply the necessary force to depress an integrated button below the surface.
+ // We don't want the second finger to be delivered to applications.
+ //
+ // For this to work well, we need to make sure to track the pointer that is really
+ // active. If the user first puts one finger down to click then adds another
+ // finger to drag then the active pointer should switch to the finger that is
+ // being dragged.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
+ "currentFingerCount=%d", activeTouchId, currentFingerCount);
+#endif
+ // Reset state when just starting.
+ if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
+ *outFinishPreviousGesture = true;
+ mPointerGesture.activeGestureId = 0;
+ }
+
+ // Switch pointers if needed.
+ // Find the fastest pointer and follow it.
+ if (activeTouchId >= 0 && currentFingerCount > 1) {
+ int32_t bestId = -1;
+ float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
+ for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ float vx, vy;
+ if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
+ float speed = hypotf(vx, vy);
+ if (speed > bestSpeed) {
+ bestId = id;
+ bestSpeed = speed;
+ }
+ }
+ }
+ if (bestId >= 0 && bestId != activeTouchId) {
+ mPointerGesture.activeTouchId = activeTouchId = bestId;
+#if DEBUG_GESTURES
+ ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
+ "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
+#endif
+ }
+ }
+
+ float deltaX = 0, deltaY = 0;
+ if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
+ const RawPointerData::Pointer& currentPointer =
+ mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
+ const RawPointerData::Pointer& lastPointer =
+ mLastRawState.rawPointerData.pointerForId(activeTouchId);
+ deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
+ deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
+
+ rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
+ mPointerVelocityControl.move(when, &deltaX, &deltaY);
+
+ // Move the pointer using a relative motion.
+ // When using spots, the click will occur at the position of the anchor
+ // spot and all other spots will move there.
+ mPointerController->move(deltaX, deltaY);
+ } else {
+ mPointerVelocityControl.reset();
+ }
+
+ float x, y;
+ mPointerController->getPosition(&x, &y);
+
+ mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
+ mPointerGesture.currentGestureIdBits.clear();
+ mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
+ mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+ mPointerGesture.currentGestureProperties[0].clear();
+ mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+ mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ mPointerGesture.currentGestureCoords[0].clear();
+ mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+ } else if (currentFingerCount == 0) {
+ // Case 3. No fingers down and button is not pressed. (NEUTRAL)
+ if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
+ *outFinishPreviousGesture = true;
+ }
+
+ // Watch for taps coming out of HOVER or TAP_DRAG mode.
+ // Checking for taps after TAP_DRAG allows us to detect double-taps.
+ bool tapped = false;
+ if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
+ || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
+ && lastFingerCount == 1) {
+ if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
+ float x, y;
+ mPointerController->getPosition(&x, &y);
+ if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
+ && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
+#if DEBUG_GESTURES
+ ALOGD("Gestures: TAP");
+#endif
+
+ mPointerGesture.tapUpTime = when;
+ getContext()->requestTimeoutAtTime(when
+ + mConfig.pointerGestureTapDragInterval);
+
+ mPointerGesture.activeGestureId = 0;
+ mPointerGesture.currentGestureMode = PointerGesture::TAP;
+ mPointerGesture.currentGestureIdBits.clear();
+ mPointerGesture.currentGestureIdBits.markBit(
+ mPointerGesture.activeGestureId);
+ mPointerGesture.currentGestureIdToIndex[
+ mPointerGesture.activeGestureId] = 0;
+ mPointerGesture.currentGestureProperties[0].clear();
+ mPointerGesture.currentGestureProperties[0].id =
+ mPointerGesture.activeGestureId;
+ mPointerGesture.currentGestureProperties[0].toolType =
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
+ mPointerGesture.currentGestureCoords[0].clear();
+ mPointerGesture.currentGestureCoords[0].setAxisValue(
+ AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
+ mPointerGesture.currentGestureCoords[0].setAxisValue(
+ AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
+ mPointerGesture.currentGestureCoords[0].setAxisValue(
+ AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+
+ tapped = true;
+ } else {
+#if DEBUG_GESTURES
+ ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
+ x - mPointerGesture.tapX,
+ y - mPointerGesture.tapY);
+#endif
+ }
+ } else {
+#if DEBUG_GESTURES
+ if (mPointerGesture.tapDownTime != LLONG_MIN) {
+ ALOGD("Gestures: Not a TAP, %0.3fms since down",
+ (when - mPointerGesture.tapDownTime) * 0.000001f);
+ } else {
+ ALOGD("Gestures: Not a TAP, incompatible mode transitions");
+ }
+#endif
+ }
+ }
+
+ mPointerVelocityControl.reset();
+
+ if (!tapped) {
+#if DEBUG_GESTURES
+ ALOGD("Gestures: NEUTRAL");
+#endif
+ mPointerGesture.activeGestureId = -1;
+ mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
+ mPointerGesture.currentGestureIdBits.clear();
+ }
+ } else if (currentFingerCount == 1) {
+ // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
+ // The pointer follows the active touch point.
+ // When in HOVER, emit HOVER_MOVE events at the pointer location.
+ // When in TAP_DRAG, emit MOVE events at the pointer location.
+ ALOG_ASSERT(activeTouchId >= 0);
+
+ mPointerGesture.currentGestureMode = PointerGesture::HOVER;
+ if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
+ if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
+ float x, y;
+ mPointerController->getPosition(&x, &y);
+ if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
+ && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
+ mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
+ } else {
+#if DEBUG_GESTURES
+ ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
+ x - mPointerGesture.tapX,
+ y - mPointerGesture.tapY);
+#endif
+ }
+ } else {
+#if DEBUG_GESTURES
+ ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
+ (when - mPointerGesture.tapUpTime) * 0.000001f);
+#endif
+ }
+ } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
+ mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
+ }
+
+ float deltaX = 0, deltaY = 0;
+ if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
+ const RawPointerData::Pointer& currentPointer =
+ mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
+ const RawPointerData::Pointer& lastPointer =
+ mLastRawState.rawPointerData.pointerForId(activeTouchId);
+ deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
+ deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
+
+ rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
+ mPointerVelocityControl.move(when, &deltaX, &deltaY);
+
+ // Move the pointer using a relative motion.
+ // When using spots, the hover or drag will occur at the position of the anchor spot.
+ mPointerController->move(deltaX, deltaY);
+ } else {
+ mPointerVelocityControl.reset();
+ }
+
+ bool down;
+ if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
+#if DEBUG_GESTURES
+ ALOGD("Gestures: TAP_DRAG");
+#endif
+ down = true;
+ } else {
+#if DEBUG_GESTURES
+ ALOGD("Gestures: HOVER");
+#endif
+ if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
+ *outFinishPreviousGesture = true;
+ }
+ mPointerGesture.activeGestureId = 0;
+ down = false;
+ }
+
+ float x, y;
+ mPointerController->getPosition(&x, &y);
+
+ mPointerGesture.currentGestureIdBits.clear();
+ mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
+ mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+ mPointerGesture.currentGestureProperties[0].clear();
+ mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+ mPointerGesture.currentGestureProperties[0].toolType =
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
+ mPointerGesture.currentGestureCoords[0].clear();
+ mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
+ down ? 1.0f : 0.0f);
+
+ if (lastFingerCount == 0 && currentFingerCount != 0) {
+ mPointerGesture.resetTap();
+ mPointerGesture.tapDownTime = when;
+ mPointerGesture.tapX = x;
+ mPointerGesture.tapY = y;
+ }
+ } else {
+ // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
+ // We need to provide feedback for each finger that goes down so we cannot wait
+ // for the fingers to move before deciding what to do.
+ //
+ // The ambiguous case is deciding what to do when there are two fingers down but they
+ // have not moved enough to determine whether they are part of a drag or part of a
+ // freeform gesture, or just a press or long-press at the pointer location.
+ //
+ // When there are two fingers we start with the PRESS hypothesis and we generate a
+ // down at the pointer location.
+ //
+ // When the two fingers move enough or when additional fingers are added, we make
+ // a decision to transition into SWIPE or FREEFORM mode accordingly.
+ ALOG_ASSERT(activeTouchId >= 0);
+
+ bool settled = when >= mPointerGesture.firstTouchTime
+ + mConfig.pointerGestureMultitouchSettleInterval;
+ if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
+ && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
+ && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
+ *outFinishPreviousGesture = true;
+ } else if (!settled && currentFingerCount > lastFingerCount) {
+ // Additional pointers have gone down but not yet settled.
+ // Reset the gesture.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
+ "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
+ + mConfig.pointerGestureMultitouchSettleInterval - when)
+ * 0.000001f);
+#endif
+ *outCancelPreviousGesture = true;
+ } else {
+ // Continue previous gesture.
+ mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
+ }
+
+ if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
+ mPointerGesture.currentGestureMode = PointerGesture::PRESS;
+ mPointerGesture.activeGestureId = 0;
+ mPointerGesture.referenceIdBits.clear();
+ mPointerVelocityControl.reset();
+
+ // Use the centroid and pointer location as the reference points for the gesture.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
+ "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
+ + mConfig.pointerGestureMultitouchSettleInterval - when)
+ * 0.000001f);
+#endif
+ mCurrentRawState.rawPointerData.getCentroidOfTouchingPointers(
+ &mPointerGesture.referenceTouchX,
+ &mPointerGesture.referenceTouchY);
+ mPointerController->getPosition(&mPointerGesture.referenceGestureX,
+ &mPointerGesture.referenceGestureY);
+ }
+
+ // Clear the reference deltas for fingers not yet included in the reference calculation.
+ for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value
+ & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ mPointerGesture.referenceDeltas[id].dx = 0;
+ mPointerGesture.referenceDeltas[id].dy = 0;
+ }
+ mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
+
+ // Add delta for all fingers and calculate a common movement delta.
+ float commonDeltaX = 0, commonDeltaY = 0;
+ BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value
+ & mCurrentCookedState.fingerIdBits.value);
+ for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
+ bool first = (idBits == commonIdBits);
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
+ const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
+ PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
+ delta.dx += cpd.x - lpd.x;
+ delta.dy += cpd.y - lpd.y;
+
+ if (first) {
+ commonDeltaX = delta.dx;
+ commonDeltaY = delta.dy;
+ } else {
+ commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
+ commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
+ }
+ }
+
+ // Consider transitions from PRESS to SWIPE or MULTITOUCH.
+ if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
+ float dist[MAX_POINTER_ID + 1];
+ int32_t distOverThreshold = 0;
+ for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
+ dist[id] = hypotf(delta.dx * mPointerXZoomScale,
+ delta.dy * mPointerYZoomScale);
+ if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
+ distOverThreshold += 1;
+ }
+ }
+
+ // Only transition when at least two pointers have moved further than
+ // the minimum distance threshold.
+ if (distOverThreshold >= 2) {
+ if (currentFingerCount > 2) {
+ // There are more than two pointers, switch to FREEFORM.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
+ currentFingerCount);
+#endif
+ *outCancelPreviousGesture = true;
+ mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ } else {
+ // There are exactly two pointers.
+ BitSet32 idBits(mCurrentCookedState.fingerIdBits);
+ uint32_t id1 = idBits.clearFirstMarkedBit();
+ uint32_t id2 = idBits.firstMarkedBit();
+ const RawPointerData::Pointer& p1 =
+ mCurrentRawState.rawPointerData.pointerForId(id1);
+ const RawPointerData::Pointer& p2 =
+ mCurrentRawState.rawPointerData.pointerForId(id2);
+ float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
+ if (mutualDistance > mPointerGestureMaxSwipeWidth) {
+ // There are two pointers but they are too far apart for a SWIPE,
+ // switch to FREEFORM.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
+ mutualDistance, mPointerGestureMaxSwipeWidth);
+#endif
+ *outCancelPreviousGesture = true;
+ mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ } else {
+ // There are two pointers. Wait for both pointers to start moving
+ // before deciding whether this is a SWIPE or FREEFORM gesture.
+ float dist1 = dist[id1];
+ float dist2 = dist[id2];
+ if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
+ && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
+ // Calculate the dot product of the displacement vectors.
+ // When the vectors are oriented in approximately the same direction,
+ // the angle betweeen them is near zero and the cosine of the angle
+ // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
+ PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
+ PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
+ float dx1 = delta1.dx * mPointerXZoomScale;
+ float dy1 = delta1.dy * mPointerYZoomScale;
+ float dx2 = delta2.dx * mPointerXZoomScale;
+ float dy2 = delta2.dy * mPointerYZoomScale;
+ float dot = dx1 * dx2 + dy1 * dy2;
+ float cosine = dot / (dist1 * dist2); // denominator always > 0
+ if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
+ // Pointers are moving in the same direction. Switch to SWIPE.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: PRESS transitioned to SWIPE, "
+ "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
+ "cosine %0.3f >= %0.3f",
+ dist1, mConfig.pointerGestureMultitouchMinDistance,
+ dist2, mConfig.pointerGestureMultitouchMinDistance,
+ cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
+#endif
+ mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
+ } else {
+ // Pointers are moving in different directions. Switch to FREEFORM.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: PRESS transitioned to FREEFORM, "
+ "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
+ "cosine %0.3f < %0.3f",
+ dist1, mConfig.pointerGestureMultitouchMinDistance,
+ dist2, mConfig.pointerGestureMultitouchMinDistance,
+ cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
+#endif
+ *outCancelPreviousGesture = true;
+ mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ }
+ }
+ }
+ }
+ }
+ } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
+ // Switch from SWIPE to FREEFORM if additional pointers go down.
+ // Cancel previous gesture.
+ if (currentFingerCount > 2) {
+#if DEBUG_GESTURES
+ ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
+ currentFingerCount);
+#endif
+ *outCancelPreviousGesture = true;
+ mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ }
+ }
+
+ // Move the reference points based on the overall group motion of the fingers
+ // except in PRESS mode while waiting for a transition to occur.
+ if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
+ && (commonDeltaX || commonDeltaY)) {
+ for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
+ delta.dx = 0;
+ delta.dy = 0;
+ }
+
+ mPointerGesture.referenceTouchX += commonDeltaX;
+ mPointerGesture.referenceTouchY += commonDeltaY;
+
+ commonDeltaX *= mPointerXMovementScale;
+ commonDeltaY *= mPointerYMovementScale;
+
+ rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
+ mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
+
+ mPointerGesture.referenceGestureX += commonDeltaX;
+ mPointerGesture.referenceGestureY += commonDeltaY;
+ }
+
+ // Report gestures.
+ if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
+ || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
+ // PRESS or SWIPE mode.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
+ "activeGestureId=%d, currentTouchPointerCount=%d",
+ activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
+#endif
+ ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
+
+ mPointerGesture.currentGestureIdBits.clear();
+ mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
+ mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
+ mPointerGesture.currentGestureProperties[0].clear();
+ mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
+ mPointerGesture.currentGestureProperties[0].toolType =
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
+ mPointerGesture.currentGestureCoords[0].clear();
+ mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
+ mPointerGesture.referenceGestureX);
+ mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
+ mPointerGesture.referenceGestureY);
+ mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+ } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
+ // FREEFORM mode.
+#if DEBUG_GESTURES
+ ALOGD("Gestures: FREEFORM activeTouchId=%d,"
+ "activeGestureId=%d, currentTouchPointerCount=%d",
+ activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
+#endif
+ ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
+
+ mPointerGesture.currentGestureIdBits.clear();
+
+ BitSet32 mappedTouchIdBits;
+ BitSet32 usedGestureIdBits;
+ if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
+ // Initially, assign the active gesture id to the active touch point
+ // if there is one. No other touch id bits are mapped yet.
+ if (!*outCancelPreviousGesture) {
+ mappedTouchIdBits.markBit(activeTouchId);
+ usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
+ mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
+ mPointerGesture.activeGestureId;
+ } else {
+ mPointerGesture.activeGestureId = -1;
+ }
+ } else {
+ // Otherwise, assume we mapped all touches from the previous frame.
+ // Reuse all mappings that are still applicable.
+ mappedTouchIdBits.value = mLastCookedState.fingerIdBits.value
+ & mCurrentCookedState.fingerIdBits.value;
+ usedGestureIdBits = mPointerGesture.lastGestureIdBits;
+
+ // Check whether we need to choose a new active gesture id because the
+ // current went went up.
+ for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value
+ & ~mCurrentCookedState.fingerIdBits.value);
+ !upTouchIdBits.isEmpty(); ) {
+ uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
+ uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
+ if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
+ mPointerGesture.activeGestureId = -1;
+ break;
+ }
+ }
+ }
+
+#if DEBUG_GESTURES
+ ALOGD("Gestures: FREEFORM follow up "
+ "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
+ "activeGestureId=%d",
+ mappedTouchIdBits.value, usedGestureIdBits.value,
+ mPointerGesture.activeGestureId);
+#endif
+
+ BitSet32 idBits(mCurrentCookedState.fingerIdBits);
+ for (uint32_t i = 0; i < currentFingerCount; i++) {
+ uint32_t touchId = idBits.clearFirstMarkedBit();
+ uint32_t gestureId;
+ if (!mappedTouchIdBits.hasBit(touchId)) {
+ gestureId = usedGestureIdBits.markFirstUnmarkedBit();
+ mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
+#if DEBUG_GESTURES
+ ALOGD("Gestures: FREEFORM "
+ "new mapping for touch id %d -> gesture id %d",
+ touchId, gestureId);
+#endif
+ } else {
+ gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
+#if DEBUG_GESTURES
+ ALOGD("Gestures: FREEFORM "
+ "existing mapping for touch id %d -> gesture id %d",
+ touchId, gestureId);
+#endif
+ }
+ mPointerGesture.currentGestureIdBits.markBit(gestureId);
+ mPointerGesture.currentGestureIdToIndex[gestureId] = i;
+
+ const RawPointerData::Pointer& pointer =
+ mCurrentRawState.rawPointerData.pointerForId(touchId);
+ float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
+ * mPointerXZoomScale;
+ float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
+ * mPointerYZoomScale;
+ rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
+
+ mPointerGesture.currentGestureProperties[i].clear();
+ mPointerGesture.currentGestureProperties[i].id = gestureId;
+ mPointerGesture.currentGestureProperties[i].toolType =
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
+ mPointerGesture.currentGestureCoords[i].clear();
+ mPointerGesture.currentGestureCoords[i].setAxisValue(
+ AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
+ mPointerGesture.currentGestureCoords[i].setAxisValue(
+ AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
+ mPointerGesture.currentGestureCoords[i].setAxisValue(
+ AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+ }
+
+ if (mPointerGesture.activeGestureId < 0) {
+ mPointerGesture.activeGestureId =
+ mPointerGesture.currentGestureIdBits.firstMarkedBit();
+#if DEBUG_GESTURES
+ ALOGD("Gestures: FREEFORM new "
+ "activeGestureId=%d", mPointerGesture.activeGestureId);
+#endif
+ }
+ }
+ }
+
+ mPointerController->setButtonState(mCurrentRawState.buttonState);
+
+#if DEBUG_GESTURES
+ ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
+ "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
+ "lastGestureMode=%d, lastGestureIdBits=0x%08x",
+ toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
+ mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
+ mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
+ for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
+ const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
+ const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
+ ALOGD(" currentGesture[%d]: index=%d, toolType=%d, "
+ "x=%0.3f, y=%0.3f, pressure=%0.3f",
+ id, index, properties.toolType,
+ coords.getAxisValue(AMOTION_EVENT_AXIS_X),
+ coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
+ coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+ }
+ for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
+ const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
+ const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
+ ALOGD(" lastGesture[%d]: index=%d, toolType=%d, "
+ "x=%0.3f, y=%0.3f, pressure=%0.3f",
+ id, index, properties.toolType,
+ coords.getAxisValue(AMOTION_EVENT_AXIS_X),
+ coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
+ coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+ }
+#endif
+ return true;
+}
+
+void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
+ mPointerSimple.currentCoords.clear();
+ mPointerSimple.currentProperties.clear();
+
+ bool down, hovering;
+ if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
+ uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
+ uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
+ float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
+ float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
+ mPointerController->setPosition(x, y);
+
+ hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
+ down = !hovering;
+
+ mPointerController->getPosition(&x, &y);
+ mPointerSimple.currentCoords.copyFrom(
+ mCurrentCookedState.cookedPointerData.pointerCoords[index]);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ mPointerSimple.currentProperties.id = 0;
+ mPointerSimple.currentProperties.toolType =
+ mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
+ } else {
+ down = false;
+ hovering = false;
+ }
+
+ dispatchPointerSimple(when, policyFlags, down, hovering);
+}
+
+void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
+ abortPointerSimple(when, policyFlags);
+}
+
+void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
+ mPointerSimple.currentCoords.clear();
+ mPointerSimple.currentProperties.clear();
+
+ bool down, hovering;
+ if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
+ uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
+ uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
+ float deltaX = 0, deltaY = 0;
+ if (mLastCookedState.mouseIdBits.hasBit(id)) {
+ uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
+ deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x
+ - mLastRawState.rawPointerData.pointers[lastIndex].x)
+ * mPointerXMovementScale;
+ deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y
+ - mLastRawState.rawPointerData.pointers[lastIndex].y)
+ * mPointerYMovementScale;
+
+ rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
+ mPointerVelocityControl.move(when, &deltaX, &deltaY);
+
+ mPointerController->move(deltaX, deltaY);
+ } else {
+ mPointerVelocityControl.reset();
+ }
+
+ down = isPointerDown(mCurrentRawState.buttonState);
+ hovering = !down;
+
+ float x, y;
+ mPointerController->getPosition(&x, &y);
+ mPointerSimple.currentCoords.copyFrom(
+ mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
+ hovering ? 0.0f : 1.0f);
+ mPointerSimple.currentProperties.id = 0;
+ mPointerSimple.currentProperties.toolType =
+ mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
+ } else {
+ mPointerVelocityControl.reset();
+
+ down = false;
+ hovering = false;
+ }
+
+ dispatchPointerSimple(when, policyFlags, down, hovering);
+}
+
+void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
+ abortPointerSimple(when, policyFlags);
+
+ mPointerVelocityControl.reset();
+}
+
+void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
+ bool down, bool hovering) {
+ int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t displayId = mViewport.displayId;
+
+ if (mPointerController != nullptr) {
+ if (down || hovering) {
+ mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+ mPointerController->clearSpots();
+ mPointerController->setButtonState(mCurrentRawState.buttonState);
+ mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+ } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+ }
+ displayId = mPointerController->getDisplayId();
+ }
+
+ if (mPointerSimple.down && !down) {
+ mPointerSimple.down = false;
+
+ // Send up.
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+ }
+
+ if (mPointerSimple.hovering && !hovering) {
+ mPointerSimple.hovering = false;
+
+ // Send hover exit.
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+ }
+
+ if (down) {
+ if (!mPointerSimple.down) {
+ mPointerSimple.down = true;
+ mPointerSimple.downTime = when;
+
+ // Send down.
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ /* deviceTimestamp */ 0,
+ 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+ }
+
+ // Send move.
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+ }
+
+ if (hovering) {
+ if (!mPointerSimple.hovering) {
+ mPointerSimple.hovering = true;
+
+ // Send hover enter.
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+ }
+
+ // Send hover move.
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+ }
+
+ if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
+ float vscroll = mCurrentRawState.rawVScroll;
+ float hscroll = mCurrentRawState.rawHScroll;
+ mWheelYVelocityControl.move(when, nullptr, &vscroll);
+ mWheelXVelocityControl.move(when, &hscroll, nullptr);
+
+ // Send scroll.
+ PointerCoords pointerCoords;
+ pointerCoords.copyFrom(mPointerSimple.currentCoords);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
+
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
+ 1, &mPointerSimple.currentProperties, &pointerCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.downTime, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+ }
+
+ // Save state.
+ if (down || hovering) {
+ mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
+ mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
+ } else {
+ mPointerSimple.reset();
+ }
+}
+
+void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
+ mPointerSimple.currentCoords.clear();
+ mPointerSimple.currentProperties.clear();
+
+ dispatchPointerSimple(when, policyFlags, false, false);
+}
+
+void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
+ int32_t action, int32_t actionButton, int32_t flags,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
+ const PointerProperties* properties, const PointerCoords* coords,
+ const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
+ float xPrecision, float yPrecision, nsecs_t downTime) {
+ PointerCoords pointerCoords[MAX_POINTERS];
+ PointerProperties pointerProperties[MAX_POINTERS];
+ uint32_t pointerCount = 0;
+ while (!idBits.isEmpty()) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ uint32_t index = idToIndex[id];
+ pointerProperties[pointerCount].copyFrom(properties[index]);
+ pointerCoords[pointerCount].copyFrom(coords[index]);
+
+ if (changedId >= 0 && id == uint32_t(changedId)) {
+ action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+ }
+
+ pointerCount += 1;
+ }
+
+ ALOG_ASSERT(pointerCount != 0);
+
+ if (changedId >= 0 && pointerCount == 1) {
+ // Replace initial down and final up action.
+ // We can compare the action without masking off the changed pointer index
+ // because we know the index is 0.
+ if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
+ action = AMOTION_EVENT_ACTION_DOWN;
+ } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
+ action = AMOTION_EVENT_ACTION_UP;
+ } else {
+ // Can't happen.
+ ALOG_ASSERT(false);
+ }
+ }
+ const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE);
+ const int32_t deviceId = getDeviceId();
+ std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
+ std::for_each(frames.begin(), frames.end(),
+ [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId,
+ source, displayId, policyFlags,
+ action, actionButton, flags, metaState, buttonState, MotionClassification::NONE,
+ edgeFlags, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
+ xPrecision, yPrecision, downTime, std::move(frames));
+ getListener()->notifyMotion(&args);
+}
+
+bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
+ const PointerCoords* inCoords, const uint32_t* inIdToIndex,
+ PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
+ BitSet32 idBits) const {
+ bool changed = false;
+ while (!idBits.isEmpty()) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ uint32_t inIndex = inIdToIndex[id];
+ uint32_t outIndex = outIdToIndex[id];
+
+ const PointerProperties& curInProperties = inProperties[inIndex];
+ const PointerCoords& curInCoords = inCoords[inIndex];
+ PointerProperties& curOutProperties = outProperties[outIndex];
+ PointerCoords& curOutCoords = outCoords[outIndex];
+
+ if (curInProperties != curOutProperties) {
+ curOutProperties.copyFrom(curInProperties);
+ changed = true;
+ }
+
+ if (curInCoords != curOutCoords) {
+ curOutCoords.copyFrom(curInCoords);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+void TouchInputMapper::fadePointer() {
+ if (mPointerController != nullptr) {
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+ }
+}
+
+void TouchInputMapper::cancelTouch(nsecs_t when) {
+ abortPointerUsage(when, 0 /*policyFlags*/);
+ abortTouches(when, 0 /* policyFlags*/);
+}
+
+bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
+ const float scaledX = x * mXScale;
+ const float scaledY = y * mYScale;
+ return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
+ && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
+ && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue
+ && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
+}
+
+const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
+
+ for (const VirtualKey& virtualKey: mVirtualKeys) {
+#if DEBUG_VIRTUAL_KEYS
+ ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
+ "left=%d, top=%d, right=%d, bottom=%d",
+ x, y,
+ virtualKey.keyCode, virtualKey.scanCode,
+ virtualKey.hitLeft, virtualKey.hitTop,
+ virtualKey.hitRight, virtualKey.hitBottom);
+#endif
+
+ if (virtualKey.isHit(x, y)) {
+ return & virtualKey;
+ }
+ }
+
+ return nullptr;
+}
+
+void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) {
+ uint32_t currentPointerCount = current->rawPointerData.pointerCount;
+ uint32_t lastPointerCount = last->rawPointerData.pointerCount;
+
+ current->rawPointerData.clearIdBits();
+
+ if (currentPointerCount == 0) {
+ // No pointers to assign.
+ return;
+ }
+
+ if (lastPointerCount == 0) {
+ // All pointers are new.
+ for (uint32_t i = 0; i < currentPointerCount; i++) {
+ uint32_t id = i;
+ current->rawPointerData.pointers[i].id = id;
+ current->rawPointerData.idToIndex[id] = i;
+ current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(i));
+ }
+ return;
+ }
+
+ if (currentPointerCount == 1 && lastPointerCount == 1
+ && current->rawPointerData.pointers[0].toolType
+ == last->rawPointerData.pointers[0].toolType) {
+ // Only one pointer and no change in count so it must have the same id as before.
+ uint32_t id = last->rawPointerData.pointers[0].id;
+ current->rawPointerData.pointers[0].id = id;
+ current->rawPointerData.idToIndex[id] = 0;
+ current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(0));
+ return;
+ }
+
+ // General case.
+ // We build a heap of squared euclidean distances between current and last pointers
+ // associated with the current and last pointer indices. Then, we find the best
+ // match (by distance) for each current pointer.
+ // The pointers must have the same tool type but it is possible for them to
+ // transition from hovering to touching or vice-versa while retaining the same id.
+ PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
+
+ uint32_t heapSize = 0;
+ for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
+ currentPointerIndex++) {
+ for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
+ lastPointerIndex++) {
+ const RawPointerData::Pointer& currentPointer =
+ current->rawPointerData.pointers[currentPointerIndex];
+ const RawPointerData::Pointer& lastPointer =
+ last->rawPointerData.pointers[lastPointerIndex];
+ if (currentPointer.toolType == lastPointer.toolType) {
+ int64_t deltaX = currentPointer.x - lastPointer.x;
+ int64_t deltaY = currentPointer.y - lastPointer.y;
+
+ uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
+
+ // Insert new element into the heap (sift up).
+ heap[heapSize].currentPointerIndex = currentPointerIndex;
+ heap[heapSize].lastPointerIndex = lastPointerIndex;
+ heap[heapSize].distance = distance;
+ heapSize += 1;
+ }
+ }
+ }
+
+ // Heapify
+ for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
+ startIndex -= 1;
+ for (uint32_t parentIndex = startIndex; ;) {
+ uint32_t childIndex = parentIndex * 2 + 1;
+ if (childIndex >= heapSize) {
+ break;
+ }
+
+ if (childIndex + 1 < heapSize
+ && heap[childIndex + 1].distance < heap[childIndex].distance) {
+ childIndex += 1;
+ }
+
+ if (heap[parentIndex].distance <= heap[childIndex].distance) {
+ break;
+ }
+
+ swap(heap[parentIndex], heap[childIndex]);
+ parentIndex = childIndex;
+ }
+ }
+
+#if DEBUG_POINTER_ASSIGNMENT
+ ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
+ for (size_t i = 0; i < heapSize; i++) {
+ ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
+ i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+ heap[i].distance);
+ }
+#endif
+
+ // Pull matches out by increasing order of distance.
+ // To avoid reassigning pointers that have already been matched, the loop keeps track
+ // of which last and current pointers have been matched using the matchedXXXBits variables.
+ // It also tracks the used pointer id bits.
+ BitSet32 matchedLastBits(0);
+ BitSet32 matchedCurrentBits(0);
+ BitSet32 usedIdBits(0);
+ bool first = true;
+ for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
+ while (heapSize > 0) {
+ if (first) {
+ // The first time through the loop, we just consume the root element of
+ // the heap (the one with smallest distance).
+ first = false;
+ } else {
+ // Previous iterations consumed the root element of the heap.
+ // Pop root element off of the heap (sift down).
+ heap[0] = heap[heapSize];
+ for (uint32_t parentIndex = 0; ;) {
+ uint32_t childIndex = parentIndex * 2 + 1;
+ if (childIndex >= heapSize) {
+ break;
+ }
+
+ if (childIndex + 1 < heapSize
+ && heap[childIndex + 1].distance < heap[childIndex].distance) {
+ childIndex += 1;
+ }
+
+ if (heap[parentIndex].distance <= heap[childIndex].distance) {
+ break;
+ }
+
+ swap(heap[parentIndex], heap[childIndex]);
+ parentIndex = childIndex;
+ }
+
+#if DEBUG_POINTER_ASSIGNMENT
+ ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
+ for (size_t i = 0; i < heapSize; i++) {
+ ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
+ i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+ heap[i].distance);
+ }
+#endif
+ }
+
+ heapSize -= 1;
+
+ uint32_t currentPointerIndex = heap[0].currentPointerIndex;
+ if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
+
+ uint32_t lastPointerIndex = heap[0].lastPointerIndex;
+ if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
+
+ matchedCurrentBits.markBit(currentPointerIndex);
+ matchedLastBits.markBit(lastPointerIndex);
+
+ uint32_t id = last->rawPointerData.pointers[lastPointerIndex].id;
+ current->rawPointerData.pointers[currentPointerIndex].id = id;
+ current->rawPointerData.idToIndex[id] = currentPointerIndex;
+ current->rawPointerData.markIdBit(id,
+ current->rawPointerData.isHovering(currentPointerIndex));
+ usedIdBits.markBit(id);
+
+#if DEBUG_POINTER_ASSIGNMENT
+ ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32
+ ", id=%" PRIu32 ", distance=%" PRIu64,
+ lastPointerIndex, currentPointerIndex, id, heap[0].distance);
+#endif
+ break;
+ }
+ }
+
+ // Assign fresh ids to pointers that were not matched in the process.
+ for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
+ uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
+ uint32_t id = usedIdBits.markFirstUnmarkedBit();
+
+ current->rawPointerData.pointers[currentPointerIndex].id = id;
+ current->rawPointerData.idToIndex[id] = currentPointerIndex;
+ current->rawPointerData.markIdBit(id,
+ current->rawPointerData.isHovering(currentPointerIndex));
+
+#if DEBUG_POINTER_ASSIGNMENT
+ ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
+#endif
+ }
+}
+
+int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+ if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
+ return AKEY_STATE_VIRTUAL;
+ }
+
+ for (const VirtualKey& virtualKey : mVirtualKeys) {
+ if (virtualKey.keyCode == keyCode) {
+ return AKEY_STATE_UP;
+ }
+ }
+
+ return AKEY_STATE_UNKNOWN;
+}
+
+int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+ if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
+ return AKEY_STATE_VIRTUAL;
+ }
+
+ for (const VirtualKey& virtualKey : mVirtualKeys) {
+ if (virtualKey.scanCode == scanCode) {
+ return AKEY_STATE_UP;
+ }
+ }
+
+ return AKEY_STATE_UNKNOWN;
+}
+
+bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags) {
+ for (const VirtualKey& virtualKey : mVirtualKeys) {
+ for (size_t i = 0; i < numCodes; i++) {
+ if (virtualKey.keyCode == keyCodes[i]) {
+ outFlags[i] = 1;
+ }
+ }
+ }
+
+ return true;
+}
+
+std::optional<int32_t> TouchInputMapper::getAssociatedDisplay() {
+ if (mParameters.hasAssociatedDisplay) {
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
+ return std::make_optional(mPointerController->getDisplayId());
+ } else {
+ return std::make_optional(mViewport.displayId);
+ }
+ }
+ return std::nullopt;
+}
+
+// --- SingleTouchInputMapper ---
+
+SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
+ TouchInputMapper(device) {
+}
+
+SingleTouchInputMapper::~SingleTouchInputMapper() {
+}
+
+void SingleTouchInputMapper::reset(nsecs_t when) {
+ mSingleTouchMotionAccumulator.reset(getDevice());
+
+ TouchInputMapper::reset(when);
+}
+
+void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
+ TouchInputMapper::process(rawEvent);
+
+ mSingleTouchMotionAccumulator.process(rawEvent);
+}
+
+void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
+ if (mTouchButtonAccumulator.isToolActive()) {
+ outState->rawPointerData.pointerCount = 1;
+ outState->rawPointerData.idToIndex[0] = 0;
+
+ bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
+ && (mTouchButtonAccumulator.isHovering()
+ || (mRawPointerAxes.pressure.valid
+ && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
+ outState->rawPointerData.markIdBit(0, isHovering);
+
+ RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[0];
+ outPointer.id = 0;
+ outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
+ outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
+ outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
+ outPointer.touchMajor = 0;
+ outPointer.touchMinor = 0;
+ outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+ outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+ outPointer.orientation = 0;
+ outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
+ outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
+ outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
+ outPointer.toolType = mTouchButtonAccumulator.getToolType();
+ if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
+ outPointer.isHovering = isHovering;
+ }
+}
+
+void SingleTouchInputMapper::configureRawPointerAxes() {
+ TouchInputMapper::configureRawPointerAxes();
+
+ getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
+ getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
+ getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
+ getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
+ getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
+ getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
+ getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
+}
+
+bool SingleTouchInputMapper::hasStylus() const {
+ return mTouchButtonAccumulator.hasStylus();
+}
+
+
+// --- MultiTouchInputMapper ---
+
+MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
+ TouchInputMapper(device) {
+}
+
+MultiTouchInputMapper::~MultiTouchInputMapper() {
+}
+
+void MultiTouchInputMapper::reset(nsecs_t when) {
+ mMultiTouchMotionAccumulator.reset(getDevice());
+
+ mPointerIdBits.clear();
+
+ TouchInputMapper::reset(when);
+}
+
+void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
+ TouchInputMapper::process(rawEvent);
+
+ mMultiTouchMotionAccumulator.process(rawEvent);
+}
+
+void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
+ size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
+ size_t outCount = 0;
+ BitSet32 newPointerIdBits;
+ mHavePointerIds = true;
+
+ for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
+ const MultiTouchMotionAccumulator::Slot* inSlot =
+ mMultiTouchMotionAccumulator.getSlot(inIndex);
+ if (!inSlot->isInUse()) {
+ continue;
+ }
+
+ if (outCount >= MAX_POINTERS) {
+#if DEBUG_POINTERS
+ ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
+ "ignoring the rest.",
+ getDeviceName().c_str(), MAX_POINTERS);
+#endif
+ break; // too many fingers!
+ }
+
+ RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
+ outPointer.x = inSlot->getX();
+ outPointer.y = inSlot->getY();
+ outPointer.pressure = inSlot->getPressure();
+ outPointer.touchMajor = inSlot->getTouchMajor();
+ outPointer.touchMinor = inSlot->getTouchMinor();
+ outPointer.toolMajor = inSlot->getToolMajor();
+ outPointer.toolMinor = inSlot->getToolMinor();
+ outPointer.orientation = inSlot->getOrientation();
+ outPointer.distance = inSlot->getDistance();
+ outPointer.tiltX = 0;
+ outPointer.tiltY = 0;
+
+ outPointer.toolType = inSlot->getToolType();
+ if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ outPointer.toolType = mTouchButtonAccumulator.getToolType();
+ if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
+ }
+
+ bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
+ && (mTouchButtonAccumulator.isHovering()
+ || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
+ outPointer.isHovering = isHovering;
+
+ // Assign pointer id using tracking id if available.
+ if (mHavePointerIds) {
+ int32_t trackingId = inSlot->getTrackingId();
+ int32_t id = -1;
+ if (trackingId >= 0) {
+ for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
+ uint32_t n = idBits.clearFirstMarkedBit();
+ if (mPointerTrackingIdMap[n] == trackingId) {
+ id = n;
+ }
+ }
+
+ if (id < 0 && !mPointerIdBits.isFull()) {
+ id = mPointerIdBits.markFirstUnmarkedBit();
+ mPointerTrackingIdMap[id] = trackingId;
+ }
+ }
+ if (id < 0) {
+ mHavePointerIds = false;
+ outState->rawPointerData.clearIdBits();
+ newPointerIdBits.clear();
+ } else {
+ outPointer.id = id;
+ outState->rawPointerData.idToIndex[id] = outCount;
+ outState->rawPointerData.markIdBit(id, isHovering);
+ newPointerIdBits.markBit(id);
+ }
+ }
+ outCount += 1;
+ }
+
+ outState->deviceTimestamp = mMultiTouchMotionAccumulator.getDeviceTimestamp();
+ outState->rawPointerData.pointerCount = outCount;
+ mPointerIdBits = newPointerIdBits;
+
+ mMultiTouchMotionAccumulator.finishSync();
+}
+
+void MultiTouchInputMapper::configureRawPointerAxes() {
+ TouchInputMapper::configureRawPointerAxes();
+
+ getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
+ getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
+ getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
+ getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
+ getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
+ getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
+ getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
+ getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
+ getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
+ getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
+ getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
+
+ if (mRawPointerAxes.trackingId.valid
+ && mRawPointerAxes.slot.valid
+ && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
+ size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
+ if (slotCount > MAX_SLOTS) {
+ ALOGW("MultiTouch Device %s reported %zu slots but the framework "
+ "only supports a maximum of %zu slots at this time.",
+ getDeviceName().c_str(), slotCount, MAX_SLOTS);
+ slotCount = MAX_SLOTS;
+ }
+ mMultiTouchMotionAccumulator.configure(getDevice(),
+ slotCount, true /*usingSlotsProtocol*/);
+ } else {
+ mMultiTouchMotionAccumulator.configure(getDevice(),
+ MAX_POINTERS, false /*usingSlotsProtocol*/);
+ }
+}
+
+bool MultiTouchInputMapper::hasStylus() const {
+ return mMultiTouchMotionAccumulator.hasStylus()
+ || mTouchButtonAccumulator.hasStylus();
+}
+
+// --- ExternalStylusInputMapper
+
+ExternalStylusInputMapper::ExternalStylusInputMapper(InputDevice* device) :
+ InputMapper(device) {
+
+}
+
+uint32_t ExternalStylusInputMapper::getSources() {
+ return AINPUT_SOURCE_STYLUS;
+}
+
+void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+ info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS,
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+}
+
+void ExternalStylusInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "External Stylus Input Mapper:\n";
+ dump += INDENT3 "Raw Stylus Axes:\n";
+ dumpRawAbsoluteAxisInfo(dump, mRawPressureAxis, "Pressure");
+ dump += INDENT3 "Stylus State:\n";
+ dumpStylusState(dump, mStylusState);
+}
+
+void ExternalStylusInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
+ mTouchButtonAccumulator.configure(getDevice());
+}
+
+void ExternalStylusInputMapper::reset(nsecs_t when) {
+ InputDevice* device = getDevice();
+ mSingleTouchMotionAccumulator.reset(device);
+ mTouchButtonAccumulator.reset(device);
+ InputMapper::reset(when);
+}
+
+void ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
+ mSingleTouchMotionAccumulator.process(rawEvent);
+ mTouchButtonAccumulator.process(rawEvent);
+
+ if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+ sync(rawEvent->when);
+ }
+}
+
+void ExternalStylusInputMapper::sync(nsecs_t when) {
+ mStylusState.clear();
+
+ mStylusState.when = when;
+
+ mStylusState.toolType = mTouchButtonAccumulator.getToolType();
+ if (mStylusState.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ mStylusState.toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ }
+
+ int32_t pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
+ if (mRawPressureAxis.valid) {
+ mStylusState.pressure = float(pressure) / mRawPressureAxis.maxValue;
+ } else if (mTouchButtonAccumulator.isToolActive()) {
+ mStylusState.pressure = 1.0f;
+ } else {
+ mStylusState.pressure = 0.0f;
+ }
+
+ mStylusState.buttons = mTouchButtonAccumulator.getButtonState();
+
+ mContext->dispatchExternalStylusState(mStylusState);
+}
+
+
+// --- JoystickInputMapper ---
+
+JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
+ InputMapper(device) {
+}
+
+JoystickInputMapper::~JoystickInputMapper() {
+}
+
+uint32_t JoystickInputMapper::getSources() {
+ return AINPUT_SOURCE_JOYSTICK;
+}
+
+void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ for (size_t i = 0; i < mAxes.size(); i++) {
+ const Axis& axis = mAxes.valueAt(i);
+ addMotionRange(axis.axisInfo.axis, axis, info);
+
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ addMotionRange(axis.axisInfo.highAxis, axis, info);
+
+ }
+ }
+}
+
+void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
+ InputDeviceInfo* info) {
+ info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
+ axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
+ /* In order to ease the transition for developers from using the old axes
+ * to the newer, more semantically correct axes, we'll continue to register
+ * the old axes as duplicates of their corresponding new ones. */
+ int32_t compatAxis = getCompatAxis(axisId);
+ if (compatAxis >= 0) {
+ info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
+ axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
+ }
+}
+
+/* A mapping from axes the joystick actually has to the axes that should be
+ * artificially created for compatibility purposes.
+ * Returns -1 if no compatibility axis is needed. */
+int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
+ switch(axis) {
+ case AMOTION_EVENT_AXIS_LTRIGGER:
+ return AMOTION_EVENT_AXIS_BRAKE;
+ case AMOTION_EVENT_AXIS_RTRIGGER:
+ return AMOTION_EVENT_AXIS_GAS;
+ }
+ return -1;
+}
+
+void JoystickInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Joystick Input Mapper:\n";
+
+ dump += INDENT3 "Axes:\n";
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ const Axis& axis = mAxes.valueAt(i);
+ const char* label = getAxisLabel(axis.axisInfo.axis);
+ if (label) {
+ dump += StringPrintf(INDENT4 "%s", label);
+ } else {
+ dump += StringPrintf(INDENT4 "%d", axis.axisInfo.axis);
+ }
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ label = getAxisLabel(axis.axisInfo.highAxis);
+ if (label) {
+ dump += StringPrintf(" / %s (split at %d)", label, axis.axisInfo.splitValue);
+ } else {
+ dump += StringPrintf(" / %d (split at %d)", axis.axisInfo.highAxis,
+ axis.axisInfo.splitValue);
+ }
+ } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
+ dump += " (invert)";
+ }
+
+ dump += StringPrintf(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
+ axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
+ dump += StringPrintf(INDENT4 " scale=%0.5f, offset=%0.5f, "
+ "highScale=%0.5f, highOffset=%0.5f\n",
+ axis.scale, axis.offset, axis.highScale, axis.highOffset);
+ dump += StringPrintf(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
+ "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
+ mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
+ axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
+ }
+}
+
+void JoystickInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ InputMapper::configure(when, config, changes);
+
+ if (!changes) { // first time only
+ // Collect all axes.
+ for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
+ if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
+ & INPUT_DEVICE_CLASS_JOYSTICK)) {
+ continue; // axis must be claimed by a different device
+ }
+
+ RawAbsoluteAxisInfo rawAxisInfo;
+ getAbsoluteAxisInfo(abs, &rawAxisInfo);
+ if (rawAxisInfo.valid) {
+ // Map axis.
+ AxisInfo axisInfo;
+ bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
+ if (!explicitlyMapped) {
+ // Axis is not explicitly mapped, will choose a generic axis later.
+ axisInfo.mode = AxisInfo::MODE_NORMAL;
+ axisInfo.axis = -1;
+ }
+
+ // Apply flat override.
+ int32_t rawFlat = axisInfo.flatOverride < 0
+ ? rawAxisInfo.flat : axisInfo.flatOverride;
+
+ // Calculate scaling factors and limits.
+ Axis axis;
+ if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
+ float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+ scale, 0.0f, highScale, 0.0f,
+ 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+ rawAxisInfo.resolution * scale);
+ } else if (isCenteredAxis(axisInfo.axis)) {
+ float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
+ float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+ scale, offset, scale, offset,
+ -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+ rawAxisInfo.resolution * scale);
+ } else {
+ float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+ scale, 0.0f, scale, 0.0f,
+ 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+ rawAxisInfo.resolution * scale);
+ }
+
+ // To eliminate noise while the joystick is at rest, filter out small variations
+ // in axis values up front.
+ axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
+
+ mAxes.add(abs, axis);
+ }
+ }
+
+ // If there are too many axes, start dropping them.
+ // Prefer to keep explicitly mapped axes.
+ if (mAxes.size() > PointerCoords::MAX_AXES) {
+ ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
+ getDeviceName().c_str(), mAxes.size(), PointerCoords::MAX_AXES);
+ pruneAxes(true);
+ pruneAxes(false);
+ }
+
+ // Assign generic axis ids to remaining axes.
+ int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ Axis& axis = mAxes.editValueAt(i);
+ if (axis.axisInfo.axis < 0) {
+ while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
+ && haveAxis(nextGenericAxisId)) {
+ nextGenericAxisId += 1;
+ }
+
+ if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
+ axis.axisInfo.axis = nextGenericAxisId;
+ nextGenericAxisId += 1;
+ } else {
+ ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
+ "have already been assigned to other axes.",
+ getDeviceName().c_str(), mAxes.keyAt(i));
+ mAxes.removeItemsAt(i--);
+ numAxes -= 1;
+ }
+ }
+ }
+ }
+}
+
+bool JoystickInputMapper::haveAxis(int32_t axisId) {
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ const Axis& axis = mAxes.valueAt(i);
+ if (axis.axisInfo.axis == axisId
+ || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
+ && axis.axisInfo.highAxis == axisId)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
+ size_t i = mAxes.size();
+ while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
+ if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
+ continue;
+ }
+ ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
+ getDeviceName().c_str(), mAxes.keyAt(i));
+ mAxes.removeItemsAt(i);
+ }
+}
+
+bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
+ switch (axis) {
+ case AMOTION_EVENT_AXIS_X:
+ case AMOTION_EVENT_AXIS_Y:
+ case AMOTION_EVENT_AXIS_Z:
+ case AMOTION_EVENT_AXIS_RX:
+ case AMOTION_EVENT_AXIS_RY:
+ case AMOTION_EVENT_AXIS_RZ:
+ case AMOTION_EVENT_AXIS_HAT_X:
+ case AMOTION_EVENT_AXIS_HAT_Y:
+ case AMOTION_EVENT_AXIS_ORIENTATION:
+ case AMOTION_EVENT_AXIS_RUDDER:
+ case AMOTION_EVENT_AXIS_WHEEL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void JoystickInputMapper::reset(nsecs_t when) {
+ // Recenter all axes.
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ Axis& axis = mAxes.editValueAt(i);
+ axis.resetValue();
+ }
+
+ InputMapper::reset(when);
+}
+
+void JoystickInputMapper::process(const RawEvent* rawEvent) {
+ switch (rawEvent->type) {
+ case EV_ABS: {
+ ssize_t index = mAxes.indexOfKey(rawEvent->code);
+ if (index >= 0) {
+ Axis& axis = mAxes.editValueAt(index);
+ float newValue, highNewValue;
+ switch (axis.axisInfo.mode) {
+ case AxisInfo::MODE_INVERT:
+ newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
+ * axis.scale + axis.offset;
+ highNewValue = 0.0f;
+ break;
+ case AxisInfo::MODE_SPLIT:
+ if (rawEvent->value < axis.axisInfo.splitValue) {
+ newValue = (axis.axisInfo.splitValue - rawEvent->value)
+ * axis.scale + axis.offset;
+ highNewValue = 0.0f;
+ } else if (rawEvent->value > axis.axisInfo.splitValue) {
+ newValue = 0.0f;
+ highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
+ * axis.highScale + axis.highOffset;
+ } else {
+ newValue = 0.0f;
+ highNewValue = 0.0f;
+ }
+ break;
+ default:
+ newValue = rawEvent->value * axis.scale + axis.offset;
+ highNewValue = 0.0f;
+ break;
+ }
+ axis.newValue = newValue;
+ axis.highNewValue = highNewValue;
+ }
+ break;
+ }
+
+ case EV_SYN:
+ switch (rawEvent->code) {
+ case SYN_REPORT:
+ sync(rawEvent->when, false /*force*/);
+ break;
+ }
+ break;
+ }
+}
+
+void JoystickInputMapper::sync(nsecs_t when, bool force) {
+ if (!filterAxes(force)) {
+ return;
+ }
+
+ int32_t metaState = mContext->getGlobalMetaState();
+ int32_t buttonState = 0;
+
+ PointerProperties pointerProperties;
+ pointerProperties.clear();
+ pointerProperties.id = 0;
+ pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+
+ PointerCoords pointerCoords;
+ pointerCoords.clear();
+
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ const Axis& axis = mAxes.valueAt(i);
+ setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
+ axis.highCurrentValue);
+ }
+ }
+
+ // Moving a joystick axis should not wake the device because joysticks can
+ // be fairly noisy even when not in use. On the other hand, pushing a gamepad
+ // button will likely wake the device.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ uint32_t policyFlags = 0;
+
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
+ &pointerProperties, &pointerCoords, 0, 0, 0, /* videoFrames */ {});
+ getListener()->notifyMotion(&args);
+}
+
+void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
+ int32_t axis, float value) {
+ pointerCoords->setAxisValue(axis, value);
+ /* In order to ease the transition for developers from using the old axes
+ * to the newer, more semantically correct axes, we'll continue to produce
+ * values for the old axes as mirrors of the value of their corresponding
+ * new axes. */
+ int32_t compatAxis = getCompatAxis(axis);
+ if (compatAxis >= 0) {
+ pointerCoords->setAxisValue(compatAxis, value);
+ }
+}
+
+bool JoystickInputMapper::filterAxes(bool force) {
+ bool atLeastOneSignificantChange = force;
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ Axis& axis = mAxes.editValueAt(i);
+ if (force || hasValueChangedSignificantly(axis.filter,
+ axis.newValue, axis.currentValue, axis.min, axis.max)) {
+ axis.currentValue = axis.newValue;
+ atLeastOneSignificantChange = true;
+ }
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ if (force || hasValueChangedSignificantly(axis.filter,
+ axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
+ axis.highCurrentValue = axis.highNewValue;
+ atLeastOneSignificantChange = true;
+ }
+ }
+ }
+ return atLeastOneSignificantChange;
+}
+
+bool JoystickInputMapper::hasValueChangedSignificantly(
+ float filter, float newValue, float currentValue, float min, float max) {
+ if (newValue != currentValue) {
+ // Filter out small changes in value unless the value is converging on the axis
+ // bounds or center point. This is intended to reduce the amount of information
+ // sent to applications by particularly noisy joysticks (such as PS3).
+ if (fabs(newValue - currentValue) > filter
+ || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
+ || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
+ || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
+ float filter, float newValue, float currentValue, float thresholdValue) {
+ float newDistance = fabs(newValue - thresholdValue);
+ if (newDistance < filter) {
+ float oldDistance = fabs(currentValue - thresholdValue);
+ if (newDistance < oldDistance) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace android
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
new file mode 100644
index 0000000000..9777779e7d
--- /dev/null
+++ b/services/inputflinger/InputReader.h
@@ -0,0 +1,1809 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _UI_INPUT_READER_H
+#define _UI_INPUT_READER_H
+
+#include "EventHub.h"
+#include "PointerControllerInterface.h"
+#include "InputListener.h"
+#include "InputReaderBase.h"
+
+#include <input/DisplayViewport.h>
+#include <input/Input.h>
+#include <input/VelocityControl.h>
+#include <input/VelocityTracker.h>
+#include <ui/DisplayInfo.h>
+#include <utils/KeyedVector.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+#include <utils/BitSet.h>
+
+#include <optional>
+#include <stddef.h>
+#include <unistd.h>
+#include <vector>
+
+namespace android {
+
+class InputDevice;
+class InputMapper;
+
+
+struct StylusState {
+ /* Time the stylus event was received. */
+ nsecs_t when;
+ /* Pressure as reported by the stylus, normalized to the range [0, 1.0]. */
+ float pressure;
+ /* The state of the stylus buttons as a bitfield (e.g. AMOTION_EVENT_BUTTON_SECONDARY). */
+ uint32_t buttons;
+ /* Which tool type the stylus is currently using (e.g. AMOTION_EVENT_TOOL_TYPE_ERASER). */
+ int32_t toolType;
+
+ void copyFrom(const StylusState& other) {
+ when = other.when;
+ pressure = other.pressure;
+ buttons = other.buttons;
+ toolType = other.toolType;
+ }
+
+ void clear() {
+ when = LLONG_MAX;
+ pressure = 0.f;
+ buttons = 0;
+ toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+ }
+};
+
+
+/* Internal interface used by individual input devices to access global input device state
+ * and parameters maintained by the input reader.
+ */
+class InputReaderContext {
+public:
+ InputReaderContext() { }
+ virtual ~InputReaderContext() { }
+
+ virtual void updateGlobalMetaState() = 0;
+ virtual int32_t getGlobalMetaState() = 0;
+
+ virtual void disableVirtualKeysUntil(nsecs_t time) = 0;
+ virtual bool shouldDropVirtualKey(nsecs_t now,
+ InputDevice* device, int32_t keyCode, int32_t scanCode) = 0;
+
+ virtual void fadePointer() = 0;
+
+ virtual void requestTimeoutAtTime(nsecs_t when) = 0;
+ virtual int32_t bumpGeneration() = 0;
+
+ virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) = 0;
+ virtual void dispatchExternalStylusState(const StylusState& outState) = 0;
+
+ virtual InputReaderPolicyInterface* getPolicy() = 0;
+ virtual InputListenerInterface* getListener() = 0;
+ virtual EventHubInterface* getEventHub() = 0;
+
+ virtual uint32_t getNextSequenceNum() = 0;
+};
+
+
+/* The input reader reads raw event data from the event hub and processes it into input events
+ * that it sends to the input listener. Some functions of the input reader, such as early
+ * event filtering in low power states, are controlled by a separate policy object.
+ *
+ * The InputReader owns a collection of InputMappers. Most of the work it does happens
+ * on the input reader thread but the InputReader can receive queries from other system
+ * components running on arbitrary threads. To keep things manageable, the InputReader
+ * uses a single Mutex to guard its state. The Mutex may be held while calling into the
+ * EventHub or the InputReaderPolicy but it is never held while calling into the
+ * InputListener.
+ */
+class InputReader : public InputReaderInterface {
+public:
+ InputReader(const sp<EventHubInterface>& eventHub,
+ const sp<InputReaderPolicyInterface>& policy,
+ const sp<InputListenerInterface>& listener);
+ virtual ~InputReader();
+
+ virtual void dump(std::string& dump);
+ virtual void monitor();
+
+ virtual void loopOnce();
+
+ virtual void getInputDevices(std::vector<InputDeviceInfo>& outInputDevices);
+
+ virtual bool isInputDeviceEnabled(int32_t deviceId);
+
+ virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+ int32_t scanCode);
+ virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+ int32_t keyCode);
+ virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
+ int32_t sw);
+
+ virtual void toggleCapsLockState(int32_t deviceId);
+
+ virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
+ size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
+
+ virtual void requestRefreshConfiguration(uint32_t changes);
+
+ virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
+ ssize_t repeat, int32_t token);
+ virtual void cancelVibrate(int32_t deviceId, int32_t token);
+
+ virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId);
+protected:
+ // These members are protected so they can be instrumented by test cases.
+ virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
+ const InputDeviceIdentifier& identifier, uint32_t classes);
+
+ class ContextImpl : public InputReaderContext {
+ InputReader* mReader;
+
+ public:
+ explicit ContextImpl(InputReader* reader);
+
+ virtual void updateGlobalMetaState();
+ virtual int32_t getGlobalMetaState();
+ virtual void disableVirtualKeysUntil(nsecs_t time);
+ virtual bool shouldDropVirtualKey(nsecs_t now,
+ InputDevice* device, int32_t keyCode, int32_t scanCode);
+ virtual void fadePointer();
+ virtual void requestTimeoutAtTime(nsecs_t when);
+ virtual int32_t bumpGeneration();
+ virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices);
+ virtual void dispatchExternalStylusState(const StylusState& outState);
+ virtual InputReaderPolicyInterface* getPolicy();
+ virtual InputListenerInterface* getListener();
+ virtual EventHubInterface* getEventHub();
+ virtual uint32_t getNextSequenceNum();
+ } mContext;
+
+ friend class ContextImpl;
+
+private:
+ Mutex mLock;
+
+ Condition mReaderIsAliveCondition;
+
+ sp<EventHubInterface> mEventHub;
+ sp<InputReaderPolicyInterface> mPolicy;
+ sp<QueuedInputListener> mQueuedListener;
+
+ InputReaderConfiguration mConfig;
+
+ // used by InputReaderContext::getNextSequenceNum() as a counter for event sequence numbers
+ uint32_t mNextSequenceNum;
+
+ // The event queue.
+ static const int EVENT_BUFFER_SIZE = 256;
+ RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
+
+ KeyedVector<int32_t, InputDevice*> mDevices;
+
+ // low-level input event decoding and device management
+ void processEventsLocked(const RawEvent* rawEvents, size_t count);
+
+ void addDeviceLocked(nsecs_t when, int32_t deviceId);
+ void removeDeviceLocked(nsecs_t when, int32_t deviceId);
+ void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count);
+ void timeoutExpiredLocked(nsecs_t when);
+
+ void handleConfigurationChangedLocked(nsecs_t when);
+
+ int32_t mGlobalMetaState;
+ void updateGlobalMetaStateLocked();
+ int32_t getGlobalMetaStateLocked();
+
+ void notifyExternalStylusPresenceChanged();
+ void getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices);
+ void dispatchExternalStylusState(const StylusState& state);
+
+ void fadePointerLocked();
+
+ int32_t mGeneration;
+ int32_t bumpGenerationLocked();
+
+ void getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices);
+
+ nsecs_t mDisableVirtualKeysTimeout;
+ void disableVirtualKeysUntilLocked(nsecs_t time);
+ bool shouldDropVirtualKeyLocked(nsecs_t now,
+ InputDevice* device, int32_t keyCode, int32_t scanCode);
+
+ nsecs_t mNextTimeout;
+ void requestTimeoutAtTimeLocked(nsecs_t when);
+
+ uint32_t mConfigurationChangesToRefresh;
+ void refreshConfigurationLocked(uint32_t changes);
+
+ // state queries
+ typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
+ int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
+ GetStateFunc getStateFunc);
+ bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags);
+};
+
+
+/* Represents the state of a single input device. */
+class InputDevice {
+public:
+ InputDevice(InputReaderContext* context, int32_t id, int32_t generation, int32_t
+ controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes);
+ ~InputDevice();
+
+ inline InputReaderContext* getContext() { return mContext; }
+ inline int32_t getId() const { return mId; }
+ inline int32_t getControllerNumber() const { return mControllerNumber; }
+ inline int32_t getGeneration() const { return mGeneration; }
+ inline const std::string getName() const { return mIdentifier.name; }
+ inline const std::string getDescriptor() { return mIdentifier.descriptor; }
+ inline uint32_t getClasses() const { return mClasses; }
+ inline uint32_t getSources() const { return mSources; }
+
+ inline bool isExternal() { return mIsExternal; }
+ inline void setExternal(bool external) { mIsExternal = external; }
+ inline std::optional<uint8_t> getAssociatedDisplayPort() const {
+ return mAssociatedDisplayPort;
+ }
+
+ inline void setMic(bool hasMic) { mHasMic = hasMic; }
+ inline bool hasMic() const { return mHasMic; }
+
+ inline bool isIgnored() { return mMappers.empty(); }
+
+ bool isEnabled();
+ void setEnabled(bool enabled, nsecs_t when);
+
+ void dump(std::string& dump);
+ void addMapper(InputMapper* mapper);
+ void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ void reset(nsecs_t when);
+ void process(const RawEvent* rawEvents, size_t count);
+ void timeoutExpired(nsecs_t when);
+ void updateExternalStylusState(const StylusState& state);
+
+ void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
+ int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+ int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+ int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+ bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags);
+ void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
+ void cancelVibrate(int32_t token);
+ void cancelTouch(nsecs_t when);
+
+ int32_t getMetaState();
+ void updateMetaState(int32_t keyCode);
+
+ void fadePointer();
+
+ void bumpGeneration();
+
+ void notifyReset(nsecs_t when);
+
+ inline const PropertyMap& getConfiguration() { return mConfiguration; }
+ inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
+
+ bool hasKey(int32_t code) {
+ return getEventHub()->hasScanCode(mId, code);
+ }
+
+ bool hasAbsoluteAxis(int32_t code) {
+ RawAbsoluteAxisInfo info;
+ getEventHub()->getAbsoluteAxisInfo(mId, code, &info);
+ return info.valid;
+ }
+
+ bool isKeyPressed(int32_t code) {
+ return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN;
+ }
+
+ int32_t getAbsoluteAxisValue(int32_t code) {
+ int32_t value;
+ getEventHub()->getAbsoluteAxisValue(mId, code, &value);
+ return value;
+ }
+
+ std::optional<int32_t> getAssociatedDisplay();
+private:
+ InputReaderContext* mContext;
+ int32_t mId;
+ int32_t mGeneration;
+ int32_t mControllerNumber;
+ InputDeviceIdentifier mIdentifier;
+ std::string mAlias;
+ uint32_t mClasses;
+
+ std::vector<InputMapper*> mMappers;
+
+ uint32_t mSources;
+ bool mIsExternal;
+ std::optional<uint8_t> mAssociatedDisplayPort;
+ bool mHasMic;
+ bool mDropUntilNextSync;
+
+ typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
+ int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
+
+ PropertyMap mConfiguration;
+};
+
+
+/* Keeps track of the state of mouse or touch pad buttons. */
+class CursorButtonAccumulator {
+public:
+ CursorButtonAccumulator();
+ void reset(InputDevice* device);
+
+ void process(const RawEvent* rawEvent);
+
+ uint32_t getButtonState() const;
+
+private:
+ bool mBtnLeft;
+ bool mBtnRight;
+ bool mBtnMiddle;
+ bool mBtnBack;
+ bool mBtnSide;
+ bool mBtnForward;
+ bool mBtnExtra;
+ bool mBtnTask;
+
+ void clearButtons();
+};
+
+
+/* Keeps track of cursor movements. */
+
+class CursorMotionAccumulator {
+public:
+ CursorMotionAccumulator();
+ void reset(InputDevice* device);
+
+ void process(const RawEvent* rawEvent);
+ void finishSync();
+
+ inline int32_t getRelativeX() const { return mRelX; }
+ inline int32_t getRelativeY() const { return mRelY; }
+
+private:
+ int32_t mRelX;
+ int32_t mRelY;
+
+ void clearRelativeAxes();
+};
+
+
+/* Keeps track of cursor scrolling motions. */
+
+class CursorScrollAccumulator {
+public:
+ CursorScrollAccumulator();
+ void configure(InputDevice* device);
+ void reset(InputDevice* device);
+
+ void process(const RawEvent* rawEvent);
+ void finishSync();
+
+ inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
+ inline bool haveRelativeHWheel() const { return mHaveRelHWheel; }
+
+ inline int32_t getRelativeX() const { return mRelX; }
+ inline int32_t getRelativeY() const { return mRelY; }
+ inline int32_t getRelativeVWheel() const { return mRelWheel; }
+ inline int32_t getRelativeHWheel() const { return mRelHWheel; }
+
+private:
+ bool mHaveRelWheel;
+ bool mHaveRelHWheel;
+
+ int32_t mRelX;
+ int32_t mRelY;
+ int32_t mRelWheel;
+ int32_t mRelHWheel;
+
+ void clearRelativeAxes();
+};
+
+
+/* Keeps track of the state of touch, stylus and tool buttons. */
+class TouchButtonAccumulator {
+public:
+ TouchButtonAccumulator();
+ void configure(InputDevice* device);
+ void reset(InputDevice* device);
+
+ void process(const RawEvent* rawEvent);
+
+ uint32_t getButtonState() const;
+ int32_t getToolType() const;
+ bool isToolActive() const;
+ bool isHovering() const;
+ bool hasStylus() const;
+
+private:
+ bool mHaveBtnTouch;
+ bool mHaveStylus;
+
+ bool mBtnTouch;
+ bool mBtnStylus;
+ bool mBtnStylus2;
+ bool mBtnToolFinger;
+ bool mBtnToolPen;
+ bool mBtnToolRubber;
+ bool mBtnToolBrush;
+ bool mBtnToolPencil;
+ bool mBtnToolAirbrush;
+ bool mBtnToolMouse;
+ bool mBtnToolLens;
+ bool mBtnToolDoubleTap;
+ bool mBtnToolTripleTap;
+ bool mBtnToolQuadTap;
+
+ void clearButtons();
+};
+
+
+/* Raw axis information from the driver. */
+struct RawPointerAxes {
+ RawAbsoluteAxisInfo x;
+ RawAbsoluteAxisInfo y;
+ RawAbsoluteAxisInfo pressure;
+ RawAbsoluteAxisInfo touchMajor;
+ RawAbsoluteAxisInfo touchMinor;
+ RawAbsoluteAxisInfo toolMajor;
+ RawAbsoluteAxisInfo toolMinor;
+ RawAbsoluteAxisInfo orientation;
+ RawAbsoluteAxisInfo distance;
+ RawAbsoluteAxisInfo tiltX;
+ RawAbsoluteAxisInfo tiltY;
+ RawAbsoluteAxisInfo trackingId;
+ RawAbsoluteAxisInfo slot;
+
+ RawPointerAxes();
+ inline int32_t getRawWidth() const { return x.maxValue - x.minValue + 1; }
+ inline int32_t getRawHeight() const { return y.maxValue - y.minValue + 1; }
+ void clear();
+};
+
+
+/* Raw data for a collection of pointers including a pointer id mapping table. */
+struct RawPointerData {
+ struct Pointer {
+ uint32_t id;
+ int32_t x;
+ int32_t y;
+ int32_t pressure;
+ int32_t touchMajor;
+ int32_t touchMinor;
+ int32_t toolMajor;
+ int32_t toolMinor;
+ int32_t orientation;
+ int32_t distance;
+ int32_t tiltX;
+ int32_t tiltY;
+ int32_t toolType; // a fully decoded AMOTION_EVENT_TOOL_TYPE constant
+ bool isHovering;
+ };
+
+ uint32_t pointerCount;
+ Pointer pointers[MAX_POINTERS];
+ BitSet32 hoveringIdBits, touchingIdBits;
+ uint32_t idToIndex[MAX_POINTER_ID + 1];
+
+ RawPointerData();
+ void clear();
+ void copyFrom(const RawPointerData& other);
+ void getCentroidOfTouchingPointers(float* outX, float* outY) const;
+
+ inline void markIdBit(uint32_t id, bool isHovering) {
+ if (isHovering) {
+ hoveringIdBits.markBit(id);
+ } else {
+ touchingIdBits.markBit(id);
+ }
+ }
+
+ inline void clearIdBits() {
+ hoveringIdBits.clear();
+ touchingIdBits.clear();
+ }
+
+ inline const Pointer& pointerForId(uint32_t id) const {
+ return pointers[idToIndex[id]];
+ }
+
+ inline bool isHovering(uint32_t pointerIndex) {
+ return pointers[pointerIndex].isHovering;
+ }
+};
+
+
+/* Cooked data for a collection of pointers including a pointer id mapping table. */
+struct CookedPointerData {
+ uint32_t pointerCount;
+ PointerProperties pointerProperties[MAX_POINTERS];
+ PointerCoords pointerCoords[MAX_POINTERS];
+ BitSet32 hoveringIdBits, touchingIdBits;
+ uint32_t idToIndex[MAX_POINTER_ID + 1];
+
+ CookedPointerData();
+ void clear();
+ void copyFrom(const CookedPointerData& other);
+
+ inline const PointerCoords& pointerCoordsForId(uint32_t id) const {
+ return pointerCoords[idToIndex[id]];
+ }
+
+ inline PointerCoords& editPointerCoordsWithId(uint32_t id) {
+ return pointerCoords[idToIndex[id]];
+ }
+
+ inline PointerProperties& editPointerPropertiesWithId(uint32_t id) {
+ return pointerProperties[idToIndex[id]];
+ }
+
+ inline bool isHovering(uint32_t pointerIndex) const {
+ return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id);
+ }
+
+ inline bool isTouching(uint32_t pointerIndex) const {
+ return touchingIdBits.hasBit(pointerProperties[pointerIndex].id);
+ }
+};
+
+/**
+ * Basic statistics information.
+ * Keep track of min, max, average, and standard deviation of the received samples.
+ * Used to report latency information about input events.
+ */
+struct LatencyStatistics {
+ float min;
+ float max;
+ // Sum of all samples
+ float sum;
+ // Sum of squares of all samples
+ float sum2;
+ // The number of samples
+ size_t count;
+ // The last time statistics were reported.
+ nsecs_t lastReportTime;
+
+ LatencyStatistics() {
+ reset(systemTime(SYSTEM_TIME_MONOTONIC));
+ }
+
+ inline void addValue(float x) {
+ if (x < min) {
+ min = x;
+ }
+ if (x > max) {
+ max = x;
+ }
+ sum += x;
+ sum2 += x * x;
+ count++;
+ }
+
+ // Get the average value. Should not be called if no samples have been added.
+ inline float mean() {
+ if (count == 0) {
+ return 0;
+ }
+ return sum / count;
+ }
+
+ // Get the standard deviation. Should not be called if no samples have been added.
+ inline float stdev() {
+ if (count == 0) {
+ return 0;
+ }
+ float average = mean();
+ return sqrt(sum2 / count - average * average);
+ }
+
+ /**
+ * Reset internal state. The variable 'when' is the time when the data collection started.
+ * Call this to start a new data collection window.
+ */
+ inline void reset(nsecs_t when) {
+ max = 0;
+ min = std::numeric_limits<float>::max();
+ sum = 0;
+ sum2 = 0;
+ count = 0;
+ lastReportTime = when;
+ }
+};
+
+/* Keeps track of the state of single-touch protocol. */
+class SingleTouchMotionAccumulator {
+public:
+ SingleTouchMotionAccumulator();
+
+ void process(const RawEvent* rawEvent);
+ void reset(InputDevice* device);
+
+ inline int32_t getAbsoluteX() const { return mAbsX; }
+ inline int32_t getAbsoluteY() const { return mAbsY; }
+ inline int32_t getAbsolutePressure() const { return mAbsPressure; }
+ inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; }
+ inline int32_t getAbsoluteDistance() const { return mAbsDistance; }
+ inline int32_t getAbsoluteTiltX() const { return mAbsTiltX; }
+ inline int32_t getAbsoluteTiltY() const { return mAbsTiltY; }
+
+private:
+ int32_t mAbsX;
+ int32_t mAbsY;
+ int32_t mAbsPressure;
+ int32_t mAbsToolWidth;
+ int32_t mAbsDistance;
+ int32_t mAbsTiltX;
+ int32_t mAbsTiltY;
+
+ void clearAbsoluteAxes();
+};
+
+
+/* Keeps track of the state of multi-touch protocol. */
+class MultiTouchMotionAccumulator {
+public:
+ class Slot {
+ public:
+ inline bool isInUse() const { return mInUse; }
+ inline int32_t getX() const { return mAbsMTPositionX; }
+ inline int32_t getY() const { return mAbsMTPositionY; }
+ inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; }
+ inline int32_t getTouchMinor() const {
+ return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor; }
+ inline int32_t getToolMajor() const { return mAbsMTWidthMajor; }
+ inline int32_t getToolMinor() const {
+ return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor; }
+ inline int32_t getOrientation() const { return mAbsMTOrientation; }
+ inline int32_t getTrackingId() const { return mAbsMTTrackingId; }
+ inline int32_t getPressure() const { return mAbsMTPressure; }
+ inline int32_t getDistance() const { return mAbsMTDistance; }
+ inline int32_t getToolType() const;
+
+ private:
+ friend class MultiTouchMotionAccumulator;
+
+ bool mInUse;
+ bool mHaveAbsMTTouchMinor;
+ bool mHaveAbsMTWidthMinor;
+ bool mHaveAbsMTToolType;
+
+ int32_t mAbsMTPositionX;
+ int32_t mAbsMTPositionY;
+ int32_t mAbsMTTouchMajor;
+ int32_t mAbsMTTouchMinor;
+ int32_t mAbsMTWidthMajor;
+ int32_t mAbsMTWidthMinor;
+ int32_t mAbsMTOrientation;
+ int32_t mAbsMTTrackingId;
+ int32_t mAbsMTPressure;
+ int32_t mAbsMTDistance;
+ int32_t mAbsMTToolType;
+
+ Slot();
+ void clear();
+ };
+
+ MultiTouchMotionAccumulator();
+ ~MultiTouchMotionAccumulator();
+
+ void configure(InputDevice* device, size_t slotCount, bool usingSlotsProtocol);
+ void reset(InputDevice* device);
+ void process(const RawEvent* rawEvent);
+ void finishSync();
+ bool hasStylus() const;
+
+ inline size_t getSlotCount() const { return mSlotCount; }
+ inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
+ inline uint32_t getDeviceTimestamp() const { return mDeviceTimestamp; }
+
+private:
+ int32_t mCurrentSlot;
+ Slot* mSlots;
+ size_t mSlotCount;
+ bool mUsingSlotsProtocol;
+ bool mHaveStylus;
+ uint32_t mDeviceTimestamp;
+
+ void clearSlots(int32_t initialSlot);
+};
+
+
+/* An input mapper transforms raw input events into cooked event data.
+ * A single input device can have multiple associated input mappers in order to interpret
+ * different classes of events.
+ *
+ * InputMapper lifecycle:
+ * - create
+ * - configure with 0 changes
+ * - reset
+ * - process, process, process (may occasionally reconfigure with non-zero changes or reset)
+ * - reset
+ * - destroy
+ */
+class InputMapper {
+public:
+ explicit InputMapper(InputDevice* device);
+ virtual ~InputMapper();
+
+ inline InputDevice* getDevice() { return mDevice; }
+ inline int32_t getDeviceId() { return mDevice->getId(); }
+ inline const std::string getDeviceName() { return mDevice->getName(); }
+ inline InputReaderContext* getContext() { return mContext; }
+ inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
+ inline InputListenerInterface* getListener() { return mContext->getListener(); }
+ inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
+
+ virtual uint32_t getSources() = 0;
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void dump(std::string& dump);
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent) = 0;
+ virtual void timeoutExpired(nsecs_t when);
+
+ virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+ virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+ virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+ virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags);
+ virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+ int32_t token);
+ virtual void cancelVibrate(int32_t token);
+ virtual void cancelTouch(nsecs_t when);
+
+ virtual int32_t getMetaState();
+ virtual void updateMetaState(int32_t keyCode);
+
+ virtual void updateExternalStylusState(const StylusState& state);
+
+ virtual void fadePointer();
+ virtual std::optional<int32_t> getAssociatedDisplay() {
+ return std::nullopt;
+ }
+protected:
+ InputDevice* mDevice;
+ InputReaderContext* mContext;
+
+ status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
+ void bumpGeneration();
+
+ static void dumpRawAbsoluteAxisInfo(std::string& dump,
+ const RawAbsoluteAxisInfo& axis, const char* name);
+ static void dumpStylusState(std::string& dump, const StylusState& state);
+};
+
+
+class SwitchInputMapper : public InputMapper {
+public:
+ explicit SwitchInputMapper(InputDevice* device);
+ virtual ~SwitchInputMapper();
+
+ virtual uint32_t getSources();
+ virtual void process(const RawEvent* rawEvent);
+
+ virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+ virtual void dump(std::string& dump);
+
+private:
+ uint32_t mSwitchValues;
+ uint32_t mUpdatedSwitchMask;
+
+ void processSwitch(int32_t switchCode, int32_t switchValue);
+ void sync(nsecs_t when);
+};
+
+
+class VibratorInputMapper : public InputMapper {
+public:
+ explicit VibratorInputMapper(InputDevice* device);
+ virtual ~VibratorInputMapper();
+
+ virtual uint32_t getSources();
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void process(const RawEvent* rawEvent);
+
+ virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+ int32_t token);
+ virtual void cancelVibrate(int32_t token);
+ virtual void timeoutExpired(nsecs_t when);
+ virtual void dump(std::string& dump);
+
+private:
+ bool mVibrating;
+ nsecs_t mPattern[MAX_VIBRATE_PATTERN_SIZE];
+ size_t mPatternSize;
+ ssize_t mRepeat;
+ int32_t mToken;
+ ssize_t mIndex;
+ nsecs_t mNextStepTime;
+
+ void nextStep();
+ void stopVibrating();
+};
+
+
+class KeyboardInputMapper : public InputMapper {
+public:
+ KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType);
+ virtual ~KeyboardInputMapper();
+
+ virtual uint32_t getSources();
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void dump(std::string& dump);
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
+
+ virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+ virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+ virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags);
+
+ virtual int32_t getMetaState();
+ virtual void updateMetaState(int32_t keyCode);
+
+private:
+ // The current viewport.
+ std::optional<DisplayViewport> mViewport;
+
+ struct KeyDown {
+ int32_t keyCode;
+ int32_t scanCode;
+ };
+
+ uint32_t mSource;
+ int32_t mKeyboardType;
+
+ std::vector<KeyDown> mKeyDowns; // keys that are down
+ int32_t mMetaState;
+ nsecs_t mDownTime; // time of most recent key down
+
+ int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none
+
+ struct LedState {
+ bool avail; // led is available
+ bool on; // we think the led is currently on
+ };
+ LedState mCapsLockLedState;
+ LedState mNumLockLedState;
+ LedState mScrollLockLedState;
+
+ // Immutable configuration parameters.
+ struct Parameters {
+ bool orientationAware;
+ bool handlesKeyRepeat;
+ } mParameters;
+
+ void configureParameters();
+ void dumpParameters(std::string& dump);
+
+ int32_t getOrientation();
+ int32_t getDisplayId();
+
+ bool isKeyboardOrGamepadKey(int32_t scanCode);
+ bool isMediaKey(int32_t keyCode);
+
+ void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
+
+ bool updateMetaStateIfNeeded(int32_t keyCode, bool down);
+
+ ssize_t findKeyDown(int32_t scanCode);
+
+ void resetLedState();
+ void initializeLedState(LedState& ledState, int32_t led);
+ void updateLedState(bool reset);
+ void updateLedStateForModifier(LedState& ledState, int32_t led,
+ int32_t modifier, bool reset);
+};
+
+
+class CursorInputMapper : public InputMapper {
+public:
+ explicit CursorInputMapper(InputDevice* device);
+ virtual ~CursorInputMapper();
+
+ virtual uint32_t getSources();
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void dump(std::string& dump);
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
+
+ virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+
+ virtual void fadePointer();
+
+ virtual std::optional<int32_t> getAssociatedDisplay();
+private:
+ // Amount that trackball needs to move in order to generate a key event.
+ static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
+
+ // Immutable configuration parameters.
+ struct Parameters {
+ enum Mode {
+ MODE_POINTER,
+ MODE_POINTER_RELATIVE,
+ MODE_NAVIGATION,
+ };
+
+ Mode mode;
+ bool hasAssociatedDisplay;
+ bool orientationAware;
+ } mParameters;
+
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ CursorMotionAccumulator mCursorMotionAccumulator;
+ CursorScrollAccumulator mCursorScrollAccumulator;
+
+ int32_t mSource;
+ float mXScale;
+ float mYScale;
+ float mXPrecision;
+ float mYPrecision;
+
+ float mVWheelScale;
+ float mHWheelScale;
+
+ // Velocity controls for mouse pointer and wheel movements.
+ // The controls for X and Y wheel movements are separate to keep them decoupled.
+ VelocityControl mPointerVelocityControl;
+ VelocityControl mWheelXVelocityControl;
+ VelocityControl mWheelYVelocityControl;
+
+ int32_t mOrientation;
+
+ sp<PointerControllerInterface> mPointerController;
+
+ int32_t mButtonState;
+ nsecs_t mDownTime;
+
+ void configureParameters();
+ void dumpParameters(std::string& dump);
+
+ void sync(nsecs_t when);
+};
+
+
+class RotaryEncoderInputMapper : public InputMapper {
+public:
+ explicit RotaryEncoderInputMapper(InputDevice* device);
+ virtual ~RotaryEncoderInputMapper();
+
+ virtual uint32_t getSources();
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void dump(std::string& dump);
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
+
+private:
+ CursorScrollAccumulator mRotaryEncoderScrollAccumulator;
+
+ int32_t mSource;
+ float mScalingFactor;
+ int32_t mOrientation;
+
+ void sync(nsecs_t when);
+};
+
+class TouchInputMapper : public InputMapper {
+public:
+ explicit TouchInputMapper(InputDevice* device);
+ virtual ~TouchInputMapper();
+
+ virtual uint32_t getSources();
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void dump(std::string& dump);
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
+
+ virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+ virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+ virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags);
+
+ virtual void fadePointer();
+ virtual void cancelTouch(nsecs_t when);
+ virtual void timeoutExpired(nsecs_t when);
+ virtual void updateExternalStylusState(const StylusState& state);
+ virtual std::optional<int32_t> getAssociatedDisplay();
+protected:
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ CursorScrollAccumulator mCursorScrollAccumulator;
+ TouchButtonAccumulator mTouchButtonAccumulator;
+
+ struct VirtualKey {
+ int32_t keyCode;
+ int32_t scanCode;
+ uint32_t flags;
+
+ // computed hit box, specified in touch screen coords based on known display size
+ int32_t hitLeft;
+ int32_t hitTop;
+ int32_t hitRight;
+ int32_t hitBottom;
+
+ inline bool isHit(int32_t x, int32_t y) const {
+ return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
+ }
+ };
+
+ // Input sources and device mode.
+ uint32_t mSource;
+
+ enum DeviceMode {
+ DEVICE_MODE_DISABLED, // input is disabled
+ DEVICE_MODE_DIRECT, // direct mapping (touchscreen)
+ DEVICE_MODE_UNSCALED, // unscaled mapping (touchpad)
+ DEVICE_MODE_NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
+ DEVICE_MODE_POINTER, // pointer mapping (pointer)
+ };
+ DeviceMode mDeviceMode;
+
+ // The reader's configuration.
+ InputReaderConfiguration mConfig;
+
+ // Immutable configuration parameters.
+ struct Parameters {
+ enum DeviceType {
+ DEVICE_TYPE_TOUCH_SCREEN,
+ DEVICE_TYPE_TOUCH_PAD,
+ DEVICE_TYPE_TOUCH_NAVIGATION,
+ DEVICE_TYPE_POINTER,
+ };
+
+ DeviceType deviceType;
+ bool hasAssociatedDisplay;
+ bool associatedDisplayIsExternal;
+ bool orientationAware;
+ bool hasButtonUnderPad;
+ std::string uniqueDisplayId;
+
+ enum GestureMode {
+ GESTURE_MODE_SINGLE_TOUCH,
+ GESTURE_MODE_MULTI_TOUCH,
+ };
+ GestureMode gestureMode;
+
+ bool wake;
+ } mParameters;
+
+ // Immutable calibration parameters in parsed form.
+ struct Calibration {
+ // Size
+ enum SizeCalibration {
+ SIZE_CALIBRATION_DEFAULT,
+ SIZE_CALIBRATION_NONE,
+ SIZE_CALIBRATION_GEOMETRIC,
+ SIZE_CALIBRATION_DIAMETER,
+ SIZE_CALIBRATION_BOX,
+ SIZE_CALIBRATION_AREA,
+ };
+
+ SizeCalibration sizeCalibration;
+
+ bool haveSizeScale;
+ float sizeScale;
+ bool haveSizeBias;
+ float sizeBias;
+ bool haveSizeIsSummed;
+ bool sizeIsSummed;
+
+ // Pressure
+ enum PressureCalibration {
+ PRESSURE_CALIBRATION_DEFAULT,
+ PRESSURE_CALIBRATION_NONE,
+ PRESSURE_CALIBRATION_PHYSICAL,
+ PRESSURE_CALIBRATION_AMPLITUDE,
+ };
+
+ PressureCalibration pressureCalibration;
+ bool havePressureScale;
+ float pressureScale;
+
+ // Orientation
+ enum OrientationCalibration {
+ ORIENTATION_CALIBRATION_DEFAULT,
+ ORIENTATION_CALIBRATION_NONE,
+ ORIENTATION_CALIBRATION_INTERPOLATED,
+ ORIENTATION_CALIBRATION_VECTOR,
+ };
+
+ OrientationCalibration orientationCalibration;
+
+ // Distance
+ enum DistanceCalibration {
+ DISTANCE_CALIBRATION_DEFAULT,
+ DISTANCE_CALIBRATION_NONE,
+ DISTANCE_CALIBRATION_SCALED,
+ };
+
+ DistanceCalibration distanceCalibration;
+ bool haveDistanceScale;
+ float distanceScale;
+
+ enum CoverageCalibration {
+ COVERAGE_CALIBRATION_DEFAULT,
+ COVERAGE_CALIBRATION_NONE,
+ COVERAGE_CALIBRATION_BOX,
+ };
+
+ CoverageCalibration coverageCalibration;
+
+ inline void applySizeScaleAndBias(float* outSize) const {
+ if (haveSizeScale) {
+ *outSize *= sizeScale;
+ }
+ if (haveSizeBias) {
+ *outSize += sizeBias;
+ }
+ if (*outSize < 0) {
+ *outSize = 0;
+ }
+ }
+ } mCalibration;
+
+ // Affine location transformation/calibration
+ struct TouchAffineTransformation mAffineTransform;
+
+ RawPointerAxes mRawPointerAxes;
+
+ struct RawState {
+ nsecs_t when;
+ uint32_t deviceTimestamp;
+
+ // Raw pointer sample data.
+ RawPointerData rawPointerData;
+
+ int32_t buttonState;
+
+ // Scroll state.
+ int32_t rawVScroll;
+ int32_t rawHScroll;
+
+ void copyFrom(const RawState& other) {
+ when = other.when;
+ deviceTimestamp = other.deviceTimestamp;
+ rawPointerData.copyFrom(other.rawPointerData);
+ buttonState = other.buttonState;
+ rawVScroll = other.rawVScroll;
+ rawHScroll = other.rawHScroll;
+ }
+
+ void clear() {
+ when = 0;
+ deviceTimestamp = 0;
+ rawPointerData.clear();
+ buttonState = 0;
+ rawVScroll = 0;
+ rawHScroll = 0;
+ }
+ };
+
+ struct CookedState {
+ uint32_t deviceTimestamp;
+ // Cooked pointer sample data.
+ CookedPointerData cookedPointerData;
+
+ // Id bits used to differentiate fingers, stylus and mouse tools.
+ BitSet32 fingerIdBits;
+ BitSet32 stylusIdBits;
+ BitSet32 mouseIdBits;
+
+ int32_t buttonState;
+
+ void copyFrom(const CookedState& other) {
+ deviceTimestamp = other.deviceTimestamp;
+ cookedPointerData.copyFrom(other.cookedPointerData);
+ fingerIdBits = other.fingerIdBits;
+ stylusIdBits = other.stylusIdBits;
+ mouseIdBits = other.mouseIdBits;
+ buttonState = other.buttonState;
+ }
+
+ void clear() {
+ deviceTimestamp = 0;
+ cookedPointerData.clear();
+ fingerIdBits.clear();
+ stylusIdBits.clear();
+ mouseIdBits.clear();
+ buttonState = 0;
+ }
+ };
+
+ std::vector<RawState> mRawStatesPending;
+ RawState mCurrentRawState;
+ CookedState mCurrentCookedState;
+ RawState mLastRawState;
+ CookedState mLastCookedState;
+
+ // State provided by an external stylus
+ StylusState mExternalStylusState;
+ int64_t mExternalStylusId;
+ nsecs_t mExternalStylusFusionTimeout;
+ bool mExternalStylusDataPending;
+
+ // True if we sent a HOVER_ENTER event.
+ bool mSentHoverEnter;
+
+ // Have we assigned pointer IDs for this stream
+ bool mHavePointerIds;
+
+ // Is the current stream of direct touch events aborted
+ bool mCurrentMotionAborted;
+
+ // The time the primary pointer last went down.
+ nsecs_t mDownTime;
+
+ // The pointer controller, or null if the device is not a pointer.
+ sp<PointerControllerInterface> mPointerController;
+
+ std::vector<VirtualKey> mVirtualKeys;
+
+ virtual void configureParameters();
+ virtual void dumpParameters(std::string& dump);
+ virtual void configureRawPointerAxes();
+ virtual void dumpRawPointerAxes(std::string& dump);
+ virtual void configureSurface(nsecs_t when, bool* outResetNeeded);
+ virtual void dumpSurface(std::string& dump);
+ virtual void configureVirtualKeys();
+ virtual void dumpVirtualKeys(std::string& dump);
+ virtual void parseCalibration();
+ virtual void resolveCalibration();
+ virtual void dumpCalibration(std::string& dump);
+ virtual void updateAffineTransformation();
+ virtual void dumpAffineTransformation(std::string& dump);
+ virtual void resolveExternalStylusPresence();
+ virtual bool hasStylus() const = 0;
+ virtual bool hasExternalStylus() const;
+
+ virtual void syncTouch(nsecs_t when, RawState* outState) = 0;
+
+private:
+ // The current viewport.
+ // The components of the viewport are specified in the display's rotated orientation.
+ DisplayViewport mViewport;
+
+ // The surface orientation, width and height set by configureSurface().
+ // The width and height are derived from the viewport but are specified
+ // in the natural orientation.
+ // The surface origin specifies how the surface coordinates should be translated
+ // to align with the logical display coordinate space.
+ int32_t mSurfaceWidth;
+ int32_t mSurfaceHeight;
+ int32_t mSurfaceLeft;
+ int32_t mSurfaceTop;
+
+ // Similar to the surface coordinates, but in the raw display coordinate space rather than in
+ // the logical coordinate space.
+ int32_t mPhysicalWidth;
+ int32_t mPhysicalHeight;
+ int32_t mPhysicalLeft;
+ int32_t mPhysicalTop;
+
+ // The orientation may be different from the viewport orientation as it specifies
+ // the rotation of the surface coordinates required to produce the viewport's
+ // requested orientation, so it will depend on whether the device is orientation aware.
+ int32_t mSurfaceOrientation;
+
+ // Translation and scaling factors, orientation-independent.
+ float mXTranslate;
+ float mXScale;
+ float mXPrecision;
+
+ float mYTranslate;
+ float mYScale;
+ float mYPrecision;
+
+ float mGeometricScale;
+
+ float mPressureScale;
+
+ float mSizeScale;
+
+ float mOrientationScale;
+
+ float mDistanceScale;
+
+ bool mHaveTilt;
+ float mTiltXCenter;
+ float mTiltXScale;
+ float mTiltYCenter;
+ float mTiltYScale;
+
+ bool mExternalStylusConnected;
+
+ // Oriented motion ranges for input device info.
+ struct OrientedRanges {
+ InputDeviceInfo::MotionRange x;
+ InputDeviceInfo::MotionRange y;
+ InputDeviceInfo::MotionRange pressure;
+
+ bool haveSize;
+ InputDeviceInfo::MotionRange size;
+
+ bool haveTouchSize;
+ InputDeviceInfo::MotionRange touchMajor;
+ InputDeviceInfo::MotionRange touchMinor;
+
+ bool haveToolSize;
+ InputDeviceInfo::MotionRange toolMajor;
+ InputDeviceInfo::MotionRange toolMinor;
+
+ bool haveOrientation;
+ InputDeviceInfo::MotionRange orientation;
+
+ bool haveDistance;
+ InputDeviceInfo::MotionRange distance;
+
+ bool haveTilt;
+ InputDeviceInfo::MotionRange tilt;
+
+ OrientedRanges() {
+ clear();
+ }
+
+ void clear() {
+ haveSize = false;
+ haveTouchSize = false;
+ haveToolSize = false;
+ haveOrientation = false;
+ haveDistance = false;
+ haveTilt = false;
+ }
+ } mOrientedRanges;
+
+ // Oriented dimensions and precision.
+ float mOrientedXPrecision;
+ float mOrientedYPrecision;
+
+ struct CurrentVirtualKeyState {
+ bool down;
+ bool ignored;
+ nsecs_t downTime;
+ int32_t keyCode;
+ int32_t scanCode;
+ } mCurrentVirtualKey;
+
+ // Scale factor for gesture or mouse based pointer movements.
+ float mPointerXMovementScale;
+ float mPointerYMovementScale;
+
+ // Scale factor for gesture based zooming and other freeform motions.
+ float mPointerXZoomScale;
+ float mPointerYZoomScale;
+
+ // The maximum swipe width.
+ float mPointerGestureMaxSwipeWidth;
+
+ struct PointerDistanceHeapElement {
+ uint32_t currentPointerIndex : 8;
+ uint32_t lastPointerIndex : 8;
+ uint64_t distance : 48; // squared distance
+ };
+
+ enum PointerUsage {
+ POINTER_USAGE_NONE,
+ POINTER_USAGE_GESTURES,
+ POINTER_USAGE_STYLUS,
+ POINTER_USAGE_MOUSE,
+ };
+ PointerUsage mPointerUsage;
+
+ struct PointerGesture {
+ enum Mode {
+ // No fingers, button is not pressed.
+ // Nothing happening.
+ NEUTRAL,
+
+ // No fingers, button is not pressed.
+ // Tap detected.
+ // Emits DOWN and UP events at the pointer location.
+ TAP,
+
+ // Exactly one finger dragging following a tap.
+ // Pointer follows the active finger.
+ // Emits DOWN, MOVE and UP events at the pointer location.
+ //
+ // Detect double-taps when the finger goes up while in TAP_DRAG mode.
+ TAP_DRAG,
+
+ // Button is pressed.
+ // Pointer follows the active finger if there is one. Other fingers are ignored.
+ // Emits DOWN, MOVE and UP events at the pointer location.
+ BUTTON_CLICK_OR_DRAG,
+
+ // Exactly one finger, button is not pressed.
+ // Pointer follows the active finger.
+ // Emits HOVER_MOVE events at the pointer location.
+ //
+ // Detect taps when the finger goes up while in HOVER mode.
+ HOVER,
+
+ // Exactly two fingers but neither have moved enough to clearly indicate
+ // whether a swipe or freeform gesture was intended. We consider the
+ // pointer to be pressed so this enables clicking or long-pressing on buttons.
+ // Pointer does not move.
+ // Emits DOWN, MOVE and UP events with a single stationary pointer coordinate.
+ PRESS,
+
+ // Exactly two fingers moving in the same direction, button is not pressed.
+ // Pointer does not move.
+ // Emits DOWN, MOVE and UP events with a single pointer coordinate that
+ // follows the midpoint between both fingers.
+ SWIPE,
+
+ // Two or more fingers moving in arbitrary directions, button is not pressed.
+ // Pointer does not move.
+ // Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow
+ // each finger individually relative to the initial centroid of the finger.
+ FREEFORM,
+
+ // Waiting for quiet time to end before starting the next gesture.
+ QUIET,
+ };
+
+ // Time the first finger went down.
+ nsecs_t firstTouchTime;
+
+ // The active pointer id from the raw touch data.
+ int32_t activeTouchId; // -1 if none
+
+ // The active pointer id from the gesture last delivered to the application.
+ int32_t activeGestureId; // -1 if none
+
+ // Pointer coords and ids for the current and previous pointer gesture.
+ Mode currentGestureMode;
+ BitSet32 currentGestureIdBits;
+ uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1];
+ PointerProperties currentGestureProperties[MAX_POINTERS];
+ PointerCoords currentGestureCoords[MAX_POINTERS];
+
+ Mode lastGestureMode;
+ BitSet32 lastGestureIdBits;
+ uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1];
+ PointerProperties lastGestureProperties[MAX_POINTERS];
+ PointerCoords lastGestureCoords[MAX_POINTERS];
+
+ // Time the pointer gesture last went down.
+ nsecs_t downTime;
+
+ // Time when the pointer went down for a TAP.
+ nsecs_t tapDownTime;
+
+ // Time when the pointer went up for a TAP.
+ nsecs_t tapUpTime;
+
+ // Location of initial tap.
+ float tapX, tapY;
+
+ // Time we started waiting for quiescence.
+ nsecs_t quietTime;
+
+ // Reference points for multitouch gestures.
+ float referenceTouchX; // reference touch X/Y coordinates in surface units
+ float referenceTouchY;
+ float referenceGestureX; // reference gesture X/Y coordinates in pixels
+ float referenceGestureY;
+
+ // Distance that each pointer has traveled which has not yet been
+ // subsumed into the reference gesture position.
+ BitSet32 referenceIdBits;
+ struct Delta {
+ float dx, dy;
+ };
+ Delta referenceDeltas[MAX_POINTER_ID + 1];
+
+ // Describes how touch ids are mapped to gesture ids for freeform gestures.
+ uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1];
+
+ // A velocity tracker for determining whether to switch active pointers during drags.
+ VelocityTracker velocityTracker;
+
+ void reset() {
+ firstTouchTime = LLONG_MIN;
+ activeTouchId = -1;
+ activeGestureId = -1;
+ currentGestureMode = NEUTRAL;
+ currentGestureIdBits.clear();
+ lastGestureMode = NEUTRAL;
+ lastGestureIdBits.clear();
+ downTime = 0;
+ velocityTracker.clear();
+ resetTap();
+ resetQuietTime();
+ }
+
+ void resetTap() {
+ tapDownTime = LLONG_MIN;
+ tapUpTime = LLONG_MIN;
+ }
+
+ void resetQuietTime() {
+ quietTime = LLONG_MIN;
+ }
+ } mPointerGesture;
+
+ struct PointerSimple {
+ PointerCoords currentCoords;
+ PointerProperties currentProperties;
+ PointerCoords lastCoords;
+ PointerProperties lastProperties;
+
+ // True if the pointer is down.
+ bool down;
+
+ // True if the pointer is hovering.
+ bool hovering;
+
+ // Time the pointer last went down.
+ nsecs_t downTime;
+
+ void reset() {
+ currentCoords.clear();
+ currentProperties.clear();
+ lastCoords.clear();
+ lastProperties.clear();
+ down = false;
+ hovering = false;
+ downTime = 0;
+ }
+ } mPointerSimple;
+
+ // The pointer and scroll velocity controls.
+ VelocityControl mPointerVelocityControl;
+ VelocityControl mWheelXVelocityControl;
+ VelocityControl mWheelYVelocityControl;
+
+ // Latency statistics for touch events
+ struct LatencyStatistics mStatistics;
+
+ std::optional<DisplayViewport> findViewport();
+
+ void resetExternalStylus();
+ void clearStylusDataPendingFlags();
+
+ void sync(nsecs_t when);
+
+ bool consumeRawTouches(nsecs_t when, uint32_t policyFlags);
+ void processRawTouches(bool timeout);
+ void cookAndDispatch(nsecs_t when);
+ void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
+ int32_t keyEventAction, int32_t keyEventFlags);
+
+ void dispatchTouches(nsecs_t when, uint32_t policyFlags);
+ void dispatchHoverExit(nsecs_t when, uint32_t policyFlags);
+ void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags);
+ void dispatchButtonRelease(nsecs_t when, uint32_t policyFlags);
+ void dispatchButtonPress(nsecs_t when, uint32_t policyFlags);
+ const BitSet32& findActiveIdBits(const CookedPointerData& cookedPointerData);
+ void cookPointerData();
+ void abortTouches(nsecs_t when, uint32_t policyFlags);
+
+ void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage);
+ void abortPointerUsage(nsecs_t when, uint32_t policyFlags);
+
+ void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
+ void abortPointerGestures(nsecs_t when, uint32_t policyFlags);
+ bool preparePointerGestures(nsecs_t when,
+ bool* outCancelPreviousGesture, bool* outFinishPreviousGesture,
+ bool isTimeout);
+
+ void dispatchPointerStylus(nsecs_t when, uint32_t policyFlags);
+ void abortPointerStylus(nsecs_t when, uint32_t policyFlags);
+
+ void dispatchPointerMouse(nsecs_t when, uint32_t policyFlags);
+ void abortPointerMouse(nsecs_t when, uint32_t policyFlags);
+
+ void dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
+ bool down, bool hovering);
+ void abortPointerSimple(nsecs_t when, uint32_t policyFlags);
+
+ bool assignExternalStylusId(const RawState& state, bool timeout);
+ void applyExternalStylusButtonState(nsecs_t when);
+ void applyExternalStylusTouchState(nsecs_t when);
+
+ // Dispatches a motion event.
+ // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
+ // method will take care of setting the index and transmuting the action to DOWN or UP
+ // it is the first / last pointer to go down / up.
+ void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
+ int32_t action, int32_t actionButton,
+ int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ uint32_t deviceTimestamp,
+ const PointerProperties* properties, const PointerCoords* coords,
+ const uint32_t* idToIndex, BitSet32 idBits,
+ int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime);
+
+ // Updates pointer coords and properties for pointers with specified ids that have moved.
+ // Returns true if any of them changed.
+ bool updateMovedPointers(const PointerProperties* inProperties,
+ const PointerCoords* inCoords, const uint32_t* inIdToIndex,
+ PointerProperties* outProperties, PointerCoords* outCoords,
+ const uint32_t* outIdToIndex, BitSet32 idBits) const;
+
+ bool isPointInsideSurface(int32_t x, int32_t y);
+ const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
+
+ static void assignPointerIds(const RawState* last, RawState* current);
+
+ void reportEventForStatistics(nsecs_t evdevTime);
+
+ const char* modeToString(DeviceMode deviceMode);
+};
+
+
+class SingleTouchInputMapper : public TouchInputMapper {
+public:
+ explicit SingleTouchInputMapper(InputDevice* device);
+ virtual ~SingleTouchInputMapper();
+
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
+
+protected:
+ virtual void syncTouch(nsecs_t when, RawState* outState);
+ virtual void configureRawPointerAxes();
+ virtual bool hasStylus() const;
+
+private:
+ SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
+};
+
+
+class MultiTouchInputMapper : public TouchInputMapper {
+public:
+ explicit MultiTouchInputMapper(InputDevice* device);
+ virtual ~MultiTouchInputMapper();
+
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
+
+protected:
+ virtual void syncTouch(nsecs_t when, RawState* outState);
+ virtual void configureRawPointerAxes();
+ virtual bool hasStylus() const;
+
+private:
+ MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
+
+ // Specifies the pointer id bits that are in use, and their associated tracking id.
+ BitSet32 mPointerIdBits;
+ int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1];
+};
+
+class ExternalStylusInputMapper : public InputMapper {
+public:
+ explicit ExternalStylusInputMapper(InputDevice* device);
+ virtual ~ExternalStylusInputMapper() = default;
+
+ virtual uint32_t getSources();
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void dump(std::string& dump);
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
+ virtual void sync(nsecs_t when);
+
+private:
+ SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
+ RawAbsoluteAxisInfo mRawPressureAxis;
+ TouchButtonAccumulator mTouchButtonAccumulator;
+
+ StylusState mStylusState;
+};
+
+
+class JoystickInputMapper : public InputMapper {
+public:
+ explicit JoystickInputMapper(InputDevice* device);
+ virtual ~JoystickInputMapper();
+
+ virtual uint32_t getSources();
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void dump(std::string& dump);
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
+
+private:
+ struct Axis {
+ RawAbsoluteAxisInfo rawAxisInfo;
+ AxisInfo axisInfo;
+
+ bool explicitlyMapped; // true if the axis was explicitly assigned an axis id
+
+ float scale; // scale factor from raw to normalized values
+ float offset; // offset to add after scaling for normalization
+ float highScale; // scale factor from raw to normalized values of high split
+ float highOffset; // offset to add after scaling for normalization of high split
+
+ float min; // normalized inclusive minimum
+ float max; // normalized inclusive maximum
+ float flat; // normalized flat region size
+ float fuzz; // normalized error tolerance
+ float resolution; // normalized resolution in units/mm
+
+ float filter; // filter out small variations of this size
+ float currentValue; // current value
+ float newValue; // most recent value
+ float highCurrentValue; // current value of high split
+ float highNewValue; // most recent value of high split
+
+ void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo,
+ bool explicitlyMapped, float scale, float offset,
+ float highScale, float highOffset,
+ float min, float max, float flat, float fuzz, float resolution) {
+ this->rawAxisInfo = rawAxisInfo;
+ this->axisInfo = axisInfo;
+ this->explicitlyMapped = explicitlyMapped;
+ this->scale = scale;
+ this->offset = offset;
+ this->highScale = highScale;
+ this->highOffset = highOffset;
+ this->min = min;
+ this->max = max;
+ this->flat = flat;
+ this->fuzz = fuzz;
+ this->resolution = resolution;
+ this->filter = 0;
+ resetValue();
+ }
+
+ void resetValue() {
+ this->currentValue = 0;
+ this->newValue = 0;
+ this->highCurrentValue = 0;
+ this->highNewValue = 0;
+ }
+ };
+
+ // Axes indexed by raw ABS_* axis index.
+ KeyedVector<int32_t, Axis> mAxes;
+
+ void sync(nsecs_t when, bool force);
+
+ bool haveAxis(int32_t axisId);
+ void pruneAxes(bool ignoreExplicitlyMappedAxes);
+ bool filterAxes(bool force);
+
+ static bool hasValueChangedSignificantly(float filter,
+ float newValue, float currentValue, float min, float max);
+ static bool hasMovedNearerToValueWithinFilteredRange(float filter,
+ float newValue, float currentValue, float thresholdValue);
+
+ static bool isCenteredAxis(int32_t axis);
+ static int32_t getCompatAxis(int32_t axis);
+
+ static void addMotionRange(int32_t axisId, const Axis& axis, InputDeviceInfo* info);
+ static void setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis,
+ float value);
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_READER_H
diff --git a/services/inputflinger/reader/InputReaderFactory.cpp b/services/inputflinger/InputReaderFactory.cpp
index 9f73680913..3534f6b760 100644
--- a/services/inputflinger/reader/InputReaderFactory.cpp
+++ b/services/inputflinger/InputReaderFactory.cpp
@@ -15,13 +15,13 @@
*/
#include "InputReaderFactory.h"
-
#include "InputReader.h"
namespace android {
-sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener) {
+sp<InputReaderInterface> createInputReader(
+ const sp<InputReaderPolicyInterface>& policy,
+ const sp<InputListenerInterface>& listener) {
return new InputReader(new EventHub(), policy, listener);
}
diff --git a/services/inputflinger/reporter/InputReporter.cpp b/services/inputflinger/InputReporter.cpp
index b591d3f909..8d3153c367 100644
--- a/services/inputflinger/reporter/InputReporter.cpp
+++ b/services/inputflinger/InputReporter.cpp
@@ -27,15 +27,15 @@ public:
};
void InputReporter::reportUnhandledKey(uint32_t sequenceNum) {
- // do nothing
+ // do nothing
}
void InputReporter::reportDroppedKey(uint32_t sequenceNum) {
- // do nothing
+ // do nothing
}
sp<InputReporterInterface> createInputReporter() {
- return new InputReporter();
+ return new InputReporter();
}
} // namespace android
diff --git a/services/inputflinger/reader/TouchVideoDevice.cpp b/services/inputflinger/TouchVideoDevice.cpp
index c075078528..19c1313dcd 100644
--- a/services/inputflinger/reader/TouchVideoDevice.cpp
+++ b/services/inputflinger/TouchVideoDevice.cpp
@@ -37,13 +37,10 @@ using android::base::unique_fd;
namespace android {
TouchVideoDevice::TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath,
- uint32_t height, uint32_t width,
- const std::array<const int16_t*, NUM_BUFFERS>& readLocations)
- : mFd(fd),
- mName(std::move(name)),
- mPath(std::move(devicePath)),
- mHeight(height),
- mWidth(width),
+ uint32_t height, uint32_t width,
+ const std::array<const int16_t*, NUM_BUFFERS>& readLocations) :
+ mFd(fd), mName(std::move(name)), mPath(std::move(devicePath)),
+ mHeight(height), mWidth(width),
mReadLocations(readLocations) {
mFrames.reserve(MAX_QUEUE_SIZE);
};
@@ -63,11 +60,11 @@ std::unique_ptr<TouchVideoDevice> TouchVideoDevice::create(std::string devicePat
}
if (!(cap.capabilities & V4L2_CAP_TOUCH)) {
ALOGE("Capability V4L2_CAP_TOUCH is not present, can't use device for heatmap data. "
- "Make sure device specifies V4L2_CAP_TOUCH");
+ "Make sure device specifies V4L2_CAP_TOUCH");
return nullptr;
}
- ALOGI("Opening video device: driver = %s, card = %s, bus_info = %s, version = %i", cap.driver,
- cap.card, cap.bus_info, cap.version);
+ ALOGI("Opening video device: driver = %s, card = %s, bus_info = %s, version = %i",
+ cap.driver, cap.card, cap.bus_info, cap.version);
std::string name = reinterpret_cast<const char*>(cap.card);
struct v4l2_input v4l2_input_struct;
@@ -80,7 +77,7 @@ std::unique_ptr<TouchVideoDevice> TouchVideoDevice::create(std::string devicePat
if (v4l2_input_struct.type != V4L2_INPUT_TYPE_TOUCH) {
ALOGE("Video device does not provide touch data. "
- "Make sure device specifies V4L2_INPUT_TYPE_TOUCH.");
+ "Make sure device specifies V4L2_INPUT_TYPE_TOUCH.");
return nullptr;
}
@@ -123,14 +120,14 @@ std::unique_ptr<TouchVideoDevice> TouchVideoDevice::create(std::string devicePat
return nullptr;
}
if (buf.length != height * width * sizeof(int16_t)) {
- ALOGE("Unexpected value of buf.length = %i (offset = %" PRIu32 ")", buf.length,
- buf.m.offset);
+ ALOGE("Unexpected value of buf.length = %i (offset = %" PRIu32 ")",
+ buf.length, buf.m.offset);
return nullptr;
}
- readLocations[i] = static_cast<const int16_t*>(
- mmap(nullptr /* start anywhere */, buf.length, PROT_READ /* required */,
- MAP_SHARED /* recommended */, fd.get(), buf.m.offset));
+ readLocations[i] = static_cast<const int16_t*>(mmap(nullptr /* start anywhere */,
+ buf.length, PROT_READ /* required */, MAP_SHARED /* recommended */,
+ fd.get(), buf.m.offset));
if (readLocations[i] == MAP_FAILED) {
ALOGE("%s: map failed: %s", __func__, strerror(errno));
return nullptr;
@@ -153,9 +150,8 @@ std::unique_ptr<TouchVideoDevice> TouchVideoDevice::create(std::string devicePat
}
}
// Using 'new' to access a non-public constructor.
- return std::unique_ptr<TouchVideoDevice>(new TouchVideoDevice(fd.release(), std::move(name),
- std::move(devicePath), height,
- width, readLocations));
+ return std::unique_ptr<TouchVideoDevice>(new TouchVideoDevice(
+ fd.release(), std::move(name), std::move(devicePath), height, width, readLocations));
}
size_t TouchVideoDevice::readAndQueueFrames() {
@@ -167,10 +163,10 @@ size_t TouchVideoDevice::readAndQueueFrames() {
}
// Concatenate the vectors, then clip up to maximum size allowed
mFrames.insert(mFrames.end(), std::make_move_iterator(frames.begin()),
- std::make_move_iterator(frames.end()));
+ std::make_move_iterator(frames.end()));
if (mFrames.size() > MAX_QUEUE_SIZE) {
ALOGE("More than %zu frames have been accumulated. Dropping %zu frames", MAX_QUEUE_SIZE,
- mFrames.size() - MAX_QUEUE_SIZE);
+ mFrames.size() - MAX_QUEUE_SIZE);
mFrames.erase(mFrames.begin(), mFrames.end() - MAX_QUEUE_SIZE);
}
return numFrames;
@@ -197,8 +193,8 @@ std::optional<TouchVideoFrame> TouchVideoDevice::readFrame() {
if ((buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) != V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
// We use CLOCK_MONOTONIC for input events, so if the clocks don't match,
// we can't compare timestamps. Just log a warning, since this is a driver issue
- ALOGW("The timestamp %ld.%ld was not acquired using CLOCK_MONOTONIC", buf.timestamp.tv_sec,
- buf.timestamp.tv_usec);
+ ALOGW("The timestamp %ld.%ld was not acquired using CLOCK_MONOTONIC",
+ buf.timestamp.tv_sec, buf.timestamp.tv_usec);
}
std::vector<int16_t> data(mHeight * mWidth);
const int16_t* readFrom = mReadLocations[buf.index];
@@ -237,7 +233,7 @@ TouchVideoDevice::~TouchVideoDevice() {
}
for (const int16_t* buffer : mReadLocations) {
void* bufferAddress = static_cast<void*>(const_cast<int16_t*>(buffer));
- result = munmap(bufferAddress, mHeight * mWidth * sizeof(int16_t));
+ result = munmap(bufferAddress, mHeight * mWidth * sizeof(int16_t));
if (result == -1) {
ALOGE("%s: Couldn't unmap: [%s]", __func__, strerror(errno));
}
@@ -246,9 +242,9 @@ TouchVideoDevice::~TouchVideoDevice() {
std::string TouchVideoDevice::dump() const {
return StringPrintf("Video device %s (%s) : height=%" PRIu32 ", width=%" PRIu32
- ", fd=%i, hasValidFd=%s",
- mName.c_str(), mPath.c_str(), mHeight, mWidth, mFd.get(),
- hasValidFd() ? "true" : "false");
+ ", fd=%i, hasValidFd=%s",
+ mName.c_str(), mPath.c_str(), mHeight, mWidth, mFd.get(),
+ hasValidFd() ? "true" : "false");
}
} // namespace android
diff --git a/services/inputflinger/reader/include/TouchVideoDevice.h b/services/inputflinger/TouchVideoDevice.h
index 5a32443f29..0e7e2ef496 100644
--- a/services/inputflinger/reader/include/TouchVideoDevice.h
+++ b/services/inputflinger/TouchVideoDevice.h
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#ifndef _UI_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
-#define _UI_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
+#ifndef _INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
+#define _INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
+#include <array>
#include <android-base/unique_fd.h>
#include <input/TouchVideoFrame.h>
-#include <stdint.h>
-#include <array>
#include <optional>
+#include <stdint.h>
#include <string>
#include <vector>
@@ -109,9 +109,9 @@ private:
* The constructor is private because opening a v4l2 device requires many checks.
* To get a new TouchVideoDevice, use 'create' instead.
*/
- explicit TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath, uint32_t height,
- uint32_t width,
- const std::array<const int16_t*, NUM_BUFFERS>& readLocations);
+ explicit TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath,
+ uint32_t height, uint32_t width,
+ const std::array<const int16_t*, NUM_BUFFERS>& readLocations);
/**
* Read all currently available frames.
*/
@@ -121,7 +121,5 @@ private:
*/
std::optional<TouchVideoFrame> readFrame();
};
-
} // namespace android
-
-#endif // _UI_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
+#endif //_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
deleted file mode 100644
index b8c3a808f1..0000000000
--- a/services/inputflinger/dispatcher/Android.bp
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-cc_library_static {
- name: "libinputdispatcher",
- defaults: ["inputflinger_defaults"],
- srcs: [
- "Connection.cpp",
- "Entry.cpp",
- "InjectionState.cpp",
- "InputDispatcher.cpp",
- "InputDispatcherFactory.cpp",
- "InputDispatcherThread.cpp",
- "InputState.cpp",
- "InputTarget.cpp",
- "Monitor.cpp",
- "TouchState.cpp"
- ],
- shared_libs: [
- "libbase",
- "libcutils",
- "libinput",
- "libinputreporter",
- "libinputflinger_base",
- "liblog",
- "libui",
- "libutils",
- ],
-
- export_include_dirs: ["include"],
-}
diff --git a/services/inputflinger/dispatcher/CancelationOptions.h b/services/inputflinger/dispatcher/CancelationOptions.h
deleted file mode 100644
index 99e2108dbf..0000000000
--- a/services/inputflinger/dispatcher/CancelationOptions.h
+++ /dev/null
@@ -1,53 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_CANCELLATIONOPTIONS_H
-#define _UI_INPUT_INPUTDISPATCHER_CANCELLATIONOPTIONS_H
-
-#include <optional>
-
-namespace android::inputdispatcher {
-
-/* Specifies which events are to be canceled and why. */
-struct CancelationOptions {
- enum Mode {
- CANCEL_ALL_EVENTS = 0,
- CANCEL_POINTER_EVENTS = 1,
- CANCEL_NON_POINTER_EVENTS = 2,
- CANCEL_FALLBACK_EVENTS = 3,
- };
-
- // The criterion to use to determine which events should be canceled.
- Mode mode;
-
- // Descriptive reason for the cancelation.
- const char* reason;
-
- // The specific keycode of the key event to cancel, or nullopt to cancel any key event.
- std::optional<int32_t> keyCode = std::nullopt;
-
- // The specific device id of events to cancel, or nullopt to cancel events from any device.
- std::optional<int32_t> deviceId = std::nullopt;
-
- // The specific display id of events to cancel, or nullopt to cancel events on any display.
- std::optional<int32_t> displayId = std::nullopt;
-
- CancelationOptions(Mode mode, const char* reason) : mode(mode), reason(reason) {}
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_CANCELLATIONOPTIONS_H
diff --git a/services/inputflinger/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp
deleted file mode 100644
index ef7f6509e4..0000000000
--- a/services/inputflinger/dispatcher/Connection.cpp
+++ /dev/null
@@ -1,64 +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 "Connection.h"
-
-#include "Entry.h"
-
-namespace android::inputdispatcher {
-
-Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor)
- : status(STATUS_NORMAL),
- inputChannel(inputChannel),
- monitor(monitor),
- inputPublisher(inputChannel),
- inputPublisherBlocked(false) {}
-
-Connection::~Connection() {}
-
-const std::string Connection::getWindowName() const {
- if (inputChannel != nullptr) {
- return inputChannel->getName();
- }
- if (monitor) {
- return "monitor";
- }
- return "?";
-}
-
-const char* Connection::getStatusLabel() const {
- switch (status) {
- case STATUS_NORMAL:
- return "NORMAL";
- case STATUS_BROKEN:
- return "BROKEN";
- case STATUS_ZOMBIE:
- return "ZOMBIE";
- default:
- return "UNKNOWN";
- }
-}
-
-DispatchEntry* Connection::findWaitQueueEntry(uint32_t seq) {
- for (DispatchEntry* entry = waitQueue.head; entry != nullptr; entry = entry->next) {
- if (entry->seq == seq) {
- return entry;
- }
- }
- return nullptr;
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h
deleted file mode 100644
index ed4eebdff4..0000000000
--- a/services/inputflinger/dispatcher/Connection.h
+++ /dev/null
@@ -1,74 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_CONNECTION_H
-#define _UI_INPUT_INPUTDISPATCHER_CONNECTION_H
-
-#include "InputState.h"
-#include "Queue.h"
-
-#include <input/InputTransport.h>
-#include <deque>
-
-namespace android::inputdispatcher {
-
-struct DispatchEntry;
-
-/* Manages the dispatch state associated with a single input channel. */
-class Connection : public RefBase {
-protected:
- virtual ~Connection();
-
-public:
- enum Status {
- // Everything is peachy.
- STATUS_NORMAL,
- // An unrecoverable communication error has occurred.
- STATUS_BROKEN,
- // The input channel has been unregistered.
- STATUS_ZOMBIE
- };
-
- Status status;
- sp<InputChannel> inputChannel; // never null
- bool monitor;
- InputPublisher inputPublisher;
- InputState inputState;
-
- // True if the socket is full and no further events can be published until
- // the application consumes some of the input.
- bool inputPublisherBlocked;
-
- // Queue of events that need to be published to the connection.
- Queue<DispatchEntry> outboundQueue;
-
- // Queue of events that have been published to the connection but that have not
- // yet received a "finished" response from the application.
- Queue<DispatchEntry> waitQueue;
-
- explicit Connection(const sp<InputChannel>& inputChannel, bool monitor);
-
- inline const std::string getInputChannelName() const { return inputChannel->getName(); }
-
- const std::string getWindowName() const;
- const char* getStatusLabel() const;
-
- DispatchEntry* findWaitQueueEntry(uint32_t seq);
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_CONNECTION_H
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
deleted file mode 100644
index 8d05640b38..0000000000
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ /dev/null
@@ -1,255 +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 "Entry.h"
-
-#include "Connection.h"
-
-#include <android-base/stringprintf.h>
-#include <cutils/atomic.h>
-#include <inttypes.h>
-
-using android::base::StringPrintf;
-
-namespace android::inputdispatcher {
-
-static std::string motionActionToString(int32_t action) {
- // Convert MotionEvent action to string
- switch (action & AMOTION_EVENT_ACTION_MASK) {
- case AMOTION_EVENT_ACTION_DOWN:
- return "DOWN";
- case AMOTION_EVENT_ACTION_MOVE:
- return "MOVE";
- case AMOTION_EVENT_ACTION_UP:
- return "UP";
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- return "POINTER_DOWN";
- case AMOTION_EVENT_ACTION_POINTER_UP:
- return "POINTER_UP";
- }
- return StringPrintf("%" PRId32, action);
-}
-
-static std::string keyActionToString(int32_t action) {
- // Convert KeyEvent action to string
- switch (action) {
- case AKEY_EVENT_ACTION_DOWN:
- return "DOWN";
- case AKEY_EVENT_ACTION_UP:
- return "UP";
- case AKEY_EVENT_ACTION_MULTIPLE:
- return "MULTIPLE";
- }
- return StringPrintf("%" PRId32, action);
-}
-
-// --- EventEntry ---
-
-EventEntry::EventEntry(uint32_t sequenceNum, int32_t type, nsecs_t eventTime, uint32_t policyFlags)
- : sequenceNum(sequenceNum),
- refCount(1),
- type(type),
- eventTime(eventTime),
- policyFlags(policyFlags),
- injectionState(nullptr),
- dispatchInProgress(false) {}
-
-EventEntry::~EventEntry() {
- releaseInjectionState();
-}
-
-void EventEntry::release() {
- refCount -= 1;
- if (refCount == 0) {
- delete this;
- } else {
- ALOG_ASSERT(refCount > 0);
- }
-}
-
-void EventEntry::releaseInjectionState() {
- if (injectionState) {
- injectionState->release();
- injectionState = nullptr;
- }
-}
-
-// --- ConfigurationChangedEntry ---
-
-ConfigurationChangedEntry::ConfigurationChangedEntry(uint32_t sequenceNum, nsecs_t eventTime)
- : EventEntry(sequenceNum, TYPE_CONFIGURATION_CHANGED, eventTime, 0) {}
-
-ConfigurationChangedEntry::~ConfigurationChangedEntry() {}
-
-void ConfigurationChangedEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("ConfigurationChangedEvent(), policyFlags=0x%08x", policyFlags);
-}
-
-// --- DeviceResetEntry ---
-
-DeviceResetEntry::DeviceResetEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId)
- : EventEntry(sequenceNum, TYPE_DEVICE_RESET, eventTime, 0), deviceId(deviceId) {}
-
-DeviceResetEntry::~DeviceResetEntry() {}
-
-void DeviceResetEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x", deviceId, policyFlags);
-}
-
-// --- KeyEntry ---
-
-KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount,
- nsecs_t downTime)
- : EventEntry(sequenceNum, TYPE_KEY, eventTime, policyFlags),
- deviceId(deviceId),
- source(source),
- displayId(displayId),
- action(action),
- flags(flags),
- keyCode(keyCode),
- scanCode(scanCode),
- metaState(metaState),
- repeatCount(repeatCount),
- downTime(downTime),
- syntheticRepeat(false),
- interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN),
- interceptKeyWakeupTime(0) {}
-
-KeyEntry::~KeyEntry() {}
-
-void KeyEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, "
- "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
- "repeatCount=%d), policyFlags=0x%08x",
- deviceId, source, displayId, keyActionToString(action).c_str(), flags,
- keyCode, scanCode, metaState, repeatCount, policyFlags);
-}
-
-void KeyEntry::recycle() {
- releaseInjectionState();
-
- dispatchInProgress = false;
- syntheticRepeat = false;
- interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
- interceptKeyWakeupTime = 0;
-}
-
-// --- MotionEntry ---
-
-MotionEntry::MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- int32_t displayId, uint32_t policyFlags, int32_t action,
- int32_t actionButton, int32_t flags, int32_t metaState,
- int32_t buttonState, MotionClassification classification,
- int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime,
- uint32_t pointerCount, const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords, float xOffset, float yOffset)
- : EventEntry(sequenceNum, TYPE_MOTION, eventTime, policyFlags),
- eventTime(eventTime),
- deviceId(deviceId),
- source(source),
- displayId(displayId),
- action(action),
- actionButton(actionButton),
- flags(flags),
- metaState(metaState),
- buttonState(buttonState),
- classification(classification),
- edgeFlags(edgeFlags),
- xPrecision(xPrecision),
- yPrecision(yPrecision),
- downTime(downTime),
- pointerCount(pointerCount) {
- for (uint32_t i = 0; i < pointerCount; i++) {
- this->pointerProperties[i].copyFrom(pointerProperties[i]);
- this->pointerCoords[i].copyFrom(pointerCoords[i]);
- if (xOffset || yOffset) {
- this->pointerCoords[i].applyOffset(xOffset, yOffset);
- }
- }
-}
-
-MotionEntry::~MotionEntry() {}
-
-void MotionEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32
- ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
- "buttonState=0x%08x, "
- "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
- "pointers=[",
- deviceId, source, displayId, motionActionToString(action).c_str(),
- actionButton, flags, metaState, buttonState,
- motionClassificationToString(classification), edgeFlags, xPrecision,
- yPrecision);
-
- for (uint32_t i = 0; i < pointerCount; i++) {
- if (i) {
- msg += ", ";
- }
- msg += StringPrintf("%d: (%.1f, %.1f)", pointerProperties[i].id, pointerCoords[i].getX(),
- pointerCoords[i].getY());
- }
- msg += StringPrintf("]), policyFlags=0x%08x", policyFlags);
-}
-
-// --- DispatchEntry ---
-
-volatile int32_t DispatchEntry::sNextSeqAtomic;
-
-DispatchEntry::DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset,
- float yOffset, float globalScaleFactor, float windowXScale,
- float windowYScale)
- : seq(nextSeq()),
- eventEntry(eventEntry),
- targetFlags(targetFlags),
- xOffset(xOffset),
- yOffset(yOffset),
- globalScaleFactor(globalScaleFactor),
- windowXScale(windowXScale),
- windowYScale(windowYScale),
- deliveryTime(0),
- resolvedAction(0),
- resolvedFlags(0) {
- eventEntry->refCount += 1;
-}
-
-DispatchEntry::~DispatchEntry() {
- eventEntry->release();
-}
-
-uint32_t DispatchEntry::nextSeq() {
- // Sequence number 0 is reserved and will never be returned.
- uint32_t seq;
- do {
- seq = android_atomic_inc(&sNextSeqAtomic);
- } while (!seq);
- return seq;
-}
-
-// --- CommandEntry ---
-
-CommandEntry::CommandEntry(Command command)
- : command(command),
- eventTime(0),
- keyEntry(nullptr),
- userActivityEventType(0),
- seq(0),
- handled(false) {}
-
-CommandEntry::~CommandEntry() {}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
deleted file mode 100644
index b904caf671..0000000000
--- a/services/inputflinger/dispatcher/Entry.h
+++ /dev/null
@@ -1,223 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_ENTRY_H
-#define _UI_INPUT_INPUTDISPATCHER_ENTRY_H
-
-#include "InjectionState.h"
-#include "InputTarget.h"
-
-#include <input/Input.h>
-#include <input/InputApplication.h>
-#include <stdint.h>
-#include <utils/Timers.h>
-#include <functional>
-#include <string>
-
-namespace android::inputdispatcher {
-
-template <typename T>
-struct Link {
- T* next;
- T* prev;
-
-protected:
- inline Link() : next(nullptr), prev(nullptr) {}
-};
-
-struct EventEntry : Link<EventEntry> {
- enum { TYPE_CONFIGURATION_CHANGED, TYPE_DEVICE_RESET, TYPE_KEY, TYPE_MOTION };
-
- uint32_t sequenceNum;
- mutable int32_t refCount;
- int32_t type;
- nsecs_t eventTime;
- uint32_t policyFlags;
- InjectionState* injectionState;
-
- bool dispatchInProgress; // initially false, set to true while dispatching
-
- inline bool isInjected() const { return injectionState != nullptr; }
-
- void release();
-
- virtual void appendDescription(std::string& msg) const = 0;
-
-protected:
- EventEntry(uint32_t sequenceNum, int32_t type, nsecs_t eventTime, uint32_t policyFlags);
- virtual ~EventEntry();
- void releaseInjectionState();
-};
-
-struct ConfigurationChangedEntry : EventEntry {
- explicit ConfigurationChangedEntry(uint32_t sequenceNum, nsecs_t eventTime);
- virtual void appendDescription(std::string& msg) const;
-
-protected:
- virtual ~ConfigurationChangedEntry();
-};
-
-struct DeviceResetEntry : EventEntry {
- int32_t deviceId;
-
- DeviceResetEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId);
- virtual void appendDescription(std::string& msg) const;
-
-protected:
- virtual ~DeviceResetEntry();
-};
-
-struct KeyEntry : EventEntry {
- int32_t deviceId;
- uint32_t source;
- int32_t displayId;
- int32_t action;
- int32_t flags;
- int32_t keyCode;
- int32_t scanCode;
- int32_t metaState;
- int32_t repeatCount;
- nsecs_t downTime;
-
- bool syntheticRepeat; // set to true for synthetic key repeats
-
- enum InterceptKeyResult {
- INTERCEPT_KEY_RESULT_UNKNOWN,
- INTERCEPT_KEY_RESULT_SKIP,
- INTERCEPT_KEY_RESULT_CONTINUE,
- INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER,
- };
- InterceptKeyResult interceptKeyResult; // set based on the interception result
- nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
-
- KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount,
- nsecs_t downTime);
- virtual void appendDescription(std::string& msg) const;
- void recycle();
-
-protected:
- virtual ~KeyEntry();
-};
-
-struct MotionEntry : EventEntry {
- nsecs_t eventTime;
- int32_t deviceId;
- uint32_t source;
- int32_t displayId;
- int32_t action;
- int32_t actionButton;
- int32_t flags;
- int32_t metaState;
- int32_t buttonState;
- MotionClassification classification;
- int32_t edgeFlags;
- float xPrecision;
- float yPrecision;
- nsecs_t downTime;
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
-
- MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
- int32_t flags, int32_t metaState, int32_t buttonState,
- MotionClassification classification, int32_t edgeFlags, float xPrecision,
- float yPrecision, nsecs_t downTime, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
- float xOffset, float yOffset);
- virtual void appendDescription(std::string& msg) const;
-
-protected:
- virtual ~MotionEntry();
-};
-
-// Tracks the progress of dispatching a particular event to a particular connection.
-struct DispatchEntry : Link<DispatchEntry> {
- const uint32_t seq; // unique sequence number, never 0
-
- EventEntry* eventEntry; // the event to dispatch
- int32_t targetFlags;
- float xOffset;
- float yOffset;
- float globalScaleFactor;
- float windowXScale = 1.0f;
- float windowYScale = 1.0f;
- nsecs_t deliveryTime; // time when the event was actually delivered
-
- // Set to the resolved action and flags when the event is enqueued.
- int32_t resolvedAction;
- int32_t resolvedFlags;
-
- DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset, float yOffset,
- float globalScaleFactor, float windowXScale, float windowYScale);
- ~DispatchEntry();
-
- inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; }
-
- inline bool isSplit() const { return targetFlags & InputTarget::FLAG_SPLIT; }
-
-private:
- static volatile int32_t sNextSeqAtomic;
-
- static uint32_t nextSeq();
-};
-
-class InputDispatcher;
-// A command entry captures state and behavior for an action to be performed in the
-// dispatch loop after the initial processing has taken place. It is essentially
-// a kind of continuation used to postpone sensitive policy interactions to a point
-// in the dispatch loop where it is safe to release the lock (generally after finishing
-// the critical parts of the dispatch cycle).
-//
-// The special thing about commands is that they can voluntarily release and reacquire
-// the dispatcher lock at will. Initially when the command starts running, the
-// dispatcher lock is held. However, if the command needs to call into the policy to
-// do some work, it can release the lock, do the work, then reacquire the lock again
-// before returning.
-//
-// This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
-// never calls into the policy while holding its lock.
-//
-// Commands are implicitly 'LockedInterruptible'.
-struct CommandEntry;
-typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
-
-class Connection;
-struct CommandEntry : Link<CommandEntry> {
- explicit CommandEntry(Command command);
- ~CommandEntry();
-
- Command command;
-
- // parameters for the command (usage varies by command)
- sp<Connection> connection;
- nsecs_t eventTime;
- KeyEntry* keyEntry;
- sp<InputApplicationHandle> inputApplicationHandle;
- std::string reason;
- int32_t userActivityEventType;
- uint32_t seq;
- bool handled;
- sp<InputChannel> inputChannel;
- sp<IBinder> oldToken;
- sp<IBinder> newToken;
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_ENTRY_H
diff --git a/services/inputflinger/dispatcher/InjectionState.cpp b/services/inputflinger/dispatcher/InjectionState.cpp
deleted file mode 100644
index b2d0a26a37..0000000000
--- a/services/inputflinger/dispatcher/InjectionState.cpp
+++ /dev/null
@@ -1,42 +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 "InjectionState.h"
-
-#include <log/log.h>
-
-namespace android::inputdispatcher {
-
-InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid)
- : refCount(1),
- injectorPid(injectorPid),
- injectorUid(injectorUid),
- injectionResult(INPUT_EVENT_INJECTION_PENDING),
- injectionIsAsync(false),
- pendingForegroundDispatches(0) {}
-
-InjectionState::~InjectionState() {}
-
-void InjectionState::release() {
- refCount -= 1;
- if (refCount == 0) {
- delete this;
- } else {
- ALOG_ASSERT(refCount > 0);
- }
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InjectionState.h b/services/inputflinger/dispatcher/InjectionState.h
deleted file mode 100644
index 311a0f11ef..0000000000
--- a/services/inputflinger/dispatcher/InjectionState.h
+++ /dev/null
@@ -1,60 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INJECTIONSTATE_H
-#define _UI_INPUT_INPUTDISPATCHER_INJECTIONSTATE_H
-
-#include "InputDispatcherInterface.h"
-
-#include <stdint.h>
-
-namespace android::inputdispatcher {
-
-/*
- * Constants used to determine the input event injection synchronization mode.
- */
-enum {
- /* Injection is asynchronous and is assumed always to be successful. */
- INPUT_EVENT_INJECTION_SYNC_NONE = 0,
-
- /* Waits for previous events to be dispatched so that the input dispatcher can determine
- * whether input event injection willbe permitted based on the current input focus.
- * Does not wait for the input event to finish processing. */
- INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1,
-
- /* Waits for the input event to be completely processed. */
- INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2,
-};
-
-struct InjectionState {
- mutable int32_t refCount;
-
- int32_t injectorPid;
- int32_t injectorUid;
- int32_t injectionResult; // initially INPUT_EVENT_INJECTION_PENDING
- bool injectionIsAsync; // set to true if injection is not waiting for the result
- int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
-
- InjectionState(int32_t injectorPid, int32_t injectorUid);
- void release();
-
-private:
- ~InjectionState();
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INJECTIONSTATE_H
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
deleted file mode 100644
index 67bf199cd0..0000000000
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 _UI_INPUT_DISPATCHER_H
-#define _UI_INPUT_DISPATCHER_H
-
-#include "CancelationOptions.h"
-#include "Entry.h"
-#include "InjectionState.h"
-#include "InputDispatcherConfiguration.h"
-#include "InputDispatcherInterface.h"
-#include "InputDispatcherPolicyInterface.h"
-#include "InputState.h"
-#include "InputTarget.h"
-#include "Monitor.h"
-#include "Queue.h"
-#include "TouchState.h"
-#include "TouchedWindow.h"
-
-#include <cutils/atomic.h>
-#include <input/Input.h>
-#include <input/InputApplication.h>
-#include <input/InputTransport.h>
-#include <input/InputWindow.h>
-#include <limits.h>
-#include <stddef.h>
-#include <ui/Region.h>
-#include <unistd.h>
-#include <utils/BitSet.h>
-#include <utils/Looper.h>
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-#include <utils/threads.h>
-#include <condition_variable>
-#include <deque>
-#include <optional>
-#include <unordered_map>
-
-#include <InputListener.h>
-#include <InputReporterInterface.h>
-
-namespace android::inputdispatcher {
-
-class Connection;
-
-/* Dispatches events to input targets. Some functions of the input dispatcher, such as
- * identifying input targets, are controlled by a separate policy object.
- *
- * IMPORTANT INVARIANT:
- * Because the policy can potentially block or cause re-entrance into the input dispatcher,
- * the input dispatcher never calls into the policy while holding its internal locks.
- * The implementation is also carefully designed to recover from scenarios such as an
- * input channel becoming unregistered while identifying input targets or processing timeouts.
- *
- * Methods marked 'Locked' must be called with the lock acquired.
- *
- * Methods marked 'LockedInterruptible' must be called with the lock acquired but
- * may during the course of their execution release the lock, call into the policy, and
- * then reacquire the lock. The caller is responsible for recovering gracefully.
- *
- * A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.
- */
-class InputDispatcher : public android::InputDispatcherInterface {
-protected:
- virtual ~InputDispatcher();
-
-public:
- explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
-
- virtual void dump(std::string& dump) override;
- virtual void monitor() override;
-
- virtual void dispatchOnce() override;
-
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
- virtual void notifyKey(const NotifyKeyArgs* args) override;
- virtual void notifyMotion(const NotifyMotionArgs* args) override;
- virtual void notifySwitch(const NotifySwitchArgs* args) override;
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
-
- virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid,
- int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
- uint32_t policyFlags) override;
-
- virtual void setInputWindows(
- const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId,
- const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) override;
- virtual void setFocusedApplication(
- int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) override;
- virtual void setFocusedDisplay(int32_t displayId) override;
- virtual void setInputDispatchMode(bool enabled, bool frozen) override;
- virtual void setInputFilterEnabled(bool enabled) override;
-
- virtual bool transferTouchFocus(const sp<IBinder>& fromToken,
- const sp<IBinder>& toToken) override;
-
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- int32_t displayId) override;
- virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel, int32_t displayId,
- bool isGestureMonitor) override;
- virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) override;
- virtual status_t pilferPointers(const sp<IBinder>& token) override;
-
-private:
-
- enum DropReason {
- DROP_REASON_NOT_DROPPED = 0,
- DROP_REASON_POLICY = 1,
- DROP_REASON_APP_SWITCH = 2,
- DROP_REASON_DISABLED = 3,
- DROP_REASON_BLOCKED = 4,
- DROP_REASON_STALE = 5,
- };
-
- sp<InputDispatcherPolicyInterface> mPolicy;
- android::InputDispatcherConfiguration mConfig;
-
- std::mutex mLock;
-
- std::condition_variable mDispatcherIsAlive;
-
- sp<Looper> mLooper;
-
- EventEntry* mPendingEvent GUARDED_BY(mLock);
- Queue<EventEntry> mInboundQueue GUARDED_BY(mLock);
- Queue<EventEntry> mRecentQueue GUARDED_BY(mLock);
- Queue<CommandEntry> mCommandQueue GUARDED_BY(mLock);
-
- DropReason mLastDropReason GUARDED_BY(mLock);
-
- void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) REQUIRES(mLock);
-
- // Enqueues an inbound event. Returns true if mLooper->wake() should be called.
- bool enqueueInboundEventLocked(EventEntry* entry) REQUIRES(mLock);
-
- // Cleans up input state when dropping an inbound event.
- void dropInboundEventLocked(EventEntry* entry, DropReason dropReason) REQUIRES(mLock);
-
- // Adds an event to a queue of recent events for debugging purposes.
- void addRecentEventLocked(EventEntry* entry) REQUIRES(mLock);
-
- // App switch latency optimization.
- bool mAppSwitchSawKeyDown GUARDED_BY(mLock);
- nsecs_t mAppSwitchDueTime GUARDED_BY(mLock);
-
- bool isAppSwitchKeyEvent(KeyEntry* keyEntry);
- bool isAppSwitchPendingLocked() REQUIRES(mLock);
- void resetPendingAppSwitchLocked(bool handled) REQUIRES(mLock);
-
- // Stale event latency optimization.
- static bool isStaleEvent(nsecs_t currentTime, EventEntry* entry);
-
- // Blocked event latency optimization. Drops old events when the user intends
- // to transfer focus to a new application.
- EventEntry* mNextUnblockedEvent GUARDED_BY(mLock);
-
- sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y,
- bool addOutsideTargets = false,
- bool addPortalWindows = false) REQUIRES(mLock);
-
- // All registered connections mapped by channel file descriptor.
- KeyedVector<int, sp<Connection>> mConnectionsByFd GUARDED_BY(mLock);
-
- struct IBinderHash {
- std::size_t operator()(const sp<IBinder>& b) const {
- return std::hash<IBinder*>{}(b.get());
- }
- };
- std::unordered_map<sp<IBinder>, sp<InputChannel>, IBinderHash> mInputChannelsByToken
- GUARDED_BY(mLock);
-
- // Finds the display ID of the gesture monitor identified by the provided token.
- std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token)
- REQUIRES(mLock);
-
- ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
-
- // Input channels that will receive a copy of all input events sent to the provided display.
- std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay GUARDED_BY(mLock);
-
- // Input channels that will receive pointer events that start within the corresponding display.
- // These are a bit special when compared to global monitors since they'll cause gesture streams
- // to continue even when there isn't a touched window,and have the ability to steal the rest of
- // the pointer stream in order to claim it for a system gesture.
- std::unordered_map<int32_t, std::vector<Monitor>> mGestureMonitorsByDisplay GUARDED_BY(mLock);
-
- // Event injection and synchronization.
- std::condition_variable mInjectionResultAvailable;
- bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
- void setInjectionResult(EventEntry* entry, int32_t injectionResult);
-
- std::condition_variable mInjectionSyncFinished;
- void incrementPendingForegroundDispatches(EventEntry* entry);
- void decrementPendingForegroundDispatches(EventEntry* entry);
-
- // Key repeat tracking.
- struct KeyRepeatState {
- KeyEntry* lastKeyEntry; // or null if no repeat
- nsecs_t nextRepeatTime;
- } mKeyRepeatState GUARDED_BY(mLock);
-
- void resetKeyRepeatLocked() REQUIRES(mLock);
- KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime) REQUIRES(mLock);
-
- // Key replacement tracking
- struct KeyReplacement {
- int32_t keyCode;
- int32_t deviceId;
- bool operator==(const KeyReplacement& rhs) const {
- return keyCode == rhs.keyCode && deviceId == rhs.deviceId;
- }
- bool operator<(const KeyReplacement& rhs) const {
- return keyCode != rhs.keyCode ? keyCode < rhs.keyCode : deviceId < rhs.deviceId;
- }
- };
- // Maps the key code replaced, device id tuple to the key code it was replaced with
- KeyedVector<KeyReplacement, int32_t> mReplacedKeys GUARDED_BY(mLock);
- // Process certain Meta + Key combinations
- void accelerateMetaShortcuts(const int32_t deviceId, const int32_t action, int32_t& keyCode,
- int32_t& metaState);
-
- // Deferred command processing.
- bool haveCommandsLocked() const REQUIRES(mLock);
- bool runCommandsLockedInterruptible() REQUIRES(mLock);
- CommandEntry* postCommandLocked(Command command) REQUIRES(mLock);
-
- // Input filter processing.
- bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) REQUIRES(mLock);
- bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) REQUIRES(mLock);
-
- // Inbound event processing.
- void drainInboundQueueLocked() REQUIRES(mLock);
- void releasePendingEventLocked() REQUIRES(mLock);
- void releaseInboundEventLocked(EventEntry* entry) REQUIRES(mLock);
-
- // Dispatch state.
- bool mDispatchEnabled GUARDED_BY(mLock);
- bool mDispatchFrozen GUARDED_BY(mLock);
- bool mInputFilterEnabled GUARDED_BY(mLock);
-
- std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay
- GUARDED_BY(mLock);
- // Get window handles by display, return an empty vector if not found.
- std::vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const
- REQUIRES(mLock);
- sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken) const
- REQUIRES(mLock);
- sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const REQUIRES(mLock);
- bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
-
- // Focus tracking for keys, trackball, etc.
- std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
- GUARDED_BY(mLock);
-
- KeyedVector<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock);
- TouchState mTempTouchState GUARDED_BY(mLock);
-
- // Focused applications.
- std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay
- GUARDED_BY(mLock);
-
- // Top focused display.
- int32_t mFocusedDisplayId GUARDED_BY(mLock);
-
- // Dispatcher state at time of last ANR.
- std::string mLastANRState GUARDED_BY(mLock);
-
- // Dispatch inbound events.
- bool dispatchConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry)
- REQUIRES(mLock);
- bool dispatchDeviceResetLocked(nsecs_t currentTime, DeviceResetEntry* entry) REQUIRES(mLock);
- bool dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, DropReason* dropReason,
- nsecs_t* nextWakeupTime) REQUIRES(mLock);
- bool dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason,
- nsecs_t* nextWakeupTime) REQUIRES(mLock);
- void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry,
- const std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
-
- void logOutboundKeyDetails(const char* prefix, const KeyEntry* entry);
- void logOutboundMotionDetails(const char* prefix, const MotionEntry* entry);
-
- // Keeping track of ANR timeouts.
- enum InputTargetWaitCause {
- INPUT_TARGET_WAIT_CAUSE_NONE,
- INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
- INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
- };
-
- InputTargetWaitCause mInputTargetWaitCause GUARDED_BY(mLock);
- nsecs_t mInputTargetWaitStartTime GUARDED_BY(mLock);
- nsecs_t mInputTargetWaitTimeoutTime GUARDED_BY(mLock);
- bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock);
- sp<IBinder> mInputTargetWaitApplicationToken GUARDED_BY(mLock);
-
- // Contains the last window which received a hover event.
- sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock);
-
- // Finding targets for input events.
- int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
- const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle,
- nsecs_t* nextWakeupTime, const char* reason)
- REQUIRES(mLock);
-
- void removeWindowByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock);
-
- void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
- const sp<InputChannel>& inputChannel)
- REQUIRES(mLock);
- nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) REQUIRES(mLock);
- void resetANRTimeoutsLocked() REQUIRES(mLock);
-
- int32_t getTargetDisplayId(const EventEntry* entry);
- int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
- std::vector<InputTarget>& inputTargets,
- nsecs_t* nextWakeupTime) REQUIRES(mLock);
- int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
- std::vector<InputTarget>& inputTargets,
- nsecs_t* nextWakeupTime,
- bool* outConflictingPointerActions) REQUIRES(mLock);
- std::vector<TouchedMonitor> findTouchedGestureMonitorsLocked(
- int32_t displayId, const std::vector<sp<InputWindowHandle>>& portalWindows)
- REQUIRES(mLock);
- void addGestureMonitors(const std::vector<Monitor>& monitors,
- std::vector<TouchedMonitor>& outTouchedMonitors, float xOffset = 0,
- float yOffset = 0);
-
- void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags,
- BitSet32 pointerIds, std::vector<InputTarget>& inputTargets)
- REQUIRES(mLock);
- void addMonitoringTargetLocked(const Monitor& monitor, float xOffset, float yOffset,
- std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
- void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId,
- float xOffset = 0, float yOffset = 0) REQUIRES(mLock);
-
- void pokeUserActivityLocked(const EventEntry* eventEntry) REQUIRES(mLock);
- bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
- const InjectionState* injectionState);
- bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle, int32_t x,
- int32_t y) const REQUIRES(mLock);
- bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
- std::string getApplicationWindowLabel(const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle);
-
- std::string checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
- const sp<InputWindowHandle>& windowHandle,
- const EventEntry* eventEntry,
- const char* targetType) REQUIRES(mLock);
-
- // Manage the dispatch cycle for a single connection.
- // These methods are deliberately not Interruptible because doing all of the work
- // with the mutex held makes it easier to ensure that connection invariants are maintained.
- // If needed, the methods post commands to run later once the critical bits are done.
- void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- EventEntry* eventEntry, const InputTarget* inputTarget)
- REQUIRES(mLock);
- void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection,
- EventEntry* eventEntry, const InputTarget* inputTarget)
- REQUIRES(mLock);
- void enqueueDispatchEntryLocked(const sp<Connection>& connection, EventEntry* eventEntry,
- const InputTarget* inputTarget, int32_t dispatchMode)
- REQUIRES(mLock);
- void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection)
- REQUIRES(mLock);
- void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- uint32_t seq, bool handled) REQUIRES(mLock);
- void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- bool notify) REQUIRES(mLock);
- void drainDispatchQueue(Queue<DispatchEntry>* queue);
- void releaseDispatchEntry(DispatchEntry* dispatchEntry);
- static int handleReceiveCallback(int fd, int events, void* data);
- // The action sent should only be of type AMOTION_EVENT_*
- void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
- const sp<IBinder>& newToken) REQUIRES(mLock);
-
- void synthesizeCancelationEventsForAllConnectionsLocked(const CancelationOptions& options)
- REQUIRES(mLock);
- void synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions& options)
- REQUIRES(mLock);
- void synthesizeCancelationEventsForMonitorsLocked(
- const CancelationOptions& options,
- std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
- void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
- const CancelationOptions& options)
- REQUIRES(mLock);
- void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
- const CancelationOptions& options)
- REQUIRES(mLock);
-
- // Splitting motion events across windows.
- MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
-
- // Reset and drop everything the dispatcher is doing.
- void resetAndDropEverythingLocked(const char* reason) REQUIRES(mLock);
-
- // Dump state.
- void dumpDispatchStateLocked(std::string& dump) REQUIRES(mLock);
- void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors);
- void logDispatchStateLocked() REQUIRES(mLock);
-
- // Registration.
- void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
- void removeMonitorChannelLocked(
- const sp<InputChannel>& inputChannel,
- std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
- status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify)
- REQUIRES(mLock);
-
- // Interesting events that we might like to log or tell the framework about.
- void onDispatchCycleFinishedLocked(nsecs_t currentTime, const sp<Connection>& connection,
- uint32_t seq, bool handled) REQUIRES(mLock);
- void onDispatchCycleBrokenLocked(nsecs_t currentTime, const sp<Connection>& connection)
- REQUIRES(mLock);
- void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
- const sp<InputWindowHandle>& newFocus) REQUIRES(mLock);
- void onANRLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime,
- nsecs_t waitStartTime, const char* reason) REQUIRES(mLock);
-
- // Outbound policy interactions.
- void doNotifyConfigurationChangedLockedInterruptible(CommandEntry* commandEntry)
- REQUIRES(mLock);
- void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
- void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
- void doNotifyANRLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
- void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry)
- REQUIRES(mLock);
- void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
- bool afterKeyEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, KeyEntry* keyEntry,
- bool handled) REQUIRES(mLock);
- bool afterMotionEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, MotionEntry* motionEntry,
- bool handled) REQUIRES(mLock);
- void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
- void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
- void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
-
- // Statistics gathering.
- void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
- int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
- void traceInboundQueueLengthLocked() REQUIRES(mLock);
- void traceOutboundQueueLength(const sp<Connection>& connection);
- void traceWaitQueueLength(const sp<Connection>& connection);
-
- sp<InputReporterInterface> mReporter;
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_DISPATCHER_H
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
deleted file mode 100644
index 7d9b03a70e..0000000000
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ /dev/null
@@ -1,370 +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 "InputState.h"
-
-namespace android::inputdispatcher {
-
-InputState::InputState() {}
-
-InputState::~InputState() {}
-
-bool InputState::isNeutral() const {
- return mKeyMementos.empty() && mMotionMementos.empty();
-}
-
-bool InputState::isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const {
- for (const MotionMemento& memento : mMotionMementos) {
- if (memento.deviceId == deviceId && memento.source == source &&
- memento.displayId == displayId && memento.hovering) {
- return true;
- }
- }
- return false;
-}
-
-bool InputState::trackKey(const KeyEntry* entry, int32_t action, int32_t flags) {
- switch (action) {
- case AKEY_EVENT_ACTION_UP: {
- if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) {
- for (size_t i = 0; i < mFallbackKeys.size();) {
- if (mFallbackKeys.valueAt(i) == entry->keyCode) {
- mFallbackKeys.removeItemsAt(i);
- } else {
- i += 1;
- }
- }
- }
- ssize_t index = findKeyMemento(entry);
- if (index >= 0) {
- mKeyMementos.erase(mKeyMementos.begin() + index);
- return true;
- }
- /* FIXME: We can't just drop the key up event because that prevents creating
- * popup windows that are automatically shown when a key is held and then
- * dismissed when the key is released. The problem is that the popup will
- * not have received the original key down, so the key up will be considered
- * to be inconsistent with its observed state. We could perhaps handle this
- * by synthesizing a key down but that will cause other problems.
- *
- * So for now, allow inconsistent key up events to be dispatched.
- *
- #if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
- "keyCode=%d, scanCode=%d",
- entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
- #endif
- return false;
- */
- return true;
- }
-
- case AKEY_EVENT_ACTION_DOWN: {
- ssize_t index = findKeyMemento(entry);
- if (index >= 0) {
- mKeyMementos.erase(mKeyMementos.begin() + index);
- }
- addKeyMemento(entry, flags);
- return true;
- }
-
- default:
- return true;
- }
-}
-
-bool InputState::trackMotion(const MotionEntry* entry, int32_t action, int32_t flags) {
- int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
- switch (actionMasked) {
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL: {
- ssize_t index = findMotionMemento(entry, false /*hovering*/);
- if (index >= 0) {
- mMotionMementos.erase(mMotionMementos.begin() + index);
- return true;
- }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
- "displayId=%" PRId32 ", actionMasked=%d",
- entry->deviceId, entry->source, entry->displayId, actionMasked);
-#endif
- return false;
- }
-
- case AMOTION_EVENT_ACTION_DOWN: {
- ssize_t index = findMotionMemento(entry, false /*hovering*/);
- if (index >= 0) {
- mMotionMementos.erase(mMotionMementos.begin() + index);
- }
- addMotionMemento(entry, flags, false /*hovering*/);
- return true;
- }
-
- case AMOTION_EVENT_ACTION_POINTER_UP:
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- case AMOTION_EVENT_ACTION_MOVE: {
- if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) {
- // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need
- // to generate cancellation events for these since they're based in relative rather
- // than absolute units.
- return true;
- }
-
- ssize_t index = findMotionMemento(entry, false /*hovering*/);
-
- if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) {
- // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
- // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral.
- // Any other value and we need to track the motion so we can send cancellation
- // events for anything generating fallback events (e.g. DPad keys for joystick
- // movements).
- if (index >= 0) {
- if (entry->pointerCoords[0].isEmpty()) {
- mMotionMementos.erase(mMotionMementos.begin() + index);
- } else {
- MotionMemento& memento = mMotionMementos[index];
- memento.setPointers(entry);
- }
- } else if (!entry->pointerCoords[0].isEmpty()) {
- addMotionMemento(entry, flags, false /*hovering*/);
- }
-
- // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
- return true;
- }
- if (index >= 0) {
- MotionMemento& memento = mMotionMementos[index];
- memento.setPointers(entry);
- return true;
- }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion pointer up/down or move event: "
- "deviceId=%d, source=%08x, displayId=%" PRId32 ", actionMasked=%d",
- entry->deviceId, entry->source, entry->displayId, actionMasked);
-#endif
- return false;
- }
-
- case AMOTION_EVENT_ACTION_HOVER_EXIT: {
- ssize_t index = findMotionMemento(entry, true /*hovering*/);
- if (index >= 0) {
- mMotionMementos.erase(mMotionMementos.begin() + index);
- return true;
- }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x, "
- "displayId=%" PRId32,
- entry->deviceId, entry->source, entry->displayId);
-#endif
- return false;
- }
-
- case AMOTION_EVENT_ACTION_HOVER_ENTER:
- case AMOTION_EVENT_ACTION_HOVER_MOVE: {
- ssize_t index = findMotionMemento(entry, true /*hovering*/);
- if (index >= 0) {
- mMotionMementos.erase(mMotionMementos.begin() + index);
- }
- addMotionMemento(entry, flags, true /*hovering*/);
- return true;
- }
-
- default:
- return true;
- }
-}
-
-ssize_t InputState::findKeyMemento(const KeyEntry* entry) const {
- for (size_t i = 0; i < mKeyMementos.size(); i++) {
- const KeyMemento& memento = mKeyMementos[i];
- if (memento.deviceId == entry->deviceId && memento.source == entry->source &&
- memento.displayId == entry->displayId && memento.keyCode == entry->keyCode &&
- memento.scanCode == entry->scanCode) {
- return i;
- }
- }
- return -1;
-}
-
-ssize_t InputState::findMotionMemento(const MotionEntry* entry, bool hovering) const {
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos[i];
- if (memento.deviceId == entry->deviceId && memento.source == entry->source &&
- memento.displayId == entry->displayId && memento.hovering == hovering) {
- return i;
- }
- }
- return -1;
-}
-
-void InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) {
- KeyMemento memento;
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.displayId = entry->displayId;
- memento.keyCode = entry->keyCode;
- memento.scanCode = entry->scanCode;
- memento.metaState = entry->metaState;
- memento.flags = flags;
- memento.downTime = entry->downTime;
- memento.policyFlags = entry->policyFlags;
- mKeyMementos.push_back(memento);
-}
-
-void InputState::addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering) {
- MotionMemento memento;
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.displayId = entry->displayId;
- memento.flags = flags;
- memento.xPrecision = entry->xPrecision;
- memento.yPrecision = entry->yPrecision;
- memento.downTime = entry->downTime;
- memento.setPointers(entry);
- memento.hovering = hovering;
- memento.policyFlags = entry->policyFlags;
- mMotionMementos.push_back(memento);
-}
-
-void InputState::MotionMemento::setPointers(const MotionEntry* entry) {
- pointerCount = entry->pointerCount;
- for (uint32_t i = 0; i < entry->pointerCount; i++) {
- pointerProperties[i].copyFrom(entry->pointerProperties[i]);
- pointerCoords[i].copyFrom(entry->pointerCoords[i]);
- }
-}
-
-void InputState::synthesizeCancelationEvents(nsecs_t currentTime,
- std::vector<EventEntry*>& outEvents,
- const CancelationOptions& options) {
- for (KeyMemento& memento : mKeyMementos) {
- if (shouldCancelKey(memento, options)) {
- outEvents.push_back(new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
- memento.deviceId, memento.source, memento.displayId,
- memento.policyFlags, AKEY_EVENT_ACTION_UP,
- memento.flags | AKEY_EVENT_FLAG_CANCELED,
- memento.keyCode, memento.scanCode, memento.metaState,
- 0, memento.downTime));
- }
- }
-
- for (const MotionMemento& memento : mMotionMementos) {
- if (shouldCancelMotion(memento, options)) {
- const int32_t action = memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT
- : AMOTION_EVENT_ACTION_CANCEL;
- outEvents.push_back(
- new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime, memento.deviceId,
- memento.source, memento.displayId, memento.policyFlags, action,
- 0 /*actionButton*/, memento.flags, AMETA_NONE,
- 0 /*buttonState*/, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
- memento.yPrecision, memento.downTime, memento.pointerCount,
- memento.pointerProperties, memento.pointerCoords, 0 /*xOffset*/,
- 0 /*yOffset*/));
- }
- }
-}
-
-void InputState::clear() {
- mKeyMementos.clear();
- mMotionMementos.clear();
- mFallbackKeys.clear();
-}
-
-void InputState::copyPointerStateTo(InputState& other) const {
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos[i];
- if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
- for (size_t j = 0; j < other.mMotionMementos.size();) {
- const MotionMemento& otherMemento = other.mMotionMementos[j];
- if (memento.deviceId == otherMemento.deviceId &&
- memento.source == otherMemento.source &&
- memento.displayId == otherMemento.displayId) {
- other.mMotionMementos.erase(other.mMotionMementos.begin() + j);
- } else {
- j += 1;
- }
- }
- other.mMotionMementos.push_back(memento);
- }
- }
-}
-
-int32_t InputState::getFallbackKey(int32_t originalKeyCode) {
- ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
- return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
-}
-
-void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) {
- ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
- if (index >= 0) {
- mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
- } else {
- mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
- }
-}
-
-void InputState::removeFallbackKey(int32_t originalKeyCode) {
- mFallbackKeys.removeItem(originalKeyCode);
-}
-
-bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) {
- if (options.keyCode && memento.keyCode != options.keyCode.value()) {
- return false;
- }
-
- if (options.deviceId && memento.deviceId != options.deviceId.value()) {
- return false;
- }
-
- if (options.displayId && memento.displayId != options.displayId.value()) {
- return false;
- }
-
- switch (options.mode) {
- case CancelationOptions::CANCEL_ALL_EVENTS:
- case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
- return true;
- case CancelationOptions::CANCEL_FALLBACK_EVENTS:
- return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
- default:
- return false;
- }
-}
-
-bool InputState::shouldCancelMotion(const MotionMemento& memento,
- const CancelationOptions& options) {
- if (options.deviceId && memento.deviceId != options.deviceId.value()) {
- return false;
- }
-
- if (options.displayId && memento.displayId != options.displayId.value()) {
- return false;
- }
-
- switch (options.mode) {
- case CancelationOptions::CANCEL_ALL_EVENTS:
- return true;
- case CancelationOptions::CANCEL_POINTER_EVENTS:
- return memento.source & AINPUT_SOURCE_CLASS_POINTER;
- case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
- return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
- default:
- return false;
- }
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
deleted file mode 100644
index 205b64728a..0000000000
--- a/services/inputflinger/dispatcher/InputState.h
+++ /dev/null
@@ -1,123 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTSTATE_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTSTATE_H
-
-#include "CancelationOptions.h"
-#include "Entry.h"
-
-#include <utils/Timers.h>
-
-namespace android::inputdispatcher {
-
-// Sequence number for synthesized or injected events.
-constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
-
-/* Tracks dispatched key and motion event state so that cancellation events can be
- * synthesized when events are dropped. */
-class InputState {
-public:
- InputState();
- ~InputState();
-
- // Returns true if there is no state to be canceled.
- bool isNeutral() const;
-
- // Returns true if the specified source is known to have received a hover enter
- // motion event.
- bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const;
-
- // Records tracking information for a key event that has just been published.
- // Returns true if the event should be delivered, false if it is inconsistent
- // and should be skipped.
- bool trackKey(const KeyEntry* entry, int32_t action, int32_t flags);
-
- // Records tracking information for a motion event that has just been published.
- // Returns true if the event should be delivered, false if it is inconsistent
- // and should be skipped.
- bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags);
-
- // Synthesizes cancelation events for the current state and resets the tracked state.
- void synthesizeCancelationEvents(nsecs_t currentTime, std::vector<EventEntry*>& outEvents,
- const CancelationOptions& options);
-
- // Clears the current state.
- void clear();
-
- // Copies pointer-related parts of the input state to another instance.
- void copyPointerStateTo(InputState& other) const;
-
- // Gets the fallback key associated with a keycode.
- // Returns -1 if none.
- // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy.
- int32_t getFallbackKey(int32_t originalKeyCode);
-
- // Sets the fallback key for a particular keycode.
- void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode);
-
- // Removes the fallback key for a particular keycode.
- void removeFallbackKey(int32_t originalKeyCode);
-
- inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const { return mFallbackKeys; }
-
-private:
- struct KeyMemento {
- int32_t deviceId;
- uint32_t source;
- int32_t displayId;
- int32_t keyCode;
- int32_t scanCode;
- int32_t metaState;
- int32_t flags;
- nsecs_t downTime;
- uint32_t policyFlags;
- };
-
- struct MotionMemento {
- int32_t deviceId;
- uint32_t source;
- int32_t displayId;
- int32_t flags;
- float xPrecision;
- float yPrecision;
- nsecs_t downTime;
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
- bool hovering;
- uint32_t policyFlags;
-
- void setPointers(const MotionEntry* entry);
- };
-
- std::vector<KeyMemento> mKeyMementos;
- std::vector<MotionMemento> mMotionMementos;
- KeyedVector<int32_t, int32_t> mFallbackKeys;
-
- ssize_t findKeyMemento(const KeyEntry* entry) const;
- ssize_t findMotionMemento(const MotionEntry* entry, bool hovering) const;
-
- void addKeyMemento(const KeyEntry* entry, int32_t flags);
- void addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering);
-
- static bool shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options);
- static bool shouldCancelMotion(const MotionMemento& memento, const CancelationOptions& options);
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTSTATE_H
diff --git a/services/inputflinger/dispatcher/InputTarget.cpp b/services/inputflinger/dispatcher/InputTarget.cpp
deleted file mode 100644
index 80fa2cb995..0000000000
--- a/services/inputflinger/dispatcher/InputTarget.cpp
+++ /dev/null
@@ -1,45 +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 "InputTarget.h"
-
-#include <android-base/stringprintf.h>
-#include <inttypes.h>
-#include <string>
-
-using android::base::StringPrintf;
-
-namespace android::inputdispatcher {
-
-std::string dispatchModeToString(int32_t dispatchMode) {
- switch (dispatchMode) {
- case InputTarget::FLAG_DISPATCH_AS_IS:
- return "DISPATCH_AS_IS";
- case InputTarget::FLAG_DISPATCH_AS_OUTSIDE:
- return "DISPATCH_AS_OUTSIDE";
- case InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER:
- return "DISPATCH_AS_HOVER_ENTER";
- case InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT:
- return "DISPATCH_AS_HOVER_EXIT";
- case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT:
- return "DISPATCH_AS_SLIPPERY_EXIT";
- case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER:
- return "DISPATCH_AS_SLIPPERY_ENTER";
- }
- return StringPrintf("%" PRId32, dispatchMode);
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
deleted file mode 100644
index 5acf92b1b1..0000000000
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ /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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H
-
-#include <input/InputTransport.h>
-#include <utils/BitSet.h>
-#include <utils/RefBase.h>
-
-namespace android::inputdispatcher {
-
-/*
- * An input target specifies how an input event is to be dispatched to a particular window
- * including the window's input channel, control flags, a timeout, and an X / Y offset to
- * be added to input event coordinates to compensate for the absolute position of the
- * window area.
- */
-struct InputTarget {
- enum {
- /* This flag indicates that the event is being delivered to a foreground application. */
- FLAG_FOREGROUND = 1 << 0,
-
- /* This flag indicates that the MotionEvent falls within the area of the target
- * obscured by another visible window above it. The motion event should be
- * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
- FLAG_WINDOW_IS_OBSCURED = 1 << 1,
-
- /* This flag indicates that a motion event is being split across multiple windows. */
- FLAG_SPLIT = 1 << 2,
-
- /* This flag indicates that the pointer coordinates dispatched to the application
- * will be zeroed out to avoid revealing information to an application. This is
- * used in conjunction with FLAG_DISPATCH_AS_OUTSIDE to prevent apps not sharing
- * the same UID from watching all touches. */
- FLAG_ZERO_COORDS = 1 << 3,
-
- /* This flag indicates that the event should be sent as is.
- * Should always be set unless the event is to be transmuted. */
- FLAG_DISPATCH_AS_IS = 1 << 8,
-
- /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
- * of the area of this target and so should instead be delivered as an
- * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
- FLAG_DISPATCH_AS_OUTSIDE = 1 << 9,
-
- /* This flag indicates that a hover sequence is starting in the given window.
- * The event is transmuted into ACTION_HOVER_ENTER. */
- FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10,
-
- /* This flag indicates that a hover event happened outside of a window which handled
- * previous hover events, signifying the end of the current hover sequence for that
- * window.
- * The event is transmuted into ACTION_HOVER_ENTER. */
- FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11,
-
- /* This flag indicates that the event should be canceled.
- * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
- * outside of a window. */
- FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,
-
- /* This flag indicates that the event should be dispatched as an initial down.
- * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
- * into a new window. */
- FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
-
- /* Mask for all dispatch modes. */
- FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS | FLAG_DISPATCH_AS_OUTSIDE |
- FLAG_DISPATCH_AS_HOVER_ENTER | FLAG_DISPATCH_AS_HOVER_EXIT |
- FLAG_DISPATCH_AS_SLIPPERY_EXIT | FLAG_DISPATCH_AS_SLIPPERY_ENTER,
-
- /* This flag indicates that the target of a MotionEvent is partly or wholly
- * obscured by another visible window above it. The motion event should be
- * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
- FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
-
- };
-
- // The input channel to be targeted.
- sp<InputChannel> inputChannel;
-
- // Flags for the input target.
- int32_t flags;
-
- // The x and y offset to add to a MotionEvent as it is delivered.
- // (ignored for KeyEvents)
- float xOffset, yOffset;
-
- // Scaling factor to apply to MotionEvent as it is delivered.
- // (ignored for KeyEvents)
- float globalScaleFactor;
- float windowXScale = 1.0f;
- float windowYScale = 1.0f;
-
- // The subset of pointer ids to include in motion events dispatched to this input target
- // if FLAG_SPLIT is set.
- BitSet32 pointerIds;
-};
-
-std::string dispatchModeToString(int32_t dispatchMode);
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H
diff --git a/services/inputflinger/dispatcher/Monitor.cpp b/services/inputflinger/dispatcher/Monitor.cpp
deleted file mode 100644
index 289b0848bf..0000000000
--- a/services/inputflinger/dispatcher/Monitor.cpp
+++ /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.
- */
-
-#include "Monitor.h"
-
-namespace android::inputdispatcher {
-
-// --- Monitor ---
-Monitor::Monitor(const sp<InputChannel>& inputChannel) : inputChannel(inputChannel) {}
-
-// --- TouchedMonitor ---
-TouchedMonitor::TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset)
- : monitor(monitor), xOffset(xOffset), yOffset(yOffset) {}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Monitor.h b/services/inputflinger/dispatcher/Monitor.h
deleted file mode 100644
index b67c9eb507..0000000000
--- a/services/inputflinger/dispatcher/Monitor.h
+++ /dev/null
@@ -1,41 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_MONITOR_H
-#define _UI_INPUT_INPUTDISPATCHER_MONITOR_H
-
-#include <input/InputTransport.h>
-
-namespace android::inputdispatcher {
-
-struct Monitor {
- sp<InputChannel> inputChannel; // never null
-
- explicit Monitor(const sp<InputChannel>& inputChannel);
-};
-
-// For tracking the offsets we need to apply when adding gesture monitor targets.
-struct TouchedMonitor {
- Monitor monitor;
- float xOffset = 0.f;
- float yOffset = 0.f;
-
- explicit TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset);
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_MONITOR_H
diff --git a/services/inputflinger/dispatcher/Queue.h b/services/inputflinger/dispatcher/Queue.h
deleted file mode 100644
index 0e75821661..0000000000
--- a/services/inputflinger/dispatcher/Queue.h
+++ /dev/null
@@ -1,88 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_QUEUE_H
-#define _UI_INPUT_INPUTDISPATCHER_QUEUE_H
-
-namespace android::inputdispatcher {
-
-// Generic queue implementation.
-template <typename T>
-struct Queue {
- T* head;
- T* tail;
- uint32_t entryCount;
-
- inline Queue() : head(nullptr), tail(nullptr), entryCount(0) {}
-
- inline bool isEmpty() const { return !head; }
-
- inline void enqueueAtTail(T* entry) {
- entryCount++;
- entry->prev = tail;
- if (tail) {
- tail->next = entry;
- } else {
- head = entry;
- }
- entry->next = nullptr;
- tail = entry;
- }
-
- inline void enqueueAtHead(T* entry) {
- entryCount++;
- entry->next = head;
- if (head) {
- head->prev = entry;
- } else {
- tail = entry;
- }
- entry->prev = nullptr;
- head = entry;
- }
-
- inline void dequeue(T* entry) {
- entryCount--;
- if (entry->prev) {
- entry->prev->next = entry->next;
- } else {
- head = entry->next;
- }
- if (entry->next) {
- entry->next->prev = entry->prev;
- } else {
- tail = entry->prev;
- }
- }
-
- inline T* dequeueAtHead() {
- entryCount--;
- T* entry = head;
- head = entry->next;
- if (head) {
- head->prev = nullptr;
- } else {
- tail = nullptr;
- }
- return entry;
- }
-
- uint32_t count() const { return entryCount; }
-};
-
-} // namespace android::inputdispatcher
-
-#endif // _UI_INPUT_INPUTDISPATCHER_QUEUE_H
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
deleted file mode 100644
index 18848a0c2f..0000000000
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ /dev/null
@@ -1,159 +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 <input/InputWindow.h>
-
-#include "InputTarget.h"
-
-#include "TouchState.h"
-
-using android::InputWindowHandle;
-
-namespace android::inputdispatcher {
-
-TouchState::TouchState()
- : down(false), split(false), deviceId(-1), source(0), displayId(ADISPLAY_ID_NONE) {}
-
-TouchState::~TouchState() {}
-
-void TouchState::reset() {
- down = false;
- split = false;
- deviceId = -1;
- source = 0;
- displayId = ADISPLAY_ID_NONE;
- windows.clear();
- portalWindows.clear();
- gestureMonitors.clear();
-}
-
-void TouchState::copyFrom(const TouchState& other) {
- down = other.down;
- split = other.split;
- deviceId = other.deviceId;
- source = other.source;
- displayId = other.displayId;
- windows = other.windows;
- portalWindows = other.portalWindows;
- gestureMonitors = other.gestureMonitors;
-}
-
-void TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags,
- BitSet32 pointerIds) {
- if (targetFlags & InputTarget::FLAG_SPLIT) {
- split = true;
- }
-
- for (size_t i = 0; i < windows.size(); i++) {
- TouchedWindow& touchedWindow = windows[i];
- if (touchedWindow.windowHandle == windowHandle) {
- touchedWindow.targetFlags |= targetFlags;
- if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
- touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
- }
- touchedWindow.pointerIds.value |= pointerIds.value;
- return;
- }
- }
-
- TouchedWindow touchedWindow;
- touchedWindow.windowHandle = windowHandle;
- touchedWindow.targetFlags = targetFlags;
- touchedWindow.pointerIds = pointerIds;
- windows.push_back(touchedWindow);
-}
-
-void TouchState::addPortalWindow(const sp<InputWindowHandle>& windowHandle) {
- size_t numWindows = portalWindows.size();
- for (size_t i = 0; i < numWindows; i++) {
- if (portalWindows[i] == windowHandle) {
- return;
- }
- }
- portalWindows.push_back(windowHandle);
-}
-
-void TouchState::addGestureMonitors(const std::vector<TouchedMonitor>& newMonitors) {
- const size_t newSize = gestureMonitors.size() + newMonitors.size();
- gestureMonitors.reserve(newSize);
- gestureMonitors.insert(std::end(gestureMonitors), std::begin(newMonitors),
- std::end(newMonitors));
-}
-
-void TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
- for (size_t i = 0; i < windows.size(); i++) {
- if (windows[i].windowHandle == windowHandle) {
- windows.erase(windows.begin() + i);
- return;
- }
- }
-}
-
-void TouchState::removeWindowByToken(const sp<IBinder>& token) {
- for (size_t i = 0; i < windows.size(); i++) {
- if (windows[i].windowHandle->getToken() == token) {
- windows.erase(windows.begin() + i);
- return;
- }
- }
-}
-
-void TouchState::filterNonAsIsTouchWindows() {
- for (size_t i = 0; i < windows.size();) {
- TouchedWindow& window = windows[i];
- if (window.targetFlags &
- (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
- window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
- window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
- i += 1;
- } else {
- windows.erase(windows.begin() + i);
- }
- }
-}
-
-void TouchState::filterNonMonitors() {
- windows.clear();
- portalWindows.clear();
-}
-
-sp<InputWindowHandle> TouchState::getFirstForegroundWindowHandle() const {
- for (size_t i = 0; i < windows.size(); i++) {
- const TouchedWindow& window = windows[i];
- if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
- return window.windowHandle;
- }
- }
- return nullptr;
-}
-
-bool TouchState::isSlippery() const {
- // Must have exactly one foreground window.
- bool haveSlipperyForegroundWindow = false;
- for (const TouchedWindow& window : windows) {
- if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
- if (haveSlipperyForegroundWindow ||
- !(window.windowHandle->getInfo()->layoutParamsFlags &
- InputWindowInfo::FLAG_SLIPPERY)) {
- return false;
- }
- haveSlipperyForegroundWindow = true;
- }
- }
- return haveSlipperyForegroundWindow;
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
deleted file mode 100644
index 3e0e0eb897..0000000000
--- a/services/inputflinger/dispatcher/TouchState.h
+++ /dev/null
@@ -1,63 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_TOUCHSTATE_H
-#define _UI_INPUT_INPUTDISPATCHER_TOUCHSTATE_H
-
-#include "Monitor.h"
-#include "TouchedWindow.h"
-
-namespace android {
-
-class InputWindowHandle;
-
-namespace inputdispatcher {
-
-struct TouchState {
- bool down;
- bool split;
- int32_t deviceId; // id of the device that is currently down, others are rejected
- uint32_t source; // source of the device that is current down, others are rejected
- int32_t displayId; // id to the display that currently has a touch, others are rejected
- std::vector<TouchedWindow> windows;
-
- // This collects the portal windows that the touch has gone through. Each portal window
- // targets a display (embedded display for most cases). With this info, we can add the
- // monitoring channels of the displays touched.
- std::vector<sp<android::InputWindowHandle>> portalWindows;
-
- std::vector<TouchedMonitor> gestureMonitors;
-
- TouchState();
- ~TouchState();
- void reset();
- void copyFrom(const TouchState& other);
- void addOrUpdateWindow(const sp<android::InputWindowHandle>& windowHandle, int32_t targetFlags,
- BitSet32 pointerIds);
- void addPortalWindow(const sp<android::InputWindowHandle>& windowHandle);
- void addGestureMonitors(const std::vector<TouchedMonitor>& monitors);
- void removeWindow(const sp<android::InputWindowHandle>& windowHandle);
- void removeWindowByToken(const sp<IBinder>& token);
- void filterNonAsIsTouchWindows();
- void filterNonMonitors();
- sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
- bool isSlippery() const;
-};
-
-} // namespace inputdispatcher
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_TOUCHSTATE_H
diff --git a/services/inputflinger/dispatcher/TouchedWindow.h b/services/inputflinger/dispatcher/TouchedWindow.h
deleted file mode 100644
index 8713aa3f56..0000000000
--- a/services/inputflinger/dispatcher/TouchedWindow.h
+++ /dev/null
@@ -1,36 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_TOUCHEDWINDOW_H
-#define _UI_INPUT_INPUTDISPATCHER_TOUCHEDWINDOW_H
-
-namespace android {
-
-class InputWindowHandle;
-
-namespace inputdispatcher {
-
-// Focus tracking for touch.
-struct TouchedWindow {
- sp<android::InputWindowHandle> windowHandle;
- int32_t targetFlags;
- BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set
-};
-
-} // namespace inputdispatcher
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_TOUCHEDWINDOW_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherConfiguration.h b/services/inputflinger/dispatcher/include/InputDispatcherConfiguration.h
deleted file mode 100644
index 00abf47cd2..0000000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherConfiguration.h
+++ /dev/null
@@ -1,44 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERCONFIGURATION_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERCONFIGURATION_H
-
-#include <utils/Timers.h>
-
-namespace android {
-
-/*
- * Input dispatcher configuration.
- *
- * Specifies various options that modify the behavior of the input dispatcher.
- * The values provided here are merely defaults. The actual values will come from ViewConfiguration
- * and are passed into the dispatcher during initialization.
- */
-struct InputDispatcherConfiguration {
- // The key repeat initial timeout.
- nsecs_t keyRepeatTimeout;
-
- // The key repeat inter-key delay.
- nsecs_t keyRepeatDelay;
-
- InputDispatcherConfiguration()
- : keyRepeatTimeout(500 * 1000000LL), keyRepeatDelay(50 * 1000000LL) {}
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERCONFIGURATION_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherFactory.h b/services/inputflinger/dispatcher/include/InputDispatcherFactory.h
deleted file mode 100644
index a359557f80..0000000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherFactory.h
+++ /dev/null
@@ -1,33 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERFACTORY_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERFACTORY_H
-
-#include <utils/RefBase.h>
-
-#include "InputDispatcherInterface.h"
-#include "InputDispatcherPolicyInterface.h"
-
-namespace android {
-
-// This factory method is used to encapsulate implementation details in internal header files.
-sp<InputDispatcherInterface> createInputDispatcher(
- const sp<InputDispatcherPolicyInterface>& policy);
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERFACTORY_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
deleted file mode 100644
index 9329ca664e..0000000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ /dev/null
@@ -1,158 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
-
-#include <InputListener.h>
-#include <input/ISetInputWindowsListener.h>
-
-namespace android {
-
-class InputApplicationHandle;
-class InputChannel;
-class InputWindowHandle;
-
-/*
- * Constants used to report the outcome of input event injection.
- */
-enum {
- /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */
- INPUT_EVENT_INJECTION_PENDING = -1,
-
- /* Injection succeeded. */
- INPUT_EVENT_INJECTION_SUCCEEDED = 0,
-
- /* Injection failed because the injector did not have permission to inject
- * into the application with input focus. */
- INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,
-
- /* Injection failed because there were no available input targets. */
- INPUT_EVENT_INJECTION_FAILED = 2,
-
- /* Injection failed due to a timeout. */
- INPUT_EVENT_INJECTION_TIMED_OUT = 3
-};
-
-/* Notifies the system about input events generated by the input reader.
- * The dispatcher is expected to be mostly asynchronous. */
-class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface {
-protected:
- InputDispatcherInterface() {}
- virtual ~InputDispatcherInterface() {}
-
-public:
- /* Dumps the state of the input dispatcher.
- *
- * This method may be called on any thread (usually by the input manager). */
- virtual void dump(std::string& dump) = 0;
-
- /* Called by the heatbeat to ensures that the dispatcher has not deadlocked. */
- virtual void monitor() = 0;
-
- /* Runs a single iteration of the dispatch loop.
- * Nominally processes one queued event, a timeout, or a response from an input consumer.
- *
- * This method should only be called on the input dispatcher thread.
- */
- virtual void dispatchOnce() = 0;
-
- /* Injects an input event and optionally waits for sync.
- * The synchronization mode determines whether the method blocks while waiting for
- * input injection to proceed.
- * Returns one of the INPUT_EVENT_INJECTION_XXX constants.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid,
- int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
- uint32_t policyFlags) = 0;
-
- /* Sets the list of input windows.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void setInputWindows(
- const std::vector<sp<InputWindowHandle> >& inputWindowHandles, int32_t displayId,
- const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) = 0;
-
- /* Sets the focused application on the given display.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void setFocusedApplication(
- int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
-
- /* Sets the focused display.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void setFocusedDisplay(int32_t displayId) = 0;
-
- /* Sets the input dispatching mode.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
-
- /* Sets whether input event filtering is enabled.
- * When enabled, incoming input events are sent to the policy's filterInputEvent
- * method instead of being dispatched. The filter is expected to use
- * injectInputEvent to inject the events it would like to have dispatched.
- * It should include POLICY_FLAG_FILTERED in the policy flags during injection.
- */
- virtual void setInputFilterEnabled(bool enabled) = 0;
-
- /* Transfers touch focus from one window to another window.
- *
- * Returns true on success. False if the window did not actually have touch focus.
- */
- virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
-
- /* Registers input channels that may be used as targets for input events.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- int32_t displayId) = 0;
-
- /* Registers input channels to be used to monitor input events.
- *
- * Each monitor must target a specific display and will only receive input events sent to that
- * display. If the monitor is a gesture monitor, it will only receive pointer events on the
- * targeted display.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel, int32_t displayId,
- bool gestureMonitor) = 0;
-
- /* Unregister input channels that will no longer receive input events.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
-
- /* Allows an input monitor steal the current pointer stream away from normal input windows.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual status_t pilferPointers(const sp<IBinder>& token) = 0;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
deleted file mode 100644
index 4214488f04..0000000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ /dev/null
@@ -1,123 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERPOLICYINTERFACE_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERPOLICYINTERFACE_H
-
-#include "InputDispatcherConfiguration.h"
-
-#include <binder/IBinder.h>
-#include <input/Input.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-class InputApplicationHandle;
-
-/*
- * Input dispatcher policy interface.
- *
- * The input reader policy is used by the input reader to interact with the Window Manager
- * and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI. This interface is also mocked in the unit tests.
- */
-class InputDispatcherPolicyInterface : public virtual RefBase {
-protected:
- InputDispatcherPolicyInterface() {}
- virtual ~InputDispatcherPolicyInterface() {}
-
-public:
- /* Notifies the system that a configuration change has occurred. */
- virtual void notifyConfigurationChanged(nsecs_t when) = 0;
-
- /* Notifies the system that an application is not responding.
- * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
- virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<IBinder>& token, const std::string& reason) = 0;
-
- /* Notifies the system that an input channel is unrecoverably broken. */
- virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
- virtual void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) = 0;
-
- /* Gets the input dispatcher configuration. */
- virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
-
- /* Filters an input event.
- * Return true to dispatch the event unmodified, false to consume the event.
- * A filter can also transform and inject events later by passing POLICY_FLAG_FILTERED
- * to injectInputEvent.
- */
- virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;
-
- /* Intercepts a key event immediately before queueing it.
- * The policy can use this method as an opportunity to perform power management functions
- * and early event preprocessing such as updating policy flags.
- *
- * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
- * should be dispatched to applications.
- */
- virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
-
- /* Intercepts a touch, trackball or other motion event before queueing it.
- * The policy can use this method as an opportunity to perform power management functions
- * and early event preprocessing such as updating policy flags.
- *
- * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
- * should be dispatched to applications.
- */
- virtual void interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
- uint32_t& policyFlags) = 0;
-
- /* Allows the policy a chance to intercept a key before dispatching. */
- virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token,
- const KeyEvent* keyEvent,
- uint32_t policyFlags) = 0;
-
- /* Allows the policy a chance to perform default processing for an unhandled key.
- * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
- virtual bool dispatchUnhandledKey(const sp<IBinder>& token, const KeyEvent* keyEvent,
- uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
-
- /* Notifies the policy about switch events.
- */
- virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
- uint32_t policyFlags) = 0;
-
- /* Poke user activity for an event dispatched to a window. */
- virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
-
- /* Checks whether a given application pid/uid has permission to inject input events
- * into other applications.
- *
- * This method is special in that its implementation promises to be non-reentrant and
- * is safe to call while holding other locks. (Most other methods make no such guarantees!)
- */
- virtual bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid,
- int32_t injectorUid) = 0;
-
- /* Notifies the policy that a pointer down event has occurred outside the current focused
- * window.
- *
- * The touchedToken passed as an argument is the window that received the input event.
- */
- virtual void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) = 0;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERPOLICYINTERFACE_H
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherThread.h b/services/inputflinger/dispatcher/include/InputDispatcherThread.h
deleted file mode 100644
index 2604959656..0000000000
--- a/services/inputflinger/dispatcher/include/InputDispatcherThread.h
+++ /dev/null
@@ -1,41 +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.
- */
-
-#ifndef _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERTHREAD_H
-#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERTHREAD_H
-
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class InputDispatcherInterface;
-
-/* Enqueues and dispatches input events, endlessly. */
-class InputDispatcherThread : public Thread {
-public:
- explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
- ~InputDispatcherThread();
-
-private:
- virtual bool threadLoop();
-
- sp<InputDispatcherInterface> mDispatcher;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERTHREAD_H
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index 683c05d8a0..2f046c3527 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -127,10 +127,10 @@ input_device_identifier_t* InputDriver::createDeviceIdentifier(
input_bus_t bus, const char* uniqueId) {
auto identifier = new ::input_device_identifier {
.name = name,
- .uniqueId = uniqueId,
- .bus = bus,
- .vendorId = vendorId,
.productId = productId,
+ .vendorId = vendorId,
+ .bus = bus,
+ .uniqueId = uniqueId,
};
// TODO: store this identifier somewhere
return identifier;
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index d8b352cbc6..973b4f92fa 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -42,7 +42,6 @@ public:
virtual status_t dump(int fd, const Vector<String16>& args);
void setInputWindows(const std::vector<InputWindowInfo>&,
const sp<ISetInputWindowsListener>&) {}
- void transferTouchFocus(const sp<IBinder>&, const sp<IBinder>&) {}
void registerInputChannel(const sp<InputChannel>&) {}
void unregisterInputChannel(const sp<InputChannel>&) {}
diff --git a/services/inputflinger/reporter/InputReporterInterface.h b/services/inputflinger/include/InputReporterInterface.h
index e5d360609f..906d7f25f2 100644
--- a/services/inputflinger/reporter/InputReporterInterface.h
+++ b/services/inputflinger/include/InputReporterInterface.h
@@ -27,7 +27,7 @@ namespace android {
*/
class InputReporterInterface : public virtual RefBase {
protected:
- virtual ~InputReporterInterface() {}
+ virtual ~InputReporterInterface() { }
public:
// Report a key that was not handled by the system or apps.
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
deleted file mode 100644
index 4e97397e2b..0000000000
--- a/services/inputflinger/reader/Android.bp
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-cc_library_headers {
- name: "libinputreader_headers",
- export_include_dirs: [
- "include",
- "mapper",
- "mapper/accumulator",
- ],
-}
-
-cc_library_shared {
- name: "libinputreader",
- defaults: ["inputflinger_defaults"],
-
- srcs: [
- "EventHub.cpp",
- "InputDevice.cpp",
- "mapper/accumulator/CursorButtonAccumulator.cpp",
- "mapper/accumulator/CursorScrollAccumulator.cpp",
- "mapper/accumulator/SingleTouchMotionAccumulator.cpp",
- "mapper/accumulator/TouchButtonAccumulator.cpp",
- "mapper/CursorInputMapper.cpp",
- "mapper/ExternalStylusInputMapper.cpp",
- "mapper/InputMapper.cpp",
- "mapper/JoystickInputMapper.cpp",
- "mapper/KeyboardInputMapper.cpp",
- "mapper/MultiTouchInputMapper.cpp",
- "mapper/RotaryEncoderInputMapper.cpp",
- "mapper/SingleTouchInputMapper.cpp",
- "mapper/SwitchInputMapper.cpp",
- "mapper/TouchInputMapper.cpp",
- "mapper/VibratorInputMapper.cpp",
- "InputReader.cpp",
- "InputReaderFactory.cpp",
- "TouchVideoDevice.cpp",
- ],
-
- shared_libs: [
- "libbase",
- "libinputflinger_base",
- "libcrypto",
- "libcutils",
- "libinput",
- "liblog",
- "libui",
- "libutils",
- "libhardware_legacy",
- "libstatslog",
- ],
-
- header_libs: [
- "libinputflinger_headers",
- "libinputreader_headers",
- ],
-
- export_header_lib_headers: [
- "libinputflinger_headers",
- ],
-}
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
deleted file mode 100644
index d0613b0c69..0000000000
--- a/services/inputflinger/reader/InputDevice.cpp
+++ /dev/null
@@ -1,338 +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 "Macros.h"
-
-#include "InputDevice.h"
-
-#include "InputMapper.h"
-
-namespace android {
-
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
- int32_t controllerNumber, const InputDeviceIdentifier& identifier,
- uint32_t classes)
- : mContext(context),
- mId(id),
- mGeneration(generation),
- mControllerNumber(controllerNumber),
- mIdentifier(identifier),
- mClasses(classes),
- mSources(0),
- mIsExternal(false),
- mHasMic(false),
- mDropUntilNextSync(false) {}
-
-InputDevice::~InputDevice() {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- delete mMappers[i];
- }
- mMappers.clear();
-}
-
-bool InputDevice::isEnabled() {
- return getEventHub()->isDeviceEnabled(mId);
-}
-
-void InputDevice::setEnabled(bool enabled, nsecs_t when) {
- if (isEnabled() == enabled) {
- return;
- }
-
- if (enabled) {
- getEventHub()->enableDevice(mId);
- reset(when);
- } else {
- reset(when);
- getEventHub()->disableDevice(mId);
- }
- // Must change generation to flag this device as changed
- bumpGeneration();
-}
-
-void InputDevice::dump(std::string& dump) {
- InputDeviceInfo deviceInfo;
- getDeviceInfo(&deviceInfo);
-
- dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
- deviceInfo.getDisplayName().c_str());
- dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
- dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
- dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
- if (mAssociatedDisplayPort) {
- dump += StringPrintf("%" PRIu8 "\n", *mAssociatedDisplayPort);
- } else {
- dump += "<none>\n";
- }
- dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
- dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
- dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
-
- const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
- if (!ranges.empty()) {
- dump += INDENT2 "Motion Ranges:\n";
- for (size_t i = 0; i < ranges.size(); i++) {
- const InputDeviceInfo::MotionRange& range = ranges[i];
- const char* label = getAxisLabel(range.axis);
- char name[32];
- if (label) {
- strncpy(name, label, sizeof(name));
- name[sizeof(name) - 1] = '\0';
- } else {
- snprintf(name, sizeof(name), "%d", range.axis);
- }
- dump += StringPrintf(INDENT3
- "%s: source=0x%08x, "
- "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
- name, range.source, range.min, range.max, range.flat, range.fuzz,
- range.resolution);
- }
- }
-
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->dump(dump);
- }
-}
-
-void InputDevice::addMapper(InputMapper* mapper) {
- mMappers.push_back(mapper);
-}
-
-void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) {
- mSources = 0;
-
- if (!isIgnored()) {
- if (!changes) { // first time only
- mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
- if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
- sp<KeyCharacterMap> keyboardLayout =
- mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
- if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
- bumpGeneration();
- }
- }
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
- if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
- std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
- if (mAlias != alias) {
- mAlias = alias;
- bumpGeneration();
- }
- }
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
- ssize_t index = config->disabledDevices.indexOf(mId);
- bool enabled = index < 0;
- setEnabled(enabled, when);
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- // In most situations, no port will be specified.
- mAssociatedDisplayPort = std::nullopt;
- // Find the display port that corresponds to the current input port.
- const std::string& inputPort = mIdentifier.location;
- if (!inputPort.empty()) {
- const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
- const auto& displayPort = ports.find(inputPort);
- if (displayPort != ports.end()) {
- mAssociatedDisplayPort = std::make_optional(displayPort->second);
- }
- }
- }
-
- for (InputMapper* mapper : mMappers) {
- mapper->configure(when, config, changes);
- mSources |= mapper->getSources();
- }
- }
-}
-
-void InputDevice::reset(nsecs_t when) {
- for (InputMapper* mapper : mMappers) {
- mapper->reset(when);
- }
-
- mContext->updateGlobalMetaState();
-
- notifyReset(when);
-}
-
-void InputDevice::process(const RawEvent* rawEvents, size_t count) {
- // Process all of the events in order for each mapper.
- // We cannot simply ask each mapper to process them in bulk because mappers may
- // have side-effects that must be interleaved. For example, joystick movement events and
- // gamepad button presses are handled by different mappers but they should be dispatched
- // in the order received.
- for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
-#if DEBUG_RAW_EVENTS
- ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
- rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);
-#endif
-
- if (mDropUntilNextSync) {
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- mDropUntilNextSync = false;
-#if DEBUG_RAW_EVENTS
- ALOGD("Recovered from input event buffer overrun.");
-#endif
- } else {
-#if DEBUG_RAW_EVENTS
- ALOGD("Dropped input event while waiting for next input sync.");
-#endif
- }
- } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
- ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
- mDropUntilNextSync = true;
- reset(rawEvent->when);
- } else {
- for (InputMapper* mapper : mMappers) {
- mapper->process(rawEvent);
- }
- }
- --count;
- }
-}
-
-void InputDevice::timeoutExpired(nsecs_t when) {
- for (InputMapper* mapper : mMappers) {
- mapper->timeoutExpired(when);
- }
-}
-
-void InputDevice::updateExternalStylusState(const StylusState& state) {
- for (InputMapper* mapper : mMappers) {
- mapper->updateExternalStylusState(state);
- }
-}
-
-void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
- outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal,
- mHasMic);
- for (InputMapper* mapper : mMappers) {
- mapper->populateDeviceInfo(outDeviceInfo);
- }
-}
-
-int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- return getState(sourceMask, keyCode, &InputMapper::getKeyCodeState);
-}
-
-int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- return getState(sourceMask, scanCode, &InputMapper::getScanCodeState);
-}
-
-int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return getState(sourceMask, switchCode, &InputMapper::getSwitchState);
-}
-
-int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
- int32_t result = AKEY_STATE_UNKNOWN;
- for (InputMapper* mapper : mMappers) {
- if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
- // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
- // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
- int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
- if (currentResult >= AKEY_STATE_DOWN) {
- return currentResult;
- } else if (currentResult == AKEY_STATE_UP) {
- result = currentResult;
- }
- }
- }
- return result;
-}
-
-bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- bool result = false;
- for (InputMapper* mapper : mMappers) {
- if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
- result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
- }
- }
- return result;
-}
-
-void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
- int32_t token) {
- for (InputMapper* mapper : mMappers) {
- mapper->vibrate(pattern, patternSize, repeat, token);
- }
-}
-
-void InputDevice::cancelVibrate(int32_t token) {
- for (InputMapper* mapper : mMappers) {
- mapper->cancelVibrate(token);
- }
-}
-
-void InputDevice::cancelTouch(nsecs_t when) {
- for (InputMapper* mapper : mMappers) {
- mapper->cancelTouch(when);
- }
-}
-
-int32_t InputDevice::getMetaState() {
- int32_t result = 0;
- for (InputMapper* mapper : mMappers) {
- result |= mapper->getMetaState();
- }
- return result;
-}
-
-void InputDevice::updateMetaState(int32_t keyCode) {
- for (InputMapper* mapper : mMappers) {
- mapper->updateMetaState(keyCode);
- }
-}
-
-void InputDevice::fadePointer() {
- for (InputMapper* mapper : mMappers) {
- mapper->fadePointer();
- }
-}
-
-void InputDevice::bumpGeneration() {
- mGeneration = mContext->bumpGeneration();
-}
-
-void InputDevice::notifyReset(nsecs_t when) {
- NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
- mContext->getListener()->notifyDeviceReset(&args);
-}
-
-std::optional<int32_t> InputDevice::getAssociatedDisplay() {
- for (InputMapper* mapper : mMappers) {
- std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay();
- if (associatedDisplayId) {
- return associatedDisplayId;
- }
- }
-
- return std::nullopt;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
deleted file mode 100644
index 27cbf192d3..0000000000
--- a/services/inputflinger/reader/InputReader.cpp
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "Macros.h"
-
-#include "InputReader.h"
-
-#include "CursorInputMapper.h"
-#include "ExternalStylusInputMapper.h"
-#include "InputReaderContext.h"
-#include "JoystickInputMapper.h"
-#include "KeyboardInputMapper.h"
-#include "MultiTouchInputMapper.h"
-#include "RotaryEncoderInputMapper.h"
-#include "SingleTouchInputMapper.h"
-#include "SwitchInputMapper.h"
-#include "VibratorInputMapper.h"
-
-#include <errno.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <math.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <log/log.h>
-
-#include <android-base/stringprintf.h>
-#include <input/Keyboard.h>
-#include <input/VirtualKeyMap.h>
-
-
-using android::base::StringPrintf;
-
-namespace android {
-
-InputReader::InputReader(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener)
- : mContext(this),
- mEventHub(eventHub),
- mPolicy(policy),
- mNextSequenceNum(1),
- mGlobalMetaState(0),
- mGeneration(1),
- mDisableVirtualKeysTimeout(LLONG_MIN),
- mNextTimeout(LLONG_MAX),
- mConfigurationChangesToRefresh(0) {
- mQueuedListener = new QueuedInputListener(listener);
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- refreshConfigurationLocked(0);
- updateGlobalMetaStateLocked();
- } // release lock
-}
-
-InputReader::~InputReader() {
- for (size_t i = 0; i < mDevices.size(); i++) {
- delete mDevices.valueAt(i);
- }
-}
-
-void InputReader::loopOnce() {
- int32_t oldGeneration;
- int32_t timeoutMillis;
- bool inputDevicesChanged = false;
- std::vector<InputDeviceInfo> inputDevices;
- { // acquire lock
- AutoMutex _l(mLock);
-
- oldGeneration = mGeneration;
- timeoutMillis = -1;
-
- uint32_t changes = mConfigurationChangesToRefresh;
- if (changes) {
- mConfigurationChangesToRefresh = 0;
- timeoutMillis = 0;
- refreshConfigurationLocked(changes);
- } else if (mNextTimeout != LLONG_MAX) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
- }
- } // release lock
-
- size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
-
- { // acquire lock
- AutoMutex _l(mLock);
- mReaderIsAliveCondition.broadcast();
-
- if (count) {
- processEventsLocked(mEventBuffer, count);
- }
-
- if (mNextTimeout != LLONG_MAX) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- if (now >= mNextTimeout) {
-#if DEBUG_RAW_EVENTS
- ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
-#endif
- mNextTimeout = LLONG_MAX;
- timeoutExpiredLocked(now);
- }
- }
-
- if (oldGeneration != mGeneration) {
- inputDevicesChanged = true;
- getInputDevicesLocked(inputDevices);
- }
- } // release lock
-
- // Send out a message that the describes the changed input devices.
- if (inputDevicesChanged) {
- mPolicy->notifyInputDevicesChanged(inputDevices);
- }
-
- // Flush queued events out to the listener.
- // This must happen outside of the lock because the listener could potentially call
- // back into the InputReader's methods, such as getScanCodeState, or become blocked
- // on another thread similarly waiting to acquire the InputReader lock thereby
- // resulting in a deadlock. This situation is actually quite plausible because the
- // listener is actually the input dispatcher, which calls into the window manager,
- // which occasionally calls into the input reader.
- mQueuedListener->flush();
-}
-
-void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
- for (const RawEvent* rawEvent = rawEvents; count;) {
- int32_t type = rawEvent->type;
- size_t batchSize = 1;
- if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
- int32_t deviceId = rawEvent->deviceId;
- while (batchSize < count) {
- if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT ||
- rawEvent[batchSize].deviceId != deviceId) {
- break;
- }
- batchSize += 1;
- }
-#if DEBUG_RAW_EVENTS
- ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
-#endif
- processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
- } else {
- switch (rawEvent->type) {
- case EventHubInterface::DEVICE_ADDED:
- addDeviceLocked(rawEvent->when, rawEvent->deviceId);
- break;
- case EventHubInterface::DEVICE_REMOVED:
- removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
- break;
- case EventHubInterface::FINISHED_DEVICE_SCAN:
- handleConfigurationChangedLocked(rawEvent->when);
- break;
- default:
- ALOG_ASSERT(false); // can't happen
- break;
- }
- }
- count -= batchSize;
- rawEvent += batchSize;
- }
-}
-
-void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
- return;
- }
-
- InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
- uint32_t classes = mEventHub->getDeviceClasses(deviceId);
- int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
-
- InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
- device->configure(when, &mConfig, 0);
- device->reset(when);
-
- if (device->isIgnored()) {
- ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
- identifier.name.c_str());
- } else {
- ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, identifier.name.c_str(),
- device->getSources());
- }
-
- mDevices.add(deviceId, device);
- bumpGenerationLocked();
-
- if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
- notifyExternalStylusPresenceChanged();
- }
-}
-
-void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
- InputDevice* device = nullptr;
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex < 0) {
- ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
- return;
- }
-
- device = mDevices.valueAt(deviceIndex);
- mDevices.removeItemsAt(deviceIndex, 1);
- bumpGenerationLocked();
-
- if (device->isIgnored()) {
- ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)", device->getId(),
- device->getName().c_str());
- } else {
- ALOGI("Device removed: id=%d, name='%s', sources=0x%08x", device->getId(),
- device->getName().c_str(), device->getSources());
- }
-
- if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
- notifyExternalStylusPresenceChanged();
- }
-
- device->reset(when);
- delete device;
-}
-
-InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier,
- uint32_t classes) {
- InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
- controllerNumber, identifier, classes);
-
- // External devices.
- if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
- device->setExternal(true);
- }
-
- // Devices with mics.
- if (classes & INPUT_DEVICE_CLASS_MIC) {
- device->setMic(true);
- }
-
- // Switch-like devices.
- if (classes & INPUT_DEVICE_CLASS_SWITCH) {
- device->addMapper(new SwitchInputMapper(device));
- }
-
- // Scroll wheel-like devices.
- if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
- device->addMapper(new RotaryEncoderInputMapper(device));
- }
-
- // Vibrator-like devices.
- if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
- device->addMapper(new VibratorInputMapper(device));
- }
-
- // Keyboard-like devices.
- uint32_t keyboardSource = 0;
- int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
- if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
- keyboardSource |= AINPUT_SOURCE_KEYBOARD;
- }
- if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
- keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
- }
- if (classes & INPUT_DEVICE_CLASS_DPAD) {
- keyboardSource |= AINPUT_SOURCE_DPAD;
- }
- if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
- keyboardSource |= AINPUT_SOURCE_GAMEPAD;
- }
-
- if (keyboardSource != 0) {
- device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
- }
-
- // Cursor-like devices.
- if (classes & INPUT_DEVICE_CLASS_CURSOR) {
- device->addMapper(new CursorInputMapper(device));
- }
-
- // Touchscreens and touchpad devices.
- if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
- device->addMapper(new MultiTouchInputMapper(device));
- } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
- device->addMapper(new SingleTouchInputMapper(device));
- }
-
- // Joystick-like devices.
- if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
- device->addMapper(new JoystickInputMapper(device));
- }
-
- // External stylus-like devices.
- if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
- device->addMapper(new ExternalStylusInputMapper(device));
- }
-
- return device;
-}
-
-void InputReader::processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents,
- size_t count) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex < 0) {
- ALOGW("Discarding event for unknown deviceId %d.", deviceId);
- return;
- }
-
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (device->isIgnored()) {
- // ALOGD("Discarding event for ignored deviceId %d.", deviceId);
- return;
- }
-
- device->process(rawEvents, count);
-}
-
-void InputReader::timeoutExpiredLocked(nsecs_t when) {
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (!device->isIgnored()) {
- device->timeoutExpired(when);
- }
- }
-}
-
-void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
- // Reset global meta state because it depends on the list of all configured devices.
- updateGlobalMetaStateLocked();
-
- // Enqueue configuration changed.
- NotifyConfigurationChangedArgs args(mContext.getNextSequenceNum(), when);
- mQueuedListener->notifyConfigurationChanged(&args);
-}
-
-void InputReader::refreshConfigurationLocked(uint32_t changes) {
- mPolicy->getReaderConfiguration(&mConfig);
- mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
-
- if (changes) {
- ALOGI("Reconfiguring input devices. changes=0x%08x", changes);
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-
- if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
- mEventHub->requestReopenDevices();
- } else {
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- device->configure(now, &mConfig, changes);
- }
- }
- }
-}
-
-void InputReader::updateGlobalMetaStateLocked() {
- mGlobalMetaState = 0;
-
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- mGlobalMetaState |= device->getMetaState();
- }
-}
-
-int32_t InputReader::getGlobalMetaStateLocked() {
- return mGlobalMetaState;
-}
-
-void InputReader::notifyExternalStylusPresenceChanged() {
- refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
-}
-
-void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) {
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
- InputDeviceInfo info;
- device->getDeviceInfo(&info);
- outDevices.push_back(info);
- }
- }
-}
-
-void InputReader::dispatchExternalStylusState(const StylusState& state) {
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- device->updateExternalStylusState(state);
- }
-}
-
-void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
- mDisableVirtualKeysTimeout = time;
-}
-
-bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now, InputDevice* device, int32_t keyCode,
- int32_t scanCode) {
- if (now < mDisableVirtualKeysTimeout) {
- ALOGI("Dropping virtual key from device %s because virtual keys are "
- "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
- device->getName().c_str(), (mDisableVirtualKeysTimeout - now) * 0.000001, keyCode,
- scanCode);
- return true;
- } else {
- return false;
- }
-}
-
-void InputReader::fadePointerLocked() {
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- device->fadePointer();
- }
-}
-
-void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
- if (when < mNextTimeout) {
- mNextTimeout = when;
- mEventHub->wake();
- }
-}
-
-int32_t InputReader::bumpGenerationLocked() {
- return ++mGeneration;
-}
-
-void InputReader::getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) {
- AutoMutex _l(mLock);
- getInputDevicesLocked(outInputDevices);
-}
-
-void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) {
- outInputDevices.clear();
-
- size_t numDevices = mDevices.size();
- for (size_t i = 0; i < numDevices; i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (!device->isIgnored()) {
- InputDeviceInfo info;
- device->getDeviceInfo(&info);
- outInputDevices.push_back(info);
- }
- }
-}
-
-int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) {
- AutoMutex _l(mLock);
-
- return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
-}
-
-int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode) {
- AutoMutex _l(mLock);
-
- return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
-}
-
-int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
- AutoMutex _l(mLock);
-
- return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
-}
-
-int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
- GetStateFunc getStateFunc) {
- int32_t result = AKEY_STATE_UNKNOWN;
- if (deviceId >= 0) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = (device->*getStateFunc)(sourceMask, code);
- }
- }
- } else {
- size_t numDevices = mDevices.size();
- for (size_t i = 0; i < numDevices; i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
- // value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
- int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
- if (currentResult >= AKEY_STATE_DOWN) {
- return currentResult;
- } else if (currentResult == AKEY_STATE_UP) {
- result = currentResult;
- }
- }
- }
- }
- return result;
-}
-
-void InputReader::toggleCapsLockState(int32_t deviceId) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex < 0) {
- ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
- return;
- }
-
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (device->isIgnored()) {
- return;
- }
-
- device->updateMetaState(AKEYCODE_CAPS_LOCK);
-}
-
-bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- AutoMutex _l(mLock);
-
- memset(outFlags, 0, numCodes);
- return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
-}
-
-bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
- size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) {
- bool result = false;
- if (deviceId >= 0) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = device->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
- }
- }
- } else {
- size_t numDevices = mDevices.size();
- for (size_t i = 0; i < numDevices; i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result |= device->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
- }
- }
- }
- return result;
-}
-
-void InputReader::requestRefreshConfiguration(uint32_t changes) {
- AutoMutex _l(mLock);
-
- if (changes) {
- bool needWake = !mConfigurationChangesToRefresh;
- mConfigurationChangesToRefresh |= changes;
-
- if (needWake) {
- mEventHub->wake();
- }
- }
-}
-
-void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
- ssize_t repeat, int32_t token) {
- AutoMutex _l(mLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- device->vibrate(pattern, patternSize, repeat, token);
- }
-}
-
-void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
- AutoMutex _l(mLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- device->cancelVibrate(token);
- }
-}
-
-bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
- AutoMutex _l(mLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- return device->isEnabled();
- }
- ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
- return false;
-}
-
-bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) {
- AutoMutex _l(mLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex < 0) {
- ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
- return false;
- }
-
- InputDevice* device = mDevices.valueAt(deviceIndex);
- std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplay();
- // No associated display. By default, can dispatch to all displays.
- if (!associatedDisplayId) {
- return true;
- }
-
- if (*associatedDisplayId == ADISPLAY_ID_NONE) {
- ALOGW("Device has associated, but no associated display id.");
- return true;
- }
-
- return *associatedDisplayId == displayId;
-}
-
-void InputReader::dump(std::string& dump) {
- AutoMutex _l(mLock);
-
- mEventHub->dump(dump);
- dump += "\n";
-
- dump += "Input Reader State:\n";
-
- for (size_t i = 0; i < mDevices.size(); i++) {
- mDevices.valueAt(i)->dump(dump);
- }
-
- dump += INDENT "Configuration:\n";
- dump += INDENT2 "ExcludedDeviceNames: [";
- for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
- if (i != 0) {
- dump += ", ";
- }
- dump += mConfig.excludedDeviceNames[i];
- }
- dump += "]\n";
- dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
- mConfig.virtualKeyQuietTime * 0.000001f);
-
- dump += StringPrintf(INDENT2 "PointerVelocityControlParameters: "
- "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, "
- "acceleration=%0.3f\n",
- mConfig.pointerVelocityControlParameters.scale,
- mConfig.pointerVelocityControlParameters.lowThreshold,
- mConfig.pointerVelocityControlParameters.highThreshold,
- mConfig.pointerVelocityControlParameters.acceleration);
-
- dump += StringPrintf(INDENT2 "WheelVelocityControlParameters: "
- "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, "
- "acceleration=%0.3f\n",
- mConfig.wheelVelocityControlParameters.scale,
- mConfig.wheelVelocityControlParameters.lowThreshold,
- mConfig.wheelVelocityControlParameters.highThreshold,
- mConfig.wheelVelocityControlParameters.acceleration);
-
- dump += StringPrintf(INDENT2 "PointerGesture:\n");
- dump += StringPrintf(INDENT3 "Enabled: %s\n", toString(mConfig.pointerGesturesEnabled));
- dump += StringPrintf(INDENT3 "QuietInterval: %0.1fms\n",
- mConfig.pointerGestureQuietInterval * 0.000001f);
- dump += StringPrintf(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
- mConfig.pointerGestureDragMinSwitchSpeed);
- dump += StringPrintf(INDENT3 "TapInterval: %0.1fms\n",
- mConfig.pointerGestureTapInterval * 0.000001f);
- dump += StringPrintf(INDENT3 "TapDragInterval: %0.1fms\n",
- mConfig.pointerGestureTapDragInterval * 0.000001f);
- dump += StringPrintf(INDENT3 "TapSlop: %0.1fpx\n", mConfig.pointerGestureTapSlop);
- dump += StringPrintf(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
- mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
- dump += StringPrintf(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
- mConfig.pointerGestureMultitouchMinDistance);
- dump += StringPrintf(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
- mConfig.pointerGestureSwipeTransitionAngleCosine);
- dump += StringPrintf(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
- mConfig.pointerGestureSwipeMaxWidthRatio);
- dump += StringPrintf(INDENT3 "MovementSpeedRatio: %0.1f\n",
- mConfig.pointerGestureMovementSpeedRatio);
- dump += StringPrintf(INDENT3 "ZoomSpeedRatio: %0.1f\n", mConfig.pointerGestureZoomSpeedRatio);
-
- dump += INDENT3 "Viewports:\n";
- mConfig.dump(dump);
-}
-
-void InputReader::monitor() {
- // Acquire and release the lock to ensure that the reader has not deadlocked.
- mLock.lock();
- mEventHub->wake();
- mReaderIsAliveCondition.wait(mLock);
- mLock.unlock();
-
- // Check the EventHub
- mEventHub->monitor();
-}
-
-// --- InputReader::ContextImpl ---
-
-InputReader::ContextImpl::ContextImpl(InputReader* reader) : mReader(reader) {}
-
-void InputReader::ContextImpl::updateGlobalMetaState() {
- // lock is already held by the input loop
- mReader->updateGlobalMetaStateLocked();
-}
-
-int32_t InputReader::ContextImpl::getGlobalMetaState() {
- // lock is already held by the input loop
- return mReader->getGlobalMetaStateLocked();
-}
-
-void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
- // lock is already held by the input loop
- mReader->disableVirtualKeysUntilLocked(time);
-}
-
-bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now, InputDevice* device,
- int32_t keyCode, int32_t scanCode) {
- // lock is already held by the input loop
- return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
-}
-
-void InputReader::ContextImpl::fadePointer() {
- // lock is already held by the input loop
- mReader->fadePointerLocked();
-}
-
-void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
- // lock is already held by the input loop
- mReader->requestTimeoutAtTimeLocked(when);
-}
-
-int32_t InputReader::ContextImpl::bumpGeneration() {
- // lock is already held by the input loop
- return mReader->bumpGenerationLocked();
-}
-
-void InputReader::ContextImpl::getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) {
- // lock is already held by whatever called refreshConfigurationLocked
- mReader->getExternalStylusDevicesLocked(outDevices);
-}
-
-void InputReader::ContextImpl::dispatchExternalStylusState(const StylusState& state) {
- mReader->dispatchExternalStylusState(state);
-}
-
-InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
- return mReader->mPolicy.get();
-}
-
-InputListenerInterface* InputReader::ContextImpl::getListener() {
- return mReader->mQueuedListener.get();
-}
-
-EventHubInterface* InputReader::ContextImpl::getEventHub() {
- return mReader->mEventHub.get();
-}
-
-uint32_t InputReader::ContextImpl::getNextSequenceNum() {
- return (mReader->mNextSequenceNum)++;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/Macros.h b/services/inputflinger/reader/Macros.h
deleted file mode 100644
index 827e31a1bd..0000000000
--- a/services/inputflinger/reader/Macros.h
+++ /dev/null
@@ -1,84 +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.
- */
-
-#ifndef _UI_INPUTREADER_MACROS_H
-#define _UI_INPUTREADER_MACROS_H
-
-#define LOG_TAG "InputReader"
-
-//#define LOG_NDEBUG 0
-
-// Log debug messages for each raw event received from the EventHub.
-#define DEBUG_RAW_EVENTS 0
-
-// Log debug messages about touch screen filtering hacks.
-#define DEBUG_HACKS 0
-
-// Log debug messages about virtual key processing.
-#define DEBUG_VIRTUAL_KEYS 0
-
-// Log debug messages about pointers.
-#define DEBUG_POINTERS 0
-
-// Log debug messages about pointer assignment calculations.
-#define DEBUG_POINTER_ASSIGNMENT 0
-
-// Log debug messages about gesture detection.
-#define DEBUG_GESTURES 0
-
-// Log debug messages about the vibrator.
-#define DEBUG_VIBRATOR 0
-
-// Log debug messages about fusing stylus data.
-#define DEBUG_STYLUS_FUSION 0
-
-#define INDENT " "
-#define INDENT2 " "
-#define INDENT3 " "
-#define INDENT4 " "
-#define INDENT5 " "
-
-#include <input/Input.h>
-
-namespace android {
-
-// --- Static Functions ---
-
-template <typename T>
-inline static T abs(const T& value) {
- return value < 0 ? -value : value;
-}
-
-template <typename T>
-inline static T min(const T& a, const T& b) {
- return a < b ? a : b;
-}
-
-inline static float avg(float x, float y) {
- return (x + y) / 2;
-}
-
-static inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
- return (sources & sourceMask & ~AINPUT_SOURCE_CLASS_MASK) != 0;
-}
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_MACROS_H \ No newline at end of file
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
deleted file mode 100644
index 57f0b319c8..0000000000
--- a/services/inputflinger/reader/include/InputDevice.h
+++ /dev/null
@@ -1,142 +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.
- */
-
-#ifndef _UI_INPUTREADER_INPUT_DEVICE_H
-#define _UI_INPUTREADER_INPUT_DEVICE_H
-
-#include "EventHub.h"
-#include "InputReaderBase.h"
-#include "InputReaderContext.h"
-
-#include <input/DisplayViewport.h>
-#include <input/InputDevice.h>
-#include <utils/PropertyMap.h>
-
-#include <stdint.h>
-#include <optional>
-#include <vector>
-
-namespace android {
-
-class InputMapper;
-
-/* Represents the state of a single input device. */
-class InputDevice {
-public:
- InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
- int32_t controllerNumber, const InputDeviceIdentifier& identifier,
- uint32_t classes);
- ~InputDevice();
-
- inline InputReaderContext* getContext() { return mContext; }
- inline int32_t getId() const { return mId; }
- inline int32_t getControllerNumber() const { return mControllerNumber; }
- inline int32_t getGeneration() const { return mGeneration; }
- inline const std::string getName() const { return mIdentifier.name; }
- inline const std::string getDescriptor() { return mIdentifier.descriptor; }
- inline uint32_t getClasses() const { return mClasses; }
- inline uint32_t getSources() const { return mSources; }
-
- inline bool isExternal() { return mIsExternal; }
- inline void setExternal(bool external) { mIsExternal = external; }
- inline std::optional<uint8_t> getAssociatedDisplayPort() const {
- return mAssociatedDisplayPort;
- }
-
- inline void setMic(bool hasMic) { mHasMic = hasMic; }
- inline bool hasMic() const { return mHasMic; }
-
- inline bool isIgnored() { return mMappers.empty(); }
-
- bool isEnabled();
- void setEnabled(bool enabled, nsecs_t when);
-
- void dump(std::string& dump);
- void addMapper(InputMapper* mapper);
- void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- void reset(nsecs_t when);
- void process(const RawEvent* rawEvents, size_t count);
- void timeoutExpired(nsecs_t when);
- void updateExternalStylusState(const StylusState& state);
-
- void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
- int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
- int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
- int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
- bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags);
- void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
- void cancelVibrate(int32_t token);
- void cancelTouch(nsecs_t when);
-
- int32_t getMetaState();
- void updateMetaState(int32_t keyCode);
-
- void fadePointer();
-
- void bumpGeneration();
-
- void notifyReset(nsecs_t when);
-
- inline const PropertyMap& getConfiguration() { return mConfiguration; }
- inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
-
- bool hasKey(int32_t code) { return getEventHub()->hasScanCode(mId, code); }
-
- bool hasAbsoluteAxis(int32_t code) {
- RawAbsoluteAxisInfo info;
- getEventHub()->getAbsoluteAxisInfo(mId, code, &info);
- return info.valid;
- }
-
- bool isKeyPressed(int32_t code) {
- return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN;
- }
-
- int32_t getAbsoluteAxisValue(int32_t code) {
- int32_t value;
- getEventHub()->getAbsoluteAxisValue(mId, code, &value);
- return value;
- }
-
- std::optional<int32_t> getAssociatedDisplay();
-
-private:
- InputReaderContext* mContext;
- int32_t mId;
- int32_t mGeneration;
- int32_t mControllerNumber;
- InputDeviceIdentifier mIdentifier;
- std::string mAlias;
- uint32_t mClasses;
-
- std::vector<InputMapper*> mMappers;
-
- uint32_t mSources;
- bool mIsExternal;
- std::optional<uint8_t> mAssociatedDisplayPort;
- bool mHasMic;
- bool mDropUntilNextSync;
-
- typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
- int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
-
- PropertyMap mConfiguration;
-};
-
-} // namespace android
-
-#endif //_UI_INPUTREADER_INPUT_DEVICE_H
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
deleted file mode 100644
index e29c8f219c..0000000000
--- a/services/inputflinger/reader/include/InputReader.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 _UI_INPUTREADER_INPUT_READER_H
-#define _UI_INPUTREADER_INPUT_READER_H
-
-#include "EventHub.h"
-#include "InputListener.h"
-#include "InputReaderBase.h"
-#include "InputReaderContext.h"
-
-#include <utils/BitSet.h>
-#include <utils/Condition.h>
-#include <utils/KeyedVector.h>
-#include <utils/Mutex.h>
-#include <utils/Timers.h>
-
-#include <vector>
-
-namespace android {
-
-class InputDevice;
-class InputMapper;
-struct StylusState;
-
-/* The input reader reads raw event data from the event hub and processes it into input events
- * that it sends to the input listener. Some functions of the input reader, such as early
- * event filtering in low power states, are controlled by a separate policy object.
- *
- * The InputReader owns a collection of InputMappers. Most of the work it does happens
- * on the input reader thread but the InputReader can receive queries from other system
- * components running on arbitrary threads. To keep things manageable, the InputReader
- * uses a single Mutex to guard its state. The Mutex may be held while calling into the
- * EventHub or the InputReaderPolicy but it is never held while calling into the
- * InputListener.
- */
-class InputReader : public InputReaderInterface {
-public:
- InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener);
- virtual ~InputReader();
-
- virtual void dump(std::string& dump);
- virtual void monitor();
-
- virtual void loopOnce();
-
- virtual void getInputDevices(std::vector<InputDeviceInfo>& outInputDevices);
-
- virtual bool isInputDeviceEnabled(int32_t deviceId);
-
- virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode);
- virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode);
- virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw);
-
- virtual void toggleCapsLockState(int32_t deviceId);
-
- virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
-
- virtual void requestRefreshConfiguration(uint32_t changes);
-
- virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
- ssize_t repeat, int32_t token);
- virtual void cancelVibrate(int32_t deviceId, int32_t token);
-
- virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId);
-protected:
- // These members are protected so they can be instrumented by test cases.
- virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier,
- uint32_t classes);
-
- class ContextImpl : public InputReaderContext {
- InputReader* mReader;
-
- public:
- explicit ContextImpl(InputReader* reader);
-
- virtual void updateGlobalMetaState();
- virtual int32_t getGlobalMetaState();
- virtual void disableVirtualKeysUntil(nsecs_t time);
- virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode,
- int32_t scanCode);
- virtual void fadePointer();
- virtual void requestTimeoutAtTime(nsecs_t when);
- virtual int32_t bumpGeneration();
- virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices);
- virtual void dispatchExternalStylusState(const StylusState& outState);
- virtual InputReaderPolicyInterface* getPolicy();
- virtual InputListenerInterface* getListener();
- virtual EventHubInterface* getEventHub();
- virtual uint32_t getNextSequenceNum();
- } mContext;
-
- friend class ContextImpl;
-
-private:
- Mutex mLock;
-
- Condition mReaderIsAliveCondition;
-
- sp<EventHubInterface> mEventHub;
- sp<InputReaderPolicyInterface> mPolicy;
- sp<QueuedInputListener> mQueuedListener;
-
- InputReaderConfiguration mConfig;
-
- // used by InputReaderContext::getNextSequenceNum() as a counter for event sequence numbers
- uint32_t mNextSequenceNum;
-
- // The event queue.
- static const int EVENT_BUFFER_SIZE = 256;
- RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
-
- KeyedVector<int32_t, InputDevice*> mDevices;
-
- // low-level input event decoding and device management
- void processEventsLocked(const RawEvent* rawEvents, size_t count);
-
- void addDeviceLocked(nsecs_t when, int32_t deviceId);
- void removeDeviceLocked(nsecs_t when, int32_t deviceId);
- void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count);
- void timeoutExpiredLocked(nsecs_t when);
-
- void handleConfigurationChangedLocked(nsecs_t when);
-
- int32_t mGlobalMetaState;
- void updateGlobalMetaStateLocked();
- int32_t getGlobalMetaStateLocked();
-
- void notifyExternalStylusPresenceChanged();
- void getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices);
- void dispatchExternalStylusState(const StylusState& state);
-
- void fadePointerLocked();
-
- int32_t mGeneration;
- int32_t bumpGenerationLocked();
-
- void getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices);
-
- nsecs_t mDisableVirtualKeysTimeout;
- void disableVirtualKeysUntilLocked(nsecs_t time);
- bool shouldDropVirtualKeyLocked(nsecs_t now, InputDevice* device, int32_t keyCode,
- int32_t scanCode);
-
- nsecs_t mNextTimeout;
- void requestTimeoutAtTimeLocked(nsecs_t when);
-
- uint32_t mConfigurationChangesToRefresh;
- void refreshConfigurationLocked(uint32_t changes);
-
- // state queries
- typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
- int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
- GetStateFunc getStateFunc);
- bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_INPUT_READER_H
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
deleted file mode 100644
index 3472346d44..0000000000
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ /dev/null
@@ -1,65 +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.
- */
-
-#ifndef _UI_INPUTREADER_INPUT_READER_CONTEXT_H
-#define _UI_INPUTREADER_INPUT_READER_CONTEXT_H
-
-#include <input/InputDevice.h>
-
-#include <vector>
-
-namespace android {
-
-class EventHubInterface;
-class InputDevice;
-class InputListenerInterface;
-class InputMapper;
-class InputReaderPolicyInterface;
-struct StylusState;
-
-/* Internal interface used by individual input devices to access global input device state
- * and parameters maintained by the input reader.
- */
-class InputReaderContext {
-public:
- InputReaderContext() {}
- virtual ~InputReaderContext() {}
-
- virtual void updateGlobalMetaState() = 0;
- virtual int32_t getGlobalMetaState() = 0;
-
- virtual void disableVirtualKeysUntil(nsecs_t time) = 0;
- virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode,
- int32_t scanCode) = 0;
-
- virtual void fadePointer() = 0;
-
- virtual void requestTimeoutAtTime(nsecs_t when) = 0;
- virtual int32_t bumpGeneration() = 0;
-
- virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) = 0;
- virtual void dispatchExternalStylusState(const StylusState& outState) = 0;
-
- virtual InputReaderPolicyInterface* getPolicy() = 0;
- virtual InputListenerInterface* getListener() = 0;
- virtual EventHubInterface* getEventHub() = 0;
-
- virtual uint32_t getNextSequenceNum() = 0;
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_INPUT_READER_CONTEXT_H
diff --git a/services/inputflinger/reader/include/StylusState.h b/services/inputflinger/reader/include/StylusState.h
deleted file mode 100644
index 17f158c9e1..0000000000
--- a/services/inputflinger/reader/include/StylusState.h
+++ /dev/null
@@ -1,53 +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.
- */
-
-#ifndef _UI_INPUTREADER_STYLUS_STATE_H
-#define _UI_INPUTREADER_STYLUS_STATE_H
-
-#include <input/Input.h>
-
-#include <limits.h>
-
-namespace android {
-
-struct StylusState {
- /* Time the stylus event was received. */
- nsecs_t when;
- /* Pressure as reported by the stylus, normalized to the range [0, 1.0]. */
- float pressure;
- /* The state of the stylus buttons as a bitfield (e.g. AMOTION_EVENT_BUTTON_SECONDARY). */
- uint32_t buttons;
- /* Which tool type the stylus is currently using (e.g. AMOTION_EVENT_TOOL_TYPE_ERASER). */
- int32_t toolType;
-
- void copyFrom(const StylusState& other) {
- when = other.when;
- pressure = other.pressure;
- buttons = other.buttons;
- toolType = other.toolType;
- }
-
- void clear() {
- when = LLONG_MAX;
- pressure = 0.f;
- buttons = 0;
- toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
- }
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_STYLUS_STATE_H
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
deleted file mode 100644
index da85fda0e9..0000000000
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ /dev/null
@@ -1,480 +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 "Macros.h"
-
-#include "CursorInputMapper.h"
-
-#include "CursorButtonAccumulator.h"
-#include "CursorScrollAccumulator.h"
-#include "TouchCursorInputMapperCommon.h"
-
-namespace android {
-
-// --- CursorMotionAccumulator ---
-
-CursorMotionAccumulator::CursorMotionAccumulator() {
- clearRelativeAxes();
-}
-
-void CursorMotionAccumulator::reset(InputDevice* device) {
- clearRelativeAxes();
-}
-
-void CursorMotionAccumulator::clearRelativeAxes() {
- mRelX = 0;
- mRelY = 0;
-}
-
-void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_REL) {
- switch (rawEvent->code) {
- case REL_X:
- mRelX = rawEvent->value;
- break;
- case REL_Y:
- mRelY = rawEvent->value;
- break;
- }
- }
-}
-
-void CursorMotionAccumulator::finishSync() {
- clearRelativeAxes();
-}
-
-// --- CursorInputMapper ---
-
-CursorInputMapper::CursorInputMapper(InputDevice* device) : InputMapper(device) {}
-
-CursorInputMapper::~CursorInputMapper() {}
-
-uint32_t CursorInputMapper::getSources() {
- return mSource;
-}
-
-void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- if (mParameters.mode == Parameters::MODE_POINTER) {
- float minX, minY, maxX, maxY;
- if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
- info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
- info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
- }
- } else {
- info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
- info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
- }
- info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
-
- if (mCursorScrollAccumulator.haveRelativeVWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
- }
- if (mCursorScrollAccumulator.haveRelativeHWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
- }
-}
-
-void CursorInputMapper::dump(std::string& dump) {
- dump += INDENT2 "Cursor Input Mapper:\n";
- dumpParameters(dump);
- dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
- dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
- dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
- dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
- dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
- toString(mCursorScrollAccumulator.haveRelativeVWheel()));
- dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
- toString(mCursorScrollAccumulator.haveRelativeHWheel()));
- dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
- dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
- dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
- dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
- dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
- dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
-}
-
-void CursorInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) {
- InputMapper::configure(when, config, changes);
-
- if (!changes) { // first time only
- mCursorScrollAccumulator.configure(getDevice());
-
- // Configure basic parameters.
- configureParameters();
-
- // Configure device mode.
- switch (mParameters.mode) {
- case Parameters::MODE_POINTER_RELATIVE:
- // Should not happen during first time configuration.
- ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
- mParameters.mode = Parameters::MODE_POINTER;
- [[fallthrough]];
- case Parameters::MODE_POINTER:
- mSource = AINPUT_SOURCE_MOUSE;
- mXPrecision = 1.0f;
- mYPrecision = 1.0f;
- mXScale = 1.0f;
- mYScale = 1.0f;
- mPointerController = getPolicy()->obtainPointerController(getDeviceId());
- break;
- case Parameters::MODE_NAVIGATION:
- mSource = AINPUT_SOURCE_TRACKBALL;
- mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
- mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
- mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
- mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
- break;
- }
-
- mVWheelScale = 1.0f;
- mHWheelScale = 1.0f;
- }
-
- if ((!changes && config->pointerCapture) ||
- (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE)) {
- if (config->pointerCapture) {
- if (mParameters.mode == Parameters::MODE_POINTER) {
- mParameters.mode = Parameters::MODE_POINTER_RELATIVE;
- mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
- // Keep PointerController around in order to preserve the pointer position.
- mPointerController->fade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- } else {
- ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
- }
- } else {
- if (mParameters.mode == Parameters::MODE_POINTER_RELATIVE) {
- mParameters.mode = Parameters::MODE_POINTER;
- mSource = AINPUT_SOURCE_MOUSE;
- } else {
- ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
- }
- }
- bumpGeneration();
- if (changes) {
- getDevice()->notifyReset(when);
- }
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
- mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
- mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
- mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- mOrientation = DISPLAY_ORIENTATION_0;
- if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
- std::optional<DisplayViewport> internalViewport =
- config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
- if (internalViewport) {
- mOrientation = internalViewport->orientation;
- }
- }
-
- // Update the PointerController if viewports changed.
- if (mParameters.mode == Parameters::MODE_POINTER) {
- getPolicy()->obtainPointerController(getDeviceId());
- }
- bumpGeneration();
- }
-}
-
-void CursorInputMapper::configureParameters() {
- mParameters.mode = Parameters::MODE_POINTER;
- String8 cursorModeString;
- if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
- if (cursorModeString == "navigation") {
- mParameters.mode = Parameters::MODE_NAVIGATION;
- } else if (cursorModeString != "pointer" && cursorModeString != "default") {
- ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
- }
- }
-
- mParameters.orientationAware = false;
- getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
- mParameters.orientationAware);
-
- mParameters.hasAssociatedDisplay = false;
- if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
- mParameters.hasAssociatedDisplay = true;
- }
-}
-
-void CursorInputMapper::dumpParameters(std::string& dump) {
- dump += INDENT3 "Parameters:\n";
- dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
- toString(mParameters.hasAssociatedDisplay));
-
- switch (mParameters.mode) {
- case Parameters::MODE_POINTER:
- dump += INDENT4 "Mode: pointer\n";
- break;
- case Parameters::MODE_POINTER_RELATIVE:
- dump += INDENT4 "Mode: relative pointer\n";
- break;
- case Parameters::MODE_NAVIGATION:
- dump += INDENT4 "Mode: navigation\n";
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
-}
-
-void CursorInputMapper::reset(nsecs_t when) {
- mButtonState = 0;
- mDownTime = 0;
-
- mPointerVelocityControl.reset();
- mWheelXVelocityControl.reset();
- mWheelYVelocityControl.reset();
-
- mCursorButtonAccumulator.reset(getDevice());
- mCursorMotionAccumulator.reset(getDevice());
- mCursorScrollAccumulator.reset(getDevice());
-
- InputMapper::reset(when);
-}
-
-void CursorInputMapper::process(const RawEvent* rawEvent) {
- mCursorButtonAccumulator.process(rawEvent);
- mCursorMotionAccumulator.process(rawEvent);
- mCursorScrollAccumulator.process(rawEvent);
-
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- sync(rawEvent->when);
- }
-}
-
-void CursorInputMapper::sync(nsecs_t when) {
- int32_t lastButtonState = mButtonState;
- int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
- mButtonState = currentButtonState;
-
- bool wasDown = isPointerDown(lastButtonState);
- bool down = isPointerDown(currentButtonState);
- bool downChanged;
- if (!wasDown && down) {
- mDownTime = when;
- downChanged = true;
- } else if (wasDown && !down) {
- downChanged = true;
- } else {
- downChanged = false;
- }
- nsecs_t downTime = mDownTime;
- bool buttonsChanged = currentButtonState != lastButtonState;
- int32_t buttonsPressed = currentButtonState & ~lastButtonState;
- int32_t buttonsReleased = lastButtonState & ~currentButtonState;
-
- float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
- float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
- bool moved = deltaX != 0 || deltaY != 0;
-
- // Rotate delta according to orientation if needed.
- if (mParameters.orientationAware && mParameters.hasAssociatedDisplay &&
- (deltaX != 0.0f || deltaY != 0.0f)) {
- rotateDelta(mOrientation, &deltaX, &deltaY);
- }
-
- // Move the pointer.
- PointerProperties pointerProperties;
- pointerProperties.clear();
- pointerProperties.id = 0;
- pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
-
- PointerCoords pointerCoords;
- pointerCoords.clear();
-
- float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
- float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
- bool scrolled = vscroll != 0 || hscroll != 0;
-
- mWheelYVelocityControl.move(when, nullptr, &vscroll);
- mWheelXVelocityControl.move(when, &hscroll, nullptr);
-
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- int32_t displayId;
- if (mSource == AINPUT_SOURCE_MOUSE) {
- if (moved || scrolled || buttonsChanged) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
-
- if (moved) {
- mPointerController->move(deltaX, deltaY);
- }
-
- if (buttonsChanged) {
- mPointerController->setButtonState(currentButtonState);
- }
-
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- }
-
- float x, y;
- mPointerController->getPosition(&x, &y);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
- displayId = mPointerController->getDisplayId();
- } else {
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
- displayId = ADISPLAY_ID_NONE;
- }
-
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
-
- // Moving an external trackball or mouse should wake the device.
- // We don't do this for internal cursor devices to prevent them from waking up
- // the device in your pocket.
- // TODO: Use the input device configuration to control this behavior more finely.
- uint32_t policyFlags = 0;
- if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
- policyFlags |= POLICY_FLAG_WAKE;
- }
-
- // Synthesize key down from buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
- displayId, policyFlags, lastButtonState, currentButtonState);
-
- // Send motion event.
- if (downChanged || moved || scrolled || buttonsChanged) {
- int32_t metaState = mContext->getGlobalMetaState();
- int32_t buttonState = lastButtonState;
- int32_t motionEventAction;
- if (downChanged) {
- motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
- } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
- motionEventAction = AMOTION_EVENT_ACTION_MOVE;
- } else {
- motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
- }
-
- if (buttonsReleased) {
- BitSet32 released(buttonsReleased);
- while (!released.isEmpty()) {
- int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
- buttonState &= ~actionButton;
- NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, displayId, policyFlags,
- AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
- metaState, buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &pointerProperties,
- &pointerCoords, mXPrecision, mYPrecision, downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&releaseArgs);
- }
- }
-
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, motionEventAction, 0, 0, metaState,
- currentButtonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
- mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
- getListener()->notifyMotion(&args);
-
- if (buttonsPressed) {
- BitSet32 pressed(buttonsPressed);
- while (!pressed.isEmpty()) {
- int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
- buttonState |= actionButton;
- NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, displayId, policyFlags,
- AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
- metaState, buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &pointerProperties,
- &pointerCoords, mXPrecision, mYPrecision, downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&pressArgs);
- }
- }
-
- ALOG_ASSERT(buttonState == currentButtonState);
-
- // Send hover move after UP to tell the application that the mouse is hovering now.
- if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) {
- NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
- 0, metaState, currentButtonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &pointerProperties,
- &pointerCoords, mXPrecision, mYPrecision, downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&hoverArgs);
- }
-
- // Send scroll events.
- if (scrolled) {
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
-
- NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, displayId, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
- currentButtonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &pointerProperties,
- &pointerCoords, mXPrecision, mYPrecision, downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&scrollArgs);
- }
- }
-
- // Synthesize key up from buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
- displayId, policyFlags, lastButtonState, currentButtonState);
-
- mCursorMotionAccumulator.finishSync();
- mCursorScrollAccumulator.finishSync();
-}
-
-int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
- return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
- } else {
- return AKEY_STATE_UNKNOWN;
- }
-}
-
-void CursorInputMapper::fadePointer() {
- if (mPointerController != nullptr) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
-}
-
-std::optional<int32_t> CursorInputMapper::getAssociatedDisplay() {
- if (mParameters.hasAssociatedDisplay) {
- if (mParameters.mode == Parameters::MODE_POINTER) {
- return std::make_optional(mPointerController->getDisplayId());
- } else {
- // If the device is orientationAware and not a mouse,
- // it expects to dispatch events to any display
- return std::make_optional(ADISPLAY_ID_NONE);
- }
- }
- return std::nullopt;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
deleted file mode 100644
index eb2ad54c80..0000000000
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ /dev/null
@@ -1,123 +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.
- */
-
-#ifndef _UI_INPUTREADER_CURSOR_INPUT_MAPPER_H
-#define _UI_INPUTREADER_CURSOR_INPUT_MAPPER_H
-
-#include "CursorButtonAccumulator.h"
-#include "CursorScrollAccumulator.h"
-#include "InputMapper.h"
-
-#include <PointerControllerInterface.h>
-#include <input/VelocityControl.h>
-
-namespace android {
-
-class VelocityControl;
-class PointerControllerInterface;
-
-class CursorButtonAccumulator;
-class CursorScrollAccumulator;
-
-/* Keeps track of cursor movements. */
-class CursorMotionAccumulator {
-public:
- CursorMotionAccumulator();
- void reset(InputDevice* device);
-
- void process(const RawEvent* rawEvent);
- void finishSync();
-
- inline int32_t getRelativeX() const { return mRelX; }
- inline int32_t getRelativeY() const { return mRelY; }
-
-private:
- int32_t mRelX;
- int32_t mRelY;
-
- void clearRelativeAxes();
-};
-
-class CursorInputMapper : public InputMapper {
-public:
- explicit CursorInputMapper(InputDevice* device);
- virtual ~CursorInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(std::string& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-
- virtual void fadePointer();
-
- virtual std::optional<int32_t> getAssociatedDisplay();
-
-private:
- // Amount that trackball needs to move in order to generate a key event.
- static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
-
- // Immutable configuration parameters.
- struct Parameters {
- enum Mode {
- MODE_POINTER,
- MODE_POINTER_RELATIVE,
- MODE_NAVIGATION,
- };
-
- Mode mode;
- bool hasAssociatedDisplay;
- bool orientationAware;
- } mParameters;
-
- CursorButtonAccumulator mCursorButtonAccumulator;
- CursorMotionAccumulator mCursorMotionAccumulator;
- CursorScrollAccumulator mCursorScrollAccumulator;
-
- int32_t mSource;
- float mXScale;
- float mYScale;
- float mXPrecision;
- float mYPrecision;
-
- float mVWheelScale;
- float mHWheelScale;
-
- // Velocity controls for mouse pointer and wheel movements.
- // The controls for X and Y wheel movements are separate to keep them decoupled.
- VelocityControl mPointerVelocityControl;
- VelocityControl mWheelXVelocityControl;
- VelocityControl mWheelYVelocityControl;
-
- int32_t mOrientation;
-
- sp<PointerControllerInterface> mPointerController;
-
- int32_t mButtonState;
- nsecs_t mDownTime;
-
- void configureParameters();
- void dumpParameters(std::string& dump);
-
- void sync(nsecs_t when);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_CURSOR_INPUT_MAPPER_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
deleted file mode 100644
index 9aa0770245..0000000000
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
+++ /dev/null
@@ -1,92 +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 "Macros.h"
-
-#include "ExternalStylusInputMapper.h"
-
-#include "SingleTouchMotionAccumulator.h"
-#include "TouchButtonAccumulator.h"
-
-namespace android {
-
-ExternalStylusInputMapper::ExternalStylusInputMapper(InputDevice* device) : InputMapper(device) {}
-
-uint32_t ExternalStylusInputMapper::getSources() {
- return AINPUT_SOURCE_STYLUS;
-}
-
-void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
- info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f);
-}
-
-void ExternalStylusInputMapper::dump(std::string& dump) {
- dump += INDENT2 "External Stylus Input Mapper:\n";
- dump += INDENT3 "Raw Stylus Axes:\n";
- dumpRawAbsoluteAxisInfo(dump, mRawPressureAxis, "Pressure");
- dump += INDENT3 "Stylus State:\n";
- dumpStylusState(dump, mStylusState);
-}
-
-void ExternalStylusInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) {
- getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
- mTouchButtonAccumulator.configure(getDevice());
-}
-
-void ExternalStylusInputMapper::reset(nsecs_t when) {
- InputDevice* device = getDevice();
- mSingleTouchMotionAccumulator.reset(device);
- mTouchButtonAccumulator.reset(device);
- InputMapper::reset(when);
-}
-
-void ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
- mSingleTouchMotionAccumulator.process(rawEvent);
- mTouchButtonAccumulator.process(rawEvent);
-
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- sync(rawEvent->when);
- }
-}
-
-void ExternalStylusInputMapper::sync(nsecs_t when) {
- mStylusState.clear();
-
- mStylusState.when = when;
-
- mStylusState.toolType = mTouchButtonAccumulator.getToolType();
- if (mStylusState.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- mStylusState.toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
- }
-
- int32_t pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
- if (mRawPressureAxis.valid) {
- mStylusState.pressure = float(pressure) / mRawPressureAxis.maxValue;
- } else if (mTouchButtonAccumulator.isToolActive()) {
- mStylusState.pressure = 1.0f;
- } else {
- mStylusState.pressure = 0.0f;
- }
-
- mStylusState.buttons = mTouchButtonAccumulator.getButtonState();
-
- mContext->dispatchExternalStylusState(mStylusState);
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
deleted file mode 100644
index 9764fbb3c1..0000000000
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUTREADER_EXTERNAL_STYLUS_INPUT_MAPPER_H
-#define _UI_INPUTREADER_EXTERNAL_STYLUS_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-#include "SingleTouchMotionAccumulator.h"
-#include "StylusState.h"
-#include "TouchButtonAccumulator.h"
-
-namespace android {
-
-class ExternalStylusInputMapper : public InputMapper {
-public:
- explicit ExternalStylusInputMapper(InputDevice* device);
- virtual ~ExternalStylusInputMapper() = default;
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(std::string& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
- virtual void sync(nsecs_t when);
-
-private:
- SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
- RawAbsoluteAxisInfo mRawPressureAxis;
- TouchButtonAccumulator mTouchButtonAccumulator;
-
- StylusState mStylusState;
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_EXTERNAL_STYLUS_INPUT_MAPPER_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp
deleted file mode 100644
index d941528d14..0000000000
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ /dev/null
@@ -1,101 +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 "Macros.h"
-
-#include "InputMapper.h"
-
-#include "InputDevice.h"
-
-namespace android {
-
-InputMapper::InputMapper(InputDevice* device) : mDevice(device), mContext(device->getContext()) {}
-
-InputMapper::~InputMapper() {}
-
-void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- info->addSource(getSources());
-}
-
-void InputMapper::dump(std::string& dump) {}
-
-void InputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) {}
-
-void InputMapper::reset(nsecs_t when) {}
-
-void InputMapper::timeoutExpired(nsecs_t when) {}
-
-int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return AKEY_STATE_UNKNOWN;
-}
-
-bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- return false;
-}
-
-void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
- int32_t token) {}
-
-void InputMapper::cancelVibrate(int32_t token) {}
-
-void InputMapper::cancelTouch(nsecs_t when) {}
-
-int32_t InputMapper::getMetaState() {
- return 0;
-}
-
-void InputMapper::updateMetaState(int32_t keyCode) {}
-
-void InputMapper::updateExternalStylusState(const StylusState& state) {}
-
-void InputMapper::fadePointer() {}
-
-status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
- return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
-}
-
-void InputMapper::bumpGeneration() {
- mDevice->bumpGeneration();
-}
-
-void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis,
- const char* name) {
- if (axis.valid) {
- dump += StringPrintf(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n", name,
- axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
- } else {
- dump += StringPrintf(INDENT4 "%s: unknown range\n", name);
- }
-}
-
-void InputMapper::dumpStylusState(std::string& dump, const StylusState& state) {
- dump += StringPrintf(INDENT4 "When: %" PRId64 "\n", state.when);
- dump += StringPrintf(INDENT4 "Pressure: %f\n", state.pressure);
- dump += StringPrintf(INDENT4 "Button State: 0x%08x\n", state.buttons);
- dump += StringPrintf(INDENT4 "Tool Type: %" PRId32 "\n", state.toolType);
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
deleted file mode 100644
index cfd207cc4d..0000000000
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ /dev/null
@@ -1,92 +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.
- */
-
-#ifndef _UI_INPUTREADER_INPUT_MAPPER_H
-#define _UI_INPUTREADER_INPUT_MAPPER_H
-
-#include "EventHub.h"
-#include "InputDevice.h"
-#include "InputListener.h"
-#include "InputReaderContext.h"
-#include "StylusState.h"
-
-namespace android {
-
-/* An input mapper transforms raw input events into cooked event data.
- * A single input device can have multiple associated input mappers in order to interpret
- * different classes of events.
- *
- * InputMapper lifecycle:
- * - create
- * - configure with 0 changes
- * - reset
- * - process, process, process (may occasionally reconfigure with non-zero changes or reset)
- * - reset
- * - destroy
- */
-class InputMapper {
-public:
- explicit InputMapper(InputDevice* device);
- virtual ~InputMapper();
-
- inline InputDevice* getDevice() { return mDevice; }
- inline int32_t getDeviceId() { return mDevice->getId(); }
- inline const std::string getDeviceName() { return mDevice->getName(); }
- inline InputReaderContext* getContext() { return mContext; }
- inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
- inline InputListenerInterface* getListener() { return mContext->getListener(); }
- inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
-
- virtual uint32_t getSources() = 0;
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(std::string& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent) = 0;
- virtual void timeoutExpired(nsecs_t when);
-
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
- virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
- virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
- virtual void cancelVibrate(int32_t token);
- virtual void cancelTouch(nsecs_t when);
-
- virtual int32_t getMetaState();
- virtual void updateMetaState(int32_t keyCode);
-
- virtual void updateExternalStylusState(const StylusState& state);
-
- virtual void fadePointer();
- virtual std::optional<int32_t> getAssociatedDisplay() { return std::nullopt; }
-
-protected:
- InputDevice* mDevice;
- InputReaderContext* mContext;
-
- status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
- void bumpGeneration();
-
- static void dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis,
- const char* name);
- static void dumpStylusState(std::string& dump, const StylusState& state);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
deleted file mode 100644
index b493e8368f..0000000000
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ /dev/null
@@ -1,408 +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 "Macros.h"
-
-#include "JoystickInputMapper.h"
-
-namespace android {
-
-JoystickInputMapper::JoystickInputMapper(InputDevice* device) : InputMapper(device) {}
-
-JoystickInputMapper::~JoystickInputMapper() {}
-
-uint32_t JoystickInputMapper::getSources() {
- return AINPUT_SOURCE_JOYSTICK;
-}
-
-void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- for (size_t i = 0; i < mAxes.size(); i++) {
- const Axis& axis = mAxes.valueAt(i);
- addMotionRange(axis.axisInfo.axis, axis, info);
-
- if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
- addMotionRange(axis.axisInfo.highAxis, axis, info);
- }
- }
-}
-
-void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis, InputDeviceInfo* info) {
- info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK, axis.min, axis.max, axis.flat, axis.fuzz,
- axis.resolution);
- /* In order to ease the transition for developers from using the old axes
- * to the newer, more semantically correct axes, we'll continue to register
- * the old axes as duplicates of their corresponding new ones. */
- int32_t compatAxis = getCompatAxis(axisId);
- if (compatAxis >= 0) {
- info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK, axis.min, axis.max, axis.flat,
- axis.fuzz, axis.resolution);
- }
-}
-
-/* A mapping from axes the joystick actually has to the axes that should be
- * artificially created for compatibility purposes.
- * Returns -1 if no compatibility axis is needed. */
-int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
- switch (axis) {
- case AMOTION_EVENT_AXIS_LTRIGGER:
- return AMOTION_EVENT_AXIS_BRAKE;
- case AMOTION_EVENT_AXIS_RTRIGGER:
- return AMOTION_EVENT_AXIS_GAS;
- }
- return -1;
-}
-
-void JoystickInputMapper::dump(std::string& dump) {
- dump += INDENT2 "Joystick Input Mapper:\n";
-
- dump += INDENT3 "Axes:\n";
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- const Axis& axis = mAxes.valueAt(i);
- const char* label = getAxisLabel(axis.axisInfo.axis);
- if (label) {
- dump += StringPrintf(INDENT4 "%s", label);
- } else {
- dump += StringPrintf(INDENT4 "%d", axis.axisInfo.axis);
- }
- if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
- label = getAxisLabel(axis.axisInfo.highAxis);
- if (label) {
- dump += StringPrintf(" / %s (split at %d)", label, axis.axisInfo.splitValue);
- } else {
- dump += StringPrintf(" / %d (split at %d)", axis.axisInfo.highAxis,
- axis.axisInfo.splitValue);
- }
- } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
- dump += " (invert)";
- }
-
- dump += StringPrintf(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
- axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
- dump += StringPrintf(INDENT4 " scale=%0.5f, offset=%0.5f, "
- "highScale=%0.5f, highOffset=%0.5f\n",
- axis.scale, axis.offset, axis.highScale, axis.highOffset);
- dump += StringPrintf(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
- "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
- mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
- axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz,
- axis.rawAxisInfo.resolution);
- }
-}
-
-void JoystickInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) {
- InputMapper::configure(when, config, changes);
-
- if (!changes) { // first time only
- // Collect all axes.
- for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
- if (!(getAbsAxisUsage(abs, getDevice()->getClasses()) & INPUT_DEVICE_CLASS_JOYSTICK)) {
- continue; // axis must be claimed by a different device
- }
-
- RawAbsoluteAxisInfo rawAxisInfo;
- getAbsoluteAxisInfo(abs, &rawAxisInfo);
- if (rawAxisInfo.valid) {
- // Map axis.
- AxisInfo axisInfo;
- bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
- if (!explicitlyMapped) {
- // Axis is not explicitly mapped, will choose a generic axis later.
- axisInfo.mode = AxisInfo::MODE_NORMAL;
- axisInfo.axis = -1;
- }
-
- // Apply flat override.
- int32_t rawFlat =
- axisInfo.flatOverride < 0 ? rawAxisInfo.flat : axisInfo.flatOverride;
-
- // Calculate scaling factors and limits.
- Axis axis;
- if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
- float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
- float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
- axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, 0.0f, highScale,
- 0.0f, 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
- rawAxisInfo.resolution * scale);
- } else if (isCenteredAxis(axisInfo.axis)) {
- float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
- float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
- axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, offset, scale,
- offset, -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
- rawAxisInfo.resolution * scale);
- } else {
- float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
- axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, 0.0f, scale,
- 0.0f, 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
- rawAxisInfo.resolution * scale);
- }
-
- // To eliminate noise while the joystick is at rest, filter out small variations
- // in axis values up front.
- axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
-
- mAxes.add(abs, axis);
- }
- }
-
- // If there are too many axes, start dropping them.
- // Prefer to keep explicitly mapped axes.
- if (mAxes.size() > PointerCoords::MAX_AXES) {
- ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
- getDeviceName().c_str(), mAxes.size(), PointerCoords::MAX_AXES);
- pruneAxes(true);
- pruneAxes(false);
- }
-
- // Assign generic axis ids to remaining axes.
- int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- Axis& axis = mAxes.editValueAt(i);
- if (axis.axisInfo.axis < 0) {
- while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16 &&
- haveAxis(nextGenericAxisId)) {
- nextGenericAxisId += 1;
- }
-
- if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
- axis.axisInfo.axis = nextGenericAxisId;
- nextGenericAxisId += 1;
- } else {
- ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
- "have already been assigned to other axes.",
- getDeviceName().c_str(), mAxes.keyAt(i));
- mAxes.removeItemsAt(i--);
- numAxes -= 1;
- }
- }
- }
- }
-}
-
-bool JoystickInputMapper::haveAxis(int32_t axisId) {
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- const Axis& axis = mAxes.valueAt(i);
- if (axis.axisInfo.axis == axisId ||
- (axis.axisInfo.mode == AxisInfo::MODE_SPLIT && axis.axisInfo.highAxis == axisId)) {
- return true;
- }
- }
- return false;
-}
-
-void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
- size_t i = mAxes.size();
- while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
- if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
- continue;
- }
- ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
- getDeviceName().c_str(), mAxes.keyAt(i));
- mAxes.removeItemsAt(i);
- }
-}
-
-bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
- switch (axis) {
- case AMOTION_EVENT_AXIS_X:
- case AMOTION_EVENT_AXIS_Y:
- case AMOTION_EVENT_AXIS_Z:
- case AMOTION_EVENT_AXIS_RX:
- case AMOTION_EVENT_AXIS_RY:
- case AMOTION_EVENT_AXIS_RZ:
- case AMOTION_EVENT_AXIS_HAT_X:
- case AMOTION_EVENT_AXIS_HAT_Y:
- case AMOTION_EVENT_AXIS_ORIENTATION:
- case AMOTION_EVENT_AXIS_RUDDER:
- case AMOTION_EVENT_AXIS_WHEEL:
- return true;
- default:
- return false;
- }
-}
-
-void JoystickInputMapper::reset(nsecs_t when) {
- // Recenter all axes.
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- Axis& axis = mAxes.editValueAt(i);
- axis.resetValue();
- }
-
- InputMapper::reset(when);
-}
-
-void JoystickInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_ABS: {
- ssize_t index = mAxes.indexOfKey(rawEvent->code);
- if (index >= 0) {
- Axis& axis = mAxes.editValueAt(index);
- float newValue, highNewValue;
- switch (axis.axisInfo.mode) {
- case AxisInfo::MODE_INVERT:
- newValue = (axis.rawAxisInfo.maxValue - rawEvent->value) * axis.scale +
- axis.offset;
- highNewValue = 0.0f;
- break;
- case AxisInfo::MODE_SPLIT:
- if (rawEvent->value < axis.axisInfo.splitValue) {
- newValue = (axis.axisInfo.splitValue - rawEvent->value) * axis.scale +
- axis.offset;
- highNewValue = 0.0f;
- } else if (rawEvent->value > axis.axisInfo.splitValue) {
- newValue = 0.0f;
- highNewValue =
- (rawEvent->value - axis.axisInfo.splitValue) * axis.highScale +
- axis.highOffset;
- } else {
- newValue = 0.0f;
- highNewValue = 0.0f;
- }
- break;
- default:
- newValue = rawEvent->value * axis.scale + axis.offset;
- highNewValue = 0.0f;
- break;
- }
- axis.newValue = newValue;
- axis.highNewValue = highNewValue;
- }
- break;
- }
-
- case EV_SYN:
- switch (rawEvent->code) {
- case SYN_REPORT:
- sync(rawEvent->when, false /*force*/);
- break;
- }
- break;
- }
-}
-
-void JoystickInputMapper::sync(nsecs_t when, bool force) {
- if (!filterAxes(force)) {
- return;
- }
-
- int32_t metaState = mContext->getGlobalMetaState();
- int32_t buttonState = 0;
-
- PointerProperties pointerProperties;
- pointerProperties.clear();
- pointerProperties.id = 0;
- pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-
- PointerCoords pointerCoords;
- pointerCoords.clear();
-
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- const Axis& axis = mAxes.valueAt(i);
- setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
- if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
- setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
- axis.highCurrentValue);
- }
- }
-
- // Moving a joystick axis should not wake the device because joysticks can
- // be fairly noisy even when not in use. On the other hand, pushing a gamepad
- // button will likely wake the device.
- // TODO: Use the input device configuration to control this behavior more finely.
- uint32_t policyFlags = 0;
-
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
- MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, 0, 0, 0,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
-}
-
-void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis,
- float value) {
- pointerCoords->setAxisValue(axis, value);
- /* In order to ease the transition for developers from using the old axes
- * to the newer, more semantically correct axes, we'll continue to produce
- * values for the old axes as mirrors of the value of their corresponding
- * new axes. */
- int32_t compatAxis = getCompatAxis(axis);
- if (compatAxis >= 0) {
- pointerCoords->setAxisValue(compatAxis, value);
- }
-}
-
-bool JoystickInputMapper::filterAxes(bool force) {
- bool atLeastOneSignificantChange = force;
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- Axis& axis = mAxes.editValueAt(i);
- if (force ||
- hasValueChangedSignificantly(axis.filter, axis.newValue, axis.currentValue, axis.min,
- axis.max)) {
- axis.currentValue = axis.newValue;
- atLeastOneSignificantChange = true;
- }
- if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
- if (force ||
- hasValueChangedSignificantly(axis.filter, axis.highNewValue, axis.highCurrentValue,
- axis.min, axis.max)) {
- axis.highCurrentValue = axis.highNewValue;
- atLeastOneSignificantChange = true;
- }
- }
- }
- return atLeastOneSignificantChange;
-}
-
-bool JoystickInputMapper::hasValueChangedSignificantly(float filter, float newValue,
- float currentValue, float min, float max) {
- if (newValue != currentValue) {
- // Filter out small changes in value unless the value is converging on the axis
- // bounds or center point. This is intended to reduce the amount of information
- // sent to applications by particularly noisy joysticks (such as PS3).
- if (fabs(newValue - currentValue) > filter ||
- hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min) ||
- hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max) ||
- hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
- return true;
- }
- }
- return false;
-}
-
-bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(float filter, float newValue,
- float currentValue,
- float thresholdValue) {
- float newDistance = fabs(newValue - thresholdValue);
- if (newDistance < filter) {
- float oldDistance = fabs(currentValue - thresholdValue);
- if (newDistance < oldDistance) {
- return true;
- }
- }
- return false;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h
deleted file mode 100644
index 1b071d0480..0000000000
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.h
+++ /dev/null
@@ -1,111 +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.
- */
-
-#ifndef _UI_INPUTREADER_JOYSTICK_INPUT_MAPPER_H
-#define _UI_INPUTREADER_JOYSTICK_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-namespace android {
-
-class JoystickInputMapper : public InputMapper {
-public:
- explicit JoystickInputMapper(InputDevice* device);
- virtual ~JoystickInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(std::string& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
-private:
- struct Axis {
- RawAbsoluteAxisInfo rawAxisInfo;
- AxisInfo axisInfo;
-
- bool explicitlyMapped; // true if the axis was explicitly assigned an axis id
-
- float scale; // scale factor from raw to normalized values
- float offset; // offset to add after scaling for normalization
- float highScale; // scale factor from raw to normalized values of high split
- float highOffset; // offset to add after scaling for normalization of high split
-
- float min; // normalized inclusive minimum
- float max; // normalized inclusive maximum
- float flat; // normalized flat region size
- float fuzz; // normalized error tolerance
- float resolution; // normalized resolution in units/mm
-
- float filter; // filter out small variations of this size
- float currentValue; // current value
- float newValue; // most recent value
- float highCurrentValue; // current value of high split
- float highNewValue; // most recent value of high split
-
- void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo,
- bool explicitlyMapped, float scale, float offset, float highScale,
- float highOffset, float min, float max, float flat, float fuzz,
- float resolution) {
- this->rawAxisInfo = rawAxisInfo;
- this->axisInfo = axisInfo;
- this->explicitlyMapped = explicitlyMapped;
- this->scale = scale;
- this->offset = offset;
- this->highScale = highScale;
- this->highOffset = highOffset;
- this->min = min;
- this->max = max;
- this->flat = flat;
- this->fuzz = fuzz;
- this->resolution = resolution;
- this->filter = 0;
- resetValue();
- }
-
- void resetValue() {
- this->currentValue = 0;
- this->newValue = 0;
- this->highCurrentValue = 0;
- this->highNewValue = 0;
- }
- };
-
- // Axes indexed by raw ABS_* axis index.
- KeyedVector<int32_t, Axis> mAxes;
-
- void sync(nsecs_t when, bool force);
-
- bool haveAxis(int32_t axisId);
- void pruneAxes(bool ignoreExplicitlyMappedAxes);
- bool filterAxes(bool force);
-
- static bool hasValueChangedSignificantly(float filter, float newValue, float currentValue,
- float min, float max);
- static bool hasMovedNearerToValueWithinFilteredRange(float filter, float newValue,
- float currentValue, float thresholdValue);
-
- static bool isCenteredAxis(int32_t axis);
- static int32_t getCompatAxis(int32_t axis);
-
- static void addMotionRange(int32_t axisId, const Axis& axis, InputDeviceInfo* info);
- static void setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis, float value);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_JOYSTICK_INPUT_MAPPER_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
deleted file mode 100644
index 0e91c0e2cc..0000000000
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ /dev/null
@@ -1,412 +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 "Macros.h"
-
-#include "KeyboardInputMapper.h"
-
-namespace android {
-
-// --- Static Definitions ---
-
-static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
- const int32_t map[][4], size_t mapSize) {
- if (orientation != DISPLAY_ORIENTATION_0) {
- for (size_t i = 0; i < mapSize; i++) {
- if (value == map[i][0]) {
- return map[i][orientation];
- }
- }
- }
- return value;
-}
-
-static const int32_t keyCodeRotationMap[][4] = {
- // key codes enumerated counter-clockwise with the original (unrotated) key first
- // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
- {AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT},
- {AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN},
- {AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT},
- {AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP},
- {AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
- AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT},
- {AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
- AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN},
- {AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
- AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT},
- {AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
- AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP},
-};
-
-static const size_t keyCodeRotationMapSize =
- sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
-
-static int32_t rotateStemKey(int32_t value, int32_t orientation, const int32_t map[][2],
- size_t mapSize) {
- if (orientation == DISPLAY_ORIENTATION_180) {
- for (size_t i = 0; i < mapSize; i++) {
- if (value == map[i][0]) {
- return map[i][1];
- }
- }
- }
- return value;
-}
-
-// The mapping can be defined using input device configuration properties keyboard.rotated.stem_X
-static int32_t stemKeyRotationMap[][2] = {
- // key codes enumerated with the original (unrotated) key first
- // no rotation, 180 degree rotation
- {AKEYCODE_STEM_PRIMARY, AKEYCODE_STEM_PRIMARY},
- {AKEYCODE_STEM_1, AKEYCODE_STEM_1},
- {AKEYCODE_STEM_2, AKEYCODE_STEM_2},
- {AKEYCODE_STEM_3, AKEYCODE_STEM_3},
-};
-
-static const size_t stemKeyRotationMapSize =
- sizeof(stemKeyRotationMap) / sizeof(stemKeyRotationMap[0]);
-
-static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
- keyCode = rotateStemKey(keyCode, orientation, stemKeyRotationMap, stemKeyRotationMapSize);
- return rotateValueUsingRotationMap(keyCode, orientation, keyCodeRotationMap,
- keyCodeRotationMapSize);
-}
-
-// --- KeyboardInputMapper ---
-
-KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType)
- : InputMapper(device), mSource(source), mKeyboardType(keyboardType) {}
-
-KeyboardInputMapper::~KeyboardInputMapper() {}
-
-uint32_t KeyboardInputMapper::getSources() {
- return mSource;
-}
-
-int32_t KeyboardInputMapper::getOrientation() {
- if (mViewport) {
- return mViewport->orientation;
- }
- return DISPLAY_ORIENTATION_0;
-}
-
-int32_t KeyboardInputMapper::getDisplayId() {
- if (mViewport) {
- return mViewport->displayId;
- }
- return ADISPLAY_ID_NONE;
-}
-
-void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- info->setKeyboardType(mKeyboardType);
- info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
-}
-
-void KeyboardInputMapper::dump(std::string& dump) {
- dump += INDENT2 "Keyboard Input Mapper:\n";
- dumpParameters(dump);
- dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
- dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
- dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
- dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
- dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
-}
-
-void KeyboardInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) {
- InputMapper::configure(when, config, changes);
-
- if (!changes) { // first time only
- // Configure basic parameters.
- configureParameters();
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- if (mParameters.orientationAware) {
- mViewport = config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
- }
- }
-}
-
-static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const* property) {
- int32_t mapped = 0;
- if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
- for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
- if (stemKeyRotationMap[i][0] == keyCode) {
- stemKeyRotationMap[i][1] = mapped;
- return;
- }
- }
- }
-}
-
-void KeyboardInputMapper::configureParameters() {
- mParameters.orientationAware = false;
- const PropertyMap& config = getDevice()->getConfiguration();
- config.tryGetProperty(String8("keyboard.orientationAware"), mParameters.orientationAware);
-
- if (mParameters.orientationAware) {
- mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
- mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
- mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
- mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
- }
-
- mParameters.handlesKeyRepeat = false;
- config.tryGetProperty(String8("keyboard.handlesKeyRepeat"), mParameters.handlesKeyRepeat);
-}
-
-void KeyboardInputMapper::dumpParameters(std::string& dump) {
- dump += INDENT3 "Parameters:\n";
- dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
- dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", toString(mParameters.handlesKeyRepeat));
-}
-
-void KeyboardInputMapper::reset(nsecs_t when) {
- mMetaState = AMETA_NONE;
- mDownTime = 0;
- mKeyDowns.clear();
- mCurrentHidUsage = 0;
-
- resetLedState();
-
- InputMapper::reset(when);
-}
-
-void KeyboardInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY: {
- int32_t scanCode = rawEvent->code;
- int32_t usageCode = mCurrentHidUsage;
- mCurrentHidUsage = 0;
-
- if (isKeyboardOrGamepadKey(scanCode)) {
- processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
- }
- break;
- }
- case EV_MSC: {
- if (rawEvent->code == MSC_SCAN) {
- mCurrentHidUsage = rawEvent->value;
- }
- break;
- }
- case EV_SYN: {
- if (rawEvent->code == SYN_REPORT) {
- mCurrentHidUsage = 0;
- }
- }
- }
-}
-
-bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
- return scanCode < BTN_MOUSE || scanCode >= KEY_OK ||
- (scanCode >= BTN_MISC && scanCode < BTN_MOUSE) ||
- (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
-}
-
-bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
- switch (keyCode) {
- case AKEYCODE_MEDIA_PLAY:
- case AKEYCODE_MEDIA_PAUSE:
- case AKEYCODE_MEDIA_PLAY_PAUSE:
- case AKEYCODE_MUTE:
- case AKEYCODE_HEADSETHOOK:
- case AKEYCODE_MEDIA_STOP:
- case AKEYCODE_MEDIA_NEXT:
- case AKEYCODE_MEDIA_PREVIOUS:
- case AKEYCODE_MEDIA_REWIND:
- case AKEYCODE_MEDIA_RECORD:
- case AKEYCODE_MEDIA_FAST_FORWARD:
- case AKEYCODE_MEDIA_SKIP_FORWARD:
- case AKEYCODE_MEDIA_SKIP_BACKWARD:
- case AKEYCODE_MEDIA_STEP_FORWARD:
- case AKEYCODE_MEDIA_STEP_BACKWARD:
- case AKEYCODE_MEDIA_AUDIO_TRACK:
- case AKEYCODE_VOLUME_UP:
- case AKEYCODE_VOLUME_DOWN:
- case AKEYCODE_VOLUME_MUTE:
- case AKEYCODE_TV_AUDIO_DESCRIPTION:
- case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
- case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
- return true;
- }
- return false;
-}
-
-void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) {
- int32_t keyCode;
- int32_t keyMetaState;
- uint32_t policyFlags;
-
- if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState, &keyCode,
- &keyMetaState, &policyFlags)) {
- keyCode = AKEYCODE_UNKNOWN;
- keyMetaState = mMetaState;
- policyFlags = 0;
- }
-
- if (down) {
- // Rotate key codes according to orientation if needed.
- if (mParameters.orientationAware) {
- keyCode = rotateKeyCode(keyCode, getOrientation());
- }
-
- // Add key down.
- ssize_t keyDownIndex = findKeyDown(scanCode);
- if (keyDownIndex >= 0) {
- // key repeat, be sure to use same keycode as before in case of rotation
- keyCode = mKeyDowns[keyDownIndex].keyCode;
- } else {
- // key down
- if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
- mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) {
- return;
- }
- if (policyFlags & POLICY_FLAG_GESTURE) {
- mDevice->cancelTouch(when);
- }
-
- KeyDown keyDown;
- keyDown.keyCode = keyCode;
- keyDown.scanCode = scanCode;
- mKeyDowns.push_back(keyDown);
- }
-
- mDownTime = when;
- } else {
- // Remove key down.
- ssize_t keyDownIndex = findKeyDown(scanCode);
- if (keyDownIndex >= 0) {
- // key up, be sure to use same keycode as before in case of rotation
- keyCode = mKeyDowns[keyDownIndex].keyCode;
- mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
- } else {
- // key was not actually down
- ALOGI("Dropping key up from device %s because the key was not down. "
- "keyCode=%d, scanCode=%d",
- getDeviceName().c_str(), keyCode, scanCode);
- return;
- }
- }
-
- if (updateMetaStateIfNeeded(keyCode, down)) {
- // If global meta state changed send it along with the key.
- // If it has not changed then we'll use what keymap gave us,
- // since key replacement logic might temporarily reset a few
- // meta bits for given key.
- keyMetaState = mMetaState;
- }
-
- nsecs_t downTime = mDownTime;
-
- // Key down on external an keyboard should wake the device.
- // We don't do this for internal keyboards to prevent them from waking up in your pocket.
- // For internal keyboards, the key layout file should specify the policy flags for
- // each wake key individually.
- // TODO: Use the input device configuration to control this behavior more finely.
- if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) {
- policyFlags |= POLICY_FLAG_WAKE;
- }
-
- if (mParameters.handlesKeyRepeat) {
- policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
- }
-
- NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource, getDisplayId(),
- policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
- getListener()->notifyKey(&args);
-}
-
-ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
- size_t n = mKeyDowns.size();
- for (size_t i = 0; i < n; i++) {
- if (mKeyDowns[i].scanCode == scanCode) {
- return i;
- }
- }
- return -1;
-}
-
-int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
-}
-
-int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
-}
-
-bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
-}
-
-int32_t KeyboardInputMapper::getMetaState() {
- return mMetaState;
-}
-
-void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
- updateMetaStateIfNeeded(keyCode, false);
-}
-
-bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
- int32_t oldMetaState = mMetaState;
- int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
- bool metaStateChanged = oldMetaState != newMetaState;
- if (metaStateChanged) {
- mMetaState = newMetaState;
- updateLedState(false);
-
- getContext()->updateGlobalMetaState();
- }
-
- return metaStateChanged;
-}
-
-void KeyboardInputMapper::resetLedState() {
- initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
- initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
- initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
-
- updateLedState(true);
-}
-
-void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
- ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
- ledState.on = false;
-}
-
-void KeyboardInputMapper::updateLedState(bool reset) {
- updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK, AMETA_CAPS_LOCK_ON, reset);
- updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK, AMETA_NUM_LOCK_ON, reset);
- updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, reset);
-}
-
-void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, int32_t led,
- int32_t modifier, bool reset) {
- if (ledState.avail) {
- bool desiredState = (mMetaState & modifier) != 0;
- if (reset || ledState.on != desiredState) {
- getEventHub()->setLedState(getDeviceId(), led, desiredState);
- ledState.on = desiredState;
- }
- }
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
deleted file mode 100644
index 7a68fc33f8..0000000000
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ /dev/null
@@ -1,99 +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.
- */
-
-#ifndef _UI_INPUTREADER_KEYBOARD_INPUT_MAPPER_H
-#define _UI_INPUTREADER_KEYBOARD_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-namespace android {
-
-class KeyboardInputMapper : public InputMapper {
-public:
- KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType);
- virtual ~KeyboardInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(std::string& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
-
- virtual int32_t getMetaState();
- virtual void updateMetaState(int32_t keyCode);
-
-private:
- // The current viewport.
- std::optional<DisplayViewport> mViewport;
-
- struct KeyDown {
- int32_t keyCode;
- int32_t scanCode;
- };
-
- uint32_t mSource;
- int32_t mKeyboardType;
-
- std::vector<KeyDown> mKeyDowns; // keys that are down
- int32_t mMetaState;
- nsecs_t mDownTime; // time of most recent key down
-
- int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none
-
- struct LedState {
- bool avail; // led is available
- bool on; // we think the led is currently on
- };
- LedState mCapsLockLedState;
- LedState mNumLockLedState;
- LedState mScrollLockLedState;
-
- // Immutable configuration parameters.
- struct Parameters {
- bool orientationAware;
- bool handlesKeyRepeat;
- } mParameters;
-
- void configureParameters();
- void dumpParameters(std::string& dump);
-
- int32_t getOrientation();
- int32_t getDisplayId();
-
- bool isKeyboardOrGamepadKey(int32_t scanCode);
- bool isMediaKey(int32_t keyCode);
-
- void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
-
- bool updateMetaStateIfNeeded(int32_t keyCode, bool down);
-
- ssize_t findKeyDown(int32_t scanCode);
-
- void resetLedState();
- void initializeLedState(LedState& ledState, int32_t led);
- void updateLedState(bool reset);
- void updateLedStateForModifier(LedState& ledState, int32_t led, int32_t modifier, bool reset);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_KEYBOARD_INPUT_MAPPER_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
deleted file mode 100644
index 7460a3130e..0000000000
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ /dev/null
@@ -1,361 +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 "Macros.h"
-
-#include "MultiTouchInputMapper.h"
-
-namespace android {
-
-// --- Constants ---
-
-// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
-static constexpr size_t MAX_SLOTS = 32;
-
-// --- MultiTouchMotionAccumulator ---
-
-MultiTouchMotionAccumulator::MultiTouchMotionAccumulator()
- : mCurrentSlot(-1),
- mSlots(nullptr),
- mSlotCount(0),
- mUsingSlotsProtocol(false),
- mHaveStylus(false) {}
-
-MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
- delete[] mSlots;
-}
-
-void MultiTouchMotionAccumulator::configure(InputDevice* device, size_t slotCount,
- bool usingSlotsProtocol) {
- mSlotCount = slotCount;
- mUsingSlotsProtocol = usingSlotsProtocol;
- mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
-
- delete[] mSlots;
- mSlots = new Slot[slotCount];
-}
-
-void MultiTouchMotionAccumulator::reset(InputDevice* device) {
- // Unfortunately there is no way to read the initial contents of the slots.
- // So when we reset the accumulator, we must assume they are all zeroes.
- if (mUsingSlotsProtocol) {
- // Query the driver for the current slot index and use it as the initial slot
- // before we start reading events from the device. It is possible that the
- // current slot index will not be the same as it was when the first event was
- // written into the evdev buffer, which means the input mapper could start
- // out of sync with the initial state of the events in the evdev buffer.
- // In the extremely unlikely case that this happens, the data from
- // two slots will be confused until the next ABS_MT_SLOT event is received.
- // This can cause the touch point to "jump", but at least there will be
- // no stuck touches.
- int32_t initialSlot;
- status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(), ABS_MT_SLOT,
- &initialSlot);
- if (status) {
- ALOGD("Could not retrieve current multitouch slot index. status=%d", status);
- initialSlot = -1;
- }
- clearSlots(initialSlot);
- } else {
- clearSlots(-1);
- }
- mDeviceTimestamp = 0;
-}
-
-void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
- if (mSlots) {
- for (size_t i = 0; i < mSlotCount; i++) {
- mSlots[i].clear();
- }
- }
- mCurrentSlot = initialSlot;
-}
-
-void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_ABS) {
- bool newSlot = false;
- if (mUsingSlotsProtocol) {
- if (rawEvent->code == ABS_MT_SLOT) {
- mCurrentSlot = rawEvent->value;
- newSlot = true;
- }
- } else if (mCurrentSlot < 0) {
- mCurrentSlot = 0;
- }
-
- if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
-#if DEBUG_POINTERS
- if (newSlot) {
- ALOGW("MultiTouch device emitted invalid slot index %d but it "
- "should be between 0 and %zd; ignoring this slot.",
- mCurrentSlot, mSlotCount - 1);
- }
-#endif
- } else {
- Slot* slot = &mSlots[mCurrentSlot];
-
- switch (rawEvent->code) {
- case ABS_MT_POSITION_X:
- slot->mInUse = true;
- slot->mAbsMTPositionX = rawEvent->value;
- break;
- case ABS_MT_POSITION_Y:
- slot->mInUse = true;
- slot->mAbsMTPositionY = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MAJOR:
- slot->mInUse = true;
- slot->mAbsMTTouchMajor = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MINOR:
- slot->mInUse = true;
- slot->mAbsMTTouchMinor = rawEvent->value;
- slot->mHaveAbsMTTouchMinor = true;
- break;
- case ABS_MT_WIDTH_MAJOR:
- slot->mInUse = true;
- slot->mAbsMTWidthMajor = rawEvent->value;
- break;
- case ABS_MT_WIDTH_MINOR:
- slot->mInUse = true;
- slot->mAbsMTWidthMinor = rawEvent->value;
- slot->mHaveAbsMTWidthMinor = true;
- break;
- case ABS_MT_ORIENTATION:
- slot->mInUse = true;
- slot->mAbsMTOrientation = rawEvent->value;
- break;
- case ABS_MT_TRACKING_ID:
- if (mUsingSlotsProtocol && rawEvent->value < 0) {
- // The slot is no longer in use but it retains its previous contents,
- // which may be reused for subsequent touches.
- slot->mInUse = false;
- } else {
- slot->mInUse = true;
- slot->mAbsMTTrackingId = rawEvent->value;
- }
- break;
- case ABS_MT_PRESSURE:
- slot->mInUse = true;
- slot->mAbsMTPressure = rawEvent->value;
- break;
- case ABS_MT_DISTANCE:
- slot->mInUse = true;
- slot->mAbsMTDistance = rawEvent->value;
- break;
- case ABS_MT_TOOL_TYPE:
- slot->mInUse = true;
- slot->mAbsMTToolType = rawEvent->value;
- slot->mHaveAbsMTToolType = true;
- break;
- }
- }
- } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
- // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
- mCurrentSlot += 1;
- } else if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
- mDeviceTimestamp = rawEvent->value;
- }
-}
-
-void MultiTouchMotionAccumulator::finishSync() {
- if (!mUsingSlotsProtocol) {
- clearSlots(-1);
- }
-}
-
-bool MultiTouchMotionAccumulator::hasStylus() const {
- return mHaveStylus;
-}
-
-// --- MultiTouchMotionAccumulator::Slot ---
-
-MultiTouchMotionAccumulator::Slot::Slot() {
- clear();
-}
-
-void MultiTouchMotionAccumulator::Slot::clear() {
- mInUse = false;
- mHaveAbsMTTouchMinor = false;
- mHaveAbsMTWidthMinor = false;
- mHaveAbsMTToolType = false;
- mAbsMTPositionX = 0;
- mAbsMTPositionY = 0;
- mAbsMTTouchMajor = 0;
- mAbsMTTouchMinor = 0;
- mAbsMTWidthMajor = 0;
- mAbsMTWidthMinor = 0;
- mAbsMTOrientation = 0;
- mAbsMTTrackingId = -1;
- mAbsMTPressure = 0;
- mAbsMTDistance = 0;
- mAbsMTToolType = 0;
-}
-
-int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
- if (mHaveAbsMTToolType) {
- switch (mAbsMTToolType) {
- case MT_TOOL_FINGER:
- return AMOTION_EVENT_TOOL_TYPE_FINGER;
- case MT_TOOL_PEN:
- return AMOTION_EVENT_TOOL_TYPE_STYLUS;
- }
- }
- return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-}
-
-// --- MultiTouchInputMapper ---
-
-MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) : TouchInputMapper(device) {}
-
-MultiTouchInputMapper::~MultiTouchInputMapper() {}
-
-void MultiTouchInputMapper::reset(nsecs_t when) {
- mMultiTouchMotionAccumulator.reset(getDevice());
-
- mPointerIdBits.clear();
-
- TouchInputMapper::reset(when);
-}
-
-void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
- TouchInputMapper::process(rawEvent);
-
- mMultiTouchMotionAccumulator.process(rawEvent);
-}
-
-void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
- size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
- size_t outCount = 0;
- BitSet32 newPointerIdBits;
- mHavePointerIds = true;
-
- for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
- const MultiTouchMotionAccumulator::Slot* inSlot =
- mMultiTouchMotionAccumulator.getSlot(inIndex);
- if (!inSlot->isInUse()) {
- continue;
- }
-
- if (outCount >= MAX_POINTERS) {
-#if DEBUG_POINTERS
- ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
- "ignoring the rest.",
- getDeviceName().c_str(), MAX_POINTERS);
-#endif
- break; // too many fingers!
- }
-
- RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
- outPointer.x = inSlot->getX();
- outPointer.y = inSlot->getY();
- outPointer.pressure = inSlot->getPressure();
- outPointer.touchMajor = inSlot->getTouchMajor();
- outPointer.touchMinor = inSlot->getTouchMinor();
- outPointer.toolMajor = inSlot->getToolMajor();
- outPointer.toolMinor = inSlot->getToolMinor();
- outPointer.orientation = inSlot->getOrientation();
- outPointer.distance = inSlot->getDistance();
- outPointer.tiltX = 0;
- outPointer.tiltY = 0;
-
- outPointer.toolType = inSlot->getToolType();
- if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- outPointer.toolType = mTouchButtonAccumulator.getToolType();
- if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
- }
- }
-
- bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE &&
- (mTouchButtonAccumulator.isHovering() ||
- (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
- outPointer.isHovering = isHovering;
-
- // Assign pointer id using tracking id if available.
- if (mHavePointerIds) {
- int32_t trackingId = inSlot->getTrackingId();
- int32_t id = -1;
- if (trackingId >= 0) {
- for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty();) {
- uint32_t n = idBits.clearFirstMarkedBit();
- if (mPointerTrackingIdMap[n] == trackingId) {
- id = n;
- }
- }
-
- if (id < 0 && !mPointerIdBits.isFull()) {
- id = mPointerIdBits.markFirstUnmarkedBit();
- mPointerTrackingIdMap[id] = trackingId;
- }
- }
- if (id < 0) {
- mHavePointerIds = false;
- outState->rawPointerData.clearIdBits();
- newPointerIdBits.clear();
- } else {
- outPointer.id = id;
- outState->rawPointerData.idToIndex[id] = outCount;
- outState->rawPointerData.markIdBit(id, isHovering);
- newPointerIdBits.markBit(id);
- }
- }
- outCount += 1;
- }
-
- outState->deviceTimestamp = mMultiTouchMotionAccumulator.getDeviceTimestamp();
- outState->rawPointerData.pointerCount = outCount;
- mPointerIdBits = newPointerIdBits;
-
- mMultiTouchMotionAccumulator.finishSync();
-}
-
-void MultiTouchInputMapper::configureRawPointerAxes() {
- TouchInputMapper::configureRawPointerAxes();
-
- getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
- getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
- getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
- getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
- getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
- getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
- getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
- getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
- getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
- getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
- getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
-
- if (mRawPointerAxes.trackingId.valid && mRawPointerAxes.slot.valid &&
- mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
- size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
- if (slotCount > MAX_SLOTS) {
- ALOGW("MultiTouch Device %s reported %zu slots but the framework "
- "only supports a maximum of %zu slots at this time.",
- getDeviceName().c_str(), slotCount, MAX_SLOTS);
- slotCount = MAX_SLOTS;
- }
- mMultiTouchMotionAccumulator.configure(getDevice(), slotCount, true /*usingSlotsProtocol*/);
- } else {
- mMultiTouchMotionAccumulator.configure(getDevice(), MAX_POINTERS,
- false /*usingSlotsProtocol*/);
- }
-}
-
-bool MultiTouchInputMapper::hasStylus() const {
- return mMultiTouchMotionAccumulator.hasStylus() || mTouchButtonAccumulator.hasStylus();
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
deleted file mode 100644
index 873dda1aec..0000000000
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ /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.
- */
-
-#ifndef _UI_INPUTREADER_MULTI_TOUCH_INPUT_MAPPER_H
-#define _UI_INPUTREADER_MULTI_TOUCH_INPUT_MAPPER_H
-
-#include "TouchInputMapper.h"
-
-namespace android {
-
-/* Keeps track of the state of multi-touch protocol. */
-class MultiTouchMotionAccumulator {
-public:
- class Slot {
- public:
- inline bool isInUse() const { return mInUse; }
- inline int32_t getX() const { return mAbsMTPositionX; }
- inline int32_t getY() const { return mAbsMTPositionY; }
- inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; }
- inline int32_t getTouchMinor() const {
- return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor;
- }
- inline int32_t getToolMajor() const { return mAbsMTWidthMajor; }
- inline int32_t getToolMinor() const {
- return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor;
- }
- inline int32_t getOrientation() const { return mAbsMTOrientation; }
- inline int32_t getTrackingId() const { return mAbsMTTrackingId; }
- inline int32_t getPressure() const { return mAbsMTPressure; }
- inline int32_t getDistance() const { return mAbsMTDistance; }
- inline int32_t getToolType() const;
-
- private:
- friend class MultiTouchMotionAccumulator;
-
- bool mInUse;
- bool mHaveAbsMTTouchMinor;
- bool mHaveAbsMTWidthMinor;
- bool mHaveAbsMTToolType;
-
- int32_t mAbsMTPositionX;
- int32_t mAbsMTPositionY;
- int32_t mAbsMTTouchMajor;
- int32_t mAbsMTTouchMinor;
- int32_t mAbsMTWidthMajor;
- int32_t mAbsMTWidthMinor;
- int32_t mAbsMTOrientation;
- int32_t mAbsMTTrackingId;
- int32_t mAbsMTPressure;
- int32_t mAbsMTDistance;
- int32_t mAbsMTToolType;
-
- Slot();
- void clear();
- };
-
- MultiTouchMotionAccumulator();
- ~MultiTouchMotionAccumulator();
-
- void configure(InputDevice* device, size_t slotCount, bool usingSlotsProtocol);
- void reset(InputDevice* device);
- void process(const RawEvent* rawEvent);
- void finishSync();
- bool hasStylus() const;
-
- inline size_t getSlotCount() const { return mSlotCount; }
- inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
- inline uint32_t getDeviceTimestamp() const { return mDeviceTimestamp; }
-
-private:
- int32_t mCurrentSlot;
- Slot* mSlots;
- size_t mSlotCount;
- bool mUsingSlotsProtocol;
- bool mHaveStylus;
- uint32_t mDeviceTimestamp;
-
- void clearSlots(int32_t initialSlot);
-};
-
-class MultiTouchInputMapper : public TouchInputMapper {
-public:
- explicit MultiTouchInputMapper(InputDevice* device);
- virtual ~MultiTouchInputMapper();
-
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
-protected:
- virtual void syncTouch(nsecs_t when, RawState* outState);
- virtual void configureRawPointerAxes();
- virtual bool hasStylus() const;
-
-private:
- MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
-
- // Specifies the pointer id bits that are in use, and their associated tracking id.
- BitSet32 mPointerIdBits;
- int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1];
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_MULTI_TOUCH_INPUT_MAPPER_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
deleted file mode 100644
index 803fdf3656..0000000000
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ /dev/null
@@ -1,134 +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 "Macros.h"
-
-#include "RotaryEncoderInputMapper.h"
-
-#include "CursorScrollAccumulator.h"
-
-namespace android {
-
-RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device)
- : InputMapper(device), mOrientation(DISPLAY_ORIENTATION_0) {
- mSource = AINPUT_SOURCE_ROTARY_ENCODER;
-}
-
-RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {}
-
-uint32_t RotaryEncoderInputMapper::getSources() {
- return mSource;
-}
-
-void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
- float res = 0.0f;
- if (!mDevice->getConfiguration().tryGetProperty(String8("device.res"), res)) {
- ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
- }
- if (!mDevice->getConfiguration().tryGetProperty(String8("device.scalingFactor"),
- mScalingFactor)) {
- ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
- "default to 1.0!\n");
- mScalingFactor = 1.0f;
- }
- info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
- res * mScalingFactor);
- }
-}
-
-void RotaryEncoderInputMapper::dump(std::string& dump) {
- dump += INDENT2 "Rotary Encoder Input Mapper:\n";
- dump += StringPrintf(INDENT3 "HaveWheel: %s\n",
- toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
-}
-
-void RotaryEncoderInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) {
- InputMapper::configure(when, config, changes);
- if (!changes) {
- mRotaryEncoderScrollAccumulator.configure(getDevice());
- }
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- std::optional<DisplayViewport> internalViewport =
- config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
- if (internalViewport) {
- mOrientation = internalViewport->orientation;
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
- }
- }
-}
-
-void RotaryEncoderInputMapper::reset(nsecs_t when) {
- mRotaryEncoderScrollAccumulator.reset(getDevice());
-
- InputMapper::reset(when);
-}
-
-void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
- mRotaryEncoderScrollAccumulator.process(rawEvent);
-
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- sync(rawEvent->when);
- }
-}
-
-void RotaryEncoderInputMapper::sync(nsecs_t when) {
- PointerCoords pointerCoords;
- pointerCoords.clear();
-
- PointerProperties pointerProperties;
- pointerProperties.clear();
- pointerProperties.id = 0;
- pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-
- float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
- bool scrolled = scroll != 0;
-
- // This is not a pointer, so it's not associated with a display.
- int32_t displayId = ADISPLAY_ID_NONE;
-
- // Moving the rotary encoder should wake the device (if specified).
- uint32_t policyFlags = 0;
- if (scrolled && getDevice()->isExternal()) {
- policyFlags |= POLICY_FLAG_WAKE;
- }
-
- if (mOrientation == DISPLAY_ORIENTATION_180) {
- scroll = -scroll;
- }
-
- // Send motion event.
- if (scrolled) {
- int32_t metaState = mContext->getGlobalMetaState();
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
-
- NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
- metaState, /* buttonState */ 0, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
- 0, 0, 0, /* videoFrames */ {});
- getListener()->notifyMotion(&scrollArgs);
- }
-
- mRotaryEncoderScrollAccumulator.finishSync();
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
deleted file mode 100644
index 26488373bd..0000000000
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ /dev/null
@@ -1,49 +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.
- */
-
-#ifndef _UI_INPUTREADER_ROTARY_ENCODER_INPUT_MAPPER_H
-#define _UI_INPUTREADER_ROTARY_ENCODER_INPUT_MAPPER_H
-
-#include "CursorScrollAccumulator.h"
-#include "InputMapper.h"
-
-namespace android {
-
-class RotaryEncoderInputMapper : public InputMapper {
-public:
- explicit RotaryEncoderInputMapper(InputDevice* device);
- virtual ~RotaryEncoderInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(std::string& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
-private:
- CursorScrollAccumulator mRotaryEncoderScrollAccumulator;
-
- int32_t mSource;
- float mScalingFactor;
- int32_t mOrientation;
-
- void sync(nsecs_t when);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_ROTARY_ENCODER_INPUT_MAPPER_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
deleted file mode 100644
index 440d282686..0000000000
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
+++ /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.
- */
-
-#include "SingleTouchInputMapper.h"
-
-namespace android {
-
-SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) : TouchInputMapper(device) {}
-
-SingleTouchInputMapper::~SingleTouchInputMapper() {}
-
-void SingleTouchInputMapper::reset(nsecs_t when) {
- mSingleTouchMotionAccumulator.reset(getDevice());
-
- TouchInputMapper::reset(when);
-}
-
-void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
- TouchInputMapper::process(rawEvent);
-
- mSingleTouchMotionAccumulator.process(rawEvent);
-}
-
-void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
- if (mTouchButtonAccumulator.isToolActive()) {
- outState->rawPointerData.pointerCount = 1;
- outState->rawPointerData.idToIndex[0] = 0;
-
- bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE &&
- (mTouchButtonAccumulator.isHovering() ||
- (mRawPointerAxes.pressure.valid &&
- mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
- outState->rawPointerData.markIdBit(0, isHovering);
-
- RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[0];
- outPointer.id = 0;
- outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
- outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
- outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
- outPointer.touchMajor = 0;
- outPointer.touchMinor = 0;
- outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
- outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
- outPointer.orientation = 0;
- outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
- outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
- outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
- outPointer.toolType = mTouchButtonAccumulator.getToolType();
- if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
- }
- outPointer.isHovering = isHovering;
- }
-}
-
-void SingleTouchInputMapper::configureRawPointerAxes() {
- TouchInputMapper::configureRawPointerAxes();
-
- getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
- getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
- getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
- getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
- getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
- getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
- getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
-}
-
-bool SingleTouchInputMapper::hasStylus() const {
- return mTouchButtonAccumulator.hasStylus();
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
deleted file mode 100644
index d6b1455b68..0000000000
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
+++ /dev/null
@@ -1,44 +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.
- */
-
-#ifndef _UI_INPUTREADER_SINGLE_TOUCH_INPUT_MAPPER_H
-#define _UI_INPUTREADER_SINGLE_TOUCH_INPUT_MAPPER_H
-
-#include "SingleTouchMotionAccumulator.h"
-#include "TouchInputMapper.h"
-
-namespace android {
-
-class SingleTouchInputMapper : public TouchInputMapper {
-public:
- explicit SingleTouchInputMapper(InputDevice* device);
- virtual ~SingleTouchInputMapper();
-
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
-protected:
- virtual void syncTouch(nsecs_t when, RawState* outState);
- virtual void configureRawPointerAxes();
- virtual bool hasStylus() const;
-
-private:
- SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_SINGLE_TOUCH_INPUT_MAPPER_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
deleted file mode 100644
index 4ff941f5cf..0000000000
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
+++ /dev/null
@@ -1,76 +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 "Macros.h"
-
-#include "SwitchInputMapper.h"
-
-namespace android {
-
-SwitchInputMapper::SwitchInputMapper(InputDevice* device)
- : InputMapper(device), mSwitchValues(0), mUpdatedSwitchMask(0) {}
-
-SwitchInputMapper::~SwitchInputMapper() {}
-
-uint32_t SwitchInputMapper::getSources() {
- return AINPUT_SOURCE_SWITCH;
-}
-
-void SwitchInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_SW:
- processSwitch(rawEvent->code, rawEvent->value);
- break;
-
- case EV_SYN:
- if (rawEvent->code == SYN_REPORT) {
- sync(rawEvent->when);
- }
- }
-}
-
-void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
- if (switchCode >= 0 && switchCode < 32) {
- if (switchValue) {
- mSwitchValues |= 1 << switchCode;
- } else {
- mSwitchValues &= ~(1 << switchCode);
- }
- mUpdatedSwitchMask |= 1 << switchCode;
- }
-}
-
-void SwitchInputMapper::sync(nsecs_t when) {
- if (mUpdatedSwitchMask) {
- uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
- NotifySwitchArgs args(mContext->getNextSequenceNum(), when, 0, updatedSwitchValues,
- mUpdatedSwitchMask);
- getListener()->notifySwitch(&args);
-
- mUpdatedSwitchMask = 0;
- }
-}
-
-int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return getEventHub()->getSwitchState(getDeviceId(), switchCode);
-}
-
-void SwitchInputMapper::dump(std::string& dump) {
- dump += INDENT2 "Switch Input Mapper:\n";
- dump += StringPrintf(INDENT3 "SwitchValues: %x\n", mSwitchValues);
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.h b/services/inputflinger/reader/mapper/SwitchInputMapper.h
deleted file mode 100644
index dd4bb9ed65..0000000000
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.h
+++ /dev/null
@@ -1,45 +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.
- */
-
-#ifndef _UI_INPUTREADER_SWITCH_INPUT_MAPPER_H
-#define _UI_INPUTREADER_SWITCH_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-namespace android {
-
-class SwitchInputMapper : public InputMapper {
-public:
- explicit SwitchInputMapper(InputDevice* device);
- virtual ~SwitchInputMapper();
-
- virtual uint32_t getSources();
- virtual void process(const RawEvent* rawEvent);
-
- virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
- virtual void dump(std::string& dump);
-
-private:
- uint32_t mSwitchValues;
- uint32_t mUpdatedSwitchMask;
-
- void processSwitch(int32_t switchCode, int32_t switchValue);
- void sync(nsecs_t when);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_SWITCH_INPUT_MAPPER_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
deleted file mode 100644
index efa3d6d2b2..0000000000
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
+++ /dev/null
@@ -1,88 +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.
- */
-
-#ifndef _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
-#define _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
-
-#include "EventHub.h"
-#include "InputListener.h"
-#include "InputReaderContext.h"
-
-#include <stdint.h>
-
-namespace android {
-
-// --- Static Definitions ---
-
-static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
- float temp;
- switch (orientation) {
- case DISPLAY_ORIENTATION_90:
- temp = *deltaX;
- *deltaX = *deltaY;
- *deltaY = -temp;
- break;
-
- case DISPLAY_ORIENTATION_180:
- *deltaX = -*deltaX;
- *deltaY = -*deltaY;
- break;
-
- case DISPLAY_ORIENTATION_270:
- temp = *deltaX;
- *deltaX = -*deltaY;
- *deltaY = temp;
- break;
- }
-}
-
-// Returns true if the pointer should be reported as being down given the specified
-// button states. This determines whether the event is reported as a touch event.
-static bool isPointerDown(int32_t buttonState) {
- return buttonState &
- (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY |
- AMOTION_EVENT_BUTTON_TERTIARY);
-}
-
-static void synthesizeButtonKey(InputReaderContext* context, int32_t action, nsecs_t when,
- int32_t deviceId, uint32_t source, int32_t displayId,
- uint32_t policyFlags, int32_t lastButtonState,
- int32_t currentButtonState, int32_t buttonState, int32_t keyCode) {
- if ((action == AKEY_EVENT_ACTION_DOWN && !(lastButtonState & buttonState) &&
- (currentButtonState & buttonState)) ||
- (action == AKEY_EVENT_ACTION_UP && (lastButtonState & buttonState) &&
- !(currentButtonState & buttonState))) {
- NotifyKeyArgs args(context->getNextSequenceNum(), when, deviceId, source, displayId,
- policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when);
- context->getListener()->notifyKey(&args);
- }
-}
-
-static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, nsecs_t when,
- int32_t deviceId, uint32_t source, int32_t displayId,
- uint32_t policyFlags, int32_t lastButtonState,
- int32_t currentButtonState) {
- synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
- lastButtonState, currentButtonState, AMOTION_EVENT_BUTTON_BACK,
- AKEYCODE_BACK);
- synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
- lastButtonState, currentButtonState, AMOTION_EVENT_BUTTON_FORWARD,
- AKEYCODE_FORWARD);
-}
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
deleted file mode 100644
index 32ed97bffe..0000000000
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ /dev/null
@@ -1,3909 +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 "Macros.h"
-
-#include "TouchInputMapper.h"
-
-#include "CursorButtonAccumulator.h"
-#include "CursorScrollAccumulator.h"
-#include "TouchButtonAccumulator.h"
-#include "TouchCursorInputMapperCommon.h"
-
-#include <statslog.h>
-
-// How often to report input event statistics
-static constexpr nsecs_t STATISTICS_REPORT_FREQUENCY = seconds_to_nanoseconds(5 * 60);
-
-namespace android {
-
-// --- Constants ---
-
-// Maximum amount of latency to add to touch events while waiting for data from an
-// external stylus.
-static constexpr nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72);
-
-// Maximum amount of time to wait on touch data before pushing out new pressure data.
-static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20);
-
-// Artificial latency on synthetic events created from stylus data without corresponding touch
-// data.
-static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
-
-// --- Static Definitions ---
-
-template <typename T>
-inline static void swap(T& a, T& b) {
- T temp = a;
- a = b;
- b = temp;
-}
-
-static float calculateCommonVector(float a, float b) {
- if (a > 0 && b > 0) {
- return a < b ? a : b;
- } else if (a < 0 && b < 0) {
- return a > b ? a : b;
- } else {
- return 0;
- }
-}
-
-inline static float distance(float x1, float y1, float x2, float y2) {
- return hypotf(x1 - x2, y1 - y2);
-}
-
-inline static int32_t signExtendNybble(int32_t value) {
- return value >= 8 ? value - 16 : value;
-}
-
-// --- RawPointerAxes ---
-
-RawPointerAxes::RawPointerAxes() {
- clear();
-}
-
-void RawPointerAxes::clear() {
- x.clear();
- y.clear();
- pressure.clear();
- touchMajor.clear();
- touchMinor.clear();
- toolMajor.clear();
- toolMinor.clear();
- orientation.clear();
- distance.clear();
- tiltX.clear();
- tiltY.clear();
- trackingId.clear();
- slot.clear();
-}
-
-// --- RawPointerData ---
-
-RawPointerData::RawPointerData() {
- clear();
-}
-
-void RawPointerData::clear() {
- pointerCount = 0;
- clearIdBits();
-}
-
-void RawPointerData::copyFrom(const RawPointerData& other) {
- pointerCount = other.pointerCount;
- hoveringIdBits = other.hoveringIdBits;
- touchingIdBits = other.touchingIdBits;
-
- for (uint32_t i = 0; i < pointerCount; i++) {
- pointers[i] = other.pointers[i];
-
- int id = pointers[i].id;
- idToIndex[id] = other.idToIndex[id];
- }
-}
-
-void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
- float x = 0, y = 0;
- uint32_t count = touchingIdBits.count();
- if (count) {
- for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const Pointer& pointer = pointerForId(id);
- x += pointer.x;
- y += pointer.y;
- }
- x /= count;
- y /= count;
- }
- *outX = x;
- *outY = y;
-}
-
-// --- CookedPointerData ---
-
-CookedPointerData::CookedPointerData() {
- clear();
-}
-
-void CookedPointerData::clear() {
- pointerCount = 0;
- hoveringIdBits.clear();
- touchingIdBits.clear();
-}
-
-void CookedPointerData::copyFrom(const CookedPointerData& other) {
- pointerCount = other.pointerCount;
- hoveringIdBits = other.hoveringIdBits;
- touchingIdBits = other.touchingIdBits;
-
- for (uint32_t i = 0; i < pointerCount; i++) {
- pointerProperties[i].copyFrom(other.pointerProperties[i]);
- pointerCoords[i].copyFrom(other.pointerCoords[i]);
-
- int id = pointerProperties[i].id;
- idToIndex[id] = other.idToIndex[id];
- }
-}
-
-// --- TouchInputMapper ---
-
-TouchInputMapper::TouchInputMapper(InputDevice* device)
- : InputMapper(device),
- mSource(0),
- mDeviceMode(DEVICE_MODE_DISABLED),
- mSurfaceWidth(-1),
- mSurfaceHeight(-1),
- mSurfaceLeft(0),
- mSurfaceTop(0),
- mPhysicalWidth(-1),
- mPhysicalHeight(-1),
- mPhysicalLeft(0),
- mPhysicalTop(0),
- mSurfaceOrientation(DISPLAY_ORIENTATION_0) {}
-
-TouchInputMapper::~TouchInputMapper() {}
-
-uint32_t TouchInputMapper::getSources() {
- return mSource;
-}
-
-void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- if (mDeviceMode != DEVICE_MODE_DISABLED) {
- info->addMotionRange(mOrientedRanges.x);
- info->addMotionRange(mOrientedRanges.y);
- info->addMotionRange(mOrientedRanges.pressure);
-
- if (mOrientedRanges.haveSize) {
- info->addMotionRange(mOrientedRanges.size);
- }
-
- if (mOrientedRanges.haveTouchSize) {
- info->addMotionRange(mOrientedRanges.touchMajor);
- info->addMotionRange(mOrientedRanges.touchMinor);
- }
-
- if (mOrientedRanges.haveToolSize) {
- info->addMotionRange(mOrientedRanges.toolMajor);
- info->addMotionRange(mOrientedRanges.toolMinor);
- }
-
- if (mOrientedRanges.haveOrientation) {
- info->addMotionRange(mOrientedRanges.orientation);
- }
-
- if (mOrientedRanges.haveDistance) {
- info->addMotionRange(mOrientedRanges.distance);
- }
-
- if (mOrientedRanges.haveTilt) {
- info->addMotionRange(mOrientedRanges.tilt);
- }
-
- if (mCursorScrollAccumulator.haveRelativeVWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
- 0.0f);
- }
- if (mCursorScrollAccumulator.haveRelativeHWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
- 0.0f);
- }
- if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
- const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
- const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
- x.fuzz, x.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
- y.fuzz, y.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
- x.fuzz, x.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
- y.fuzz, y.resolution);
- }
- info->setButtonUnderPad(mParameters.hasButtonUnderPad);
- }
-}
-
-void TouchInputMapper::dump(std::string& dump) {
- dump += StringPrintf(INDENT2 "Touch Input Mapper (mode - %s):\n", modeToString(mDeviceMode));
- dumpParameters(dump);
- dumpVirtualKeys(dump);
- dumpRawPointerAxes(dump);
- dumpCalibration(dump);
- dumpAffineTransformation(dump);
- dumpSurface(dump);
-
- dump += StringPrintf(INDENT3 "Translation and Scaling Factors:\n");
- dump += StringPrintf(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
- dump += StringPrintf(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
- dump += StringPrintf(INDENT4 "XScale: %0.3f\n", mXScale);
- dump += StringPrintf(INDENT4 "YScale: %0.3f\n", mYScale);
- dump += StringPrintf(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
- dump += StringPrintf(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
- dump += StringPrintf(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
- dump += StringPrintf(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
- dump += StringPrintf(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
- dump += StringPrintf(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
- dump += StringPrintf(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
- dump += StringPrintf(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
- dump += StringPrintf(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
- dump += StringPrintf(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
- dump += StringPrintf(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
- dump += StringPrintf(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
-
- dump += StringPrintf(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState);
- dump += StringPrintf(INDENT3 "Last Raw Touch: pointerCount=%d\n",
- mLastRawState.rawPointerData.pointerCount);
- for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
- const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
- dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
- "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
- "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
- "toolType=%d, isHovering=%s\n",
- i, pointer.id, pointer.x, pointer.y, pointer.pressure,
- pointer.touchMajor, pointer.touchMinor, pointer.toolMajor,
- pointer.toolMinor, pointer.orientation, pointer.tiltX, pointer.tiltY,
- pointer.distance, pointer.toolType, toString(pointer.isHovering));
- }
-
- dump += StringPrintf(INDENT3 "Last Cooked Button State: 0x%08x\n",
- mLastCookedState.buttonState);
- dump += StringPrintf(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
- mLastCookedState.cookedPointerData.pointerCount);
- for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
- const PointerProperties& pointerProperties =
- mLastCookedState.cookedPointerData.pointerProperties[i];
- const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
- dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
- "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, "
- "toolMinor=%0.3f, "
- "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
- "toolType=%d, isHovering=%s\n",
- i, pointerProperties.id, pointerCoords.getX(), pointerCoords.getY(),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
- pointerProperties.toolType,
- toString(mLastCookedState.cookedPointerData.isHovering(i)));
- }
-
- dump += INDENT3 "Stylus Fusion:\n";
- dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n",
- toString(mExternalStylusConnected));
- dump += StringPrintf(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
- dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
- mExternalStylusFusionTimeout);
- dump += INDENT3 "External Stylus State:\n";
- dumpStylusState(dump, mExternalStylusState);
-
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- dump += StringPrintf(INDENT3 "Pointer Gesture Detector:\n");
- dump += StringPrintf(INDENT4 "XMovementScale: %0.3f\n", mPointerXMovementScale);
- dump += StringPrintf(INDENT4 "YMovementScale: %0.3f\n", mPointerYMovementScale);
- dump += StringPrintf(INDENT4 "XZoomScale: %0.3f\n", mPointerXZoomScale);
- dump += StringPrintf(INDENT4 "YZoomScale: %0.3f\n", mPointerYZoomScale);
- dump += StringPrintf(INDENT4 "MaxSwipeWidth: %f\n", mPointerGestureMaxSwipeWidth);
- }
-}
-
-const char* TouchInputMapper::modeToString(DeviceMode deviceMode) {
- switch (deviceMode) {
- case DEVICE_MODE_DISABLED:
- return "disabled";
- case DEVICE_MODE_DIRECT:
- return "direct";
- case DEVICE_MODE_UNSCALED:
- return "unscaled";
- case DEVICE_MODE_NAVIGATION:
- return "navigation";
- case DEVICE_MODE_POINTER:
- return "pointer";
- }
- return "unknown";
-}
-
-void TouchInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) {
- InputMapper::configure(when, config, changes);
-
- mConfig = *config;
-
- if (!changes) { // first time only
- // Configure basic parameters.
- configureParameters();
-
- // Configure common accumulators.
- mCursorScrollAccumulator.configure(getDevice());
- mTouchButtonAccumulator.configure(getDevice());
-
- // Configure absolute axis information.
- configureRawPointerAxes();
-
- // Prepare input device calibration.
- parseCalibration();
- resolveCalibration();
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) {
- // Update location calibration to reflect current settings
- updateAffineTransformation();
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
- // Update pointer speed.
- mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
- mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
- mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
- }
-
- bool resetNeeded = false;
- if (!changes ||
- (changes &
- (InputReaderConfiguration::CHANGE_DISPLAY_INFO |
- InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT |
- InputReaderConfiguration::CHANGE_SHOW_TOUCHES |
- InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
- // Configure device sources, surface dimensions, orientation and
- // scaling factors.
- configureSurface(when, &resetNeeded);
- }
-
- if (changes && resetNeeded) {
- // Send reset, unless this is the first time the device has been configured,
- // in which case the reader will call reset itself after all mappers are ready.
- getDevice()->notifyReset(when);
- }
-}
-
-void TouchInputMapper::resolveExternalStylusPresence() {
- std::vector<InputDeviceInfo> devices;
- mContext->getExternalStylusDevices(devices);
- mExternalStylusConnected = !devices.empty();
-
- if (!mExternalStylusConnected) {
- resetExternalStylus();
- }
-}
-
-void TouchInputMapper::configureParameters() {
- // Use the pointer presentation mode for devices that do not support distinct
- // multitouch. The spot-based presentation relies on being able to accurately
- // locate two or more fingers on the touch pad.
- mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
- ? Parameters::GESTURE_MODE_SINGLE_TOUCH
- : Parameters::GESTURE_MODE_MULTI_TOUCH;
-
- String8 gestureModeString;
- if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
- gestureModeString)) {
- if (gestureModeString == "single-touch") {
- mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
- } else if (gestureModeString == "multi-touch") {
- mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
- } else if (gestureModeString != "default") {
- ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
- }
- }
-
- if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
- // The device is a touch screen.
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
- } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
- // The device is a pointing device like a track pad.
- mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
- } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X) ||
- getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
- // The device is a cursor device with a touch pad attached.
- // By default don't use the touch pad to move the pointer.
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
- } else {
- // The device is a touch pad of unknown purpose.
- mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
- }
-
- mParameters.hasButtonUnderPad =
- getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_BUTTONPAD);
-
- String8 deviceTypeString;
- if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
- deviceTypeString)) {
- if (deviceTypeString == "touchScreen") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
- } else if (deviceTypeString == "touchPad") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
- } else if (deviceTypeString == "touchNavigation") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
- } else if (deviceTypeString == "pointer") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
- } else if (deviceTypeString != "default") {
- ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
- }
- }
-
- mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
- getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
- mParameters.orientationAware);
-
- mParameters.hasAssociatedDisplay = false;
- mParameters.associatedDisplayIsExternal = false;
- if (mParameters.orientationAware ||
- mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN ||
- mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
- mParameters.hasAssociatedDisplay = true;
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
- mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
- String8 uniqueDisplayId;
- getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
- uniqueDisplayId);
- mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
- }
- }
- if (getDevice()->getAssociatedDisplayPort()) {
- mParameters.hasAssociatedDisplay = true;
- }
-
- // Initial downs on external touch devices should wake the device.
- // Normally we don't do this for internal touch screens to prevent them from waking
- // up in your pocket but you can enable it using the input device configuration.
- mParameters.wake = getDevice()->isExternal();
- getDevice()->getConfiguration().tryGetProperty(String8("touch.wake"), mParameters.wake);
-}
-
-void TouchInputMapper::dumpParameters(std::string& dump) {
- dump += INDENT3 "Parameters:\n";
-
- switch (mParameters.gestureMode) {
- case Parameters::GESTURE_MODE_SINGLE_TOUCH:
- dump += INDENT4 "GestureMode: single-touch\n";
- break;
- case Parameters::GESTURE_MODE_MULTI_TOUCH:
- dump += INDENT4 "GestureMode: multi-touch\n";
- break;
- default:
- assert(false);
- }
-
- switch (mParameters.deviceType) {
- case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
- dump += INDENT4 "DeviceType: touchScreen\n";
- break;
- case Parameters::DEVICE_TYPE_TOUCH_PAD:
- dump += INDENT4 "DeviceType: touchPad\n";
- break;
- case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
- dump += INDENT4 "DeviceType: touchNavigation\n";
- break;
- case Parameters::DEVICE_TYPE_POINTER:
- dump += INDENT4 "DeviceType: pointer\n";
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- dump += StringPrintf(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, "
- "displayId='%s'\n",
- toString(mParameters.hasAssociatedDisplay),
- toString(mParameters.associatedDisplayIsExternal),
- mParameters.uniqueDisplayId.c_str());
- dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
-}
-
-void TouchInputMapper::configureRawPointerAxes() {
- mRawPointerAxes.clear();
-}
-
-void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
- dump += INDENT3 "Raw Touch Axes:\n";
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
-}
-
-bool TouchInputMapper::hasExternalStylus() const {
- return mExternalStylusConnected;
-}
-
-/**
- * Determine which DisplayViewport to use.
- * 1. If display port is specified, return the matching viewport. If matching viewport not
- * found, then return.
- * 2. If a device has associated display, get the matching viewport by either unique id or by
- * the display type (internal or external).
- * 3. Otherwise, use a non-display viewport.
- */
-std::optional<DisplayViewport> TouchInputMapper::findViewport() {
- if (mParameters.hasAssociatedDisplay) {
- const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
- if (displayPort) {
- // Find the viewport that contains the same port
- std::optional<DisplayViewport> v = mConfig.getDisplayViewportByPort(*displayPort);
- if (!v) {
- ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
- "but the corresponding viewport is not found.",
- getDeviceName().c_str(), *displayPort);
- }
- return v;
- }
-
- if (!mParameters.uniqueDisplayId.empty()) {
- return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
- }
-
- ViewportType viewportTypeToUse;
- if (mParameters.associatedDisplayIsExternal) {
- viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
- } else {
- viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
- }
-
- std::optional<DisplayViewport> viewport =
- mConfig.getDisplayViewportByType(viewportTypeToUse);
- if (!viewport && viewportTypeToUse == ViewportType::VIEWPORT_EXTERNAL) {
- ALOGW("Input device %s should be associated with external display, "
- "fallback to internal one for the external viewport is not found.",
- getDeviceName().c_str());
- viewport = mConfig.getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
- }
-
- return viewport;
- }
-
- DisplayViewport newViewport;
- // Raw width and height in the natural orientation.
- int32_t rawWidth = mRawPointerAxes.getRawWidth();
- int32_t rawHeight = mRawPointerAxes.getRawHeight();
- newViewport.setNonDisplayViewport(rawWidth, rawHeight);
- return std::make_optional(newViewport);
-}
-
-void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
- int32_t oldDeviceMode = mDeviceMode;
-
- resolveExternalStylusPresence();
-
- // Determine device mode.
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER &&
- mConfig.pointerGesturesEnabled) {
- mSource = AINPUT_SOURCE_MOUSE;
- mDeviceMode = DEVICE_MODE_POINTER;
- if (hasStylus()) {
- mSource |= AINPUT_SOURCE_STYLUS;
- }
- } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN &&
- mParameters.hasAssociatedDisplay) {
- mSource = AINPUT_SOURCE_TOUCHSCREEN;
- mDeviceMode = DEVICE_MODE_DIRECT;
- if (hasStylus()) {
- mSource |= AINPUT_SOURCE_STYLUS;
- }
- if (hasExternalStylus()) {
- mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
- }
- } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
- mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
- mDeviceMode = DEVICE_MODE_NAVIGATION;
- } else {
- mSource = AINPUT_SOURCE_TOUCHPAD;
- mDeviceMode = DEVICE_MODE_UNSCALED;
- }
-
- // Ensure we have valid X and Y axes.
- if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
- ALOGW("Touch device '%s' did not report support for X or Y axis! "
- "The device will be inoperable.",
- getDeviceName().c_str());
- mDeviceMode = DEVICE_MODE_DISABLED;
- return;
- }
-
- // Get associated display dimensions.
- std::optional<DisplayViewport> newViewport = findViewport();
- if (!newViewport) {
- ALOGI("Touch device '%s' could not query the properties of its associated "
- "display. The device will be inoperable until the display size "
- "becomes available.",
- getDeviceName().c_str());
- mDeviceMode = DEVICE_MODE_DISABLED;
- return;
- }
-
- // Raw width and height in the natural orientation.
- int32_t rawWidth = mRawPointerAxes.getRawWidth();
- int32_t rawHeight = mRawPointerAxes.getRawHeight();
-
- bool viewportChanged = mViewport != *newViewport;
- if (viewportChanged) {
- mViewport = *newViewport;
-
- if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
- // Convert rotated viewport to natural surface coordinates.
- int32_t naturalLogicalWidth, naturalLogicalHeight;
- int32_t naturalPhysicalWidth, naturalPhysicalHeight;
- int32_t naturalPhysicalLeft, naturalPhysicalTop;
- int32_t naturalDeviceWidth, naturalDeviceHeight;
- switch (mViewport.orientation) {
- case DISPLAY_ORIENTATION_90:
- naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
- naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
- naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
- naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
- naturalPhysicalTop = mViewport.physicalLeft;
- naturalDeviceWidth = mViewport.deviceHeight;
- naturalDeviceHeight = mViewport.deviceWidth;
- break;
- case DISPLAY_ORIENTATION_180:
- naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
- naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
- naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
- naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
- naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
- naturalDeviceWidth = mViewport.deviceWidth;
- naturalDeviceHeight = mViewport.deviceHeight;
- break;
- case DISPLAY_ORIENTATION_270:
- naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
- naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
- naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
- naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalLeft = mViewport.physicalTop;
- naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
- naturalDeviceWidth = mViewport.deviceHeight;
- naturalDeviceHeight = mViewport.deviceWidth;
- break;
- case DISPLAY_ORIENTATION_0:
- default:
- naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
- naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
- naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
- naturalPhysicalLeft = mViewport.physicalLeft;
- naturalPhysicalTop = mViewport.physicalTop;
- naturalDeviceWidth = mViewport.deviceWidth;
- naturalDeviceHeight = mViewport.deviceHeight;
- break;
- }
-
- if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
- ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
- naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
- naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
- }
-
- mPhysicalWidth = naturalPhysicalWidth;
- mPhysicalHeight = naturalPhysicalHeight;
- mPhysicalLeft = naturalPhysicalLeft;
- mPhysicalTop = naturalPhysicalTop;
-
- mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
- mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
- mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
- mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
-
- mSurfaceOrientation =
- mParameters.orientationAware ? mViewport.orientation : DISPLAY_ORIENTATION_0;
- } else {
- mPhysicalWidth = rawWidth;
- mPhysicalHeight = rawHeight;
- mPhysicalLeft = 0;
- mPhysicalTop = 0;
-
- mSurfaceWidth = rawWidth;
- mSurfaceHeight = rawHeight;
- mSurfaceLeft = 0;
- mSurfaceTop = 0;
- mSurfaceOrientation = DISPLAY_ORIENTATION_0;
- }
- }
-
- // If moving between pointer modes, need to reset some state.
- bool deviceModeChanged = mDeviceMode != oldDeviceMode;
- if (deviceModeChanged) {
- mOrientedRanges.clear();
- }
-
- // Create or update pointer controller if needed.
- if (mDeviceMode == DEVICE_MODE_POINTER ||
- (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
- if (mPointerController == nullptr || viewportChanged) {
- mPointerController = getPolicy()->obtainPointerController(getDeviceId());
- }
- } else {
- mPointerController.clear();
- }
-
- if (viewportChanged || deviceModeChanged) {
- ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
- "display id %d",
- getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
- mSurfaceOrientation, mDeviceMode, mViewport.displayId);
-
- // Configure X and Y factors.
- mXScale = float(mSurfaceWidth) / rawWidth;
- mYScale = float(mSurfaceHeight) / rawHeight;
- mXTranslate = -mSurfaceLeft;
- mYTranslate = -mSurfaceTop;
- mXPrecision = 1.0f / mXScale;
- mYPrecision = 1.0f / mYScale;
-
- mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
- mOrientedRanges.x.source = mSource;
- mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
- mOrientedRanges.y.source = mSource;
-
- configureVirtualKeys();
-
- // Scale factor for terms that are not oriented in a particular axis.
- // If the pixels are square then xScale == yScale otherwise we fake it
- // by choosing an average.
- mGeometricScale = avg(mXScale, mYScale);
-
- // Size of diagonal axis.
- float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
-
- // Size factors.
- if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
- if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.touchMajor.maxValue != 0) {
- mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
- } else if (mRawPointerAxes.toolMajor.valid && mRawPointerAxes.toolMajor.maxValue != 0) {
- mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
- } else {
- mSizeScale = 0.0f;
- }
-
- mOrientedRanges.haveTouchSize = true;
- mOrientedRanges.haveToolSize = true;
- mOrientedRanges.haveSize = true;
-
- mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
- mOrientedRanges.touchMajor.source = mSource;
- mOrientedRanges.touchMajor.min = 0;
- mOrientedRanges.touchMajor.max = diagonalSize;
- mOrientedRanges.touchMajor.flat = 0;
- mOrientedRanges.touchMajor.fuzz = 0;
- mOrientedRanges.touchMajor.resolution = 0;
-
- mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
- mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
-
- mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
- mOrientedRanges.toolMajor.source = mSource;
- mOrientedRanges.toolMajor.min = 0;
- mOrientedRanges.toolMajor.max = diagonalSize;
- mOrientedRanges.toolMajor.flat = 0;
- mOrientedRanges.toolMajor.fuzz = 0;
- mOrientedRanges.toolMajor.resolution = 0;
-
- mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
- mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
-
- mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
- mOrientedRanges.size.source = mSource;
- mOrientedRanges.size.min = 0;
- mOrientedRanges.size.max = 1.0;
- mOrientedRanges.size.flat = 0;
- mOrientedRanges.size.fuzz = 0;
- mOrientedRanges.size.resolution = 0;
- } else {
- mSizeScale = 0.0f;
- }
-
- // Pressure factors.
- mPressureScale = 0;
- float pressureMax = 1.0;
- if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL ||
- mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
- if (mCalibration.havePressureScale) {
- mPressureScale = mCalibration.pressureScale;
- pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
- } else if (mRawPointerAxes.pressure.valid && mRawPointerAxes.pressure.maxValue != 0) {
- mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
- }
- }
-
- mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
- mOrientedRanges.pressure.source = mSource;
- mOrientedRanges.pressure.min = 0;
- mOrientedRanges.pressure.max = pressureMax;
- mOrientedRanges.pressure.flat = 0;
- mOrientedRanges.pressure.fuzz = 0;
- mOrientedRanges.pressure.resolution = 0;
-
- // Tilt
- mTiltXCenter = 0;
- mTiltXScale = 0;
- mTiltYCenter = 0;
- mTiltYScale = 0;
- mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
- if (mHaveTilt) {
- mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue, mRawPointerAxes.tiltX.maxValue);
- mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue, mRawPointerAxes.tiltY.maxValue);
- mTiltXScale = M_PI / 180;
- mTiltYScale = M_PI / 180;
-
- mOrientedRanges.haveTilt = true;
-
- mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
- mOrientedRanges.tilt.source = mSource;
- mOrientedRanges.tilt.min = 0;
- mOrientedRanges.tilt.max = M_PI_2;
- mOrientedRanges.tilt.flat = 0;
- mOrientedRanges.tilt.fuzz = 0;
- mOrientedRanges.tilt.resolution = 0;
- }
-
- // Orientation
- mOrientationScale = 0;
- if (mHaveTilt) {
- mOrientedRanges.haveOrientation = true;
-
- mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
- mOrientedRanges.orientation.source = mSource;
- mOrientedRanges.orientation.min = -M_PI;
- mOrientedRanges.orientation.max = M_PI;
- mOrientedRanges.orientation.flat = 0;
- mOrientedRanges.orientation.fuzz = 0;
- mOrientedRanges.orientation.resolution = 0;
- } else if (mCalibration.orientationCalibration !=
- Calibration::ORIENTATION_CALIBRATION_NONE) {
- if (mCalibration.orientationCalibration ==
- Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
- if (mRawPointerAxes.orientation.valid) {
- if (mRawPointerAxes.orientation.maxValue > 0) {
- mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
- } else if (mRawPointerAxes.orientation.minValue < 0) {
- mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
- } else {
- mOrientationScale = 0;
- }
- }
- }
-
- mOrientedRanges.haveOrientation = true;
-
- mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
- mOrientedRanges.orientation.source = mSource;
- mOrientedRanges.orientation.min = -M_PI_2;
- mOrientedRanges.orientation.max = M_PI_2;
- mOrientedRanges.orientation.flat = 0;
- mOrientedRanges.orientation.fuzz = 0;
- mOrientedRanges.orientation.resolution = 0;
- }
-
- // Distance
- mDistanceScale = 0;
- if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
- if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_SCALED) {
- if (mCalibration.haveDistanceScale) {
- mDistanceScale = mCalibration.distanceScale;
- } else {
- mDistanceScale = 1.0f;
- }
- }
-
- mOrientedRanges.haveDistance = true;
-
- mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
- mOrientedRanges.distance.source = mSource;
- mOrientedRanges.distance.min = mRawPointerAxes.distance.minValue * mDistanceScale;
- mOrientedRanges.distance.max = mRawPointerAxes.distance.maxValue * mDistanceScale;
- mOrientedRanges.distance.flat = 0;
- mOrientedRanges.distance.fuzz = mRawPointerAxes.distance.fuzz * mDistanceScale;
- mOrientedRanges.distance.resolution = 0;
- }
-
- // Compute oriented precision, scales and ranges.
- // Note that the maximum value reported is an inclusive maximum value so it is one
- // unit less than the total width or height of surface.
- switch (mSurfaceOrientation) {
- case DISPLAY_ORIENTATION_90:
- case DISPLAY_ORIENTATION_270:
- mOrientedXPrecision = mYPrecision;
- mOrientedYPrecision = mXPrecision;
-
- mOrientedRanges.x.min = mYTranslate;
- mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
- mOrientedRanges.x.flat = 0;
- mOrientedRanges.x.fuzz = 0;
- mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
-
- mOrientedRanges.y.min = mXTranslate;
- mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
- mOrientedRanges.y.flat = 0;
- mOrientedRanges.y.fuzz = 0;
- mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
- break;
-
- default:
- mOrientedXPrecision = mXPrecision;
- mOrientedYPrecision = mYPrecision;
-
- mOrientedRanges.x.min = mXTranslate;
- mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
- mOrientedRanges.x.flat = 0;
- mOrientedRanges.x.fuzz = 0;
- mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
-
- mOrientedRanges.y.min = mYTranslate;
- mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
- mOrientedRanges.y.flat = 0;
- mOrientedRanges.y.fuzz = 0;
- mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
- break;
- }
-
- // Location
- updateAffineTransformation();
-
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- // Compute pointer gesture detection parameters.
- float rawDiagonal = hypotf(rawWidth, rawHeight);
- float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
-
- // Scale movements such that one whole swipe of the touch pad covers a
- // given area relative to the diagonal size of the display when no acceleration
- // is applied.
- // Assume that the touch pad has a square aspect ratio such that movements in
- // X and Y of the same number of raw units cover the same physical distance.
- mPointerXMovementScale =
- mConfig.pointerGestureMovementSpeedRatio * displayDiagonal / rawDiagonal;
- mPointerYMovementScale = mPointerXMovementScale;
-
- // Scale zooms to cover a smaller range of the display than movements do.
- // This value determines the area around the pointer that is affected by freeform
- // pointer gestures.
- mPointerXZoomScale =
- mConfig.pointerGestureZoomSpeedRatio * displayDiagonal / rawDiagonal;
- mPointerYZoomScale = mPointerXZoomScale;
-
- // Max width between pointers to detect a swipe gesture is more than some fraction
- // of the diagonal axis of the touch pad. Touches that are wider than this are
- // translated into freeform gestures.
- mPointerGestureMaxSwipeWidth = mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
-
- // Abort current pointer usages because the state has changed.
- abortPointerUsage(when, 0 /*policyFlags*/);
- }
-
- // Inform the dispatcher about the changes.
- *outResetNeeded = true;
- bumpGeneration();
- }
-}
-
-void TouchInputMapper::dumpSurface(std::string& dump) {
- dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
- dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
- dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
- dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
- dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
- dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
- dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
- dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
- dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
- dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
-}
-
-void TouchInputMapper::configureVirtualKeys() {
- std::vector<VirtualKeyDefinition> virtualKeyDefinitions;
- getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
-
- mVirtualKeys.clear();
-
- if (virtualKeyDefinitions.size() == 0) {
- return;
- }
-
- int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
- int32_t touchScreenTop = mRawPointerAxes.y.minValue;
- int32_t touchScreenWidth = mRawPointerAxes.getRawWidth();
- int32_t touchScreenHeight = mRawPointerAxes.getRawHeight();
-
- for (const VirtualKeyDefinition& virtualKeyDefinition : virtualKeyDefinitions) {
- VirtualKey virtualKey;
-
- virtualKey.scanCode = virtualKeyDefinition.scanCode;
- int32_t keyCode;
- int32_t dummyKeyMetaState;
- uint32_t flags;
- if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, 0, &keyCode,
- &dummyKeyMetaState, &flags)) {
- ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
- continue; // drop the key
- }
-
- virtualKey.keyCode = keyCode;
- virtualKey.flags = flags;
-
- // convert the key definition's display coordinates into touch coordinates for a hit box
- int32_t halfWidth = virtualKeyDefinition.width / 2;
- int32_t halfHeight = virtualKeyDefinition.height / 2;
-
- virtualKey.hitLeft =
- (virtualKeyDefinition.centerX - halfWidth) * touchScreenWidth / mSurfaceWidth +
- touchScreenLeft;
- virtualKey.hitRight =
- (virtualKeyDefinition.centerX + halfWidth) * touchScreenWidth / mSurfaceWidth +
- touchScreenLeft;
- virtualKey.hitTop =
- (virtualKeyDefinition.centerY - halfHeight) * touchScreenHeight / mSurfaceHeight +
- touchScreenTop;
- virtualKey.hitBottom =
- (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight / mSurfaceHeight +
- touchScreenTop;
- mVirtualKeys.push_back(virtualKey);
- }
-}
-
-void TouchInputMapper::dumpVirtualKeys(std::string& dump) {
- if (!mVirtualKeys.empty()) {
- dump += INDENT3 "Virtual Keys:\n";
-
- for (size_t i = 0; i < mVirtualKeys.size(); i++) {
- const VirtualKey& virtualKey = mVirtualKeys[i];
- dump += StringPrintf(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
- "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
- i, virtualKey.scanCode, virtualKey.keyCode, virtualKey.hitLeft,
- virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
- }
- }
-}
-
-void TouchInputMapper::parseCalibration() {
- const PropertyMap& in = getDevice()->getConfiguration();
- Calibration& out = mCalibration;
-
- // Size
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
- String8 sizeCalibrationString;
- if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
- if (sizeCalibrationString == "none") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
- } else if (sizeCalibrationString == "geometric") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
- } else if (sizeCalibrationString == "diameter") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
- } else if (sizeCalibrationString == "box") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
- } else if (sizeCalibrationString == "area") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
- } else if (sizeCalibrationString != "default") {
- ALOGW("Invalid value for touch.size.calibration: '%s'", sizeCalibrationString.string());
- }
- }
-
- out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"), out.sizeScale);
- out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"), out.sizeBias);
- out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"), out.sizeIsSummed);
-
- // Pressure
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
- String8 pressureCalibrationString;
- if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
- if (pressureCalibrationString == "none") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
- } else if (pressureCalibrationString == "physical") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
- } else if (pressureCalibrationString == "amplitude") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
- } else if (pressureCalibrationString != "default") {
- ALOGW("Invalid value for touch.pressure.calibration: '%s'",
- pressureCalibrationString.string());
- }
- }
-
- out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"), out.pressureScale);
-
- // Orientation
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
- String8 orientationCalibrationString;
- if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
- if (orientationCalibrationString == "none") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
- } else if (orientationCalibrationString == "interpolated") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
- } else if (orientationCalibrationString == "vector") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
- } else if (orientationCalibrationString != "default") {
- ALOGW("Invalid value for touch.orientation.calibration: '%s'",
- orientationCalibrationString.string());
- }
- }
-
- // Distance
- out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
- String8 distanceCalibrationString;
- if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
- if (distanceCalibrationString == "none") {
- out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
- } else if (distanceCalibrationString == "scaled") {
- out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
- } else if (distanceCalibrationString != "default") {
- ALOGW("Invalid value for touch.distance.calibration: '%s'",
- distanceCalibrationString.string());
- }
- }
-
- out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"), out.distanceScale);
-
- out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
- String8 coverageCalibrationString;
- if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
- if (coverageCalibrationString == "none") {
- out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
- } else if (coverageCalibrationString == "box") {
- out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
- } else if (coverageCalibrationString != "default") {
- ALOGW("Invalid value for touch.coverage.calibration: '%s'",
- coverageCalibrationString.string());
- }
- }
-}
-
-void TouchInputMapper::resolveCalibration() {
- // Size
- if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
- if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
- mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
- }
- } else {
- mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
- }
-
- // Pressure
- if (mRawPointerAxes.pressure.valid) {
- if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
- mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
- }
- } else {
- mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
- }
-
- // Orientation
- if (mRawPointerAxes.orientation.valid) {
- if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
- mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
- }
- } else {
- mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
- }
-
- // Distance
- if (mRawPointerAxes.distance.valid) {
- if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
- mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
- }
- } else {
- mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
- }
-
- // Coverage
- if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
- mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
- }
-}
-
-void TouchInputMapper::dumpCalibration(std::string& dump) {
- dump += INDENT3 "Calibration:\n";
-
- // Size
- switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_NONE:
- dump += INDENT4 "touch.size.calibration: none\n";
- break;
- case Calibration::SIZE_CALIBRATION_GEOMETRIC:
- dump += INDENT4 "touch.size.calibration: geometric\n";
- break;
- case Calibration::SIZE_CALIBRATION_DIAMETER:
- dump += INDENT4 "touch.size.calibration: diameter\n";
- break;
- case Calibration::SIZE_CALIBRATION_BOX:
- dump += INDENT4 "touch.size.calibration: box\n";
- break;
- case Calibration::SIZE_CALIBRATION_AREA:
- dump += INDENT4 "touch.size.calibration: area\n";
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- if (mCalibration.haveSizeScale) {
- dump += StringPrintf(INDENT4 "touch.size.scale: %0.3f\n", mCalibration.sizeScale);
- }
-
- if (mCalibration.haveSizeBias) {
- dump += StringPrintf(INDENT4 "touch.size.bias: %0.3f\n", mCalibration.sizeBias);
- }
-
- if (mCalibration.haveSizeIsSummed) {
- dump += StringPrintf(INDENT4 "touch.size.isSummed: %s\n",
- toString(mCalibration.sizeIsSummed));
- }
-
- // Pressure
- switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_NONE:
- dump += INDENT4 "touch.pressure.calibration: none\n";
- break;
- case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
- dump += INDENT4 "touch.pressure.calibration: physical\n";
- break;
- case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
- dump += INDENT4 "touch.pressure.calibration: amplitude\n";
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- if (mCalibration.havePressureScale) {
- dump += StringPrintf(INDENT4 "touch.pressure.scale: %0.3f\n", mCalibration.pressureScale);
- }
-
- // Orientation
- switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_NONE:
- dump += INDENT4 "touch.orientation.calibration: none\n";
- break;
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
- dump += INDENT4 "touch.orientation.calibration: interpolated\n";
- break;
- case Calibration::ORIENTATION_CALIBRATION_VECTOR:
- dump += INDENT4 "touch.orientation.calibration: vector\n";
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- // Distance
- switch (mCalibration.distanceCalibration) {
- case Calibration::DISTANCE_CALIBRATION_NONE:
- dump += INDENT4 "touch.distance.calibration: none\n";
- break;
- case Calibration::DISTANCE_CALIBRATION_SCALED:
- dump += INDENT4 "touch.distance.calibration: scaled\n";
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- if (mCalibration.haveDistanceScale) {
- dump += StringPrintf(INDENT4 "touch.distance.scale: %0.3f\n", mCalibration.distanceScale);
- }
-
- switch (mCalibration.coverageCalibration) {
- case Calibration::COVERAGE_CALIBRATION_NONE:
- dump += INDENT4 "touch.coverage.calibration: none\n";
- break;
- case Calibration::COVERAGE_CALIBRATION_BOX:
- dump += INDENT4 "touch.coverage.calibration: box\n";
- break;
- default:
- ALOG_ASSERT(false);
- }
-}
-
-void TouchInputMapper::dumpAffineTransformation(std::string& dump) {
- dump += INDENT3 "Affine Transformation:\n";
-
- dump += StringPrintf(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
- dump += StringPrintf(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
- dump += StringPrintf(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
- dump += StringPrintf(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
- dump += StringPrintf(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
- dump += StringPrintf(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
-}
-
-void TouchInputMapper::updateAffineTransformation() {
- mAffineTransform = getPolicy()->getTouchAffineTransformation(mDevice->getDescriptor(),
- mSurfaceOrientation);
-}
-
-void TouchInputMapper::reset(nsecs_t when) {
- mCursorButtonAccumulator.reset(getDevice());
- mCursorScrollAccumulator.reset(getDevice());
- mTouchButtonAccumulator.reset(getDevice());
-
- mPointerVelocityControl.reset();
- mWheelXVelocityControl.reset();
- mWheelYVelocityControl.reset();
-
- mRawStatesPending.clear();
- mCurrentRawState.clear();
- mCurrentCookedState.clear();
- mLastRawState.clear();
- mLastCookedState.clear();
- mPointerUsage = POINTER_USAGE_NONE;
- mSentHoverEnter = false;
- mHavePointerIds = false;
- mCurrentMotionAborted = false;
- mDownTime = 0;
-
- mCurrentVirtualKey.down = false;
-
- mPointerGesture.reset();
- mPointerSimple.reset();
- resetExternalStylus();
-
- if (mPointerController != nullptr) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- mPointerController->clearSpots();
- }
-
- InputMapper::reset(when);
-}
-
-void TouchInputMapper::resetExternalStylus() {
- mExternalStylusState.clear();
- mExternalStylusId = -1;
- mExternalStylusFusionTimeout = LLONG_MAX;
- mExternalStylusDataPending = false;
-}
-
-void TouchInputMapper::clearStylusDataPendingFlags() {
- mExternalStylusDataPending = false;
- mExternalStylusFusionTimeout = LLONG_MAX;
-}
-
-void TouchInputMapper::reportEventForStatistics(nsecs_t evdevTime) {
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
- nsecs_t latency = now - evdevTime;
- mStatistics.addValue(nanoseconds_to_microseconds(latency));
- nsecs_t timeSinceLastReport = now - mStatistics.lastReportTime;
- if (timeSinceLastReport > STATISTICS_REPORT_FREQUENCY) {
- android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mStatistics.min,
- mStatistics.max, mStatistics.mean(), mStatistics.stdev(),
- mStatistics.count);
- mStatistics.reset(now);
- }
-}
-
-void TouchInputMapper::process(const RawEvent* rawEvent) {
- mCursorButtonAccumulator.process(rawEvent);
- mCursorScrollAccumulator.process(rawEvent);
- mTouchButtonAccumulator.process(rawEvent);
-
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- reportEventForStatistics(rawEvent->when);
- sync(rawEvent->when);
- }
-}
-
-void TouchInputMapper::sync(nsecs_t when) {
- const RawState* last =
- mRawStatesPending.empty() ? &mCurrentRawState : &mRawStatesPending.back();
-
- // Push a new state.
- mRawStatesPending.emplace_back();
-
- RawState* next = &mRawStatesPending.back();
- next->clear();
- next->when = when;
-
- // Sync button state.
- next->buttonState =
- mTouchButtonAccumulator.getButtonState() | mCursorButtonAccumulator.getButtonState();
-
- // Sync scroll
- next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
- next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
- mCursorScrollAccumulator.finishSync();
-
- // Sync touch
- syncTouch(when, next);
-
- // Assign pointer ids.
- if (!mHavePointerIds) {
- assignPointerIds(last, next);
- }
-
-#if DEBUG_RAW_EVENTS
- ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
- "hovering ids 0x%08x -> 0x%08x",
- last->rawPointerData.pointerCount, next->rawPointerData.pointerCount,
- last->rawPointerData.touchingIdBits.value, next->rawPointerData.touchingIdBits.value,
- last->rawPointerData.hoveringIdBits.value, next->rawPointerData.hoveringIdBits.value);
-#endif
-
- processRawTouches(false /*timeout*/);
-}
-
-void TouchInputMapper::processRawTouches(bool timeout) {
- if (mDeviceMode == DEVICE_MODE_DISABLED) {
- // Drop all input if the device is disabled.
- mCurrentRawState.clear();
- mRawStatesPending.clear();
- return;
- }
-
- // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
- // valid and must go through the full cook and dispatch cycle. This ensures that anything
- // touching the current state will only observe the events that have been dispatched to the
- // rest of the pipeline.
- const size_t N = mRawStatesPending.size();
- size_t count;
- for (count = 0; count < N; count++) {
- const RawState& next = mRawStatesPending[count];
-
- // A failure to assign the stylus id means that we're waiting on stylus data
- // and so should defer the rest of the pipeline.
- if (assignExternalStylusId(next, timeout)) {
- break;
- }
-
- // All ready to go.
- clearStylusDataPendingFlags();
- mCurrentRawState.copyFrom(next);
- if (mCurrentRawState.when < mLastRawState.when) {
- mCurrentRawState.when = mLastRawState.when;
- }
- cookAndDispatch(mCurrentRawState.when);
- }
- if (count != 0) {
- mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count);
- }
-
- if (mExternalStylusDataPending) {
- if (timeout) {
- nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
- clearStylusDataPendingFlags();
- mCurrentRawState.copyFrom(mLastRawState);
-#if DEBUG_STYLUS_FUSION
- ALOGD("Timeout expired, synthesizing event with new stylus data");
-#endif
- cookAndDispatch(when);
- } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
- mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
- getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
- }
- }
-}
-
-void TouchInputMapper::cookAndDispatch(nsecs_t when) {
- // Always start with a clean state.
- mCurrentCookedState.clear();
-
- // Apply stylus buttons to current raw state.
- applyExternalStylusButtonState(when);
-
- // Handle policy on initial down or hover events.
- bool initialDown = mLastRawState.rawPointerData.pointerCount == 0 &&
- mCurrentRawState.rawPointerData.pointerCount != 0;
-
- uint32_t policyFlags = 0;
- bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
- if (initialDown || buttonsPressed) {
- // If this is a touch screen, hide the pointer on an initial down.
- if (mDeviceMode == DEVICE_MODE_DIRECT) {
- getContext()->fadePointer();
- }
-
- if (mParameters.wake) {
- policyFlags |= POLICY_FLAG_WAKE;
- }
- }
-
- // Consume raw off-screen touches before cooking pointer data.
- // If touches are consumed, subsequent code will not receive any pointer data.
- if (consumeRawTouches(when, policyFlags)) {
- mCurrentRawState.rawPointerData.clear();
- }
-
- // Cook pointer data. This call populates the mCurrentCookedState.cookedPointerData structure
- // with cooked pointer data that has the same ids and indices as the raw data.
- // The following code can use either the raw or cooked data, as needed.
- cookPointerData();
-
- // Apply stylus pressure to current cooked state.
- applyExternalStylusTouchState(when);
-
- // Synthesize key down from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
- mViewport.displayId, policyFlags, mLastCookedState.buttonState,
- mCurrentCookedState.buttonState);
-
- // Dispatch the touches either directly or by translation through a pointer on screen.
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits); !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer =
- mCurrentRawState.rawPointerData.pointerForId(id);
- if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS ||
- pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
- mCurrentCookedState.stylusIdBits.markBit(id);
- } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER ||
- pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- mCurrentCookedState.fingerIdBits.markBit(id);
- } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
- mCurrentCookedState.mouseIdBits.markBit(id);
- }
- }
- for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits); !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer =
- mCurrentRawState.rawPointerData.pointerForId(id);
- if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS ||
- pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
- mCurrentCookedState.stylusIdBits.markBit(id);
- }
- }
-
- // Stylus takes precedence over all tools, then mouse, then finger.
- PointerUsage pointerUsage = mPointerUsage;
- if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
- mCurrentCookedState.mouseIdBits.clear();
- mCurrentCookedState.fingerIdBits.clear();
- pointerUsage = POINTER_USAGE_STYLUS;
- } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
- mCurrentCookedState.fingerIdBits.clear();
- pointerUsage = POINTER_USAGE_MOUSE;
- } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
- isPointerDown(mCurrentRawState.buttonState)) {
- pointerUsage = POINTER_USAGE_GESTURES;
- }
-
- dispatchPointerUsage(when, policyFlags, pointerUsage);
- } else {
- if (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches &&
- mPointerController != nullptr) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-
- mPointerController->setButtonState(mCurrentRawState.buttonState);
- mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex,
- mCurrentCookedState.cookedPointerData.touchingIdBits,
- mViewport.displayId);
- }
-
- if (!mCurrentMotionAborted) {
- dispatchButtonRelease(when, policyFlags);
- dispatchHoverExit(when, policyFlags);
- dispatchTouches(when, policyFlags);
- dispatchHoverEnterAndMove(when, policyFlags);
- dispatchButtonPress(when, policyFlags);
- }
-
- if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
- mCurrentMotionAborted = false;
- }
- }
-
- // Synthesize key up from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
- mViewport.displayId, policyFlags, mLastCookedState.buttonState,
- mCurrentCookedState.buttonState);
-
- // Clear some transient state.
- mCurrentRawState.rawVScroll = 0;
- mCurrentRawState.rawHScroll = 0;
-
- // Copy current touch to last touch in preparation for the next cycle.
- mLastRawState.copyFrom(mCurrentRawState);
- mLastCookedState.copyFrom(mCurrentCookedState);
-}
-
-void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
- if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
- mCurrentRawState.buttonState |= mExternalStylusState.buttons;
- }
-}
-
-void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
- CookedPointerData& currentPointerData = mCurrentCookedState.cookedPointerData;
- const CookedPointerData& lastPointerData = mLastCookedState.cookedPointerData;
-
- if (mExternalStylusId != -1 && currentPointerData.isTouching(mExternalStylusId)) {
- float pressure = mExternalStylusState.pressure;
- if (pressure == 0.0f && lastPointerData.isTouching(mExternalStylusId)) {
- const PointerCoords& coords = lastPointerData.pointerCoordsForId(mExternalStylusId);
- pressure = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
- }
- PointerCoords& coords = currentPointerData.editPointerCoordsWithId(mExternalStylusId);
- coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
-
- PointerProperties& properties =
- currentPointerData.editPointerPropertiesWithId(mExternalStylusId);
- if (mExternalStylusState.toolType != AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- properties.toolType = mExternalStylusState.toolType;
- }
- }
-}
-
-bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
- if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
- return false;
- }
-
- const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0 &&
- state.rawPointerData.pointerCount != 0;
- if (initialDown) {
- if (mExternalStylusState.pressure != 0.0f) {
-#if DEBUG_STYLUS_FUSION
- ALOGD("Have both stylus and touch data, beginning fusion");
-#endif
- mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
- } else if (timeout) {
-#if DEBUG_STYLUS_FUSION
- ALOGD("Timeout expired, assuming touch is not a stylus.");
-#endif
- resetExternalStylus();
- } else {
- if (mExternalStylusFusionTimeout == LLONG_MAX) {
- mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
- }
-#if DEBUG_STYLUS_FUSION
- ALOGD("No stylus data but stylus is connected, requesting timeout "
- "(%" PRId64 "ms)",
- mExternalStylusFusionTimeout);
-#endif
- getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
- return true;
- }
- }
-
- // Check if the stylus pointer has gone up.
- if (mExternalStylusId != -1 && !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
-#if DEBUG_STYLUS_FUSION
- ALOGD("Stylus pointer is going up");
-#endif
- mExternalStylusId = -1;
- }
-
- return false;
-}
-
-void TouchInputMapper::timeoutExpired(nsecs_t when) {
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- if (mPointerUsage == POINTER_USAGE_GESTURES) {
- dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
- }
- } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
- if (mExternalStylusFusionTimeout < when) {
- processRawTouches(true /*timeout*/);
- } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
- getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
- }
- }
-}
-
-void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
- mExternalStylusState.copyFrom(state);
- if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
- // We're either in the middle of a fused stream of data or we're waiting on data before
- // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
- // data.
- mExternalStylusDataPending = true;
- processRawTouches(false /*timeout*/);
- }
-}
-
-bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
- // Check for release of a virtual key.
- if (mCurrentVirtualKey.down) {
- if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
- // Pointer went up while virtual key was down.
- mCurrentVirtualKey.down = false;
- if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
- ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
- mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
-#endif
- dispatchVirtualKey(when, policyFlags, AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
- }
- return true;
- }
-
- if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
- uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
- const RawPointerData::Pointer& pointer =
- mCurrentRawState.rawPointerData.pointerForId(id);
- const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
- if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
- // Pointer is still within the space of the virtual key.
- return true;
- }
- }
-
- // Pointer left virtual key area or another pointer also went down.
- // Send key cancellation but do not consume the touch yet.
- // This is useful when the user swipes through from the virtual key area
- // into the main display surface.
- mCurrentVirtualKey.down = false;
- if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
- ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d", mCurrentVirtualKey.keyCode,
- mCurrentVirtualKey.scanCode);
-#endif
- dispatchVirtualKey(when, policyFlags, AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY |
- AKEY_EVENT_FLAG_CANCELED);
- }
- }
-
- if (mLastRawState.rawPointerData.touchingIdBits.isEmpty() &&
- !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
- // Pointer just went down. Check for virtual key press or off-screen touches.
- uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
- if (!isPointInsideSurface(pointer.x, pointer.y)) {
- // If exactly one pointer went down, check for virtual key hit.
- // Otherwise we will drop the entire stroke.
- if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
- const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
- if (virtualKey) {
- mCurrentVirtualKey.down = true;
- mCurrentVirtualKey.downTime = when;
- mCurrentVirtualKey.keyCode = virtualKey->keyCode;
- mCurrentVirtualKey.scanCode = virtualKey->scanCode;
- mCurrentVirtualKey.ignored =
- mContext->shouldDropVirtualKey(when, getDevice(), virtualKey->keyCode,
- virtualKey->scanCode);
-
- if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
- ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
- mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
-#endif
- dispatchVirtualKey(when, policyFlags, AKEY_EVENT_ACTION_DOWN,
- AKEY_EVENT_FLAG_FROM_SYSTEM |
- AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
- }
- }
- }
- return true;
- }
- }
-
- // Disable all virtual key touches that happen within a short time interval of the
- // most recent touch within the screen area. The idea is to filter out stray
- // virtual key presses when interacting with the touch screen.
- //
- // Problems we're trying to solve:
- //
- // 1. While scrolling a list or dragging the window shade, the user swipes down into a
- // virtual key area that is implemented by a separate touch panel and accidentally
- // triggers a virtual key.
- //
- // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
- // area and accidentally triggers a virtual key. This often happens when virtual keys
- // are layed out below the screen near to where the on screen keyboard's space bar
- // is displayed.
- if (mConfig.virtualKeyQuietTime > 0 &&
- !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
- mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
- }
- return false;
-}
-
-void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
- int32_t keyEventAction, int32_t keyEventFlags) {
- int32_t keyCode = mCurrentVirtualKey.keyCode;
- int32_t scanCode = mCurrentVirtualKey.scanCode;
- nsecs_t downTime = mCurrentVirtualKey.downTime;
- int32_t metaState = mContext->getGlobalMetaState();
- policyFlags |= POLICY_FLAG_VIRTUAL;
-
- NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
- mViewport.displayId, policyFlags, keyEventAction, keyEventFlags, keyCode,
- scanCode, metaState, downTime);
- getListener()->notifyKey(&args);
-}
-
-void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
- BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
- if (!currentIdBits.isEmpty()) {
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentCookedState.buttonState;
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
- buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mCurrentCookedState.deviceTimestamp,
- mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- mCurrentMotionAborted = true;
- }
-}
-
-void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
- BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
- BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentCookedState.buttonState;
-
- if (currentIdBits == lastIdBits) {
- if (!currentIdBits.isEmpty()) {
- // No pointer id changes so this is a move event.
- // The listener takes care of batching moves so we don't have to deal with that here.
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
- buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mCurrentCookedState.deviceTimestamp,
- mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
- } else {
- // There may be pointers going up and pointers going down and pointers moving
- // all at the same time.
- BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
- BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
- BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
- BitSet32 dispatchedIdBits(lastIdBits.value);
-
- // Update last coordinates of pointers that have moved so that we observe the new
- // pointer positions at the same time as other pointers that have just gone up.
- bool moveNeeded =
- updateMovedPointers(mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex,
- mLastCookedState.cookedPointerData.pointerProperties,
- mLastCookedState.cookedPointerData.pointerCoords,
- mLastCookedState.cookedPointerData.idToIndex, moveIdBits);
- if (buttonState != mLastCookedState.buttonState) {
- moveNeeded = true;
- }
-
- // Dispatch pointer up events.
- while (!upIdBits.isEmpty()) {
- uint32_t upId = upIdBits.clearFirstMarkedBit();
-
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
- metaState, buttonState, 0, mCurrentCookedState.deviceTimestamp,
- mLastCookedState.cookedPointerData.pointerProperties,
- mLastCookedState.cookedPointerData.pointerCoords,
- mLastCookedState.cookedPointerData.idToIndex, dispatchedIdBits, upId,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- dispatchedIdBits.clearBit(upId);
- }
-
- // Dispatch move events if any of the remaining pointers moved from their old locations.
- // Although applications receive new locations as part of individual pointer up
- // events, they do not generally handle them except when presented in a move event.
- if (moveNeeded && !moveIdBits.isEmpty()) {
- ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
- buttonState, 0, mCurrentCookedState.deviceTimestamp,
- mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
-
- // Dispatch pointer down events using the new pointer locations.
- while (!downIdBits.isEmpty()) {
- uint32_t downId = downIdBits.clearFirstMarkedBit();
- dispatchedIdBits.markBit(downId);
-
- if (dispatchedIdBits.count() == 1) {
- // First pointer is going down. Set down time.
- mDownTime = when;
- }
-
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0,
- metaState, buttonState, 0, mCurrentCookedState.deviceTimestamp,
- mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits,
- downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
- }
-}
-
-void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
- if (mSentHoverEnter &&
- (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty() ||
- !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
- int32_t metaState = getContext()->getGlobalMetaState();
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState,
- mLastCookedState.buttonState, 0, mLastCookedState.deviceTimestamp,
- mLastCookedState.cookedPointerData.pointerProperties,
- mLastCookedState.cookedPointerData.pointerCoords,
- mLastCookedState.cookedPointerData.idToIndex,
- mLastCookedState.cookedPointerData.hoveringIdBits, -1, mOrientedXPrecision,
- mOrientedYPrecision, mDownTime);
- mSentHoverEnter = false;
- }
-}
-
-void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
- if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty() &&
- !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
- int32_t metaState = getContext()->getGlobalMetaState();
- if (!mSentHoverEnter) {
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
- metaState, mCurrentRawState.buttonState, 0,
- mCurrentCookedState.deviceTimestamp,
- mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex,
- mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- mSentHoverEnter = true;
- }
-
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
- mCurrentRawState.buttonState, 0, mCurrentCookedState.deviceTimestamp,
- mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex,
- mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
-}
-
-void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) {
- BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
- const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData);
- const int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mLastCookedState.buttonState;
- while (!releasedButtons.isEmpty()) {
- int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
- buttonState &= ~actionButton;
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
- actionButton, 0, metaState, buttonState, 0,
- mCurrentCookedState.deviceTimestamp,
- mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
-}
-
-void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) {
- BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
- const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData);
- const int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mLastCookedState.buttonState;
- while (!pressedButtons.isEmpty()) {
- int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
- buttonState |= actionButton;
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
- 0, metaState, buttonState, 0, mCurrentCookedState.deviceTimestamp,
- mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
-}
-
-const BitSet32& TouchInputMapper::findActiveIdBits(const CookedPointerData& cookedPointerData) {
- if (!cookedPointerData.touchingIdBits.isEmpty()) {
- return cookedPointerData.touchingIdBits;
- }
- return cookedPointerData.hoveringIdBits;
-}
-
-void TouchInputMapper::cookPointerData() {
- uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
-
- mCurrentCookedState.cookedPointerData.clear();
- mCurrentCookedState.deviceTimestamp = mCurrentRawState.deviceTimestamp;
- mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
- mCurrentCookedState.cookedPointerData.hoveringIdBits =
- mCurrentRawState.rawPointerData.hoveringIdBits;
- mCurrentCookedState.cookedPointerData.touchingIdBits =
- mCurrentRawState.rawPointerData.touchingIdBits;
-
- if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
- mCurrentCookedState.buttonState = 0;
- } else {
- mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
- }
-
- // Walk through the the active pointers and map device coordinates onto
- // surface coordinates and adjust for display orientation.
- for (uint32_t i = 0; i < currentPointerCount; i++) {
- const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
-
- // Size
- float touchMajor, touchMinor, toolMajor, toolMinor, size;
- switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_GEOMETRIC:
- case Calibration::SIZE_CALIBRATION_DIAMETER:
- case Calibration::SIZE_CALIBRATION_BOX:
- case Calibration::SIZE_CALIBRATION_AREA:
- if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
- touchMajor = in.touchMajor;
- touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
- toolMajor = in.toolMajor;
- toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
- size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
- : in.touchMajor;
- } else if (mRawPointerAxes.touchMajor.valid) {
- toolMajor = touchMajor = in.touchMajor;
- toolMinor = touchMinor =
- mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
- size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
- : in.touchMajor;
- } else if (mRawPointerAxes.toolMajor.valid) {
- touchMajor = toolMajor = in.toolMajor;
- touchMinor = toolMinor =
- mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
- size = mRawPointerAxes.toolMinor.valid ? avg(in.toolMajor, in.toolMinor)
- : in.toolMajor;
- } else {
- ALOG_ASSERT(false,
- "No touch or tool axes. "
- "Size calibration should have been resolved to NONE.");
- touchMajor = 0;
- touchMinor = 0;
- toolMajor = 0;
- toolMinor = 0;
- size = 0;
- }
-
- if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
- uint32_t touchingCount = mCurrentRawState.rawPointerData.touchingIdBits.count();
- if (touchingCount > 1) {
- touchMajor /= touchingCount;
- touchMinor /= touchingCount;
- toolMajor /= touchingCount;
- toolMinor /= touchingCount;
- size /= touchingCount;
- }
- }
-
- if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
- touchMajor *= mGeometricScale;
- touchMinor *= mGeometricScale;
- toolMajor *= mGeometricScale;
- toolMinor *= mGeometricScale;
- } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
- touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
- touchMinor = touchMajor;
- toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
- toolMinor = toolMajor;
- } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
- touchMinor = touchMajor;
- toolMinor = toolMajor;
- }
-
- mCalibration.applySizeScaleAndBias(&touchMajor);
- mCalibration.applySizeScaleAndBias(&touchMinor);
- mCalibration.applySizeScaleAndBias(&toolMajor);
- mCalibration.applySizeScaleAndBias(&toolMinor);
- size *= mSizeScale;
- break;
- default:
- touchMajor = 0;
- touchMinor = 0;
- toolMajor = 0;
- toolMinor = 0;
- size = 0;
- break;
- }
-
- // Pressure
- float pressure;
- switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
- case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
- pressure = in.pressure * mPressureScale;
- break;
- default:
- pressure = in.isHovering ? 0 : 1;
- break;
- }
-
- // Tilt and Orientation
- float tilt;
- float orientation;
- if (mHaveTilt) {
- float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
- float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
- orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
- tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
- } else {
- tilt = 0;
-
- switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
- orientation = in.orientation * mOrientationScale;
- break;
- case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
- int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
- int32_t c2 = signExtendNybble(in.orientation & 0x0f);
- if (c1 != 0 || c2 != 0) {
- orientation = atan2f(c1, c2) * 0.5f;
- float confidence = hypotf(c1, c2);
- float scale = 1.0f + confidence / 16.0f;
- touchMajor *= scale;
- touchMinor /= scale;
- toolMajor *= scale;
- toolMinor /= scale;
- } else {
- orientation = 0;
- }
- break;
- }
- default:
- orientation = 0;
- }
- }
-
- // Distance
- float distance;
- switch (mCalibration.distanceCalibration) {
- case Calibration::DISTANCE_CALIBRATION_SCALED:
- distance = in.distance * mDistanceScale;
- break;
- default:
- distance = 0;
- }
-
- // Coverage
- int32_t rawLeft, rawTop, rawRight, rawBottom;
- switch (mCalibration.coverageCalibration) {
- case Calibration::COVERAGE_CALIBRATION_BOX:
- rawLeft = (in.toolMinor & 0xffff0000) >> 16;
- rawRight = in.toolMinor & 0x0000ffff;
- rawBottom = in.toolMajor & 0x0000ffff;
- rawTop = (in.toolMajor & 0xffff0000) >> 16;
- break;
- default:
- rawLeft = rawTop = rawRight = rawBottom = 0;
- break;
- }
-
- // Adjust X,Y coords for device calibration
- // TODO: Adjust coverage coords?
- float xTransformed = in.x, yTransformed = in.y;
- mAffineTransform.applyTo(xTransformed, yTransformed);
-
- // Adjust X, Y, and coverage coords for surface orientation.
- float x, y;
- float left, top, right, bottom;
-
- switch (mSurfaceOrientation) {
- case DISPLAY_ORIENTATION_90:
- x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
- left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- right = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
- top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
- orientation -= M_PI_2;
- if (mOrientedRanges.haveOrientation &&
- orientation < mOrientedRanges.orientation.min) {
- orientation +=
- (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
- }
- break;
- case DISPLAY_ORIENTATION_180:
- x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
- y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
- left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
- right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
- bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
- top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
- orientation -= M_PI;
- if (mOrientedRanges.haveOrientation &&
- orientation < mOrientedRanges.orientation.min) {
- orientation +=
- (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
- }
- break;
- case DISPLAY_ORIENTATION_270:
- x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
- y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
- right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
- bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- orientation += M_PI_2;
- if (mOrientedRanges.haveOrientation &&
- orientation > mOrientedRanges.orientation.max) {
- orientation -=
- (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
- }
- break;
- default:
- x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- break;
- }
-
- // Write output coords.
- PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
- out.clear();
- out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
- out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
- out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
- out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
- out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
- out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
- out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
- if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
- out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
- out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
- out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
- out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
- } else {
- out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
- out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
- }
-
- // Write output properties.
- PointerProperties& properties = mCurrentCookedState.cookedPointerData.pointerProperties[i];
- uint32_t id = in.id;
- properties.clear();
- properties.id = id;
- properties.toolType = in.toolType;
-
- // Write id index.
- mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
- }
-}
-
-void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
- PointerUsage pointerUsage) {
- if (pointerUsage != mPointerUsage) {
- abortPointerUsage(when, policyFlags);
- mPointerUsage = pointerUsage;
- }
-
- switch (mPointerUsage) {
- case POINTER_USAGE_GESTURES:
- dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
- break;
- case POINTER_USAGE_STYLUS:
- dispatchPointerStylus(when, policyFlags);
- break;
- case POINTER_USAGE_MOUSE:
- dispatchPointerMouse(when, policyFlags);
- break;
- default:
- break;
- }
-}
-
-void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
- switch (mPointerUsage) {
- case POINTER_USAGE_GESTURES:
- abortPointerGestures(when, policyFlags);
- break;
- case POINTER_USAGE_STYLUS:
- abortPointerStylus(when, policyFlags);
- break;
- case POINTER_USAGE_MOUSE:
- abortPointerMouse(when, policyFlags);
- break;
- default:
- break;
- }
-
- mPointerUsage = POINTER_USAGE_NONE;
-}
-
-void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout) {
- // Update current gesture coordinates.
- bool cancelPreviousGesture, finishPreviousGesture;
- bool sendEvents =
- preparePointerGestures(when, &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
- if (!sendEvents) {
- return;
- }
- if (finishPreviousGesture) {
- cancelPreviousGesture = false;
- }
-
- // Update the pointer presentation and spots.
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
- if (finishPreviousGesture || cancelPreviousGesture) {
- mPointerController->clearSpots();
- }
-
- if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
- mPointerController->setSpots(mPointerGesture.currentGestureCoords,
- mPointerGesture.currentGestureIdToIndex,
- mPointerGesture.currentGestureIdBits,
- mPointerController->getDisplayId());
- }
- } else {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
- }
-
- // Show or hide the pointer if needed.
- switch (mPointerGesture.currentGestureMode) {
- case PointerGesture::NEUTRAL:
- case PointerGesture::QUIET:
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH &&
- mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
- // Remind the user of where the pointer is after finishing a gesture with spots.
- mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
- break;
- case PointerGesture::TAP:
- case PointerGesture::TAP_DRAG:
- case PointerGesture::BUTTON_CLICK_OR_DRAG:
- case PointerGesture::HOVER:
- case PointerGesture::PRESS:
- case PointerGesture::SWIPE:
- // Unfade the pointer when the current gesture manipulates the
- // area directly under the pointer.
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- break;
- case PointerGesture::FREEFORM:
- // Fade the pointer when the current gesture manipulates a different
- // area and there are spots to guide the user experience.
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- } else {
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- }
- break;
- }
-
- // Send events!
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentCookedState.buttonState;
-
- // Update last coordinates of pointers that have moved so that we observe the new
- // pointer positions at the same time as other pointers that have just gone up.
- bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP ||
- mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG ||
- mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG ||
- mPointerGesture.currentGestureMode == PointerGesture::PRESS ||
- mPointerGesture.currentGestureMode == PointerGesture::SWIPE ||
- mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
- bool moveNeeded = false;
- if (down && !cancelPreviousGesture && !finishPreviousGesture &&
- !mPointerGesture.lastGestureIdBits.isEmpty() &&
- !mPointerGesture.currentGestureIdBits.isEmpty()) {
- BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value &
- mPointerGesture.lastGestureIdBits.value);
- moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
- mPointerGesture.currentGestureCoords,
- mPointerGesture.currentGestureIdToIndex,
- mPointerGesture.lastGestureProperties,
- mPointerGesture.lastGestureCoords,
- mPointerGesture.lastGestureIdToIndex, movedGestureIdBits);
- if (buttonState != mLastCookedState.buttonState) {
- moveNeeded = true;
- }
- }
-
- // Send motion events for all pointers that went up or were canceled.
- BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
- if (!dispatchedGestureIdBits.isEmpty()) {
- if (cancelPreviousGesture) {
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
- buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
- mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
- mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
- mPointerGesture.downTime);
-
- dispatchedGestureIdBits.clear();
- } else {
- BitSet32 upGestureIdBits;
- if (finishPreviousGesture) {
- upGestureIdBits = dispatchedGestureIdBits;
- } else {
- upGestureIdBits.value =
- dispatchedGestureIdBits.value & ~mPointerGesture.currentGestureIdBits.value;
- }
- while (!upGestureIdBits.isEmpty()) {
- uint32_t id = upGestureIdBits.clearFirstMarkedBit();
-
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
- metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, mPointerGesture.lastGestureProperties,
- mPointerGesture.lastGestureCoords,
- mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, id, 0,
- 0, mPointerGesture.downTime);
-
- dispatchedGestureIdBits.clearBit(id);
- }
- }
- }
-
- // Send motion events for all pointers that moved.
- if (moveNeeded) {
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
- buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
- mPointerGesture.currentGestureProperties,
- mPointerGesture.currentGestureCoords,
- mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
- mPointerGesture.downTime);
- }
-
- // Send motion events for all pointers that went down.
- if (down) {
- BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value &
- ~dispatchedGestureIdBits.value);
- while (!downGestureIdBits.isEmpty()) {
- uint32_t id = downGestureIdBits.clearFirstMarkedBit();
- dispatchedGestureIdBits.markBit(id);
-
- if (dispatchedGestureIdBits.count() == 1) {
- mPointerGesture.downTime = when;
- }
-
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0,
- metaState, buttonState, 0,
- /* deviceTimestamp */ 0, mPointerGesture.currentGestureProperties,
- mPointerGesture.currentGestureCoords,
- mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, id, 0,
- 0, mPointerGesture.downTime);
- }
- }
-
- // Send motion events for hover.
- if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
- buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
- mPointerGesture.currentGestureProperties,
- mPointerGesture.currentGestureCoords,
- mPointerGesture.currentGestureIdToIndex,
- mPointerGesture.currentGestureIdBits, -1, 0, 0, mPointerGesture.downTime);
- } else if (dispatchedGestureIdBits.isEmpty() && !mPointerGesture.lastGestureIdBits.isEmpty()) {
- // Synthesize a hover move event after all pointers go up to indicate that
- // the pointer is hovering again even if the user is not currently touching
- // the touch pad. This ensures that a view will receive a fresh hover enter
- // event after a tap.
- float x, y;
- mPointerController->getPosition(&x, &y);
-
- PointerProperties pointerProperties;
- pointerProperties.clear();
- pointerProperties.id = 0;
- pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-
- PointerCoords pointerCoords;
- pointerCoords.clear();
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-
- const int32_t displayId = mPointerController->getDisplayId();
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
- metaState, buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords, 0, 0,
- mPointerGesture.downTime, /* videoFrames */ {});
- getListener()->notifyMotion(&args);
- }
-
- // Update state.
- mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
- if (!down) {
- mPointerGesture.lastGestureIdBits.clear();
- } else {
- mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
- for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
- mPointerGesture.lastGestureProperties[index].copyFrom(
- mPointerGesture.currentGestureProperties[index]);
- mPointerGesture.lastGestureCoords[index].copyFrom(
- mPointerGesture.currentGestureCoords[index]);
- mPointerGesture.lastGestureIdToIndex[id] = index;
- }
- }
-}
-
-void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
- // Cancel previously dispatches pointers.
- if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentRawState.buttonState;
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
- buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
- mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
- mPointerGesture.lastGestureIdToIndex, mPointerGesture.lastGestureIdBits, -1,
- 0, 0, mPointerGesture.downTime);
- }
-
- // Reset the current pointer gesture.
- mPointerGesture.reset();
- mPointerVelocityControl.reset();
-
- // Remove any current spots.
- if (mPointerController != nullptr) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- mPointerController->clearSpots();
- }
-}
-
-bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture,
- bool* outFinishPreviousGesture, bool isTimeout) {
- *outCancelPreviousGesture = false;
- *outFinishPreviousGesture = false;
-
- // Handle TAP timeout.
- if (isTimeout) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: Processing timeout");
-#endif
-
- if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
- if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
- // The tap/drag timeout has not yet expired.
- getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime +
- mConfig.pointerGestureTapDragInterval);
- } else {
- // The tap is finished.
-#if DEBUG_GESTURES
- ALOGD("Gestures: TAP finished");
-#endif
- *outFinishPreviousGesture = true;
-
- mPointerGesture.activeGestureId = -1;
- mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
- mPointerGesture.currentGestureIdBits.clear();
-
- mPointerVelocityControl.reset();
- return true;
- }
- }
-
- // We did not handle this timeout.
- return false;
- }
-
- const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
- const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
-
- // Update the velocity tracker.
- {
- VelocityTracker::Position positions[MAX_POINTERS];
- uint32_t count = 0;
- for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); count++) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer =
- mCurrentRawState.rawPointerData.pointerForId(id);
- positions[count].x = pointer.x * mPointerXMovementScale;
- positions[count].y = pointer.y * mPointerYMovementScale;
- }
- mPointerGesture.velocityTracker.addMovement(when, mCurrentCookedState.fingerIdBits,
- positions);
- }
-
- // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
- // to NEUTRAL, then we should not generate tap event.
- if (mPointerGesture.lastGestureMode != PointerGesture::HOVER &&
- mPointerGesture.lastGestureMode != PointerGesture::TAP &&
- mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
- mPointerGesture.resetTap();
- }
-
- // Pick a new active touch id if needed.
- // Choose an arbitrary pointer that just went down, if there is one.
- // Otherwise choose an arbitrary remaining pointer.
- // This guarantees we always have an active touch id when there is at least one pointer.
- // We keep the same active touch id for as long as possible.
- int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
- int32_t activeTouchId = lastActiveTouchId;
- if (activeTouchId < 0) {
- if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
- activeTouchId = mPointerGesture.activeTouchId =
- mCurrentCookedState.fingerIdBits.firstMarkedBit();
- mPointerGesture.firstTouchTime = when;
- }
- } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
- if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
- activeTouchId = mPointerGesture.activeTouchId =
- mCurrentCookedState.fingerIdBits.firstMarkedBit();
- } else {
- activeTouchId = mPointerGesture.activeTouchId = -1;
- }
- }
-
- // Determine whether we are in quiet time.
- bool isQuietTime = false;
- if (activeTouchId < 0) {
- mPointerGesture.resetQuietTime();
- } else {
- isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
- if (!isQuietTime) {
- if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS ||
- mPointerGesture.lastGestureMode == PointerGesture::SWIPE ||
- mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) &&
- currentFingerCount < 2) {
- // Enter quiet time when exiting swipe or freeform state.
- // This is to prevent accidentally entering the hover state and flinging the
- // pointer when finishing a swipe and there is still one pointer left onscreen.
- isQuietTime = true;
- } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG &&
- currentFingerCount >= 2 && !isPointerDown(mCurrentRawState.buttonState)) {
- // Enter quiet time when releasing the button and there are still two or more
- // fingers down. This may indicate that one finger was used to press the button
- // but it has not gone up yet.
- isQuietTime = true;
- }
- if (isQuietTime) {
- mPointerGesture.quietTime = when;
- }
- }
- }
-
- // Switch states based on button and pointer state.
- if (isQuietTime) {
- // Case 1: Quiet time. (QUIET)
-#if DEBUG_GESTURES
- ALOGD("Gestures: QUIET for next %0.3fms",
- (mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
-#endif
- if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
- *outFinishPreviousGesture = true;
- }
-
- mPointerGesture.activeGestureId = -1;
- mPointerGesture.currentGestureMode = PointerGesture::QUIET;
- mPointerGesture.currentGestureIdBits.clear();
-
- mPointerVelocityControl.reset();
- } else if (isPointerDown(mCurrentRawState.buttonState)) {
- // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
- // The pointer follows the active touch point.
- // Emit DOWN, MOVE, UP events at the pointer location.
- //
- // Only the active touch matters; other fingers are ignored. This policy helps
- // to handle the case where the user places a second finger on the touch pad
- // to apply the necessary force to depress an integrated button below the surface.
- // We don't want the second finger to be delivered to applications.
- //
- // For this to work well, we need to make sure to track the pointer that is really
- // active. If the user first puts one finger down to click then adds another
- // finger to drag then the active pointer should switch to the finger that is
- // being dragged.
-#if DEBUG_GESTURES
- ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
- "currentFingerCount=%d",
- activeTouchId, currentFingerCount);
-#endif
- // Reset state when just starting.
- if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
- *outFinishPreviousGesture = true;
- mPointerGesture.activeGestureId = 0;
- }
-
- // Switch pointers if needed.
- // Find the fastest pointer and follow it.
- if (activeTouchId >= 0 && currentFingerCount > 1) {
- int32_t bestId = -1;
- float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
- for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- float vx, vy;
- if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
- float speed = hypotf(vx, vy);
- if (speed > bestSpeed) {
- bestId = id;
- bestSpeed = speed;
- }
- }
- }
- if (bestId >= 0 && bestId != activeTouchId) {
- mPointerGesture.activeTouchId = activeTouchId = bestId;
-#if DEBUG_GESTURES
- ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
- "bestId=%d, bestSpeed=%0.3f",
- bestId, bestSpeed);
-#endif
- }
- }
-
- float deltaX = 0, deltaY = 0;
- if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
- const RawPointerData::Pointer& currentPointer =
- mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
- const RawPointerData::Pointer& lastPointer =
- mLastRawState.rawPointerData.pointerForId(activeTouchId);
- deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
- deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
-
- rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- // Move the pointer using a relative motion.
- // When using spots, the click will occur at the position of the anchor
- // spot and all other spots will move there.
- mPointerController->move(deltaX, deltaY);
- } else {
- mPointerVelocityControl.reset();
- }
-
- float x, y;
- mPointerController->getPosition(&x, &y);
-
- mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
- mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
- mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
- mPointerGesture.currentGestureProperties[0].clear();
- mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[0].clear();
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- } else if (currentFingerCount == 0) {
- // Case 3. No fingers down and button is not pressed. (NEUTRAL)
- if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
- *outFinishPreviousGesture = true;
- }
-
- // Watch for taps coming out of HOVER or TAP_DRAG mode.
- // Checking for taps after TAP_DRAG allows us to detect double-taps.
- bool tapped = false;
- if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER ||
- mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) &&
- lastFingerCount == 1) {
- if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
- float x, y;
- mPointerController->getPosition(&x, &y);
- if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
- fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: TAP");
-#endif
-
- mPointerGesture.tapUpTime = when;
- getContext()->requestTimeoutAtTime(when +
- mConfig.pointerGestureTapDragInterval);
-
- mPointerGesture.activeGestureId = 0;
- mPointerGesture.currentGestureMode = PointerGesture::TAP;
- mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
- mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
- mPointerGesture.currentGestureProperties[0].clear();
- mPointerGesture.currentGestureProperties[0].id =
- mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[0].clear();
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
- mPointerGesture.tapX);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
- mPointerGesture.tapY);
- mPointerGesture.currentGestureCoords[0]
- .setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
-
- tapped = true;
- } else {
-#if DEBUG_GESTURES
- ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f", x - mPointerGesture.tapX,
- y - mPointerGesture.tapY);
-#endif
- }
- } else {
-#if DEBUG_GESTURES
- if (mPointerGesture.tapDownTime != LLONG_MIN) {
- ALOGD("Gestures: Not a TAP, %0.3fms since down",
- (when - mPointerGesture.tapDownTime) * 0.000001f);
- } else {
- ALOGD("Gestures: Not a TAP, incompatible mode transitions");
- }
-#endif
- }
- }
-
- mPointerVelocityControl.reset();
-
- if (!tapped) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: NEUTRAL");
-#endif
- mPointerGesture.activeGestureId = -1;
- mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
- mPointerGesture.currentGestureIdBits.clear();
- }
- } else if (currentFingerCount == 1) {
- // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
- // The pointer follows the active touch point.
- // When in HOVER, emit HOVER_MOVE events at the pointer location.
- // When in TAP_DRAG, emit MOVE events at the pointer location.
- ALOG_ASSERT(activeTouchId >= 0);
-
- mPointerGesture.currentGestureMode = PointerGesture::HOVER;
- if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
- if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
- float x, y;
- mPointerController->getPosition(&x, &y);
- if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
- fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
- mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
- } else {
-#if DEBUG_GESTURES
- ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
- x - mPointerGesture.tapX, y - mPointerGesture.tapY);
-#endif
- }
- } else {
-#if DEBUG_GESTURES
- ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
- (when - mPointerGesture.tapUpTime) * 0.000001f);
-#endif
- }
- } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
- mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
- }
-
- float deltaX = 0, deltaY = 0;
- if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
- const RawPointerData::Pointer& currentPointer =
- mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
- const RawPointerData::Pointer& lastPointer =
- mLastRawState.rawPointerData.pointerForId(activeTouchId);
- deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
- deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
-
- rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- // Move the pointer using a relative motion.
- // When using spots, the hover or drag will occur at the position of the anchor spot.
- mPointerController->move(deltaX, deltaY);
- } else {
- mPointerVelocityControl.reset();
- }
-
- bool down;
- if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: TAP_DRAG");
-#endif
- down = true;
- } else {
-#if DEBUG_GESTURES
- ALOGD("Gestures: HOVER");
-#endif
- if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
- *outFinishPreviousGesture = true;
- }
- mPointerGesture.activeGestureId = 0;
- down = false;
- }
-
- float x, y;
- mPointerController->getPosition(&x, &y);
-
- mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
- mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
- mPointerGesture.currentGestureProperties[0].clear();
- mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[0].clear();
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
- down ? 1.0f : 0.0f);
-
- if (lastFingerCount == 0 && currentFingerCount != 0) {
- mPointerGesture.resetTap();
- mPointerGesture.tapDownTime = when;
- mPointerGesture.tapX = x;
- mPointerGesture.tapY = y;
- }
- } else {
- // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
- // We need to provide feedback for each finger that goes down so we cannot wait
- // for the fingers to move before deciding what to do.
- //
- // The ambiguous case is deciding what to do when there are two fingers down but they
- // have not moved enough to determine whether they are part of a drag or part of a
- // freeform gesture, or just a press or long-press at the pointer location.
- //
- // When there are two fingers we start with the PRESS hypothesis and we generate a
- // down at the pointer location.
- //
- // When the two fingers move enough or when additional fingers are added, we make
- // a decision to transition into SWIPE or FREEFORM mode accordingly.
- ALOG_ASSERT(activeTouchId >= 0);
-
- bool settled = when >=
- mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval;
- if (mPointerGesture.lastGestureMode != PointerGesture::PRESS &&
- mPointerGesture.lastGestureMode != PointerGesture::SWIPE &&
- mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
- *outFinishPreviousGesture = true;
- } else if (!settled && currentFingerCount > lastFingerCount) {
- // Additional pointers have gone down but not yet settled.
- // Reset the gesture.
-#if DEBUG_GESTURES
- ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
- "settle time remaining %0.3fms",
- (mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval -
- when) * 0.000001f);
-#endif
- *outCancelPreviousGesture = true;
- } else {
- // Continue previous gesture.
- mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
- }
-
- if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
- mPointerGesture.currentGestureMode = PointerGesture::PRESS;
- mPointerGesture.activeGestureId = 0;
- mPointerGesture.referenceIdBits.clear();
- mPointerVelocityControl.reset();
-
- // Use the centroid and pointer location as the reference points for the gesture.
-#if DEBUG_GESTURES
- ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
- "settle time remaining %0.3fms",
- (mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval -
- when) * 0.000001f);
-#endif
- mCurrentRawState.rawPointerData
- .getCentroidOfTouchingPointers(&mPointerGesture.referenceTouchX,
- &mPointerGesture.referenceTouchY);
- mPointerController->getPosition(&mPointerGesture.referenceGestureX,
- &mPointerGesture.referenceGestureY);
- }
-
- // Clear the reference deltas for fingers not yet included in the reference calculation.
- for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value &
- ~mPointerGesture.referenceIdBits.value);
- !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- mPointerGesture.referenceDeltas[id].dx = 0;
- mPointerGesture.referenceDeltas[id].dy = 0;
- }
- mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
-
- // Add delta for all fingers and calculate a common movement delta.
- float commonDeltaX = 0, commonDeltaY = 0;
- BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value &
- mCurrentCookedState.fingerIdBits.value);
- for (BitSet32 idBits(commonIdBits); !idBits.isEmpty();) {
- bool first = (idBits == commonIdBits);
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
- const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
- PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
- delta.dx += cpd.x - lpd.x;
- delta.dy += cpd.y - lpd.y;
-
- if (first) {
- commonDeltaX = delta.dx;
- commonDeltaY = delta.dy;
- } else {
- commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
- commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
- }
- }
-
- // Consider transitions from PRESS to SWIPE or MULTITOUCH.
- if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
- float dist[MAX_POINTER_ID + 1];
- int32_t distOverThreshold = 0;
- for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
- dist[id] = hypotf(delta.dx * mPointerXZoomScale, delta.dy * mPointerYZoomScale);
- if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
- distOverThreshold += 1;
- }
- }
-
- // Only transition when at least two pointers have moved further than
- // the minimum distance threshold.
- if (distOverThreshold >= 2) {
- if (currentFingerCount > 2) {
- // There are more than two pointers, switch to FREEFORM.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
- currentFingerCount);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
- } else {
- // There are exactly two pointers.
- BitSet32 idBits(mCurrentCookedState.fingerIdBits);
- uint32_t id1 = idBits.clearFirstMarkedBit();
- uint32_t id2 = idBits.firstMarkedBit();
- const RawPointerData::Pointer& p1 =
- mCurrentRawState.rawPointerData.pointerForId(id1);
- const RawPointerData::Pointer& p2 =
- mCurrentRawState.rawPointerData.pointerForId(id2);
- float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
- if (mutualDistance > mPointerGestureMaxSwipeWidth) {
- // There are two pointers but they are too far apart for a SWIPE,
- // switch to FREEFORM.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
- mutualDistance, mPointerGestureMaxSwipeWidth);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
- } else {
- // There are two pointers. Wait for both pointers to start moving
- // before deciding whether this is a SWIPE or FREEFORM gesture.
- float dist1 = dist[id1];
- float dist2 = dist[id2];
- if (dist1 >= mConfig.pointerGestureMultitouchMinDistance &&
- dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
- // Calculate the dot product of the displacement vectors.
- // When the vectors are oriented in approximately the same direction,
- // the angle betweeen them is near zero and the cosine of the angle
- // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) *
- // mag(v2).
- PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
- PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
- float dx1 = delta1.dx * mPointerXZoomScale;
- float dy1 = delta1.dy * mPointerYZoomScale;
- float dx2 = delta2.dx * mPointerXZoomScale;
- float dy2 = delta2.dy * mPointerYZoomScale;
- float dot = dx1 * dx2 + dy1 * dy2;
- float cosine = dot / (dist1 * dist2); // denominator always > 0
- if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
- // Pointers are moving in the same direction. Switch to SWIPE.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS transitioned to SWIPE, "
- "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
- "cosine %0.3f >= %0.3f",
- dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
- mConfig.pointerGestureMultitouchMinDistance, cosine,
- mConfig.pointerGestureSwipeTransitionAngleCosine);
-#endif
- mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
- } else {
- // Pointers are moving in different directions. Switch to FREEFORM.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS transitioned to FREEFORM, "
- "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
- "cosine %0.3f < %0.3f",
- dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
- mConfig.pointerGestureMultitouchMinDistance, cosine,
- mConfig.pointerGestureSwipeTransitionAngleCosine);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
- }
- }
- }
- }
- }
- } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
- // Switch from SWIPE to FREEFORM if additional pointers go down.
- // Cancel previous gesture.
- if (currentFingerCount > 2) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
- currentFingerCount);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
- }
- }
-
- // Move the reference points based on the overall group motion of the fingers
- // except in PRESS mode while waiting for a transition to occur.
- if (mPointerGesture.currentGestureMode != PointerGesture::PRESS &&
- (commonDeltaX || commonDeltaY)) {
- for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
- delta.dx = 0;
- delta.dy = 0;
- }
-
- mPointerGesture.referenceTouchX += commonDeltaX;
- mPointerGesture.referenceTouchY += commonDeltaY;
-
- commonDeltaX *= mPointerXMovementScale;
- commonDeltaY *= mPointerYMovementScale;
-
- rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
- mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
-
- mPointerGesture.referenceGestureX += commonDeltaX;
- mPointerGesture.referenceGestureY += commonDeltaY;
- }
-
- // Report gestures.
- if (mPointerGesture.currentGestureMode == PointerGesture::PRESS ||
- mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
- // PRESS or SWIPE mode.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
- "activeGestureId=%d, currentTouchPointerCount=%d",
- activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
-#endif
- ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
-
- mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
- mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
- mPointerGesture.currentGestureProperties[0].clear();
- mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[0].clear();
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
- mPointerGesture.referenceGestureX);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
- mPointerGesture.referenceGestureY);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
- // FREEFORM mode.
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM activeTouchId=%d,"
- "activeGestureId=%d, currentTouchPointerCount=%d",
- activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
-#endif
- ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
-
- mPointerGesture.currentGestureIdBits.clear();
-
- BitSet32 mappedTouchIdBits;
- BitSet32 usedGestureIdBits;
- if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
- // Initially, assign the active gesture id to the active touch point
- // if there is one. No other touch id bits are mapped yet.
- if (!*outCancelPreviousGesture) {
- mappedTouchIdBits.markBit(activeTouchId);
- usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
- mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
- mPointerGesture.activeGestureId;
- } else {
- mPointerGesture.activeGestureId = -1;
- }
- } else {
- // Otherwise, assume we mapped all touches from the previous frame.
- // Reuse all mappings that are still applicable.
- mappedTouchIdBits.value = mLastCookedState.fingerIdBits.value &
- mCurrentCookedState.fingerIdBits.value;
- usedGestureIdBits = mPointerGesture.lastGestureIdBits;
-
- // Check whether we need to choose a new active gesture id because the
- // current went went up.
- for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value &
- ~mCurrentCookedState.fingerIdBits.value);
- !upTouchIdBits.isEmpty();) {
- uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
- uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
- if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
- mPointerGesture.activeGestureId = -1;
- break;
- }
- }
- }
-
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM follow up "
- "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
- "activeGestureId=%d",
- mappedTouchIdBits.value, usedGestureIdBits.value,
- mPointerGesture.activeGestureId);
-#endif
-
- BitSet32 idBits(mCurrentCookedState.fingerIdBits);
- for (uint32_t i = 0; i < currentFingerCount; i++) {
- uint32_t touchId = idBits.clearFirstMarkedBit();
- uint32_t gestureId;
- if (!mappedTouchIdBits.hasBit(touchId)) {
- gestureId = usedGestureIdBits.markFirstUnmarkedBit();
- mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM "
- "new mapping for touch id %d -> gesture id %d",
- touchId, gestureId);
-#endif
- } else {
- gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM "
- "existing mapping for touch id %d -> gesture id %d",
- touchId, gestureId);
-#endif
- }
- mPointerGesture.currentGestureIdBits.markBit(gestureId);
- mPointerGesture.currentGestureIdToIndex[gestureId] = i;
-
- const RawPointerData::Pointer& pointer =
- mCurrentRawState.rawPointerData.pointerForId(touchId);
- float deltaX = (pointer.x - mPointerGesture.referenceTouchX) * mPointerXZoomScale;
- float deltaY = (pointer.y - mPointerGesture.referenceTouchY) * mPointerYZoomScale;
- rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
-
- mPointerGesture.currentGestureProperties[i].clear();
- mPointerGesture.currentGestureProperties[i].id = gestureId;
- mPointerGesture.currentGestureProperties[i].toolType =
- AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[i].clear();
- mPointerGesture.currentGestureCoords[i]
- .setAxisValue(AMOTION_EVENT_AXIS_X,
- mPointerGesture.referenceGestureX + deltaX);
- mPointerGesture.currentGestureCoords[i]
- .setAxisValue(AMOTION_EVENT_AXIS_Y,
- mPointerGesture.referenceGestureY + deltaY);
- mPointerGesture.currentGestureCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
- 1.0f);
- }
-
- if (mPointerGesture.activeGestureId < 0) {
- mPointerGesture.activeGestureId =
- mPointerGesture.currentGestureIdBits.firstMarkedBit();
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM new "
- "activeGestureId=%d",
- mPointerGesture.activeGestureId);
-#endif
- }
- }
- }
-
- mPointerController->setButtonState(mCurrentRawState.buttonState);
-
-#if DEBUG_GESTURES
- ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
- "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
- "lastGestureMode=%d, lastGestureIdBits=0x%08x",
- toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
- mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
- mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
- for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
- const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
- const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
- ALOGD(" currentGesture[%d]: index=%d, toolType=%d, "
- "x=%0.3f, y=%0.3f, pressure=%0.3f",
- id, index, properties.toolType, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
- coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
- coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
- }
- for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
- const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
- const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
- ALOGD(" lastGesture[%d]: index=%d, toolType=%d, "
- "x=%0.3f, y=%0.3f, pressure=%0.3f",
- id, index, properties.toolType, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
- coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
- coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
- }
-#endif
- return true;
-}
-
-void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
- mPointerSimple.currentCoords.clear();
- mPointerSimple.currentProperties.clear();
-
- bool down, hovering;
- if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
- uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
- uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
- float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
- float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
- mPointerController->setPosition(x, y);
-
- hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
- down = !hovering;
-
- mPointerController->getPosition(&x, &y);
- mPointerSimple.currentCoords.copyFrom(
- mCurrentCookedState.cookedPointerData.pointerCoords[index]);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- mPointerSimple.currentProperties.id = 0;
- mPointerSimple.currentProperties.toolType =
- mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
- } else {
- down = false;
- hovering = false;
- }
-
- dispatchPointerSimple(when, policyFlags, down, hovering);
-}
-
-void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
- abortPointerSimple(when, policyFlags);
-}
-
-void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
- mPointerSimple.currentCoords.clear();
- mPointerSimple.currentProperties.clear();
-
- bool down, hovering;
- if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
- uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
- uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
- float deltaX = 0, deltaY = 0;
- if (mLastCookedState.mouseIdBits.hasBit(id)) {
- uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
- deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x -
- mLastRawState.rawPointerData.pointers[lastIndex].x) *
- mPointerXMovementScale;
- deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y -
- mLastRawState.rawPointerData.pointers[lastIndex].y) *
- mPointerYMovementScale;
-
- rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- mPointerController->move(deltaX, deltaY);
- } else {
- mPointerVelocityControl.reset();
- }
-
- down = isPointerDown(mCurrentRawState.buttonState);
- hovering = !down;
-
- float x, y;
- mPointerController->getPosition(&x, &y);
- mPointerSimple.currentCoords.copyFrom(
- mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
- hovering ? 0.0f : 1.0f);
- mPointerSimple.currentProperties.id = 0;
- mPointerSimple.currentProperties.toolType =
- mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
- } else {
- mPointerVelocityControl.reset();
-
- down = false;
- hovering = false;
- }
-
- dispatchPointerSimple(when, policyFlags, down, hovering);
-}
-
-void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
- abortPointerSimple(when, policyFlags);
-
- mPointerVelocityControl.reset();
-}
-
-void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, bool down,
- bool hovering) {
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t displayId = mViewport.displayId;
-
- if (mPointerController != nullptr) {
- if (down || hovering) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
- mPointerController->clearSpots();
- mPointerController->setButtonState(mCurrentRawState.buttonState);
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
- displayId = mPointerController->getDisplayId();
- }
-
- if (mPointerSimple.down && !down) {
- mPointerSimple.down = false;
-
- // Send up.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
- mLastRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
- &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
- mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
- }
-
- if (mPointerSimple.hovering && !hovering) {
- mPointerSimple.hovering = false;
-
- // Send hover exit.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0,
- metaState, mLastRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
- &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
- mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
- }
-
- if (down) {
- if (!mPointerSimple.down) {
- mPointerSimple.down = true;
- mPointerSimple.downTime = when;
-
- // Send down.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0,
- metaState, mCurrentRawState.buttonState,
- MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &mPointerSimple.currentProperties,
- &mPointerSimple.currentCoords, mOrientedXPrecision,
- mOrientedYPrecision, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
- }
-
- // Send move.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
- mCurrentRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
- &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
- }
-
- if (hovering) {
- if (!mPointerSimple.hovering) {
- mPointerSimple.hovering = true;
-
- // Send hover enter.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
- metaState, mCurrentRawState.buttonState,
- MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &mPointerSimple.currentProperties,
- &mPointerSimple.currentCoords, mOrientedXPrecision,
- mOrientedYPrecision, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
- }
-
- // Send hover move.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
- metaState, mCurrentRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
- &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
- }
-
- if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
- float vscroll = mCurrentRawState.rawVScroll;
- float hscroll = mCurrentRawState.rawHScroll;
- mWheelYVelocityControl.move(when, nullptr, &vscroll);
- mWheelXVelocityControl.move(when, &hscroll, nullptr);
-
- // Send scroll.
- PointerCoords pointerCoords;
- pointerCoords.copyFrom(mPointerSimple.currentCoords);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
-
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
- mCurrentRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
- &mPointerSimple.currentProperties, &pointerCoords,
- mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
- }
-
- // Save state.
- if (down || hovering) {
- mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
- mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
- } else {
- mPointerSimple.reset();
- }
-}
-
-void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
- mPointerSimple.currentCoords.clear();
- mPointerSimple.currentProperties.clear();
-
- dispatchPointerSimple(when, policyFlags, false, false);
-}
-
-void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
- int32_t action, int32_t actionButton, int32_t flags,
- int32_t metaState, int32_t buttonState, int32_t edgeFlags,
- uint32_t deviceTimestamp, const PointerProperties* properties,
- const PointerCoords* coords, const uint32_t* idToIndex,
- BitSet32 idBits, int32_t changedId, float xPrecision,
- float yPrecision, nsecs_t downTime) {
- PointerCoords pointerCoords[MAX_POINTERS];
- PointerProperties pointerProperties[MAX_POINTERS];
- uint32_t pointerCount = 0;
- while (!idBits.isEmpty()) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t index = idToIndex[id];
- pointerProperties[pointerCount].copyFrom(properties[index]);
- pointerCoords[pointerCount].copyFrom(coords[index]);
-
- if (changedId >= 0 && id == uint32_t(changedId)) {
- action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
- }
-
- pointerCount += 1;
- }
-
- ALOG_ASSERT(pointerCount != 0);
-
- if (changedId >= 0 && pointerCount == 1) {
- // Replace initial down and final up action.
- // We can compare the action without masking off the changed pointer index
- // because we know the index is 0.
- if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
- action = AMOTION_EVENT_ACTION_DOWN;
- } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
- action = AMOTION_EVENT_ACTION_UP;
- } else {
- // Can't happen.
- ALOG_ASSERT(false);
- }
- }
- const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE);
- const int32_t deviceId = getDeviceId();
- std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
- std::for_each(frames.begin(), frames.end(),
- [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId, source, displayId,
- policyFlags, action, actionButton, flags, metaState, buttonState,
- MotionClassification::NONE, edgeFlags, deviceTimestamp, pointerCount,
- pointerProperties, pointerCoords, xPrecision, yPrecision, downTime,
- std::move(frames));
- getListener()->notifyMotion(&args);
-}
-
-bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
- const PointerCoords* inCoords,
- const uint32_t* inIdToIndex,
- PointerProperties* outProperties,
- PointerCoords* outCoords, const uint32_t* outIdToIndex,
- BitSet32 idBits) const {
- bool changed = false;
- while (!idBits.isEmpty()) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t inIndex = inIdToIndex[id];
- uint32_t outIndex = outIdToIndex[id];
-
- const PointerProperties& curInProperties = inProperties[inIndex];
- const PointerCoords& curInCoords = inCoords[inIndex];
- PointerProperties& curOutProperties = outProperties[outIndex];
- PointerCoords& curOutCoords = outCoords[outIndex];
-
- if (curInProperties != curOutProperties) {
- curOutProperties.copyFrom(curInProperties);
- changed = true;
- }
-
- if (curInCoords != curOutCoords) {
- curOutCoords.copyFrom(curInCoords);
- changed = true;
- }
- }
- return changed;
-}
-
-void TouchInputMapper::fadePointer() {
- if (mPointerController != nullptr) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
-}
-
-void TouchInputMapper::cancelTouch(nsecs_t when) {
- abortPointerUsage(when, 0 /*policyFlags*/);
- abortTouches(when, 0 /* policyFlags*/);
-}
-
-bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
- const float scaledX = x * mXScale;
- const float scaledY = y * mYScale;
- return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue &&
- scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth &&
- y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue &&
- scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
-}
-
-const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
- for (const VirtualKey& virtualKey : mVirtualKeys) {
-#if DEBUG_VIRTUAL_KEYS
- ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
- "left=%d, top=%d, right=%d, bottom=%d",
- x, y, virtualKey.keyCode, virtualKey.scanCode, virtualKey.hitLeft, virtualKey.hitTop,
- virtualKey.hitRight, virtualKey.hitBottom);
-#endif
-
- if (virtualKey.isHit(x, y)) {
- return &virtualKey;
- }
- }
-
- return nullptr;
-}
-
-void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) {
- uint32_t currentPointerCount = current->rawPointerData.pointerCount;
- uint32_t lastPointerCount = last->rawPointerData.pointerCount;
-
- current->rawPointerData.clearIdBits();
-
- if (currentPointerCount == 0) {
- // No pointers to assign.
- return;
- }
-
- if (lastPointerCount == 0) {
- // All pointers are new.
- for (uint32_t i = 0; i < currentPointerCount; i++) {
- uint32_t id = i;
- current->rawPointerData.pointers[i].id = id;
- current->rawPointerData.idToIndex[id] = i;
- current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(i));
- }
- return;
- }
-
- if (currentPointerCount == 1 && lastPointerCount == 1 &&
- current->rawPointerData.pointers[0].toolType == last->rawPointerData.pointers[0].toolType) {
- // Only one pointer and no change in count so it must have the same id as before.
- uint32_t id = last->rawPointerData.pointers[0].id;
- current->rawPointerData.pointers[0].id = id;
- current->rawPointerData.idToIndex[id] = 0;
- current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(0));
- return;
- }
-
- // General case.
- // We build a heap of squared euclidean distances between current and last pointers
- // associated with the current and last pointer indices. Then, we find the best
- // match (by distance) for each current pointer.
- // The pointers must have the same tool type but it is possible for them to
- // transition from hovering to touching or vice-versa while retaining the same id.
- PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
-
- uint32_t heapSize = 0;
- for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
- currentPointerIndex++) {
- for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
- lastPointerIndex++) {
- const RawPointerData::Pointer& currentPointer =
- current->rawPointerData.pointers[currentPointerIndex];
- const RawPointerData::Pointer& lastPointer =
- last->rawPointerData.pointers[lastPointerIndex];
- if (currentPointer.toolType == lastPointer.toolType) {
- int64_t deltaX = currentPointer.x - lastPointer.x;
- int64_t deltaY = currentPointer.y - lastPointer.y;
-
- uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
- // Insert new element into the heap (sift up).
- heap[heapSize].currentPointerIndex = currentPointerIndex;
- heap[heapSize].lastPointerIndex = lastPointerIndex;
- heap[heapSize].distance = distance;
- heapSize += 1;
- }
- }
- }
-
- // Heapify
- for (uint32_t startIndex = heapSize / 2; startIndex != 0;) {
- startIndex -= 1;
- for (uint32_t parentIndex = startIndex;;) {
- uint32_t childIndex = parentIndex * 2 + 1;
- if (childIndex >= heapSize) {
- break;
- }
-
- if (childIndex + 1 < heapSize &&
- heap[childIndex + 1].distance < heap[childIndex].distance) {
- childIndex += 1;
- }
-
- if (heap[parentIndex].distance <= heap[childIndex].distance) {
- break;
- }
-
- swap(heap[parentIndex], heap[childIndex]);
- parentIndex = childIndex;
- }
- }
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
- for (size_t i = 0; i < heapSize; i++) {
- ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, i,
- heap[i].currentPointerIndex, heap[i].lastPointerIndex, heap[i].distance);
- }
-#endif
-
- // Pull matches out by increasing order of distance.
- // To avoid reassigning pointers that have already been matched, the loop keeps track
- // of which last and current pointers have been matched using the matchedXXXBits variables.
- // It also tracks the used pointer id bits.
- BitSet32 matchedLastBits(0);
- BitSet32 matchedCurrentBits(0);
- BitSet32 usedIdBits(0);
- bool first = true;
- for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
- while (heapSize > 0) {
- if (first) {
- // The first time through the loop, we just consume the root element of
- // the heap (the one with smallest distance).
- first = false;
- } else {
- // Previous iterations consumed the root element of the heap.
- // Pop root element off of the heap (sift down).
- heap[0] = heap[heapSize];
- for (uint32_t parentIndex = 0;;) {
- uint32_t childIndex = parentIndex * 2 + 1;
- if (childIndex >= heapSize) {
- break;
- }
-
- if (childIndex + 1 < heapSize &&
- heap[childIndex + 1].distance < heap[childIndex].distance) {
- childIndex += 1;
- }
-
- if (heap[parentIndex].distance <= heap[childIndex].distance) {
- break;
- }
-
- swap(heap[parentIndex], heap[childIndex]);
- parentIndex = childIndex;
- }
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
- for (size_t i = 0; i < heapSize; i++) {
- ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, i,
- heap[i].currentPointerIndex, heap[i].lastPointerIndex, heap[i].distance);
- }
-#endif
- }
-
- heapSize -= 1;
-
- uint32_t currentPointerIndex = heap[0].currentPointerIndex;
- if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
-
- uint32_t lastPointerIndex = heap[0].lastPointerIndex;
- if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
-
- matchedCurrentBits.markBit(currentPointerIndex);
- matchedLastBits.markBit(lastPointerIndex);
-
- uint32_t id = last->rawPointerData.pointers[lastPointerIndex].id;
- current->rawPointerData.pointers[currentPointerIndex].id = id;
- current->rawPointerData.idToIndex[id] = currentPointerIndex;
- current->rawPointerData.markIdBit(id,
- current->rawPointerData.isHovering(
- currentPointerIndex));
- usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32 ", id=%" PRIu32
- ", distance=%" PRIu64,
- lastPointerIndex, currentPointerIndex, id, heap[0].distance);
-#endif
- break;
- }
- }
-
- // Assign fresh ids to pointers that were not matched in the process.
- for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
- uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
- uint32_t id = usedIdBits.markFirstUnmarkedBit();
-
- current->rawPointerData.pointers[currentPointerIndex].id = id;
- current->rawPointerData.idToIndex[id] = currentPointerIndex;
- current->rawPointerData.markIdBit(id,
- current->rawPointerData.isHovering(currentPointerIndex));
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
-#endif
- }
-}
-
-int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
- return AKEY_STATE_VIRTUAL;
- }
-
- for (const VirtualKey& virtualKey : mVirtualKeys) {
- if (virtualKey.keyCode == keyCode) {
- return AKEY_STATE_UP;
- }
- }
-
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
- return AKEY_STATE_VIRTUAL;
- }
-
- for (const VirtualKey& virtualKey : mVirtualKeys) {
- if (virtualKey.scanCode == scanCode) {
- return AKEY_STATE_UP;
- }
- }
-
- return AKEY_STATE_UNKNOWN;
-}
-
-bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- for (const VirtualKey& virtualKey : mVirtualKeys) {
- for (size_t i = 0; i < numCodes; i++) {
- if (virtualKey.keyCode == keyCodes[i]) {
- outFlags[i] = 1;
- }
- }
- }
-
- return true;
-}
-
-std::optional<int32_t> TouchInputMapper::getAssociatedDisplay() {
- if (mParameters.hasAssociatedDisplay) {
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- return std::make_optional(mPointerController->getDisplayId());
- } else {
- return std::make_optional(mViewport.displayId);
- }
- }
- return std::nullopt;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
deleted file mode 100644
index d14812aecd..0000000000
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ /dev/null
@@ -1,838 +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.
- */
-
-#ifndef _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H
-#define _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H
-
-#include "CursorButtonAccumulator.h"
-#include "CursorScrollAccumulator.h"
-#include "EventHub.h"
-#include "InputMapper.h"
-#include "InputReaderBase.h"
-#include "TouchButtonAccumulator.h"
-
-#include <stdint.h>
-
-namespace android {
-
-/**
- * Basic statistics information.
- * Keep track of min, max, average, and standard deviation of the received samples.
- * Used to report latency information about input events.
- */
-struct LatencyStatistics {
- float min;
- float max;
- // Sum of all samples
- float sum;
- // Sum of squares of all samples
- float sum2;
- // The number of samples
- size_t count;
- // The last time statistics were reported.
- nsecs_t lastReportTime;
-
- LatencyStatistics() { reset(systemTime(SYSTEM_TIME_MONOTONIC)); }
-
- inline void addValue(float x) {
- if (x < min) {
- min = x;
- }
- if (x > max) {
- max = x;
- }
- sum += x;
- sum2 += x * x;
- count++;
- }
-
- // Get the average value. Should not be called if no samples have been added.
- inline float mean() {
- if (count == 0) {
- return 0;
- }
- return sum / count;
- }
-
- // Get the standard deviation. Should not be called if no samples have been added.
- inline float stdev() {
- if (count == 0) {
- return 0;
- }
- float average = mean();
- return sqrt(sum2 / count - average * average);
- }
-
- /**
- * Reset internal state. The variable 'when' is the time when the data collection started.
- * Call this to start a new data collection window.
- */
- inline void reset(nsecs_t when) {
- max = 0;
- min = std::numeric_limits<float>::max();
- sum = 0;
- sum2 = 0;
- count = 0;
- lastReportTime = when;
- }
-};
-
-/* Raw axis information from the driver. */
-struct RawPointerAxes {
- RawAbsoluteAxisInfo x;
- RawAbsoluteAxisInfo y;
- RawAbsoluteAxisInfo pressure;
- RawAbsoluteAxisInfo touchMajor;
- RawAbsoluteAxisInfo touchMinor;
- RawAbsoluteAxisInfo toolMajor;
- RawAbsoluteAxisInfo toolMinor;
- RawAbsoluteAxisInfo orientation;
- RawAbsoluteAxisInfo distance;
- RawAbsoluteAxisInfo tiltX;
- RawAbsoluteAxisInfo tiltY;
- RawAbsoluteAxisInfo trackingId;
- RawAbsoluteAxisInfo slot;
-
- RawPointerAxes();
- inline int32_t getRawWidth() const { return x.maxValue - x.minValue + 1; }
- inline int32_t getRawHeight() const { return y.maxValue - y.minValue + 1; }
- void clear();
-};
-
-/* Raw data for a collection of pointers including a pointer id mapping table. */
-struct RawPointerData {
- struct Pointer {
- uint32_t id;
- int32_t x;
- int32_t y;
- int32_t pressure;
- int32_t touchMajor;
- int32_t touchMinor;
- int32_t toolMajor;
- int32_t toolMinor;
- int32_t orientation;
- int32_t distance;
- int32_t tiltX;
- int32_t tiltY;
- int32_t toolType; // a fully decoded AMOTION_EVENT_TOOL_TYPE constant
- bool isHovering;
- };
-
- uint32_t pointerCount;
- Pointer pointers[MAX_POINTERS];
- BitSet32 hoveringIdBits, touchingIdBits;
- uint32_t idToIndex[MAX_POINTER_ID + 1];
-
- RawPointerData();
- void clear();
- void copyFrom(const RawPointerData& other);
- void getCentroidOfTouchingPointers(float* outX, float* outY) const;
-
- inline void markIdBit(uint32_t id, bool isHovering) {
- if (isHovering) {
- hoveringIdBits.markBit(id);
- } else {
- touchingIdBits.markBit(id);
- }
- }
-
- inline void clearIdBits() {
- hoveringIdBits.clear();
- touchingIdBits.clear();
- }
-
- inline const Pointer& pointerForId(uint32_t id) const { return pointers[idToIndex[id]]; }
-
- inline bool isHovering(uint32_t pointerIndex) { return pointers[pointerIndex].isHovering; }
-};
-
-/* Cooked data for a collection of pointers including a pointer id mapping table. */
-struct CookedPointerData {
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
- BitSet32 hoveringIdBits, touchingIdBits;
- uint32_t idToIndex[MAX_POINTER_ID + 1];
-
- CookedPointerData();
- void clear();
- void copyFrom(const CookedPointerData& other);
-
- inline const PointerCoords& pointerCoordsForId(uint32_t id) const {
- return pointerCoords[idToIndex[id]];
- }
-
- inline PointerCoords& editPointerCoordsWithId(uint32_t id) {
- return pointerCoords[idToIndex[id]];
- }
-
- inline PointerProperties& editPointerPropertiesWithId(uint32_t id) {
- return pointerProperties[idToIndex[id]];
- }
-
- inline bool isHovering(uint32_t pointerIndex) const {
- return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id);
- }
-
- inline bool isTouching(uint32_t pointerIndex) const {
- return touchingIdBits.hasBit(pointerProperties[pointerIndex].id);
- }
-};
-
-class TouchInputMapper : public InputMapper {
-public:
- explicit TouchInputMapper(InputDevice* device);
- virtual ~TouchInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(std::string& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
-
- virtual void fadePointer();
- virtual void cancelTouch(nsecs_t when);
- virtual void timeoutExpired(nsecs_t when);
- virtual void updateExternalStylusState(const StylusState& state);
- virtual std::optional<int32_t> getAssociatedDisplay();
-
-protected:
- CursorButtonAccumulator mCursorButtonAccumulator;
- CursorScrollAccumulator mCursorScrollAccumulator;
- TouchButtonAccumulator mTouchButtonAccumulator;
-
- struct VirtualKey {
- int32_t keyCode;
- int32_t scanCode;
- uint32_t flags;
-
- // computed hit box, specified in touch screen coords based on known display size
- int32_t hitLeft;
- int32_t hitTop;
- int32_t hitRight;
- int32_t hitBottom;
-
- inline bool isHit(int32_t x, int32_t y) const {
- return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
- }
- };
-
- // Input sources and device mode.
- uint32_t mSource;
-
- enum DeviceMode {
- DEVICE_MODE_DISABLED, // input is disabled
- DEVICE_MODE_DIRECT, // direct mapping (touchscreen)
- DEVICE_MODE_UNSCALED, // unscaled mapping (touchpad)
- DEVICE_MODE_NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
- DEVICE_MODE_POINTER, // pointer mapping (pointer)
- };
- DeviceMode mDeviceMode;
-
- // The reader's configuration.
- InputReaderConfiguration mConfig;
-
- // Immutable configuration parameters.
- struct Parameters {
- enum DeviceType {
- DEVICE_TYPE_TOUCH_SCREEN,
- DEVICE_TYPE_TOUCH_PAD,
- DEVICE_TYPE_TOUCH_NAVIGATION,
- DEVICE_TYPE_POINTER,
- };
-
- DeviceType deviceType;
- bool hasAssociatedDisplay;
- bool associatedDisplayIsExternal;
- bool orientationAware;
- bool hasButtonUnderPad;
- std::string uniqueDisplayId;
-
- enum GestureMode {
- GESTURE_MODE_SINGLE_TOUCH,
- GESTURE_MODE_MULTI_TOUCH,
- };
- GestureMode gestureMode;
-
- bool wake;
- } mParameters;
-
- // Immutable calibration parameters in parsed form.
- struct Calibration {
- // Size
- enum SizeCalibration {
- SIZE_CALIBRATION_DEFAULT,
- SIZE_CALIBRATION_NONE,
- SIZE_CALIBRATION_GEOMETRIC,
- SIZE_CALIBRATION_DIAMETER,
- SIZE_CALIBRATION_BOX,
- SIZE_CALIBRATION_AREA,
- };
-
- SizeCalibration sizeCalibration;
-
- bool haveSizeScale;
- float sizeScale;
- bool haveSizeBias;
- float sizeBias;
- bool haveSizeIsSummed;
- bool sizeIsSummed;
-
- // Pressure
- enum PressureCalibration {
- PRESSURE_CALIBRATION_DEFAULT,
- PRESSURE_CALIBRATION_NONE,
- PRESSURE_CALIBRATION_PHYSICAL,
- PRESSURE_CALIBRATION_AMPLITUDE,
- };
-
- PressureCalibration pressureCalibration;
- bool havePressureScale;
- float pressureScale;
-
- // Orientation
- enum OrientationCalibration {
- ORIENTATION_CALIBRATION_DEFAULT,
- ORIENTATION_CALIBRATION_NONE,
- ORIENTATION_CALIBRATION_INTERPOLATED,
- ORIENTATION_CALIBRATION_VECTOR,
- };
-
- OrientationCalibration orientationCalibration;
-
- // Distance
- enum DistanceCalibration {
- DISTANCE_CALIBRATION_DEFAULT,
- DISTANCE_CALIBRATION_NONE,
- DISTANCE_CALIBRATION_SCALED,
- };
-
- DistanceCalibration distanceCalibration;
- bool haveDistanceScale;
- float distanceScale;
-
- enum CoverageCalibration {
- COVERAGE_CALIBRATION_DEFAULT,
- COVERAGE_CALIBRATION_NONE,
- COVERAGE_CALIBRATION_BOX,
- };
-
- CoverageCalibration coverageCalibration;
-
- inline void applySizeScaleAndBias(float* outSize) const {
- if (haveSizeScale) {
- *outSize *= sizeScale;
- }
- if (haveSizeBias) {
- *outSize += sizeBias;
- }
- if (*outSize < 0) {
- *outSize = 0;
- }
- }
- } mCalibration;
-
- // Affine location transformation/calibration
- struct TouchAffineTransformation mAffineTransform;
-
- RawPointerAxes mRawPointerAxes;
-
- struct RawState {
- nsecs_t when;
- uint32_t deviceTimestamp;
-
- // Raw pointer sample data.
- RawPointerData rawPointerData;
-
- int32_t buttonState;
-
- // Scroll state.
- int32_t rawVScroll;
- int32_t rawHScroll;
-
- void copyFrom(const RawState& other) {
- when = other.when;
- deviceTimestamp = other.deviceTimestamp;
- rawPointerData.copyFrom(other.rawPointerData);
- buttonState = other.buttonState;
- rawVScroll = other.rawVScroll;
- rawHScroll = other.rawHScroll;
- }
-
- void clear() {
- when = 0;
- deviceTimestamp = 0;
- rawPointerData.clear();
- buttonState = 0;
- rawVScroll = 0;
- rawHScroll = 0;
- }
- };
-
- struct CookedState {
- uint32_t deviceTimestamp;
- // Cooked pointer sample data.
- CookedPointerData cookedPointerData;
-
- // Id bits used to differentiate fingers, stylus and mouse tools.
- BitSet32 fingerIdBits;
- BitSet32 stylusIdBits;
- BitSet32 mouseIdBits;
-
- int32_t buttonState;
-
- void copyFrom(const CookedState& other) {
- deviceTimestamp = other.deviceTimestamp;
- cookedPointerData.copyFrom(other.cookedPointerData);
- fingerIdBits = other.fingerIdBits;
- stylusIdBits = other.stylusIdBits;
- mouseIdBits = other.mouseIdBits;
- buttonState = other.buttonState;
- }
-
- void clear() {
- deviceTimestamp = 0;
- cookedPointerData.clear();
- fingerIdBits.clear();
- stylusIdBits.clear();
- mouseIdBits.clear();
- buttonState = 0;
- }
- };
-
- std::vector<RawState> mRawStatesPending;
- RawState mCurrentRawState;
- CookedState mCurrentCookedState;
- RawState mLastRawState;
- CookedState mLastCookedState;
-
- // State provided by an external stylus
- StylusState mExternalStylusState;
- int64_t mExternalStylusId;
- nsecs_t mExternalStylusFusionTimeout;
- bool mExternalStylusDataPending;
-
- // True if we sent a HOVER_ENTER event.
- bool mSentHoverEnter;
-
- // Have we assigned pointer IDs for this stream
- bool mHavePointerIds;
-
- // Is the current stream of direct touch events aborted
- bool mCurrentMotionAborted;
-
- // The time the primary pointer last went down.
- nsecs_t mDownTime;
-
- // The pointer controller, or null if the device is not a pointer.
- sp<PointerControllerInterface> mPointerController;
-
- std::vector<VirtualKey> mVirtualKeys;
-
- virtual void configureParameters();
- virtual void dumpParameters(std::string& dump);
- virtual void configureRawPointerAxes();
- virtual void dumpRawPointerAxes(std::string& dump);
- virtual void configureSurface(nsecs_t when, bool* outResetNeeded);
- virtual void dumpSurface(std::string& dump);
- virtual void configureVirtualKeys();
- virtual void dumpVirtualKeys(std::string& dump);
- virtual void parseCalibration();
- virtual void resolveCalibration();
- virtual void dumpCalibration(std::string& dump);
- virtual void updateAffineTransformation();
- virtual void dumpAffineTransformation(std::string& dump);
- virtual void resolveExternalStylusPresence();
- virtual bool hasStylus() const = 0;
- virtual bool hasExternalStylus() const;
-
- virtual void syncTouch(nsecs_t when, RawState* outState) = 0;
-
-private:
- // The current viewport.
- // The components of the viewport are specified in the display's rotated orientation.
- DisplayViewport mViewport;
-
- // The surface orientation, width and height set by configureSurface().
- // The width and height are derived from the viewport but are specified
- // in the natural orientation.
- // The surface origin specifies how the surface coordinates should be translated
- // to align with the logical display coordinate space.
- int32_t mSurfaceWidth;
- int32_t mSurfaceHeight;
- int32_t mSurfaceLeft;
- int32_t mSurfaceTop;
-
- // Similar to the surface coordinates, but in the raw display coordinate space rather than in
- // the logical coordinate space.
- int32_t mPhysicalWidth;
- int32_t mPhysicalHeight;
- int32_t mPhysicalLeft;
- int32_t mPhysicalTop;
-
- // The orientation may be different from the viewport orientation as it specifies
- // the rotation of the surface coordinates required to produce the viewport's
- // requested orientation, so it will depend on whether the device is orientation aware.
- int32_t mSurfaceOrientation;
-
- // Translation and scaling factors, orientation-independent.
- float mXTranslate;
- float mXScale;
- float mXPrecision;
-
- float mYTranslate;
- float mYScale;
- float mYPrecision;
-
- float mGeometricScale;
-
- float mPressureScale;
-
- float mSizeScale;
-
- float mOrientationScale;
-
- float mDistanceScale;
-
- bool mHaveTilt;
- float mTiltXCenter;
- float mTiltXScale;
- float mTiltYCenter;
- float mTiltYScale;
-
- bool mExternalStylusConnected;
-
- // Oriented motion ranges for input device info.
- struct OrientedRanges {
- InputDeviceInfo::MotionRange x;
- InputDeviceInfo::MotionRange y;
- InputDeviceInfo::MotionRange pressure;
-
- bool haveSize;
- InputDeviceInfo::MotionRange size;
-
- bool haveTouchSize;
- InputDeviceInfo::MotionRange touchMajor;
- InputDeviceInfo::MotionRange touchMinor;
-
- bool haveToolSize;
- InputDeviceInfo::MotionRange toolMajor;
- InputDeviceInfo::MotionRange toolMinor;
-
- bool haveOrientation;
- InputDeviceInfo::MotionRange orientation;
-
- bool haveDistance;
- InputDeviceInfo::MotionRange distance;
-
- bool haveTilt;
- InputDeviceInfo::MotionRange tilt;
-
- OrientedRanges() { clear(); }
-
- void clear() {
- haveSize = false;
- haveTouchSize = false;
- haveToolSize = false;
- haveOrientation = false;
- haveDistance = false;
- haveTilt = false;
- }
- } mOrientedRanges;
-
- // Oriented dimensions and precision.
- float mOrientedXPrecision;
- float mOrientedYPrecision;
-
- struct CurrentVirtualKeyState {
- bool down;
- bool ignored;
- nsecs_t downTime;
- int32_t keyCode;
- int32_t scanCode;
- } mCurrentVirtualKey;
-
- // Scale factor for gesture or mouse based pointer movements.
- float mPointerXMovementScale;
- float mPointerYMovementScale;
-
- // Scale factor for gesture based zooming and other freeform motions.
- float mPointerXZoomScale;
- float mPointerYZoomScale;
-
- // The maximum swipe width.
- float mPointerGestureMaxSwipeWidth;
-
- struct PointerDistanceHeapElement {
- uint32_t currentPointerIndex : 8;
- uint32_t lastPointerIndex : 8;
- uint64_t distance : 48; // squared distance
- };
-
- enum PointerUsage {
- POINTER_USAGE_NONE,
- POINTER_USAGE_GESTURES,
- POINTER_USAGE_STYLUS,
- POINTER_USAGE_MOUSE,
- };
- PointerUsage mPointerUsage;
-
- struct PointerGesture {
- enum Mode {
- // No fingers, button is not pressed.
- // Nothing happening.
- NEUTRAL,
-
- // No fingers, button is not pressed.
- // Tap detected.
- // Emits DOWN and UP events at the pointer location.
- TAP,
-
- // Exactly one finger dragging following a tap.
- // Pointer follows the active finger.
- // Emits DOWN, MOVE and UP events at the pointer location.
- //
- // Detect double-taps when the finger goes up while in TAP_DRAG mode.
- TAP_DRAG,
-
- // Button is pressed.
- // Pointer follows the active finger if there is one. Other fingers are ignored.
- // Emits DOWN, MOVE and UP events at the pointer location.
- BUTTON_CLICK_OR_DRAG,
-
- // Exactly one finger, button is not pressed.
- // Pointer follows the active finger.
- // Emits HOVER_MOVE events at the pointer location.
- //
- // Detect taps when the finger goes up while in HOVER mode.
- HOVER,
-
- // Exactly two fingers but neither have moved enough to clearly indicate
- // whether a swipe or freeform gesture was intended. We consider the
- // pointer to be pressed so this enables clicking or long-pressing on buttons.
- // Pointer does not move.
- // Emits DOWN, MOVE and UP events with a single stationary pointer coordinate.
- PRESS,
-
- // Exactly two fingers moving in the same direction, button is not pressed.
- // Pointer does not move.
- // Emits DOWN, MOVE and UP events with a single pointer coordinate that
- // follows the midpoint between both fingers.
- SWIPE,
-
- // Two or more fingers moving in arbitrary directions, button is not pressed.
- // Pointer does not move.
- // Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow
- // each finger individually relative to the initial centroid of the finger.
- FREEFORM,
-
- // Waiting for quiet time to end before starting the next gesture.
- QUIET,
- };
-
- // Time the first finger went down.
- nsecs_t firstTouchTime;
-
- // The active pointer id from the raw touch data.
- int32_t activeTouchId; // -1 if none
-
- // The active pointer id from the gesture last delivered to the application.
- int32_t activeGestureId; // -1 if none
-
- // Pointer coords and ids for the current and previous pointer gesture.
- Mode currentGestureMode;
- BitSet32 currentGestureIdBits;
- uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1];
- PointerProperties currentGestureProperties[MAX_POINTERS];
- PointerCoords currentGestureCoords[MAX_POINTERS];
-
- Mode lastGestureMode;
- BitSet32 lastGestureIdBits;
- uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1];
- PointerProperties lastGestureProperties[MAX_POINTERS];
- PointerCoords lastGestureCoords[MAX_POINTERS];
-
- // Time the pointer gesture last went down.
- nsecs_t downTime;
-
- // Time when the pointer went down for a TAP.
- nsecs_t tapDownTime;
-
- // Time when the pointer went up for a TAP.
- nsecs_t tapUpTime;
-
- // Location of initial tap.
- float tapX, tapY;
-
- // Time we started waiting for quiescence.
- nsecs_t quietTime;
-
- // Reference points for multitouch gestures.
- float referenceTouchX; // reference touch X/Y coordinates in surface units
- float referenceTouchY;
- float referenceGestureX; // reference gesture X/Y coordinates in pixels
- float referenceGestureY;
-
- // Distance that each pointer has traveled which has not yet been
- // subsumed into the reference gesture position.
- BitSet32 referenceIdBits;
- struct Delta {
- float dx, dy;
- };
- Delta referenceDeltas[MAX_POINTER_ID + 1];
-
- // Describes how touch ids are mapped to gesture ids for freeform gestures.
- uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1];
-
- // A velocity tracker for determining whether to switch active pointers during drags.
- VelocityTracker velocityTracker;
-
- void reset() {
- firstTouchTime = LLONG_MIN;
- activeTouchId = -1;
- activeGestureId = -1;
- currentGestureMode = NEUTRAL;
- currentGestureIdBits.clear();
- lastGestureMode = NEUTRAL;
- lastGestureIdBits.clear();
- downTime = 0;
- velocityTracker.clear();
- resetTap();
- resetQuietTime();
- }
-
- void resetTap() {
- tapDownTime = LLONG_MIN;
- tapUpTime = LLONG_MIN;
- }
-
- void resetQuietTime() { quietTime = LLONG_MIN; }
- } mPointerGesture;
-
- struct PointerSimple {
- PointerCoords currentCoords;
- PointerProperties currentProperties;
- PointerCoords lastCoords;
- PointerProperties lastProperties;
-
- // True if the pointer is down.
- bool down;
-
- // True if the pointer is hovering.
- bool hovering;
-
- // Time the pointer last went down.
- nsecs_t downTime;
-
- void reset() {
- currentCoords.clear();
- currentProperties.clear();
- lastCoords.clear();
- lastProperties.clear();
- down = false;
- hovering = false;
- downTime = 0;
- }
- } mPointerSimple;
-
- // The pointer and scroll velocity controls.
- VelocityControl mPointerVelocityControl;
- VelocityControl mWheelXVelocityControl;
- VelocityControl mWheelYVelocityControl;
-
- // Latency statistics for touch events
- struct LatencyStatistics mStatistics;
-
- std::optional<DisplayViewport> findViewport();
-
- void resetExternalStylus();
- void clearStylusDataPendingFlags();
-
- void sync(nsecs_t when);
-
- bool consumeRawTouches(nsecs_t when, uint32_t policyFlags);
- void processRawTouches(bool timeout);
- void cookAndDispatch(nsecs_t when);
- void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, int32_t keyEventAction,
- int32_t keyEventFlags);
-
- void dispatchTouches(nsecs_t when, uint32_t policyFlags);
- void dispatchHoverExit(nsecs_t when, uint32_t policyFlags);
- void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags);
- void dispatchButtonRelease(nsecs_t when, uint32_t policyFlags);
- void dispatchButtonPress(nsecs_t when, uint32_t policyFlags);
- const BitSet32& findActiveIdBits(const CookedPointerData& cookedPointerData);
- void cookPointerData();
- void abortTouches(nsecs_t when, uint32_t policyFlags);
-
- void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage);
- void abortPointerUsage(nsecs_t when, uint32_t policyFlags);
-
- void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
- void abortPointerGestures(nsecs_t when, uint32_t policyFlags);
- bool preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture,
- bool* outFinishPreviousGesture, bool isTimeout);
-
- void dispatchPointerStylus(nsecs_t when, uint32_t policyFlags);
- void abortPointerStylus(nsecs_t when, uint32_t policyFlags);
-
- void dispatchPointerMouse(nsecs_t when, uint32_t policyFlags);
- void abortPointerMouse(nsecs_t when, uint32_t policyFlags);
-
- void dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, bool down, bool hovering);
- void abortPointerSimple(nsecs_t when, uint32_t policyFlags);
-
- bool assignExternalStylusId(const RawState& state, bool timeout);
- void applyExternalStylusButtonState(nsecs_t when);
- void applyExternalStylusTouchState(nsecs_t when);
-
- // Dispatches a motion event.
- // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
- // method will take care of setting the index and transmuting the action to DOWN or UP
- // it is the first / last pointer to go down / up.
- void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, int32_t action,
- int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, uint32_t deviceTimestamp,
- const PointerProperties* properties, const PointerCoords* coords,
- const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
- float xPrecision, float yPrecision, nsecs_t downTime);
-
- // Updates pointer coords and properties for pointers with specified ids that have moved.
- // Returns true if any of them changed.
- bool updateMovedPointers(const PointerProperties* inProperties, const PointerCoords* inCoords,
- const uint32_t* inIdToIndex, PointerProperties* outProperties,
- PointerCoords* outCoords, const uint32_t* outIdToIndex,
- BitSet32 idBits) const;
-
- bool isPointInsideSurface(int32_t x, int32_t y);
- const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
-
- static void assignPointerIds(const RawState* last, RawState* current);
-
- void reportEventForStatistics(nsecs_t evdevTime);
-
- const char* modeToString(DeviceMode deviceMode);
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
deleted file mode 100644
index a27fab4581..0000000000
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ /dev/null
@@ -1,131 +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 "Macros.h"
-
-#include "VibratorInputMapper.h"
-
-namespace android {
-
-VibratorInputMapper::VibratorInputMapper(InputDevice* device)
- : InputMapper(device), mVibrating(false) {}
-
-VibratorInputMapper::~VibratorInputMapper() {}
-
-uint32_t VibratorInputMapper::getSources() {
- return 0;
-}
-
-void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- info->setVibrator(true);
-}
-
-void VibratorInputMapper::process(const RawEvent* rawEvent) {
- // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
-}
-
-void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
- int32_t token) {
-#if DEBUG_VIBRATOR
- std::string patternStr;
- for (size_t i = 0; i < patternSize; i++) {
- if (i != 0) {
- patternStr += ", ";
- }
- patternStr += StringPrintf("%" PRId64, pattern[i]);
- }
- ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d", getDeviceId(),
- patternStr.c_str(), repeat, token);
-#endif
-
- mVibrating = true;
- memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
- mPatternSize = patternSize;
- mRepeat = repeat;
- mToken = token;
- mIndex = -1;
-
- nextStep();
-}
-
-void VibratorInputMapper::cancelVibrate(int32_t token) {
-#if DEBUG_VIBRATOR
- ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
-#endif
-
- if (mVibrating && mToken == token) {
- stopVibrating();
- }
-}
-
-void VibratorInputMapper::timeoutExpired(nsecs_t when) {
- if (mVibrating) {
- if (when >= mNextStepTime) {
- nextStep();
- } else {
- getContext()->requestTimeoutAtTime(mNextStepTime);
- }
- }
-}
-
-void VibratorInputMapper::nextStep() {
- mIndex += 1;
- if (size_t(mIndex) >= mPatternSize) {
- if (mRepeat < 0) {
- // We are done.
- stopVibrating();
- return;
- }
- mIndex = mRepeat;
- }
-
- bool vibratorOn = mIndex & 1;
- nsecs_t duration = mPattern[mIndex];
- if (vibratorOn) {
-#if DEBUG_VIBRATOR
- ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
-#endif
- getEventHub()->vibrate(getDeviceId(), duration);
- } else {
-#if DEBUG_VIBRATOR
- ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
-#endif
- getEventHub()->cancelVibrate(getDeviceId());
- }
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- mNextStepTime = now + duration;
- getContext()->requestTimeoutAtTime(mNextStepTime);
-#if DEBUG_VIBRATOR
- ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
-#endif
-}
-
-void VibratorInputMapper::stopVibrating() {
- mVibrating = false;
-#if DEBUG_VIBRATOR
- ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
-#endif
- getEventHub()->cancelVibrate(getDeviceId());
-}
-
-void VibratorInputMapper::dump(std::string& dump) {
- dump += INDENT2 "Vibrator Input Mapper:\n";
- dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.h b/services/inputflinger/reader/mapper/VibratorInputMapper.h
deleted file mode 100644
index 6b33f4811e..0000000000
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.h
+++ /dev/null
@@ -1,53 +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.
- */
-
-#ifndef _UI_INPUTREADER_VIBRATOR_INPUT_MAPPER_H
-#define _UI_INPUTREADER_VIBRATOR_INPUT_MAPPER_H
-
-#include "InputMapper.h"
-
-namespace android {
-
-class VibratorInputMapper : public InputMapper {
-public:
- explicit VibratorInputMapper(InputDevice* device);
- virtual ~VibratorInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void process(const RawEvent* rawEvent);
-
- virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
- virtual void cancelVibrate(int32_t token);
- virtual void timeoutExpired(nsecs_t when);
- virtual void dump(std::string& dump);
-
-private:
- bool mVibrating;
- nsecs_t mPattern[MAX_VIBRATE_PATTERN_SIZE];
- size_t mPatternSize;
- ssize_t mRepeat;
- int32_t mToken;
- ssize_t mIndex;
- nsecs_t mNextStepTime;
-
- void nextStep();
- void stopVibrating();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_VIBRATOR_INPUT_MAPPER_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
deleted file mode 100644
index 0337d51126..0000000000
--- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
+++ /dev/null
@@ -1,101 +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 "CursorButtonAccumulator.h"
-
-#include "EventHub.h"
-#include "InputDevice.h"
-
-namespace android {
-
-CursorButtonAccumulator::CursorButtonAccumulator() {
- clearButtons();
-}
-
-void CursorButtonAccumulator::reset(InputDevice* device) {
- mBtnLeft = device->isKeyPressed(BTN_LEFT);
- mBtnRight = device->isKeyPressed(BTN_RIGHT);
- mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
- mBtnBack = device->isKeyPressed(BTN_BACK);
- mBtnSide = device->isKeyPressed(BTN_SIDE);
- mBtnForward = device->isKeyPressed(BTN_FORWARD);
- mBtnExtra = device->isKeyPressed(BTN_EXTRA);
- mBtnTask = device->isKeyPressed(BTN_TASK);
-}
-
-void CursorButtonAccumulator::clearButtons() {
- mBtnLeft = 0;
- mBtnRight = 0;
- mBtnMiddle = 0;
- mBtnBack = 0;
- mBtnSide = 0;
- mBtnForward = 0;
- mBtnExtra = 0;
- mBtnTask = 0;
-}
-
-void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_KEY) {
- switch (rawEvent->code) {
- case BTN_LEFT:
- mBtnLeft = rawEvent->value;
- break;
- case BTN_RIGHT:
- mBtnRight = rawEvent->value;
- break;
- case BTN_MIDDLE:
- mBtnMiddle = rawEvent->value;
- break;
- case BTN_BACK:
- mBtnBack = rawEvent->value;
- break;
- case BTN_SIDE:
- mBtnSide = rawEvent->value;
- break;
- case BTN_FORWARD:
- mBtnForward = rawEvent->value;
- break;
- case BTN_EXTRA:
- mBtnExtra = rawEvent->value;
- break;
- case BTN_TASK:
- mBtnTask = rawEvent->value;
- break;
- }
- }
-}
-
-uint32_t CursorButtonAccumulator::getButtonState() const {
- uint32_t result = 0;
- if (mBtnLeft) {
- result |= AMOTION_EVENT_BUTTON_PRIMARY;
- }
- if (mBtnRight) {
- result |= AMOTION_EVENT_BUTTON_SECONDARY;
- }
- if (mBtnMiddle) {
- result |= AMOTION_EVENT_BUTTON_TERTIARY;
- }
- if (mBtnBack || mBtnSide) {
- result |= AMOTION_EVENT_BUTTON_BACK;
- }
- if (mBtnForward || mBtnExtra) {
- result |= AMOTION_EVENT_BUTTON_FORWARD;
- }
- return result;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
deleted file mode 100644
index d9123109a3..0000000000
--- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.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.
- */
-
-#ifndef _UI_INPUTREADER_CURSOR_BUTTON_ACCUMULATOR_H
-#define _UI_INPUTREADER_CURSOR_BUTTON_ACCUMULATOR_H
-
-#include <stdint.h>
-
-namespace android {
-
-class InputDevice;
-struct RawEvent;
-
-/* Keeps track of the state of mouse or touch pad buttons. */
-class CursorButtonAccumulator {
-public:
- CursorButtonAccumulator();
- void reset(InputDevice* device);
-
- void process(const RawEvent* rawEvent);
-
- uint32_t getButtonState() const;
-
-private:
- bool mBtnLeft;
- bool mBtnRight;
- bool mBtnMiddle;
- bool mBtnBack;
- bool mBtnSide;
- bool mBtnForward;
- bool mBtnExtra;
- bool mBtnTask;
-
- void clearButtons();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_CURSOR_BUTTON_ACCUMULATOR_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
deleted file mode 100644
index d744096d94..0000000000
--- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
+++ /dev/null
@@ -1,59 +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 "CursorScrollAccumulator.h"
-
-#include "EventHub.h"
-#include "InputDevice.h"
-
-namespace android {
-
-CursorScrollAccumulator::CursorScrollAccumulator() : mHaveRelWheel(false), mHaveRelHWheel(false) {
- clearRelativeAxes();
-}
-
-void CursorScrollAccumulator::configure(InputDevice* device) {
- mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
- mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
-}
-
-void CursorScrollAccumulator::reset(InputDevice* device) {
- clearRelativeAxes();
-}
-
-void CursorScrollAccumulator::clearRelativeAxes() {
- mRelWheel = 0;
- mRelHWheel = 0;
-}
-
-void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_REL) {
- switch (rawEvent->code) {
- case REL_WHEEL:
- mRelWheel = rawEvent->value;
- break;
- case REL_HWHEEL:
- mRelHWheel = rawEvent->value;
- break;
- }
- }
-}
-
-void CursorScrollAccumulator::finishSync() {
- clearRelativeAxes();
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
deleted file mode 100644
index 85f331fd8a..0000000000
--- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
+++ /dev/null
@@ -1,60 +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.
- */
-
-#ifndef _UI_INPUTREADER_CURSOR_SCROLL_ACCUMULATOR_H
-#define _UI_INPUTREADER_CURSOR_SCROLL_ACCUMULATOR_H
-
-#include <stdint.h>
-
-namespace android {
-
-class InputDevice;
-struct RawEvent;
-
-/* Keeps track of cursor scrolling motions. */
-
-class CursorScrollAccumulator {
-public:
- CursorScrollAccumulator();
- void configure(InputDevice* device);
- void reset(InputDevice* device);
-
- void process(const RawEvent* rawEvent);
- void finishSync();
-
- inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
- inline bool haveRelativeHWheel() const { return mHaveRelHWheel; }
-
- inline int32_t getRelativeX() const { return mRelX; }
- inline int32_t getRelativeY() const { return mRelY; }
- inline int32_t getRelativeVWheel() const { return mRelWheel; }
- inline int32_t getRelativeHWheel() const { return mRelHWheel; }
-
-private:
- bool mHaveRelWheel;
- bool mHaveRelHWheel;
-
- int32_t mRelX;
- int32_t mRelY;
- int32_t mRelWheel;
- int32_t mRelHWheel;
-
- void clearRelativeAxes();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_CURSOR_SCROLL_ACCUMULATOR_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
deleted file mode 100644
index e9ba727a0d..0000000000
--- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
+++ /dev/null
@@ -1,76 +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 "SingleTouchMotionAccumulator.h"
-
-#include "EventHub.h"
-#include "InputDevice.h"
-
-namespace android {
-
-SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
- clearAbsoluteAxes();
-}
-
-void SingleTouchMotionAccumulator::reset(InputDevice* device) {
- mAbsX = device->getAbsoluteAxisValue(ABS_X);
- mAbsY = device->getAbsoluteAxisValue(ABS_Y);
- mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
- mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
- mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
- mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
- mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
-}
-
-void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
- mAbsX = 0;
- mAbsY = 0;
- mAbsPressure = 0;
- mAbsToolWidth = 0;
- mAbsDistance = 0;
- mAbsTiltX = 0;
- mAbsTiltY = 0;
-}
-
-void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_ABS) {
- switch (rawEvent->code) {
- case ABS_X:
- mAbsX = rawEvent->value;
- break;
- case ABS_Y:
- mAbsY = rawEvent->value;
- break;
- case ABS_PRESSURE:
- mAbsPressure = rawEvent->value;
- break;
- case ABS_TOOL_WIDTH:
- mAbsToolWidth = rawEvent->value;
- break;
- case ABS_DISTANCE:
- mAbsDistance = rawEvent->value;
- break;
- case ABS_TILT_X:
- mAbsTiltX = rawEvent->value;
- break;
- case ABS_TILT_Y:
- mAbsTiltY = rawEvent->value;
- break;
- }
- }
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
deleted file mode 100644
index 75f8a961b3..0000000000
--- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
+++ /dev/null
@@ -1,57 +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.
- */
-
-#ifndef _UI_INPUTREADER_SINGLE_TOUCH_MOTION_ACCUMULATOR_H
-#define _UI_INPUTREADER_SINGLE_TOUCH_MOTION_ACCUMULATOR_H
-
-#include <stdint.h>
-
-namespace android {
-
-class InputDevice;
-struct RawEvent;
-
-/* Keeps track of the state of single-touch protocol. */
-class SingleTouchMotionAccumulator {
-public:
- SingleTouchMotionAccumulator();
-
- void process(const RawEvent* rawEvent);
- void reset(InputDevice* device);
-
- inline int32_t getAbsoluteX() const { return mAbsX; }
- inline int32_t getAbsoluteY() const { return mAbsY; }
- inline int32_t getAbsolutePressure() const { return mAbsPressure; }
- inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; }
- inline int32_t getAbsoluteDistance() const { return mAbsDistance; }
- inline int32_t getAbsoluteTiltX() const { return mAbsTiltX; }
- inline int32_t getAbsoluteTiltY() const { return mAbsTiltY; }
-
-private:
- int32_t mAbsX;
- int32_t mAbsY;
- int32_t mAbsPressure;
- int32_t mAbsToolWidth;
- int32_t mAbsDistance;
- int32_t mAbsTiltX;
- int32_t mAbsTiltY;
-
- void clearAbsoluteAxes();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_SINGLE_TOUCH_MOTION_ACCUMULATOR_H \ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
deleted file mode 100644
index d2f06c86fd..0000000000
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
+++ /dev/null
@@ -1,162 +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 "TouchButtonAccumulator.h"
-
-#include "EventHub.h"
-#include "InputDevice.h"
-
-namespace android {
-
-TouchButtonAccumulator::TouchButtonAccumulator() : mHaveBtnTouch(false), mHaveStylus(false) {
- clearButtons();
-}
-
-void TouchButtonAccumulator::configure(InputDevice* device) {
- mHaveBtnTouch = device->hasKey(BTN_TOUCH);
- mHaveStylus = device->hasKey(BTN_TOOL_PEN) || device->hasKey(BTN_TOOL_RUBBER) ||
- device->hasKey(BTN_TOOL_BRUSH) || device->hasKey(BTN_TOOL_PENCIL) ||
- device->hasKey(BTN_TOOL_AIRBRUSH);
-}
-
-void TouchButtonAccumulator::reset(InputDevice* device) {
- mBtnTouch = device->isKeyPressed(BTN_TOUCH);
- mBtnStylus = device->isKeyPressed(BTN_STYLUS);
- // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
- mBtnStylus2 = device->isKeyPressed(BTN_STYLUS2) || device->isKeyPressed(BTN_0);
- mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
- mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
- mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
- mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
- mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
- mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
- mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
- mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
- mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
- mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
- mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
-}
-
-void TouchButtonAccumulator::clearButtons() {
- mBtnTouch = 0;
- mBtnStylus = 0;
- mBtnStylus2 = 0;
- mBtnToolFinger = 0;
- mBtnToolPen = 0;
- mBtnToolRubber = 0;
- mBtnToolBrush = 0;
- mBtnToolPencil = 0;
- mBtnToolAirbrush = 0;
- mBtnToolMouse = 0;
- mBtnToolLens = 0;
- mBtnToolDoubleTap = 0;
- mBtnToolTripleTap = 0;
- mBtnToolQuadTap = 0;
-}
-
-void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_KEY) {
- switch (rawEvent->code) {
- case BTN_TOUCH:
- mBtnTouch = rawEvent->value;
- break;
- case BTN_STYLUS:
- mBtnStylus = rawEvent->value;
- break;
- case BTN_STYLUS2:
- case BTN_0: // BTN_0 is what gets mapped for the HID usage
- // Digitizers.SecondaryBarrelSwitch
- mBtnStylus2 = rawEvent->value;
- break;
- case BTN_TOOL_FINGER:
- mBtnToolFinger = rawEvent->value;
- break;
- case BTN_TOOL_PEN:
- mBtnToolPen = rawEvent->value;
- break;
- case BTN_TOOL_RUBBER:
- mBtnToolRubber = rawEvent->value;
- break;
- case BTN_TOOL_BRUSH:
- mBtnToolBrush = rawEvent->value;
- break;
- case BTN_TOOL_PENCIL:
- mBtnToolPencil = rawEvent->value;
- break;
- case BTN_TOOL_AIRBRUSH:
- mBtnToolAirbrush = rawEvent->value;
- break;
- case BTN_TOOL_MOUSE:
- mBtnToolMouse = rawEvent->value;
- break;
- case BTN_TOOL_LENS:
- mBtnToolLens = rawEvent->value;
- break;
- case BTN_TOOL_DOUBLETAP:
- mBtnToolDoubleTap = rawEvent->value;
- break;
- case BTN_TOOL_TRIPLETAP:
- mBtnToolTripleTap = rawEvent->value;
- break;
- case BTN_TOOL_QUADTAP:
- mBtnToolQuadTap = rawEvent->value;
- break;
- }
- }
-}
-
-uint32_t TouchButtonAccumulator::getButtonState() const {
- uint32_t result = 0;
- if (mBtnStylus) {
- result |= AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
- }
- if (mBtnStylus2) {
- result |= AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
- }
- return result;
-}
-
-int32_t TouchButtonAccumulator::getToolType() const {
- if (mBtnToolMouse || mBtnToolLens) {
- return AMOTION_EVENT_TOOL_TYPE_MOUSE;
- }
- if (mBtnToolRubber) {
- return AMOTION_EVENT_TOOL_TYPE_ERASER;
- }
- if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
- return AMOTION_EVENT_TOOL_TYPE_STYLUS;
- }
- if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
- return AMOTION_EVENT_TOOL_TYPE_FINGER;
- }
- return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-}
-
-bool TouchButtonAccumulator::isToolActive() const {
- return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber || mBtnToolBrush ||
- mBtnToolPencil || mBtnToolAirbrush || mBtnToolMouse || mBtnToolLens ||
- mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
-}
-
-bool TouchButtonAccumulator::isHovering() const {
- return mHaveBtnTouch && !mBtnTouch;
-}
-
-bool TouchButtonAccumulator::hasStylus() const {
- return mHaveStylus;
-}
-
-} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
deleted file mode 100644
index 65b6bdcc12..0000000000
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
+++ /dev/null
@@ -1,66 +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.
- */
-
-#ifndef _UI_INPUTREADER_TOUCH_BUTTON_ACCUMULATOR_H
-#define _UI_INPUTREADER_TOUCH_BUTTON_ACCUMULATOR_H
-
-#include <stdint.h>
-
-namespace android {
-
-class InputDevice;
-struct RawEvent;
-
-/* Keeps track of the state of touch, stylus and tool buttons. */
-class TouchButtonAccumulator {
-public:
- TouchButtonAccumulator();
- void configure(InputDevice* device);
- void reset(InputDevice* device);
-
- void process(const RawEvent* rawEvent);
-
- uint32_t getButtonState() const;
- int32_t getToolType() const;
- bool isToolActive() const;
- bool isHovering() const;
- bool hasStylus() const;
-
-private:
- bool mHaveBtnTouch;
- bool mHaveStylus;
-
- bool mBtnTouch;
- bool mBtnStylus;
- bool mBtnStylus2;
- bool mBtnToolFinger;
- bool mBtnToolPen;
- bool mBtnToolRubber;
- bool mBtnToolBrush;
- bool mBtnToolPencil;
- bool mBtnToolAirbrush;
- bool mBtnToolMouse;
- bool mBtnToolLens;
- bool mBtnToolDoubleTap;
- bool mBtnToolTripleTap;
- bool mBtnToolQuadTap;
-
- void clearButtons();
-};
-
-} // namespace android
-
-#endif // _UI_INPUTREADER_TOUCH_BUTTON_ACCUMULATOR_H \ No newline at end of file
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index c4f8626a98..9054316204 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -32,7 +32,4 @@ cc_test {
"libinputflinger_base",
"libinputservice",
],
- header_libs: [
- "libinputreader_headers",
- ],
}
diff --git a/services/inputflinger/tests/InputClassifier_test.cpp b/services/inputflinger/tests/InputClassifier_test.cpp
index 7cc17a2215..4cddec50d0 100644
--- a/services/inputflinger/tests/InputClassifier_test.cpp
+++ b/services/inputflinger/tests/InputClassifier_test.cpp
@@ -22,6 +22,9 @@
#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
using namespace android::hardware::input;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::input::common::V1_0::Classification;
namespace android {
@@ -129,6 +132,49 @@ TEST_F(InputClassifierTest, SendToNextStage_NotifyDeviceResetArgs) {
ASSERT_EQ(args, outArgs);
}
+TEST_F(InputClassifierTest, SetMotionClassifier_Enabled) {
+ mClassifier->setMotionClassifierEnabled(true);
+}
+
+TEST_F(InputClassifierTest, SetMotionClassifier_Disabled) {
+ mClassifier->setMotionClassifierEnabled(false);
+}
+
+/**
+ * Try to break it by calling setMotionClassifierEnabled multiple times.
+ */
+TEST_F(InputClassifierTest, SetMotionClassifier_Multiple) {
+ mClassifier->setMotionClassifierEnabled(true);
+ mClassifier->setMotionClassifierEnabled(true);
+ mClassifier->setMotionClassifierEnabled(true);
+ mClassifier->setMotionClassifierEnabled(false);
+ mClassifier->setMotionClassifierEnabled(false);
+ mClassifier->setMotionClassifierEnabled(true);
+ mClassifier->setMotionClassifierEnabled(true);
+ mClassifier->setMotionClassifierEnabled(true);
+}
+
+/**
+ * A minimal implementation of IInputClassifier.
+ */
+struct TestHal : public android::hardware::input::classifier::V1_0::IInputClassifier {
+ Return<Classification> classify(
+ const android::hardware::input::common::V1_0::MotionEvent& event) override {
+ return Classification::NONE;
+ };
+ Return<void> reset() override { return Void(); };
+ Return<void> resetDevice(int32_t deviceId) override { return Void(); };
+};
+
+/**
+ * An entity that will be subscribed to the HAL death.
+ */
+class TestDeathRecipient : public android::hardware::hidl_death_recipient {
+public:
+ virtual void serviceDied(uint64_t cookie,
+ const wp<android::hidl::base::V1_0::IBase>& who) override{};
+};
+
// --- MotionClassifierTest ---
class MotionClassifierTest : public testing::Test {
@@ -136,7 +182,14 @@ protected:
std::unique_ptr<MotionClassifierInterface> mMotionClassifier;
virtual void SetUp() override {
- mMotionClassifier = std::make_unique<MotionClassifier>();
+ mMotionClassifier = MotionClassifier::create(new TestDeathRecipient());
+ if (mMotionClassifier == nullptr) {
+ // If the device running this test does not have IInputClassifier service,
+ // use the test HAL instead.
+ // Using 'new' to access non-public constructor
+ mMotionClassifier =
+ std::unique_ptr<MotionClassifier>(new MotionClassifier(new TestHal()));
+ }
}
};
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 551bee18e8..9fe6481ca0 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -14,16 +14,14 @@
* limitations under the License.
*/
-#include "../dispatcher/InputDispatcher.h"
-
-#include <InputDispatcherThread.h>
+#include "../InputDispatcher.h"
#include <binder/Binder.h>
#include <gtest/gtest.h>
#include <linux/input.h>
-namespace android::inputdispatcher {
+namespace android {
// An arbitrary time value.
static const nsecs_t ARBITRARY_TIME = 1234;
@@ -1027,4 +1025,4 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus,
mFakePolicy->assertOnPointerDownEquals(nullptr);
}
-} // namespace android::inputdispatcher
+} // namespace android
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index aeb4ad62a8..d35302885d 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -14,16 +14,8 @@
* limitations under the License.
*/
-#include <CursorInputMapper.h>
-#include <InputDevice.h>
-#include <InputMapper.h>
-#include <InputReader.h>
-#include <KeyboardInputMapper.h>
-#include <MultiTouchInputMapper.h>
-#include <SingleTouchInputMapper.h>
-#include <SwitchInputMapper.h>
-#include <TestInputListener.h>
-#include <TouchInputMapper.h>
+#include "../InputReader.h"
+#include "TestInputListener.h"
#include <gtest/gtest.h>
#include <inttypes.h>
diff --git a/services/nativeperms/.clang-format b/services/nativeperms/.clang-format
new file mode 100644
index 0000000000..6006e6f4fd
--- /dev/null
+++ b/services/nativeperms/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+ColumnLimit: 80
+CommentPragmas: NOLINT:.*
+ContinuationIndentWidth: 8
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
diff --git a/services/inputflinger/reporter/Android.bp b/services/nativeperms/Android.bp
index 5956fb0794..cbc7d665e3 100644
--- a/services/inputflinger/reporter/Android.bp
+++ b/services/nativeperms/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 The Android Open Source Project
+// 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.
@@ -11,31 +11,24 @@
// WITHOUT 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_headers {
- name: "libinputreporter_headers",
- export_include_dirs: ["."],
-}
-
-cc_library_shared {
- name: "libinputreporter",
- defaults: ["inputflinger_defaults"],
-
+cc_binary {
+ name: "nativeperms",
srcs: [
- "InputReporter.cpp",
+ "nativeperms.cpp",
+ "android/os/IPermissionController.aidl",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
],
-
shared_libs: [
- "liblog",
+ "libbinder",
+ "libbrillo",
+ "libbrillo-binder",
+ "libchrome",
"libutils",
],
-
- header_libs: [
- "libinputflinger_headers",
- ],
-
- export_header_lib_headers: [
- "libinputflinger_headers",
- ],
+ init_rc: ["nativeperms.rc"],
}
-
diff --git a/services/nativeperms/android/os/IPermissionController.aidl b/services/nativeperms/android/os/IPermissionController.aidl
new file mode 100644
index 0000000000..89db85ca0a
--- /dev/null
+++ b/services/nativeperms/android/os/IPermissionController.aidl
@@ -0,0 +1,25 @@
+/* //device/java/android/android/os/IPowerManager.aidl
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 android.os;
+
+/** @hide */
+interface IPermissionController {
+ boolean checkPermission(String permission, int pid, int uid);
+ String[] getPackagesForUid(int uid);
+ boolean isRuntimePermission(String permission);
+}
diff --git a/services/nativeperms/android/os/README b/services/nativeperms/android/os/README
new file mode 100644
index 0000000000..e4144995b0
--- /dev/null
+++ b/services/nativeperms/android/os/README
@@ -0,0 +1,4 @@
+IPermissionController.aidl in this directory is a verbatim copy of
+https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/IPermissionController.aidl,
+because some Brillo manifests do not currently include the frameworks/base repo.
+TODO(jorgelo): Figure out a way to use the .aidl file in frameworks/base.
diff --git a/services/nativeperms/nativeperms.cpp b/services/nativeperms/nativeperms.cpp
new file mode 100644
index 0000000000..7f03bedb29
--- /dev/null
+++ b/services/nativeperms/nativeperms.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#include <base/at_exit.h>
+#include <base/logging.h>
+#include <base/message_loop/message_loop.h>
+#include <binder/IServiceManager.h>
+#include <binder/Status.h>
+#include <brillo/binder_watcher.h>
+#include <brillo/message_loops/base_message_loop.h>
+#include <brillo/syslog_logging.h>
+#include <utils/String16.h>
+
+#include "android/os/BnPermissionController.h"
+
+namespace {
+static android::String16 serviceName("permission");
+}
+
+namespace android {
+
+class PermissionService : public android::os::BnPermissionController {
+ public:
+ ::android::binder::Status checkPermission(
+ const ::android::String16& permission, int32_t pid, int32_t uid,
+ bool* _aidl_return) {
+ (void)permission;
+ (void)pid;
+ (void)uid;
+ *_aidl_return = true;
+ return binder::Status::ok();
+ }
+
+ ::android::binder::Status getPackagesForUid(
+ int32_t uid, ::std::vector<::android::String16>* _aidl_return) {
+ (void)uid;
+ // Brillo doesn't currently have installable packages.
+ if (_aidl_return) {
+ _aidl_return->clear();
+ }
+ return binder::Status::ok();
+ }
+
+ ::android::binder::Status isRuntimePermission(
+ const ::android::String16& permission, bool* _aidl_return) {
+ (void)permission;
+ // Brillo doesn't currently have runtime permissions.
+ *_aidl_return = false;
+ return binder::Status::ok();
+ }
+};
+
+} // namespace android
+
+int main() {
+ base::AtExitManager atExitManager;
+ brillo::InitLog(brillo::kLogToSyslog);
+ // Register the service with servicemanager.
+ android::status_t status = android::defaultServiceManager()->addService(
+ serviceName, new android::PermissionService());
+ CHECK(status == android::OK) << "Failed to get IPermissionController "
+ "binder from servicemanager.";
+
+ // Create a message loop.
+ base::MessageLoopForIO messageLoopForIo;
+ brillo::BaseMessageLoop messageLoop{&messageLoopForIo};
+
+ // Initialize a binder watcher.
+ brillo::BinderWatcher watcher(&messageLoop);
+ watcher.Init();
+
+ // Run the message loop.
+ messageLoop.Run();
+}
diff --git a/services/nativeperms/nativeperms.rc b/services/nativeperms/nativeperms.rc
new file mode 100644
index 0000000000..704c0a2acc
--- /dev/null
+++ b/services/nativeperms/nativeperms.rc
@@ -0,0 +1,4 @@
+service nativeperms /system/bin/nativeperms
+ class main
+ user system
+ group system
diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp
index 73802dbc9f..0227164ef5 100644
--- a/services/schedulerservice/Android.bp
+++ b/services/schedulerservice/Android.bp
@@ -6,6 +6,8 @@ cc_library_shared {
cflags: ["-Wall", "-Werror"],
shared_libs: [
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"libmediautils",
"liblog",
"libutils",
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 1c9a4af72b..33a2747312 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -45,6 +45,8 @@ cc_library_shared {
"libcrypto",
"libbase",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"libfmq",
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
diff --git a/services/sensorservice/OWNERS b/services/sensorservice/OWNERS
index 90c233030e..81099e895c 100644
--- a/services/sensorservice/OWNERS
+++ b/services/sensorservice/OWNERS
@@ -1,3 +1,3 @@
arthuri@google.com
bduddie@google.com
-stange@google.com
+bstack@google.com
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 14ed73deaf..090a0ce478 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -208,12 +208,6 @@ void SensorService::onFirstRef() {
registerSensor(new RotationVectorSensor(), !needRotationVector, true);
registerSensor(new OrientationSensor(), !needRotationVector, true);
- bool needLinearAcceleration =
- (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;
-
- registerSensor(new LinearAccelerationSensor(list, count),
- !needLinearAcceleration, true);
-
// virtual debugging sensors are not for user
registerSensor( new CorrectedGyroSensor(list, count), true, true);
registerSensor( new GyroDriftSensor(), true, true);
@@ -223,6 +217,11 @@ void SensorService::onFirstRef() {
bool needGravitySensor = (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) != 0;
registerSensor(new GravitySensor(list, count), !needGravitySensor, true);
+ bool needLinearAcceleration =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;
+ registerSensor(new LinearAccelerationSensor(list, count),
+ !needLinearAcceleration, true);
+
bool needGameRotationVector =
(virtualSensorsNeeds & (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) != 0;
registerSensor(new GameRotationVectorSensor(), !needGameRotationVector, true);
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
index d0c83d6002..02c13fa579 100644
--- a/services/sensorservice/hidl/Android.bp
+++ b/services/sensorservice/hidl/Android.bp
@@ -13,6 +13,8 @@ cc_library_shared {
shared_libs: [
"libbase",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"libutils",
"libsensor",
"android.frameworks.sensorservice@1.0",
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index cda982ac23..501d176401 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -43,6 +43,8 @@ cc_defaults {
"libgui",
"libhardware",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"liblayers_proto",
"liblog",
"libnativewindow",
@@ -83,6 +85,8 @@ cc_defaults {
"android.hardware.graphics.composer@2.3",
"android.hardware.power@1.3",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
],
}
@@ -96,10 +100,6 @@ cc_defaults {
lto: {
thin: true,
},
- // TODO(b/131771163): Fix broken fuzzer support with LTO.
- sanitize: {
- fuzzer: false,
- },
}
cc_library_headers {
@@ -183,6 +183,9 @@ cc_defaults {
cflags: [
"-DLOG_TAG=\"SurfaceFlinger\"",
],
+ whole_static_libs: [
+ "libsigchain",
+ ],
shared_libs: [
"android.frameworks.displayservice@1.0",
"android.hardware.configstore-utils",
@@ -193,6 +196,7 @@ cc_defaults {
"libcutils",
"libdisplayservicehidl",
"libhidlbase",
+ "libhidltransport",
"libinput",
"liblayers_proto",
"liblog",
@@ -241,6 +245,8 @@ cc_library_shared {
"android.hardware.configstore@1.1",
"android.hardware.graphics.common@1.2",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"libui",
"libutils",
"liblog",
@@ -251,6 +257,8 @@ cc_library_shared {
export_shared_lib_headers: [
"android.hardware.graphics.common@1.2",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
],
export_static_lib_headers: [
"SurfaceFlingerProperties",
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index cbb9d658e4..eb1bf66cd6 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -243,9 +243,8 @@ bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
bool sidebandStreamChanged = true;
if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
// mSidebandStreamChanged was changed to false
- mSidebandStream = mConsumer->getSidebandStream();
auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
- layerCompositionState.sidebandStream = mSidebandStream;
+ layerCompositionState.sidebandStream = mConsumer->getSidebandStream();
if (layerCompositionState.sidebandStream != nullptr) {
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
@@ -462,6 +461,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
if (result != NO_ERROR) {
ALOGE("[%s] Timed out waiting on callback", mName.string());
+ break;
}
}
@@ -496,6 +496,7 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
if (result != NO_ERROR) {
ALOGE("[%s] Timed out waiting on callback", mName.string());
+ break;
}
}
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 1c31ab9d7d..6f076ad11f 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -118,13 +118,6 @@ cc_test {
//
// You can either "make dist tests" before flashing, or set this
// option to false temporarily.
-
-
- // FIXME: ASAN build is broken for a while, but was not discovered
- // since new PM silently suppressed ASAN. Temporarily turn off ASAN
- // to unblock the compiler upgrade process.
- // address: true,
- // http://b/139747256
- address: false,
+ address: true,
},
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 5700d72cae..4a13bfb7ae 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -272,17 +272,13 @@ void DisplayDevice::setProjection(int orientation,
scissor = displayBounds;
}
- uint32_t transformOrientation;
-
if (isPrimary()) {
sPrimaryDisplayOrientation = displayStateOrientationToTransformOrientation(orientation);
- transformOrientation = displayStateOrientationToTransformOrientation(
- (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1));
- } else {
- transformOrientation = displayStateOrientationToTransformOrientation(orientation);
}
- getCompositionDisplay()->setProjection(globalTransform, transformOrientation,
+ getCompositionDisplay()->setProjection(globalTransform,
+ displayStateOrientationToTransformOrientation(
+ orientation),
frame, viewport, scissor, needsFiltering);
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3e6ddedf48..44f3eae1ea 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -153,6 +153,7 @@ void Layer::removeRemoteSyncPoints() {
mRemoteSyncPoints.clear();
{
+ Mutex::Autolock pendingStateLock(mPendingStateMutex);
for (State pendingState : mPendingStates) {
pendingState.barrierLayer_legacy = nullptr;
}
@@ -906,7 +907,6 @@ uint32_t Layer::doTransaction(uint32_t flags) {
// Commit the transaction
commitTransaction(c);
- mPendingStatesSnapshot = mPendingStates;
mCurrentState.callbackHandles = {};
return flags;
}
@@ -1874,61 +1874,14 @@ void Layer::setInputInfo(const InputWindowInfo& info) {
setTransactionFlags(eTransactionNeeded);
}
-void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) const {
- ui::Transform transform = getTransform();
-
- if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
- for (const auto& pendingState : mPendingStatesSnapshot) {
- auto barrierLayer = pendingState.barrierLayer_legacy.promote();
- if (barrierLayer != nullptr) {
- BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
- barrierLayerProto->set_id(barrierLayer->sequence);
- barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
- }
- }
-
- auto buffer = mActiveBuffer;
- if (buffer != nullptr) {
- LayerProtoHelper::writeToProto(buffer,
- [&]() { return layerInfo->mutable_active_buffer(); });
- LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
- layerInfo->mutable_buffer_transform());
- }
- layerInfo->set_invalidate(contentDirty);
- layerInfo->set_is_protected(isProtected());
- layerInfo->set_dataspace(
- dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
- layerInfo->set_queued_frames(getQueuedFrameCount());
- layerInfo->set_refresh_pending(isBufferLatched());
- layerInfo->set_curr_frame(mCurrentFrameNumber);
- layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
-
- layerInfo->set_corner_radius(getRoundedCornerState().radius);
- LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
- LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
- [&]() { return layerInfo->mutable_position(); });
- LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
- LayerProtoHelper::writeToProto(visibleRegion,
- [&]() { return layerInfo->mutable_visible_region(); });
- LayerProtoHelper::writeToProto(surfaceDamageRegion,
- [&]() { return layerInfo->mutable_damage_region(); });
- }
-
- if (traceFlags & SurfaceTracing::TRACE_EXTRA) {
- LayerProtoHelper::writeToProto(mSourceBounds,
- [&]() { return layerInfo->mutable_source_bounds(); });
- LayerProtoHelper::writeToProto(mScreenBounds,
- [&]() { return layerInfo->mutable_screen_bounds(); });
- }
-}
-
-void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
- uint32_t traceFlags) const {
+void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+ uint32_t traceFlags) {
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
const State& state = useDrawing ? mDrawingState : mCurrentState;
ui::Transform requestedTransform = state.active_legacy.transform;
+ ui::Transform transform = getTransform();
if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
layerInfo->set_id(sequence);
@@ -1948,10 +1901,17 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
[&]() { return layerInfo->mutable_transparent_region(); });
+ LayerProtoHelper::writeToProto(visibleRegion,
+ [&]() { return layerInfo->mutable_visible_region(); });
+ LayerProtoHelper::writeToProto(surfaceDamageRegion,
+ [&]() { return layerInfo->mutable_damage_region(); });
layerInfo->set_layer_stack(getLayerStack());
layerInfo->set_z(state.z);
+ LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
+ [&]() { return layerInfo->mutable_position(); });
+
LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(),
[&]() {
return layerInfo->mutable_requested_position();
@@ -1962,9 +1922,15 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
LayerProtoHelper::writeToProto(state.crop_legacy,
[&]() { return layerInfo->mutable_crop(); });
+ layerInfo->set_corner_radius(getRoundedCornerState().radius);
layerInfo->set_is_opaque(isOpaque(state));
+ layerInfo->set_invalidate(contentDirty);
+ layerInfo->set_is_protected(isProtected());
+ // XXX (b/79210409) mCurrentDataSpace is not protected
+ layerInfo->set_dataspace(
+ dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
LayerProtoHelper::writeToProto(getColor(), [&]() { return layerInfo->mutable_color(); });
@@ -1972,6 +1938,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
[&]() { return layerInfo->mutable_requested_color(); });
layerInfo->set_flags(state.flags);
+ LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
LayerProtoHelper::writeToProto(requestedTransform,
layerInfo->mutable_requested_transform());
@@ -1988,6 +1955,29 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
} else {
layerInfo->set_z_order_relative_of(-1);
}
+
+ auto buffer = mActiveBuffer;
+ if (buffer != nullptr) {
+ LayerProtoHelper::writeToProto(buffer,
+ [&]() { return layerInfo->mutable_active_buffer(); });
+ LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
+ layerInfo->mutable_buffer_transform());
+ }
+
+ layerInfo->set_queued_frames(getQueuedFrameCount());
+ layerInfo->set_refresh_pending(isBufferLatched());
+ layerInfo->set_curr_frame(mCurrentFrameNumber);
+ layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
+
+ for (const auto& pendingState : mPendingStates) {
+ auto barrierLayer = pendingState.barrierLayer_legacy.promote();
+ if (barrierLayer != nullptr) {
+ BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
+ barrierLayerProto->set_id(barrierLayer->sequence);
+ barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
+ }
+ }
+ LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
}
if (traceFlags & SurfaceTracing::TRACE_INPUT) {
@@ -2000,19 +1990,23 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
for (const auto& entry : state.metadata.mMap) {
(*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
}
+ LayerProtoHelper::writeToProto(mEffectiveTransform,
+ layerInfo->mutable_effective_transform());
+ LayerProtoHelper::writeToProto(mSourceBounds,
+ [&]() { return layerInfo->mutable_source_bounds(); });
+ LayerProtoHelper::writeToProto(mScreenBounds,
+ [&]() { return layerInfo->mutable_screen_bounds(); });
}
}
-void Layer::writeToProtoCompositionState(LayerProto* layerInfo,
- const sp<DisplayDevice>& displayDevice,
- uint32_t traceFlags) const {
+void Layer::writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
+ uint32_t traceFlags) {
auto outputLayer = findOutputLayerForDisplay(displayDevice);
if (!outputLayer) {
return;
}
- writeToProtoDrawingState(layerInfo, traceFlags);
- writeToProtoCommonState(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
+ writeToProto(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
const auto& compositionState = outputLayer->getState();
@@ -2030,12 +2024,26 @@ void Layer::writeToProtoCompositionState(LayerProto* layerInfo,
static_cast<int32_t>(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType
: Hwc2::IComposerClient::Composition::CLIENT);
layerInfo->set_hwc_composition_type(compositionType);
+
+ if (std::strcmp(getTypeId(), "BufferLayer") == 0 &&
+ static_cast<BufferLayer*>(this)->isProtected()) {
+ layerInfo->set_is_protected(true);
+ } else {
+ layerInfo->set_is_protected(false);
+ }
}
bool Layer::isRemovedFromCurrentState() const {
return mRemovedFromCurrentState;
}
+// Debug helper for b/137560795
+#define INT32_MIGHT_OVERFLOW(n) (((n) >= INT32_MAX / 2) || ((n) <= INT32_MIN / 2))
+
+#define RECT_BOUNDS_INVALID(rect) \
+ (INT32_MIGHT_OVERFLOW((rect).left) || INT32_MIGHT_OVERFLOW((rect).right) || \
+ INT32_MIGHT_OVERFLOW((rect).bottom) || INT32_MIGHT_OVERFLOW((rect).top))
+
InputWindowInfo Layer::fillInputInfo() {
InputWindowInfo info = mDrawingState.inputInfo;
@@ -2046,14 +2054,14 @@ InputWindowInfo Layer::fillInputInfo() {
ui::Transform t = getTransform();
const float xScale = t.sx();
const float yScale = t.sy();
- int32_t xSurfaceInset = info.surfaceInset;
- int32_t ySurfaceInset = info.surfaceInset;
+ float xSurfaceInset = info.surfaceInset;
+ float ySurfaceInset = info.surfaceInset;
if (xScale != 1.0f || yScale != 1.0f) {
- info.windowXScale *= (xScale != 0.0f) ? 1.0f / xScale : 0.0f;
- info.windowYScale *= (yScale != 0.0f) ? 1.0f / yScale : 0.0f;
+ info.windowXScale *= 1.0f / xScale;
+ info.windowYScale *= 1.0f / yScale;
info.touchableRegion.scaleSelf(xScale, yScale);
- xSurfaceInset = std::round(xSurfaceInset * xScale);
- ySurfaceInset = std::round(ySurfaceInset * yScale);
+ xSurfaceInset *= xScale;
+ ySurfaceInset *= yScale;
}
// Transform layer size to screen space and inset it by surface insets.
@@ -2066,10 +2074,25 @@ InputWindowInfo Layer::fillInputInfo() {
}
layerBounds = t.transform(layerBounds);
- // clamp inset to layer bounds
- xSurfaceInset = (xSurfaceInset >= 0) ? std::min(xSurfaceInset, layerBounds.getWidth() / 2) : 0;
- ySurfaceInset = (ySurfaceInset >= 0) ? std::min(ySurfaceInset, layerBounds.getHeight() / 2) : 0;
+ // debug check for b/137560795
+ {
+ if (RECT_BOUNDS_INVALID(layerBounds)) {
+ ALOGE("layer %s bounds are invalid (%" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32
+ ")",
+ mName.c_str(), layerBounds.left, layerBounds.top, layerBounds.right,
+ layerBounds.bottom);
+ std::string out;
+ getTransform().dump(out, "Transform");
+ ALOGE("%s", out.c_str());
+ layerBounds.left = layerBounds.top = layerBounds.right = layerBounds.bottom = 0;
+ }
+ if (INT32_MIGHT_OVERFLOW(xSurfaceInset) || INT32_MIGHT_OVERFLOW(ySurfaceInset)) {
+ ALOGE("layer %s surface inset are invalid (%" PRIi32 ", %" PRIi32 ")", mName.c_str(),
+ int32_t(xSurfaceInset), int32_t(ySurfaceInset));
+ xSurfaceInset = ySurfaceInset = 0;
+ }
+ }
layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset);
// Input coordinate should match the layer bounds.
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3b4d8733c7..b46eb112e7 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -437,21 +437,11 @@ public:
bool isRemovedFromCurrentState() const;
- // Write states that are modified by the main thread. This includes drawing
- // state as well as buffer data. This should be called in the main or tracing
- // thread.
- void writeToProtoDrawingState(LayerProto* layerInfo,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
- // Write states that are modified by the main thread. This includes drawing
- // state as well as buffer data and composition data for layers on the specified
- // display. This should be called in the main or tracing thread.
- void writeToProtoCompositionState(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
- // Write drawing or current state. If writing current state, the caller should hold the
- // external mStateLock. If writing drawing state, this function should be called on the
- // main or tracing thread.
- void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
+
+ void writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
@@ -841,15 +831,13 @@ protected:
bool mPrimaryDisplayOnly = false;
- // These are only accessed by the main thread or the tracing thread.
- State mDrawingState;
- // Store a copy of the pending state so that the drawing thread can access the
- // states without a lock.
- Vector<State> mPendingStatesSnapshot;
-
- // these are protected by an external lock (mStateLock)
+ // these are protected by an external lock
State mCurrentState;
+ State mDrawingState;
std::atomic<uint32_t> mTransactionFlags{0};
+
+ // Accessed from main thread and binder threads
+ Mutex mPendingStateMutex;
Vector<State> mPendingStates;
// Timestamp history for UIAutomation. Thread safe.
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 07fdead310..80da154278 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -200,9 +200,10 @@ RegionSamplingThread::~RegionSamplingThread() {
void RegionSamplingThread::addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) {
- wp<Layer> stopLayer = stopLayerHandle != nullptr
- ? static_cast<Layer::Handle*>(stopLayerHandle.get())->owner
- : nullptr;
+ wp<Layer> stopLayer;
+ if (stopLayerHandle != nullptr && stopLayerHandle->localBinder() != nullptr) {
+ stopLayer = static_cast<Layer::Handle*>(stopLayerHandle.get())->owner;
+ }
sp<IBinder> asBinder = IInterface::asBinder(listener);
asBinder->linkToDeath(this);
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 8a2604f4a3..9fa2bbc96e 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -96,7 +96,6 @@ PhaseOffsets::PhaseOffsets() {
highFpsOffsets.late = {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs,
highFpsLateAppOffsetNs};
- mOffsets.insert({RefreshRateType::POWER_SAVING, defaultOffsets});
mOffsets.insert({RefreshRateType::DEFAULT, defaultOffsets});
mOffsets.insert({RefreshRateType::PERFORMANCE, highFpsOffsets});
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index d7300583c3..d8137085dd 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -34,10 +34,9 @@ namespace scheduler {
*/
class RefreshRateConfigs {
public:
- // Enum to indicate which vsync rate to run at. Power saving is intended to be the lowest
- // (eg. when the screen is in AOD mode or off), default is the old 60Hz, and performance
+ // Enum to indicate which vsync rate to run at. Default is the old 60Hz, and performance
// is the new 90Hz. Eventually we want to have a way for vendors to map these in the configs.
- enum class RefreshRateType { POWER_SAVING, DEFAULT, PERFORMANCE };
+ enum class RefreshRateType { DEFAULT, PERFORMANCE };
struct RefreshRate {
// This config ID corresponds to the position of the config in the vector that is stored
@@ -47,26 +46,57 @@ public:
std::string name;
// Refresh rate in frames per second, rounded to the nearest integer.
uint32_t fps = 0;
- // config Id (returned from HWC2::Display::Config::getId())
- hwc2_config_t id;
+ // Vsync period in nanoseconds.
+ nsecs_t vsyncPeriod;
+ // Hwc config Id (returned from HWC2::Display::Config::getId())
+ hwc2_config_t hwcId;
};
+ // Returns true if this device is doing refresh rate switching. This won't change at runtime.
+ bool refreshRateSwitchingSupported() const { return mRefreshRateSwitchingSupported; }
+
+ // Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access
+ // from multiple threads. This can only be called if refreshRateSwitching() returns true.
// TODO(b/122916473): Get this information from configs prepared by vendors, instead of
// baking them in.
- const std::map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() const {
- return mRefreshRates;
+ const std::map<RefreshRateType, RefreshRate>& getRefreshRateMap() const {
+ LOG_ALWAYS_FATAL_IF(!mRefreshRateSwitchingSupported);
+ return mRefreshRateMap;
}
- std::shared_ptr<RefreshRate> getRefreshRate(RefreshRateType type) const {
- const auto& refreshRate = mRefreshRates.find(type);
- if (refreshRate != mRefreshRates.end()) {
+
+ const RefreshRate& getRefreshRateFromType(RefreshRateType type) const {
+ if (!mRefreshRateSwitchingSupported) {
+ return getCurrentRefreshRate().second;
+ } else {
+ auto refreshRate = mRefreshRateMap.find(type);
+ LOG_ALWAYS_FATAL_IF(refreshRate == mRefreshRateMap.end());
return refreshRate->second;
}
- return nullptr;
}
- RefreshRateType getRefreshRateType(hwc2_config_t id) const {
- for (const auto& [type, refreshRate] : mRefreshRates) {
- if (refreshRate->id == id) {
+ std::pair<RefreshRateType, const RefreshRate&> getCurrentRefreshRate() const {
+ int currentConfig = mCurrentConfig;
+ if (mRefreshRateSwitchingSupported) {
+ for (const auto& [type, refresh] : mRefreshRateMap) {
+ if (refresh.configId == currentConfig) {
+ return {type, refresh};
+ }
+ }
+ LOG_ALWAYS_FATAL();
+ }
+ return {RefreshRateType::DEFAULT, mRefreshRates[currentConfig]};
+ }
+
+ const RefreshRate& getRefreshRateFromConfigId(int configId) const {
+ LOG_ALWAYS_FATAL_IF(configId >= mRefreshRates.size());
+ return mRefreshRates[configId];
+ }
+
+ RefreshRateType getRefreshRateTypeFromHwcConfigId(hwc2_config_t hwcId) const {
+ if (!mRefreshRateSwitchingSupported) return RefreshRateType::DEFAULT;
+
+ for (const auto& [type, refreshRate] : mRefreshRateMap) {
+ if (refreshRate.hwcId == hwcId) {
return type;
}
}
@@ -74,64 +104,102 @@ public:
return RefreshRateType::DEFAULT;
}
- void populate(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
- mRefreshRates.clear();
+ void setCurrentConfig(int config) {
+ LOG_ALWAYS_FATAL_IF(config >= mRefreshRates.size());
+ mCurrentConfig = config;
+ }
- // This is the rate that HWC encapsulates right now when the device is in DOZE mode.
- mRefreshRates.emplace(RefreshRateType::POWER_SAVING,
- std::make_shared<RefreshRate>(
- RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0,
- HWC2_SCREEN_OFF_CONFIG_ID}));
+ struct InputConfig {
+ hwc2_config_t hwcId = 0;
+ nsecs_t vsyncPeriod = 0;
+ };
- if (configs.size() < 1) {
- ALOGE("Device does not have valid configs. Config size is 0.");
- return;
+ RefreshRateConfigs(bool refreshRateSwitching, const std::vector<InputConfig>& configs,
+ int currentConfig) {
+ init(refreshRateSwitching, configs, currentConfig);
+ }
+
+ RefreshRateConfigs(bool refreshRateSwitching,
+ const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
+ int currentConfig) {
+ std::vector<InputConfig> inputConfigs;
+ for (const auto& config : configs) {
+ inputConfigs.push_back({config->getId(), config->getVsyncPeriod()});
}
+ init(refreshRateSwitching, inputConfigs, currentConfig);
+ }
+
+private:
+ void init(bool refreshRateSwitching, const std::vector<InputConfig>& configs,
+ int currentConfig) {
+ mRefreshRateSwitchingSupported = refreshRateSwitching;
+ LOG_ALWAYS_FATAL_IF(configs.empty());
+ LOG_ALWAYS_FATAL_IF(currentConfig >= configs.size());
+ mCurrentConfig = currentConfig;
+
+ auto buildRefreshRate = [&](int configId) -> RefreshRate {
+ const nsecs_t vsyncPeriod = configs[configId].vsyncPeriod;
+ const float fps = 1e9 / vsyncPeriod;
+ return {configId, base::StringPrintf("%2.ffps", fps), static_cast<uint32_t>(fps),
+ vsyncPeriod, configs[configId].hwcId};
+ };
- // Create a map between config index and vsync period. This is all the info we need
- // from the configs.
- std::vector<std::pair<int, nsecs_t>> configIdToVsyncPeriod;
for (int i = 0; i < configs.size(); ++i) {
- configIdToVsyncPeriod.emplace_back(i, configs.at(i)->getVsyncPeriod());
+ mRefreshRates.push_back(buildRefreshRate(i));
}
- std::sort(configIdToVsyncPeriod.begin(), configIdToVsyncPeriod.end(),
- [](const std::pair<int, nsecs_t>& a, const std::pair<int, nsecs_t>& b) {
- return a.second > b.second;
- });
+ if (!mRefreshRateSwitchingSupported) return;
- // When the configs are ordered by the resync rate. We assume that the first one is DEFAULT.
- nsecs_t vsyncPeriod = configIdToVsyncPeriod[0].second;
- if (vsyncPeriod != 0) {
- const float fps = 1e9 / vsyncPeriod;
- const int configId = configIdToVsyncPeriod[0].first;
- mRefreshRates.emplace(RefreshRateType::DEFAULT,
- std::make_shared<RefreshRate>(
- RefreshRate{configId, base::StringPrintf("%2.ffps", fps),
- static_cast<uint32_t>(fps),
- configs.at(configId)->getId()}));
- }
+ auto findDefaultAndPerfConfigs = [&]() -> std::optional<std::pair<int, int>> {
+ if (configs.size() < 2) {
+ return {};
+ }
- if (configs.size() < 2) {
+ std::vector<const RefreshRate*> sortedRefreshRates;
+ for (const auto& refreshRate : mRefreshRates) {
+ sortedRefreshRates.push_back(&refreshRate);
+ }
+ std::sort(sortedRefreshRates.begin(), sortedRefreshRates.end(),
+ [](const RefreshRate* refreshRate1, const RefreshRate* refreshRate2) {
+ return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod;
+ });
+
+ // When the configs are ordered by the resync rate, we assume that
+ // the first one is DEFAULT and the second one is PERFORMANCE,
+ // i.e. the higher rate.
+ if (sortedRefreshRates[0]->vsyncPeriod == 0 ||
+ sortedRefreshRates[1]->vsyncPeriod == 0) {
+ return {};
+ }
+
+ return std::pair<int, int>(sortedRefreshRates[0]->configId,
+ sortedRefreshRates[1]->configId);
+ };
+
+ auto defaultAndPerfConfigs = findDefaultAndPerfConfigs();
+ if (!defaultAndPerfConfigs) {
+ mRefreshRateSwitchingSupported = false;
return;
}
- // When the configs are ordered by the resync rate. We assume that the second one is
- // PERFORMANCE, eg. the higher rate.
- vsyncPeriod = configIdToVsyncPeriod[1].second;
- if (vsyncPeriod != 0) {
- const float fps = 1e9 / vsyncPeriod;
- const int configId = configIdToVsyncPeriod[1].first;
- mRefreshRates.emplace(RefreshRateType::PERFORMANCE,
- std::make_shared<RefreshRate>(
- RefreshRate{configId, base::StringPrintf("%2.ffps", fps),
- static_cast<uint32_t>(fps),
- configs.at(configId)->getId()}));
- }
+ mRefreshRateMap[RefreshRateType::DEFAULT] = mRefreshRates[defaultAndPerfConfigs->first];
+ mRefreshRateMap[RefreshRateType::PERFORMANCE] =
+ mRefreshRates[defaultAndPerfConfigs->second];
}
-private:
- std::map<RefreshRateType, std::shared_ptr<RefreshRate>> mRefreshRates;
+ // Whether this device is doing refresh rate switching or not. This must not change after this
+ // object is initialized.
+ bool mRefreshRateSwitchingSupported;
+ // The list of refresh rates, indexed by display config ID. This must not change after this
+ // object is initialized.
+ std::vector<RefreshRate> mRefreshRates;
+ // The mapping of refresh rate type to RefreshRate. This must not change after this object is
+ // initialized.
+ std::map<RefreshRateType, RefreshRate> mRefreshRateMap;
+ // The ID of the current config. This will change at runtime. This is set by SurfaceFlinger on
+ // the main thread, and read by the Scheduler (and other objects) on other threads, so it's
+ // atomic.
+ std::atomic<int> mCurrentConfig;
};
} // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index 7e7c6307a4..947eb08d90 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -41,21 +41,18 @@ class RefreshRateStats {
static constexpr int64_t MS_PER_DAY = 24 * MS_PER_HOUR;
public:
- RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats)
- : mRefreshRateConfigs(refreshRateConfigs), mTimeStats(timeStats) {}
-
- // Sets power mode. We only collect the information when the power mode is not
- // HWC_POWER_MODE_NORMAL. When power mode is HWC_POWER_MODE_NORMAL, we collect the stats based
- // on config mode.
+ RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats,
+ int currentConfigMode, int currentPowerMode)
+ : mRefreshRateConfigs(refreshRateConfigs),
+ mTimeStats(timeStats),
+ mCurrentConfigMode(currentConfigMode),
+ mCurrentPowerMode(currentPowerMode) {}
+
+ // Sets power mode.
void setPowerMode(int mode) {
if (mCurrentPowerMode == mode) {
return;
}
- // If power mode is normal, the time is going to be recorded under config modes.
- if (mode == HWC_POWER_MODE_NORMAL) {
- mCurrentPowerMode = mode;
- return;
- }
flushTime();
mCurrentPowerMode = mode;
}
@@ -79,16 +76,15 @@ public:
flushTime();
std::unordered_map<std::string, int64_t> totalTime;
- for (const auto& [type, config] : mRefreshRateConfigs.getRefreshRates()) {
- int64_t totalTimeForConfig = 0;
- if (!config) {
- continue;
- }
- if (mConfigModesTotalTime.find(config->configId) != mConfigModesTotalTime.end()) {
- totalTimeForConfig = mConfigModesTotalTime.at(config->configId);
- }
- totalTime[config->name] = totalTimeForConfig;
+ // Multiple configs may map to the same name, e.g. "60fps". Add the
+ // times for such configs together.
+ for (const auto& [config, time] : mConfigModesTotalTime) {
+ totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(config).name] = 0;
+ }
+ for (const auto& [config, time] : mConfigModesTotalTime) {
+ totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(config).name] += time;
}
+ totalTime["ScreenOff"] = mScreenOffTime;
return totalTime;
}
@@ -104,32 +100,26 @@ public:
}
private:
- void flushTime() {
- // Normal power mode is counted under different config modes.
- if (mCurrentPowerMode == HWC_POWER_MODE_NORMAL) {
- flushTimeForMode(mCurrentConfigMode);
- } else {
- flushTimeForMode(SCREEN_OFF_CONFIG_ID);
- }
- }
-
// Calculates the time that passed in ms between the last time we recorded time and the time
// this method was called.
- void flushTimeForMode(int mode) {
+ void flushTime() {
nsecs_t currentTime = systemTime();
nsecs_t timeElapsed = currentTime - mPreviousRecordedTime;
int64_t timeElapsedMs = ns2ms(timeElapsed);
mPreviousRecordedTime = currentTime;
- mConfigModesTotalTime[mode] += timeElapsedMs;
- for (const auto& [type, config] : mRefreshRateConfigs.getRefreshRates()) {
- if (!config) {
- continue;
- }
- if (config->configId == mode) {
- mTimeStats.recordRefreshRate(config->fps, timeElapsed);
+ uint32_t fps = 0;
+ if (mCurrentPowerMode == HWC_POWER_MODE_NORMAL) {
+ // Normal power mode is counted under different config modes.
+ if (mConfigModesTotalTime.find(mCurrentConfigMode) == mConfigModesTotalTime.end()) {
+ mConfigModesTotalTime[mCurrentConfigMode] = 0;
}
+ mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs;
+ fps = mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).fps;
+ } else {
+ mScreenOffTime += timeElapsedMs;
}
+ mTimeStats.recordRefreshRate(fps, timeElapsed);
}
// Formats the time in milliseconds into easy to read format.
@@ -149,10 +139,11 @@ private:
// Aggregate refresh rate statistics for telemetry.
TimeStats& mTimeStats;
- int64_t mCurrentConfigMode = SCREEN_OFF_CONFIG_ID;
- int32_t mCurrentPowerMode = HWC_POWER_MODE_OFF;
+ int mCurrentConfigMode;
+ int32_t mCurrentPowerMode;
- std::unordered_map<int /* power mode */, int64_t /* duration in ms */> mConfigModesTotalTime;
+ std::unordered_map<int /* config */, int64_t /* duration in ms */> mConfigModesTotalTime;
+ int64_t mScreenOffTime = 0;
nsecs_t mPreviousRecordedTime = systemTime();
};
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 8da5612b5b..0b43378394 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -133,7 +133,6 @@ Scheduler::~Scheduler() {
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
const char* connectionName, nsecs_t phaseOffsetNs, nsecs_t offsetThresholdForNextVsync,
- ResyncCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const int64_t id = sNextId++;
ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
@@ -143,8 +142,7 @@ sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
offsetThresholdForNextVsync, std::move(interceptCallback));
auto eventThreadConnection =
- createConnectionInternal(eventThread.get(), std::move(resyncCallback),
- ISurfaceComposer::eConfigChangedSuppress);
+ createConnectionInternal(eventThread.get(), ISurfaceComposer::eConfigChangedSuppress);
mConnections.emplace(id,
std::make_unique<Connection>(new ConnectionHandle(id),
eventThreadConnection,
@@ -164,17 +162,15 @@ std::unique_ptr<EventThread> Scheduler::makeEventThread(
}
sp<EventThreadConnection> Scheduler::createConnectionInternal(
- EventThread* eventThread, ResyncCallback&& resyncCallback,
- ISurfaceComposer::ConfigChanged configChanged) {
- return eventThread->createEventConnection(std::move(resyncCallback), configChanged);
+ EventThread* eventThread, ISurfaceComposer::ConfigChanged configChanged) {
+ return eventThread->createEventConnection([&] { resync(); }, configChanged);
}
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
- const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback,
+ const sp<Scheduler::ConnectionHandle>& handle,
ISurfaceComposer::ConfigChanged configChanged) {
RETURN_VALUE_IF_INVALID(nullptr);
- return createConnectionInternal(mConnections[handle->id]->thread.get(),
- std::move(resyncCallback), configChanged);
+ return createConnectionInternal(mConnections[handle->id]->thread.get(), configChanged);
}
EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
@@ -264,23 +260,15 @@ void Scheduler::resyncToHardwareVsync(bool makeAvailable, nsecs_t period) {
setVsyncPeriod(period);
}
-ResyncCallback Scheduler::makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod) {
- std::weak_ptr<VsyncState> ptr = mPrimaryVsyncState;
- return [ptr, getVsyncPeriod = std::move(getVsyncPeriod)]() {
- if (const auto vsync = ptr.lock()) {
- vsync->resync(getVsyncPeriod);
- }
- };
-}
-
-void Scheduler::VsyncState::resync(const GetVsyncPeriod& getVsyncPeriod) {
+void Scheduler::resync() {
static constexpr nsecs_t kIgnoreDelay = ms2ns(750);
const nsecs_t now = systemTime();
- const nsecs_t last = lastResyncTime.exchange(now);
+ const nsecs_t last = mLastResyncTime.exchange(now);
if (now - last > kIgnoreDelay) {
- scheduler.resyncToHardwareVsync(false, getVsyncPeriod());
+ resyncToHardwareVsync(false,
+ mRefreshRateConfigs.getCurrentRefreshRate().second.vsyncPeriod);
}
}
@@ -338,15 +326,19 @@ void Scheduler::dumpPrimaryDispSync(std::string& result) const {
std::unique_ptr<scheduler::LayerHistory::LayerHandle> Scheduler::registerLayer(
std::string const& name, int windowType) {
- RefreshRateType refreshRateType = (windowType == InputWindowInfo::TYPE_WALLPAPER)
- ? RefreshRateType::DEFAULT
- : RefreshRateType::PERFORMANCE;
-
- const auto refreshRate = mRefreshRateConfigs.getRefreshRate(refreshRateType);
- const uint32_t performanceFps = (refreshRate) ? refreshRate->fps : 0;
-
- const auto defaultRefreshRate = mRefreshRateConfigs.getRefreshRate(RefreshRateType::DEFAULT);
- const uint32_t defaultFps = (defaultRefreshRate) ? defaultRefreshRate->fps : 0;
+ uint32_t defaultFps, performanceFps;
+ if (mRefreshRateConfigs.refreshRateSwitchingSupported()) {
+ defaultFps = mRefreshRateConfigs.getRefreshRateFromType(RefreshRateType::DEFAULT).fps;
+ performanceFps =
+ mRefreshRateConfigs
+ .getRefreshRateFromType((windowType == InputWindowInfo::TYPE_WALLPAPER)
+ ? RefreshRateType::DEFAULT
+ : RefreshRateType::PERFORMANCE)
+ .fps;
+ } else {
+ defaultFps = mRefreshRateConfigs.getCurrentRefreshRate().second.fps;
+ performanceFps = defaultFps;
+ }
return mLayerHistory.createLayer(name, defaultFps, performanceFps);
}
@@ -398,17 +390,6 @@ void Scheduler::setChangeRefreshRateCallback(
mChangeRefreshRateCallback = changeRefreshRateCallback;
}
-void Scheduler::setGetCurrentRefreshRateTypeCallback(
- const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateTypeCallback) {
- std::lock_guard<std::mutex> lock(mCallbackLock);
- mGetCurrentRefreshRateTypeCallback = getCurrentRefreshRateTypeCallback;
-}
-
-void Scheduler::setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod) {
- std::lock_guard<std::mutex> lock(mCallbackLock);
- mGetVsyncPeriod = getVsyncPeriod;
-}
-
void Scheduler::updateFrameSkipping(const int64_t skipCount) {
ATRACE_INT("FrameSkipCount", skipCount);
if (mSkipCount != skipCount) {
@@ -460,14 +441,12 @@ void Scheduler::resetTimerCallback() {
void Scheduler::resetKernelTimerCallback() {
ATRACE_INT("ExpiredKernelIdleTimer", 0);
- std::lock_guard<std::mutex> lock(mCallbackLock);
- if (mGetVsyncPeriod && mGetCurrentRefreshRateTypeCallback) {
+ const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
+ if (refreshRate.first == RefreshRateType::PERFORMANCE) {
// If we're not in performance mode then the kernel timer shouldn't do
// anything, as the refresh rate during DPU power collapse will be the
// same.
- if (mGetCurrentRefreshRateTypeCallback() == Scheduler::RefreshRateType::PERFORMANCE) {
- resyncToHardwareVsync(true, mGetVsyncPeriod());
- }
+ resyncToHardwareVsync(true, refreshRate.second.vsyncPeriod);
}
}
@@ -497,15 +476,13 @@ void Scheduler::expiredDisplayPowerTimerCallback() {
}
void Scheduler::expiredKernelTimerCallback() {
- std::lock_guard<std::mutex> lock(mCallbackLock);
ATRACE_INT("ExpiredKernelIdleTimer", 1);
- if (mGetCurrentRefreshRateTypeCallback) {
- if (mGetCurrentRefreshRateTypeCallback() != Scheduler::RefreshRateType::PERFORMANCE) {
- // Disable HW Vsync if the timer expired, as we don't need it
- // enabled if we're not pushing frames, and if we're in PERFORMANCE
- // mode then we'll need to re-update the DispSync model anyways.
- disableHardwareVsync(false);
- }
+ const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
+ if (refreshRate.first != RefreshRateType::PERFORMANCE) {
+ // Disable HW Vsync if the timer expired, as we don't need it
+ // enabled if we're not pushing frames, and if we're in PERFORMANCE
+ // mode then we'll need to re-update the DispSync model anyways.
+ disableHardwareVsync(false);
}
}
@@ -540,6 +517,10 @@ void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventO
}
Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() {
+ if (!mRefreshRateConfigs.refreshRateSwitchingSupported()) {
+ return RefreshRateType::DEFAULT;
+ }
+
// HDR content is not supported on PERFORMANCE mode
if (mForceHDRContentToDefaultRefreshRate && mIsHDRContent) {
return RefreshRateType::DEFAULT;
@@ -567,16 +548,12 @@ Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() {
}
// Content detection is on, find the appropriate refresh rate with minimal error
- auto begin = mRefreshRateConfigs.getRefreshRates().cbegin();
+ auto begin = mRefreshRateConfigs.getRefreshRateMap().cbegin();
- // Skip POWER_SAVING config as it is not a real config
- if (begin->first == RefreshRateType::POWER_SAVING) {
- ++begin;
- }
- auto iter = min_element(begin, mRefreshRateConfigs.getRefreshRates().cend(),
+ auto iter = min_element(begin, mRefreshRateConfigs.getRefreshRateMap().cend(),
[rate = mContentRefreshRate](const auto& l, const auto& r) -> bool {
- return std::abs(l.second->fps - static_cast<float>(rate)) <
- std::abs(r.second->fps - static_cast<float>(rate));
+ return std::abs(l.second.fps - static_cast<float>(rate)) <
+ std::abs(r.second.fps - static_cast<float>(rate));
});
RefreshRateType currRefreshRateType = iter->first;
@@ -584,11 +561,11 @@ Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() {
// 90Hz config. However we should still prefer a lower refresh rate if the content doesn't
// align well with both
constexpr float MARGIN = 0.05f;
- float ratio = mRefreshRateConfigs.getRefreshRate(currRefreshRateType)->fps /
+ float ratio = mRefreshRateConfigs.getRefreshRateFromType(currRefreshRateType).fps /
float(mContentRefreshRate);
if (std::abs(std::round(ratio) - ratio) > MARGIN) {
- while (iter != mRefreshRateConfigs.getRefreshRates().cend()) {
- ratio = iter->second->fps / float(mContentRefreshRate);
+ while (iter != mRefreshRateConfigs.getRefreshRateMap().cend()) {
+ ratio = iter->second.fps / float(mContentRefreshRate);
if (std::abs(std::round(ratio) - ratio) <= MARGIN) {
currRefreshRateType = iter->first;
@@ -601,6 +578,11 @@ Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() {
return currRefreshRateType;
}
+Scheduler::RefreshRateType Scheduler::getPreferredRefreshRateType() {
+ std::lock_guard<std::mutex> lock(mFeatureStateLock);
+ return mRefreshRateType;
+}
+
void Scheduler::changeRefreshRate(RefreshRateType refreshRateType, ConfigEvent configEvent) {
std::lock_guard<std::mutex> lock(mCallbackLock);
if (mChangeRefreshRateCallback) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 5d8bb4cd2f..4b21dadde9 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -49,9 +49,7 @@ public:
}
using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
- using GetCurrentRefreshRateTypeCallback = std::function<RefreshRateType()>;
using ChangeRefreshRateCallback = std::function<void(RefreshRateType, ConfigEvent)>;
- using GetVsyncPeriod = std::function<nsecs_t()>;
// Enum to indicate whether to start the transaction early, or at vsync time.
enum class TransactionStart { EARLY, NORMAL };
@@ -81,16 +79,6 @@ public:
const std::unique_ptr<EventThread> thread;
};
- // Stores per-display state about VSYNC.
- struct VsyncState {
- explicit VsyncState(Scheduler& scheduler) : scheduler(scheduler) {}
-
- void resync(const GetVsyncPeriod&);
-
- Scheduler& scheduler;
- std::atomic<nsecs_t> lastResyncTime = 0;
- };
-
explicit Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
const scheduler::RefreshRateConfigs& refreshRateConfig);
@@ -98,12 +86,11 @@ public:
/** Creates an EventThread connection. */
sp<ConnectionHandle> createConnection(const char* connectionName, nsecs_t phaseOffsetNs,
- nsecs_t offsetThresholdForNextVsync, ResyncCallback,
+ nsecs_t offsetThresholdForNextVsync,
impl::EventThread::InterceptVSyncsCallback);
sp<IDisplayEventConnection> createDisplayEventConnection(
- const sp<ConnectionHandle>& handle, ResyncCallback,
- ISurfaceComposer::ConfigChanged configChanged);
+ const sp<ConnectionHandle>& handle, ISurfaceComposer::ConfigChanged configChanged);
// Getter methods.
EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -143,8 +130,7 @@ public:
// no-op.
// The period is the vsync period from the current display configuration.
void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
- // Creates a callback for resyncing.
- ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod);
+ void resync();
void setRefreshSkipCount(int count);
// Passes a vsync sample to DispSync. periodFlushed will be true if
// DispSync detected that the vsync period changed, and false otherwise.
@@ -167,9 +153,6 @@ public:
void updateFpsBasedOnContent();
// Callback that gets invoked when Scheduler wants to change the refresh rate.
void setChangeRefreshRateCallback(const ChangeRefreshRateCallback&& changeRefreshRateCallback);
- void setGetCurrentRefreshRateTypeCallback(
- const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateType);
- void setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod);
// Returns whether idle timer is enabled or not
bool isIdleTimerEnabled() { return mSetIdleTimerMs > 0; }
@@ -189,6 +172,9 @@ public:
// calls DispSync::dump() on primary disp sync
void dumpPrimaryDispSync(std::string& result) const;
+ // Get the appropriate refresh type for current conditions.
+ RefreshRateType getPreferredRefreshRateType();
+
protected:
virtual std::unique_ptr<EventThread> makeEventThread(
const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
@@ -206,7 +192,7 @@ private:
enum class DisplayPowerTimerState { EXPIRED, RESET };
// Creates a connection on the given EventThread and forwards the given callbacks.
- sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
+ sp<EventThreadConnection> createConnectionInternal(EventThread*,
ISurfaceComposer::ConfigChanged);
nsecs_t calculateAverage() const;
@@ -261,7 +247,8 @@ private:
std::mutex mHWVsyncLock;
bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock);
bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock);
- const std::shared_ptr<VsyncState> mPrimaryVsyncState{std::make_shared<VsyncState>(*this)};
+
+ std::atomic<nsecs_t> mLastResyncTime = 0;
std::unique_ptr<DispSync> mPrimaryDispSync;
std::unique_ptr<EventControlThread> mEventControlThread;
@@ -297,9 +284,7 @@ private:
std::unique_ptr<scheduler::IdleTimer> mDisplayPowerTimer;
std::mutex mCallbackLock;
- GetCurrentRefreshRateTypeCallback mGetCurrentRefreshRateTypeCallback GUARDED_BY(mCallbackLock);
ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock);
- GetVsyncPeriod mGetVsyncPeriod GUARDED_BY(mCallbackLock);
// In order to make sure that the features don't override themselves, we need a state machine
// to keep track which feature requested the config change.
diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h
index ac10f83ad9..f193553ea3 100644
--- a/services/surfaceflinger/Scheduler/SchedulerUtils.h
+++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h
@@ -30,12 +30,6 @@ using namespace std::chrono_literals;
// about layers.
static constexpr size_t ARRAY_SIZE = 30;
-// This number is used to have a place holder for when the screen is not NORMAL/ON. Currently
-// the config is not visible to SF, and is completely maintained by HWC. However, we would
-// still like to keep track of time when the device is in this config.
-static constexpr int SCREEN_OFF_CONFIG_ID = -1;
-static constexpr uint32_t HWC2_SCREEN_OFF_CONFIG_ID = 0xffffffff;
-
// This number is used when we try to determine how long do we keep layer information around
// before we remove it. It is also used to determine how long the layer stays relevant.
// This time period captures infrequent updates when playing YouTube video with static image,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 200da2e814..fd7f128411 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -540,9 +540,9 @@ void SurfaceFlinger::bootFinished()
// wait patiently for the window manager death
const String16 name("window");
- mWindowManager = defaultServiceManager()->getService(name);
- if (mWindowManager != 0) {
- mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
+ sp<IBinder> window(defaultServiceManager()->getService(name));
+ if (window != 0) {
+ window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
}
sp<IBinder> input(defaultServiceManager()->getService(
String16("inputflinger")));
@@ -569,14 +569,16 @@ void SurfaceFlinger::bootFinished()
readPersistentProperties();
mBootStage = BootStage::FINISHED;
- // set the refresh rate according to the policy
- const auto& performanceRefreshRate =
- mRefreshRateConfigs.getRefreshRate(RefreshRateType::PERFORMANCE);
+ if (mRefreshRateConfigs->refreshRateSwitchingSupported()) {
+ // set the refresh rate according to the policy
+ const auto& performanceRefreshRate =
+ mRefreshRateConfigs->getRefreshRateFromType(RefreshRateType::PERFORMANCE);
- if (performanceRefreshRate && isDisplayConfigAllowed(performanceRefreshRate->configId)) {
- setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None);
- } else {
- setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None);
+ if (isDisplayConfigAllowed(performanceRefreshRate.configId)) {
+ setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None);
+ } else {
+ setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None);
+ }
}
}));
}
@@ -619,32 +621,6 @@ void SurfaceFlinger::init() {
ALOGI("Phase offset NS: %" PRId64 "", mPhaseOffsets->getCurrentAppOffset());
Mutex::Autolock _l(mStateLock);
- // start the EventThread
- mScheduler =
- getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
- mRefreshRateConfigs);
- auto resyncCallback =
- mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
-
- mAppConnectionHandle =
- mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
- mPhaseOffsets->getOffsetThresholdForNextVsync(),
- resyncCallback,
- impl::EventThread::InterceptVSyncsCallback());
- mSfConnectionHandle =
- mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
- mPhaseOffsets->getOffsetThresholdForNextVsync(),
- resyncCallback, [this](nsecs_t timestamp) {
- mInterceptor->saveVSyncEvent(timestamp);
- });
-
- mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
- mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
- mSfConnectionHandle.get());
-
- mRegionSamplingThread =
- new RegionSamplingThread(*this, *mScheduler,
- RegionSamplingThread::EnvironmentTimingTunables());
// Get a RenderEngine for the given display / config (can't fail)
int32_t renderEngineFeature = 0;
@@ -715,37 +691,6 @@ void SurfaceFlinger::init() {
ALOGE("Run StartPropertySetThread failed!");
}
- mScheduler->setChangeRefreshRateCallback(
- [this](RefreshRateType type, Scheduler::ConfigEvent event) {
- Mutex::Autolock lock(mStateLock);
- setRefreshRateTo(type, event);
- });
- mScheduler->setGetCurrentRefreshRateTypeCallback([this] {
- Mutex::Autolock lock(mStateLock);
- const auto display = getDefaultDisplayDeviceLocked();
- if (!display) {
- // If we don't have a default display the fallback to the default
- // refresh rate type
- return RefreshRateType::DEFAULT;
- }
-
- const int configId = display->getActiveConfig();
- for (const auto& [type, refresh] : mRefreshRateConfigs.getRefreshRates()) {
- if (refresh && refresh->configId == configId) {
- return type;
- }
- }
- // This should never happen, but just gracefully fallback to default.
- return RefreshRateType::DEFAULT;
- });
- mScheduler->setGetVsyncPeriodCallback([this] {
- Mutex::Autolock lock(mStateLock);
- return getVsyncPeriod();
- });
-
- mRefreshRateConfigs.populate(getHwComposer().getConfigs(*display->getId()));
- mRefreshRateStats.setConfigMode(getHwComposer().getActiveConfigIndex(*display->getId()));
-
ALOGV("Done initializing");
}
@@ -899,7 +844,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken,
info.xdpi = xdpi;
info.ydpi = ydpi;
info.fps = 1e9 / hwConfig->getVsyncPeriod();
- const auto refreshRateType = mRefreshRateConfigs.getRefreshRateType(hwConfig->getId());
+ const auto refreshRateType =
+ mRefreshRateConfigs->getRefreshRateTypeFromHwcConfigId(hwConfig->getId());
const auto offset = mPhaseOffsets->getOffsetsForRefreshRate(refreshRateType);
info.appVsyncOffset = offset.late.app;
@@ -1001,7 +947,8 @@ void SurfaceFlinger::setActiveConfigInternal() {
}
std::lock_guard<std::mutex> lock(mActiveConfigLock);
- mRefreshRateStats.setConfigMode(mUpcomingActiveConfig.configId);
+ mRefreshRateConfigs->setCurrentConfig(mUpcomingActiveConfig.configId);
+ mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
display->setActiveConfig(mUpcomingActiveConfig.configId);
@@ -1280,9 +1227,6 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
return;
}
- auto resyncCallback =
- mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
-
// TODO(b/128863962): Part of the Injector should be refactored, so that it
// can be passed to Scheduler.
if (enable) {
@@ -1294,11 +1238,11 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
impl::EventThread::InterceptVSyncsCallback(),
"injEventThread");
}
- mEventQueue->setEventThread(mInjectorEventThread.get(), std::move(resyncCallback));
+ mEventQueue->setEventThread(mInjectorEventThread.get(), [&] { mScheduler->resync(); });
} else {
ALOGV("VSync Injections disabled");
mEventQueue->setEventThread(mScheduler->getEventThread(mSfConnectionHandle),
- std::move(resyncCallback));
+ [&] { mScheduler->resync(); });
}
mInjectVSyncs = enable;
@@ -1409,16 +1353,10 @@ status_t SurfaceFlinger::notifyPowerHint(int32_t hintId) {
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) {
- auto resyncCallback = mScheduler->makeResyncCallback([this] {
- Mutex::Autolock lock(mStateLock);
- return getVsyncPeriod();
- });
-
const auto& handle =
vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
- return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback),
- configChanged);
+ return mScheduler->createDisplayEventConnection(handle, configChanged);
}
// ----------------------------------------------------------------------------
@@ -1515,13 +1453,8 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::Co
ATRACE_CALL();
// Don't do any updating if the current fps is the same as the new one.
- const auto& refreshRateConfig = mRefreshRateConfigs.getRefreshRate(refreshRate);
- if (!refreshRateConfig) {
- ALOGV("Skipping refresh rate change request for unsupported rate.");
- return;
- }
-
- const int desiredConfigId = refreshRateConfig->configId;
+ const auto& refreshRateConfig = mRefreshRateConfigs->getRefreshRateFromType(refreshRate);
+ const int desiredConfigId = refreshRateConfig.configId;
if (!isDisplayConfigAllowed(desiredConfigId)) {
ALOGV("Skipping config %d as it is not part of allowed configs", desiredConfigId);
@@ -1851,12 +1784,6 @@ void SurfaceFlinger::handleMessageRefresh() {
mVsyncModulator.onRefreshed(mHadClientComposition);
mLayersWithQueuedFrames.clear();
- if (mVisibleRegionsDirty) {
- mVisibleRegionsDirty = false;
- if (mTracingEnabled) {
- mTracing.notify("visibleRegionsDirty");
- }
- }
}
@@ -1866,6 +1793,9 @@ bool SurfaceFlinger::handleMessageInvalidate() {
if (mVisibleRegionsDirty) {
computeLayerBounds();
+ if (mTracingEnabled) {
+ mTracing.notify("visibleRegionsDirty");
+ }
}
for (auto& layer : mLayersPendingRefresh) {
@@ -2272,6 +2202,7 @@ void SurfaceFlinger::rebuildLayerStacks() {
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
ATRACE_NAME("rebuildLayerStacks VR Dirty");
+ mVisibleRegionsDirty = false;
invalidateHwcGeometry();
for (const auto& pair : mDisplays) {
@@ -2628,6 +2559,9 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() {
if (event.connection == HWC2::Connection::Connected) {
if (!mPhysicalDisplayTokens.count(info->id)) {
ALOGV("Creating display %s", to_string(info->id).c_str());
+ if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
+ initScheduler(info->id);
+ }
mPhysicalDisplayTokens[info->id] = new BBinder();
DisplayDeviceState state;
state.displayId = info->id;
@@ -3028,7 +2962,7 @@ void SurfaceFlinger::updateInputFlinger() {
setInputWindowsFinished();
}
- executeInputWindowCommands();
+ mInputWindowCommands.clear();
}
void SurfaceFlinger::updateInputWindowInfo() {
@@ -3052,19 +2986,6 @@ void SurfaceFlinger::commitInputWindowCommands() {
mPendingInputWindowCommands.clear();
}
-void SurfaceFlinger::executeInputWindowCommands() {
- for (const auto& transferTouchFocusCommand : mInputWindowCommands.transferTouchFocusCommands) {
- if (transferTouchFocusCommand.fromToken != nullptr &&
- transferTouchFocusCommand.toToken != nullptr &&
- transferTouchFocusCommand.fromToken != transferTouchFocusCommand.toToken) {
- mInputFlinger->transferTouchFocus(transferTouchFocusCommand.fromToken,
- transferTouchFocusCommand.toToken);
- }
- }
-
- mInputWindowCommands.clear();
-}
-
void SurfaceFlinger::updateCursorAsync()
{
for (const auto& [token, display] : mDisplays) {
@@ -3086,6 +3007,55 @@ void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) {
layer->releasePendingBuffer(systemTime());
}
+void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) {
+ if (mScheduler) {
+ // In practice it's not allowed to hotplug in/out the primary display once it's been
+ // connected during startup, but some tests do it, so just warn and return.
+ ALOGW("Can't re-init scheduler");
+ return;
+ }
+
+ int currentConfig = getHwComposer().getActiveConfigIndex(primaryDisplayId);
+ mRefreshRateConfigs =
+ std::make_unique<scheduler::RefreshRateConfigs>(refresh_rate_switching(false),
+ getHwComposer().getConfigs(
+ primaryDisplayId),
+ currentConfig);
+ mRefreshRateStats =
+ std::make_unique<scheduler::RefreshRateStats>(*mRefreshRateConfigs, *mTimeStats,
+ currentConfig, HWC_POWER_MODE_OFF);
+ mRefreshRateStats->setConfigMode(currentConfig);
+
+ // start the EventThread
+ mScheduler =
+ getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
+ *mRefreshRateConfigs);
+ mAppConnectionHandle =
+ mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
+ mPhaseOffsets->getOffsetThresholdForNextVsync(),
+ impl::EventThread::InterceptVSyncsCallback());
+ mSfConnectionHandle =
+ mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
+ mPhaseOffsets->getOffsetThresholdForNextVsync(),
+ [this](nsecs_t timestamp) {
+ mInterceptor->saveVSyncEvent(timestamp);
+ });
+
+ mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
+ mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
+ mSfConnectionHandle.get());
+
+ mRegionSamplingThread =
+ new RegionSamplingThread(*this, *mScheduler,
+ RegionSamplingThread::EnvironmentTimingTunables());
+
+ mScheduler->setChangeRefreshRateCallback(
+ [this](RefreshRateType type, Scheduler::ConfigEvent event) {
+ Mutex::Autolock lock(mStateLock);
+ setRefreshRateTo(type, event);
+ });
+}
+
void SurfaceFlinger::commitTransaction()
{
if (!mLayersPendingRemoval.isEmpty()) {
@@ -4598,7 +4568,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int
if (display->isPrimary()) {
mTimeStats->setPowerMode(mode);
- mRefreshRateStats.setPowerMode(mode);
+ mRefreshRateStats->setPowerMode(mode);
mScheduler->setDisplayPowerState(mode == HWC_POWER_MODE_NORMAL);
}
@@ -4671,22 +4641,18 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args,
if (const auto it = dumpers.find(flag); it != dumpers.end()) {
(it->second)(args, asProto, result);
- } else if (!asProto) {
- dumpAllLocked(args, result);
+ } else {
+ if (asProto) {
+ LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
+ result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+ } else {
+ dumpAllLocked(args, result);
+ }
}
if (locked) {
mStateLock.unlock();
}
-
- LayersProto layersProto = dumpProtoFromMainThread();
- if (asProto) {
- result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
- } else {
- auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
- result.append(LayerProtoParser::layerTreeToString(layerTree));
- result.append("\n");
- }
}
write(fd, result.c_str(), result.size());
return NO_ERROR;
@@ -4770,15 +4736,14 @@ void SurfaceFlinger::dumpVSync(std::string& result) const {
mUseSmart90ForVideo ? "on" : "off");
StringAppendF(&result, "Allowed Display Configs: ");
for (int32_t configId : mAllowedDisplayConfigs) {
- for (auto refresh : mRefreshRateConfigs.getRefreshRates()) {
- if (refresh.second && refresh.second->configId == configId) {
- StringAppendF(&result, "%dHz, ", refresh.second->fps);
- }
- }
+ StringAppendF(&result, "%" PRIu32 " Hz, ",
+ mRefreshRateConfigs->getRefreshRateFromConfigId(configId).fps);
}
StringAppendF(&result, "(config override by backdoor: %s)\n\n",
mDebugDisplayConfigSetByBackdoor ? "yes" : "no");
mScheduler->dump(mAppConnectionHandle, result);
+ StringAppendF(&result, "+ Refresh rate switching: %s\n",
+ mRefreshRateConfigs->refreshRateSwitchingSupported() ? "on" : "off");
}
void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const {
@@ -4929,23 +4894,19 @@ void SurfaceFlinger::dumpWideColorInfo(std::string& result) const {
result.append("\n");
}
-LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
+LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet,
+ uint32_t traceFlags) const {
LayersProto layersProto;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
+ const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+ const State& state = useDrawing ? mDrawingState : mCurrentState;
+ state.traverseInZOrder([&](Layer* layer) {
LayerProto* layerProto = layersProto.add_layers();
- layer->writeToProtoDrawingState(layerProto, traceFlags);
- layer->writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
+ layer->writeToProto(layerProto, stateSet, traceFlags);
});
return layersProto;
}
-LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
- LayersProto layersProto;
- postMessageSync(new LambdaMessage([&]() { layersProto = dumpDrawingStateProto(traceFlags); }));
- return layersProto;
-}
-
LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(
const sp<DisplayDevice>& displayDevice) const {
LayersProto layersProto;
@@ -4966,7 +4927,7 @@ LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (!layer->visibleRegion.isEmpty() && !display->getOutputLayersOrderedByZ().empty()) {
LayerProto* layerProto = layersProto.add_layers();
- layer->writeToProtoCompositionState(layerProto, displayDevice);
+ layer->writeToProto(layerProto, displayDevice);
}
});
@@ -5031,6 +4992,13 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co
colorizer.reset(result);
{
+ LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
+ auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+ result.append(LayerProtoParser::layerTreeToString(layerTree));
+ result.append("\n");
+ }
+
+ {
StringAppendF(&result, "Composition layers\n");
mDrawingState.traverseInZOrder([&](Layer* layer) {
auto compositionLayer = layer->getCompositionLayer();
@@ -5140,7 +5108,7 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co
result.append("\nScheduler state:\n");
result.append(mScheduler->doDump() + "\n");
StringAppendF(&result, "+ Smart video mode: %s\n\n", mUseSmart90ForVideo ? "on" : "off");
- result.append(mRefreshRateStats.doDump() + "\n");
+ result.append(mRefreshRateStats->doDump() + "\n");
result.append(mTimeStats->miniDump());
result.append("\n");
@@ -5611,7 +5579,8 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
case 1034: {
// TODO(b/129297325): expose this via developer menu option
n = data.readInt32();
- if (n && !mRefreshRateOverlay) {
+ if (n && !mRefreshRateOverlay &&
+ mRefreshRateConfigs->refreshRateSwitchingSupported()) {
RefreshRateType type;
{
std::lock_guard<std::mutex> lock(mActiveConfigLock);
@@ -6210,15 +6179,28 @@ void SurfaceFlinger::setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& d
mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
display->getActiveConfig());
- // Set the highest allowed config by iterating backwards on available refresh rates
- const auto& refreshRates = mRefreshRateConfigs.getRefreshRates();
- for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
- if (iter->second && isDisplayConfigAllowed(iter->second->configId)) {
- ALOGV("switching to config %d", iter->second->configId);
- setDesiredActiveConfig(
- {iter->first, iter->second->configId, Scheduler::ConfigEvent::Changed});
- break;
+ if (mRefreshRateConfigs->refreshRateSwitchingSupported()) {
+ const auto& type = mScheduler->getPreferredRefreshRateType();
+ const auto& config = mRefreshRateConfigs->getRefreshRateFromType(type);
+ if (isDisplayConfigAllowed(config.configId)) {
+ ALOGV("switching to Scheduler preferred config %d", config.configId);
+ setDesiredActiveConfig({type, config.configId, Scheduler::ConfigEvent::Changed});
+ } else {
+ // Set the highest allowed config by iterating backwards on available refresh rates
+ const auto& refreshRates = mRefreshRateConfigs->getRefreshRateMap();
+ for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
+ if (isDisplayConfigAllowed(iter->second.configId)) {
+ ALOGV("switching to allowed config %d", iter->second.configId);
+ setDesiredActiveConfig(
+ {iter->first, iter->second.configId, Scheduler::ConfigEvent::Changed});
+ break;
+ }
+ }
}
+ } else if (!isDisplayConfigAllowed(display->getActiveConfig())) {
+ ALOGV("switching to config %d", allowedConfigs[0]);
+ setDesiredActiveConfig(
+ {RefreshRateType::DEFAULT, allowedConfigs[0], Scheduler::ConfigEvent::Changed});
}
}
@@ -6235,7 +6217,7 @@ status_t SurfaceFlinger::setAllowedDisplayConfigs(const sp<IBinder>& displayToke
return NO_ERROR;
}
- postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
+ postMessageSync(new LambdaMessage([&]() {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set allowed display configs for invalid display token %p",
@@ -6243,6 +6225,7 @@ status_t SurfaceFlinger::setAllowedDisplayConfigs(const sp<IBinder>& displayToke
} else if (display->isVirtual()) {
ALOGW("Attempt to set allowed display configs for virtual display");
} else {
+ Mutex::Autolock lock(mStateLock);
setAllowedDisplayConfigsInternal(display, allowedConfigs);
}
}));
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5778be6900..a22d6fc649 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -263,8 +263,7 @@ public:
status_t postMessageAsync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0);
// post a synchronous message to the main thread
- status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0)
- EXCLUDES(mStateLock);
+ status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0);
// force full composition on all displays
void repaintEverything();
@@ -554,9 +553,9 @@ private:
void updateInputFlinger();
void updateInputWindowInfo();
void commitInputWindowCommands() REQUIRES(mStateLock);
- void executeInputWindowCommands();
void setInputWindowsFinished();
void updateCursorAsync();
+ void initScheduler(DisplayId primaryDisplayId);
/* handlePageFlip - latch a new buffer if available and compute the dirty
* region. Returns whether a new buffer has been latched, i.e., whether it
@@ -901,9 +900,8 @@ private:
void dumpBufferingStats(std::string& result) const;
void dumpDisplayIdentificationData(std::string& result) const;
void dumpWideColorInfo(std::string& result) const;
- LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
- LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL)
- EXCLUDES(mStateLock);
+ LayersProto dumpProtoInfo(LayerVector::StateSet stateSet,
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
void withTracingLock(std::function<void()> operation) REQUIRES(mStateLock);
LayersProto dumpVisibleLayersProtoInfo(const sp<DisplayDevice>& display) const;
@@ -1104,9 +1102,6 @@ private:
// either AID_GRAPHICS or AID_SYSTEM.
status_t CheckTransactCodeCredentials(uint32_t code);
- // to linkToDeath
- sp<IBinder> mWindowManager;
-
std::unique_ptr<dvr::VrFlinger> mVrFlinger;
std::atomic<bool> mVrFlingerRequestsDisplay = false;
static bool useVrFlinger;
@@ -1138,8 +1133,8 @@ private:
sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
- scheduler::RefreshRateConfigs mRefreshRateConfigs;
- scheduler::RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, *mTimeStats};
+ std::unique_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
+ std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
// All configs are allowed if the set is empty.
using DisplayConfigs = std::set<int32_t>;
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index 768074a6cd..b4716eb61e 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -226,6 +226,14 @@ int64_t color_space_agnostic_dataspace(Dataspace defaultValue) {
return static_cast<int64_t>(defaultValue);
}
+bool refresh_rate_switching(bool defaultValue) {
+ auto temp = SurfaceFlingerProperties::refresh_rate_switching();
+ if (temp.has_value()) {
+ return *temp;
+ }
+ return defaultValue;
+}
+
int32_t set_idle_timer_ms(int32_t defaultValue) {
auto temp = SurfaceFlingerProperties::set_idle_timer_ms();
if (temp.has_value()) {
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 5f88322f71..e394ccab7b 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -73,6 +73,8 @@ int32_t wcg_composition_pixel_format(
int64_t color_space_agnostic_dataspace(
android::hardware::graphics::common::V1_2::Dataspace defaultValue);
+bool refresh_rate_switching(bool defaultValue);
+
int32_t set_idle_timer_ms(int32_t defaultValue);
int32_t set_touch_timer_ms(int32_t defaultValue);
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index 9053f2c7de..c4ab0668e7 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -162,7 +162,7 @@ LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
LayersTraceProto entry;
entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
entry.set_where(where);
- LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
+ LayersProto layers(mFlinger.dumpProtoInfo(LayerVector::StateSet::Drawing, mTraceFlags));
entry.mutable_layers()->Swap(&layers);
return entry;
diff --git a/services/surfaceflinger/TimeStats/OWNERS b/services/surfaceflinger/TimeStats/OWNERS
index 1441f91489..ac02d12fcd 100644
--- a/services/surfaceflinger/TimeStats/OWNERS
+++ b/services/surfaceflinger/TimeStats/OWNERS
@@ -1,2 +1 @@
-alecmouri@google.com
-zzyiwei@google.com
+zzyiwei@google.com \ No newline at end of file
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index d03cb7b22a..cb368b0886 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -43,7 +43,7 @@ java_library_static {
type: "nano",
},
srcs: ["*.proto"],
- sdk_version: "core_platform",
+ no_framework_libs: true,
target: {
android: {
jarjar_rules: "jarjar-rules.txt",
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index 56ab4e3f33..000f21c545 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -15,7 +15,7 @@
module: "android.sysprop.SurfaceFlingerProperties"
owner: Platform
-# The following two propertiess define (respectively):
+# The following two properties define (respectively):
#
# - The phase offset between hardware vsync and when apps are woken up by the
# Choreographer callback
@@ -36,7 +36,7 @@ owner: Platform
prop {
api_name: "vsync_event_phase_offset_ns"
type: Long
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
}
@@ -44,7 +44,7 @@ prop {
prop {
api_name: "vsync_sf_event_phase_offset_ns"
type: Long
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
}
@@ -53,7 +53,7 @@ prop {
prop {
api_name: "use_context_priority"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.use_context_priority"
}
@@ -62,7 +62,7 @@ prop {
prop {
api_name: "max_frame_buffer_acquired_buffers"
type: Long
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
}
@@ -80,7 +80,7 @@ prop {
prop {
api_name: "has_wide_color_display"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.has_wide_color_display"
}
@@ -90,7 +90,7 @@ prop {
prop {
api_name: "running_without_sync_framework"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.running_without_sync_framework"
}
@@ -108,7 +108,7 @@ prop {
prop {
api_name: "has_HDR_display"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.has_HDR_display"
}
@@ -117,7 +117,7 @@ prop {
prop {
api_name: "present_time_offset_from_vsync_ns"
type: Long
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
}
@@ -129,7 +129,7 @@ prop {
prop {
api_name: "force_hwc_copy_for_virtual_displays"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
}
@@ -139,7 +139,7 @@ prop {
prop {
api_name: "max_virtual_display_dimension"
type: Long
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.max_virtual_display_dimension"
}
@@ -151,7 +151,7 @@ prop {
prop {
api_name: "use_vr_flinger"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.use_vr_flinger"
}
@@ -161,7 +161,7 @@ prop {
prop {
api_name: "start_graphics_allocator_service"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.start_graphics_allocator_service"
}
@@ -171,7 +171,7 @@ prop {
api_name: "primary_display_orientation"
type: Enum
enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.primary_display_orientation"
}
@@ -182,7 +182,7 @@ prop {
prop {
api_name: "use_color_management"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.use_color_management"
}
@@ -209,7 +209,7 @@ prop {
prop {
api_name: "default_composition_dataspace"
type: Long
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.default_composition_dataspace"
}
@@ -220,7 +220,7 @@ prop {
prop {
api_name: "default_composition_pixel_format"
type: Integer
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.default_composition_pixel_format"
}
@@ -235,7 +235,7 @@ prop {
prop {
api_name: "wcg_composition_dataspace"
type: Long
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.wcg_composition_dataspace"
}
@@ -246,7 +246,7 @@ prop {
prop {
api_name: "wcg_composition_pixel_format"
type: Integer
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
}
@@ -272,7 +272,7 @@ prop {
prop {
api_name: "display_primary_red"
type: DoubleList
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.display_primary_red"
}
@@ -280,7 +280,7 @@ prop {
prop {
api_name: "display_primary_green"
type: DoubleList
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.display_primary_green"
}
@@ -288,7 +288,7 @@ prop {
prop {
api_name: "display_primary_blue"
type: DoubleList
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.display_primary_blue"
}
@@ -296,18 +296,30 @@ prop {
prop {
api_name: "display_primary_white"
type: DoubleList
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.display_primary_white"
}
+# refreshRateSwitching indicates whether SurfaceFlinger should use refresh rate
+# switching on the device, e.g. to switch between 60 and 90 Hz. The settings
+# below that are related to refresh rate switching will only have an effect if
+# refresh_rate_switching is enabled.
+prop {
+ api_name: "refresh_rate_switching"
+ type: Boolean
+ scope: System
+ access: Readonly
+ prop_name: "ro.surface_flinger.refresh_rate_switching"
+}
+
# setIdleTimerMs indicates what is considered a timeout in milliseconds for Scheduler. This value is
# used by the Scheduler to trigger inactivity callbacks that will switch the display to a lower
# refresh rate. Setting this property to 0 means there is no timer.
prop {
api_name: "set_idle_timer_ms"
type: Integer
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.set_idle_timer_ms"
}
@@ -318,7 +330,7 @@ prop {
prop {
api_name: "set_touch_timer_ms"
type: Integer
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.set_touch_timer_ms"
}
@@ -340,7 +352,7 @@ prop {
prop {
api_name: "use_smart_90_for_video"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.use_smart_90_for_video"
}
@@ -348,7 +360,7 @@ prop {
prop {
api_name: "enable_protected_contents"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.protected_contents"
}
@@ -358,7 +370,7 @@ prop {
prop {
api_name: "support_kernel_idle_timer"
type: Boolean
- scope: Public
+ scope: System
access: Readonly
prop_name: "ro.surface_flinger.support_kernel_idle_timer"
}
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
deleted file mode 100644
index b66e56ecc7..0000000000
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ /dev/null
@@ -1,138 +0,0 @@
-props {
- module: "android.sysprop.SurfaceFlingerProperties"
- prop {
- api_name: "color_space_agnostic_dataspace"
- type: Long
- prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
- }
- prop {
- api_name: "default_composition_dataspace"
- type: Long
- prop_name: "ro.surface_flinger.default_composition_dataspace"
- }
- prop {
- api_name: "default_composition_pixel_format"
- type: Integer
- prop_name: "ro.surface_flinger.default_composition_pixel_format"
- }
- prop {
- api_name: "display_primary_blue"
- type: DoubleList
- prop_name: "ro.surface_flinger.display_primary_blue"
- }
- prop {
- api_name: "display_primary_green"
- type: DoubleList
- prop_name: "ro.surface_flinger.display_primary_green"
- }
- prop {
- api_name: "display_primary_red"
- type: DoubleList
- prop_name: "ro.surface_flinger.display_primary_red"
- }
- prop {
- api_name: "display_primary_white"
- type: DoubleList
- prop_name: "ro.surface_flinger.display_primary_white"
- }
- prop {
- api_name: "enable_protected_contents"
- prop_name: "ro.surface_flinger.protected_contents"
- }
- prop {
- api_name: "force_hwc_copy_for_virtual_displays"
- prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
- }
- prop {
- api_name: "has_HDR_display"
- prop_name: "ro.surface_flinger.has_HDR_display"
- }
- prop {
- api_name: "has_wide_color_display"
- prop_name: "ro.surface_flinger.has_wide_color_display"
- }
- prop {
- api_name: "max_frame_buffer_acquired_buffers"
- type: Long
- prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
- }
- prop {
- api_name: "max_virtual_display_dimension"
- type: Long
- prop_name: "ro.surface_flinger.max_virtual_display_dimension"
- }
- prop {
- api_name: "present_time_offset_from_vsync_ns"
- type: Long
- prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
- }
- prop {
- api_name: "primary_display_orientation"
- type: Enum
- prop_name: "ro.surface_flinger.primary_display_orientation"
- enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
- }
- prop {
- api_name: "running_without_sync_framework"
- prop_name: "ro.surface_flinger.running_without_sync_framework"
- }
- prop {
- api_name: "set_display_power_timer_ms"
- type: Integer
- prop_name: "ro.surface_flinger.set_display_power_timer_ms"
- }
- prop {
- api_name: "set_idle_timer_ms"
- type: Integer
- prop_name: "ro.surface_flinger.set_idle_timer_ms"
- }
- prop {
- api_name: "set_touch_timer_ms"
- type: Integer
- prop_name: "ro.surface_flinger.set_touch_timer_ms"
- }
- prop {
- api_name: "start_graphics_allocator_service"
- prop_name: "ro.surface_flinger.start_graphics_allocator_service"
- }
- prop {
- api_name: "support_kernel_idle_timer"
- prop_name: "ro.surface_flinger.support_kernel_idle_timer"
- }
- prop {
- api_name: "use_color_management"
- prop_name: "ro.surface_flinger.use_color_management"
- }
- prop {
- api_name: "use_context_priority"
- prop_name: "ro.surface_flinger.use_context_priority"
- }
- prop {
- api_name: "use_smart_90_for_video"
- prop_name: "ro.surface_flinger.use_smart_90_for_video"
- }
- prop {
- api_name: "use_vr_flinger"
- prop_name: "ro.surface_flinger.use_vr_flinger"
- }
- prop {
- api_name: "vsync_event_phase_offset_ns"
- type: Long
- prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
- }
- prop {
- api_name: "vsync_sf_event_phase_offset_ns"
- type: Long
- prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
- }
- prop {
- api_name: "wcg_composition_dataspace"
- type: Long
- prop_name: "ro.surface_flinger.wcg_composition_dataspace"
- }
- prop {
- api_name: "wcg_composition_pixel_format"
- type: Integer
- prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
- }
-}
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt
deleted file mode 100644
index b66e56ecc7..0000000000
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt
+++ /dev/null
@@ -1,138 +0,0 @@
-props {
- module: "android.sysprop.SurfaceFlingerProperties"
- prop {
- api_name: "color_space_agnostic_dataspace"
- type: Long
- prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
- }
- prop {
- api_name: "default_composition_dataspace"
- type: Long
- prop_name: "ro.surface_flinger.default_composition_dataspace"
- }
- prop {
- api_name: "default_composition_pixel_format"
- type: Integer
- prop_name: "ro.surface_flinger.default_composition_pixel_format"
- }
- prop {
- api_name: "display_primary_blue"
- type: DoubleList
- prop_name: "ro.surface_flinger.display_primary_blue"
- }
- prop {
- api_name: "display_primary_green"
- type: DoubleList
- prop_name: "ro.surface_flinger.display_primary_green"
- }
- prop {
- api_name: "display_primary_red"
- type: DoubleList
- prop_name: "ro.surface_flinger.display_primary_red"
- }
- prop {
- api_name: "display_primary_white"
- type: DoubleList
- prop_name: "ro.surface_flinger.display_primary_white"
- }
- prop {
- api_name: "enable_protected_contents"
- prop_name: "ro.surface_flinger.protected_contents"
- }
- prop {
- api_name: "force_hwc_copy_for_virtual_displays"
- prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
- }
- prop {
- api_name: "has_HDR_display"
- prop_name: "ro.surface_flinger.has_HDR_display"
- }
- prop {
- api_name: "has_wide_color_display"
- prop_name: "ro.surface_flinger.has_wide_color_display"
- }
- prop {
- api_name: "max_frame_buffer_acquired_buffers"
- type: Long
- prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
- }
- prop {
- api_name: "max_virtual_display_dimension"
- type: Long
- prop_name: "ro.surface_flinger.max_virtual_display_dimension"
- }
- prop {
- api_name: "present_time_offset_from_vsync_ns"
- type: Long
- prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
- }
- prop {
- api_name: "primary_display_orientation"
- type: Enum
- prop_name: "ro.surface_flinger.primary_display_orientation"
- enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
- }
- prop {
- api_name: "running_without_sync_framework"
- prop_name: "ro.surface_flinger.running_without_sync_framework"
- }
- prop {
- api_name: "set_display_power_timer_ms"
- type: Integer
- prop_name: "ro.surface_flinger.set_display_power_timer_ms"
- }
- prop {
- api_name: "set_idle_timer_ms"
- type: Integer
- prop_name: "ro.surface_flinger.set_idle_timer_ms"
- }
- prop {
- api_name: "set_touch_timer_ms"
- type: Integer
- prop_name: "ro.surface_flinger.set_touch_timer_ms"
- }
- prop {
- api_name: "start_graphics_allocator_service"
- prop_name: "ro.surface_flinger.start_graphics_allocator_service"
- }
- prop {
- api_name: "support_kernel_idle_timer"
- prop_name: "ro.surface_flinger.support_kernel_idle_timer"
- }
- prop {
- api_name: "use_color_management"
- prop_name: "ro.surface_flinger.use_color_management"
- }
- prop {
- api_name: "use_context_priority"
- prop_name: "ro.surface_flinger.use_context_priority"
- }
- prop {
- api_name: "use_smart_90_for_video"
- prop_name: "ro.surface_flinger.use_smart_90_for_video"
- }
- prop {
- api_name: "use_vr_flinger"
- prop_name: "ro.surface_flinger.use_vr_flinger"
- }
- prop {
- api_name: "vsync_event_phase_offset_ns"
- type: Long
- prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
- }
- prop {
- api_name: "vsync_sf_event_phase_offset_ns"
- type: Long
- prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
- }
- prop {
- api_name: "wcg_composition_dataspace"
- type: Long
- prop_name: "ro.surface_flinger.wcg_composition_dataspace"
- }
- prop {
- api_name: "wcg_composition_pixel_format"
- type: Integer
- prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
- }
-}
diff --git a/services/surfaceflinger/sysprop/api/current.txt b/services/surfaceflinger/sysprop/api/current.txt
new file mode 100644
index 0000000000..d802177e24
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/removed.txt b/services/surfaceflinger/sysprop/api/removed.txt
new file mode 100644
index 0000000000..d802177e24
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/system-current.txt b/services/surfaceflinger/sysprop/api/system-current.txt
new file mode 100644
index 0000000000..2e804c8a31
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/system-current.txt
@@ -0,0 +1,46 @@
+// Signature format: 2.0
+package android.sysprop {
+
+ public final class SurfaceFlingerProperties {
+ method public static java.util.Optional<java.lang.Long> color_space_agnostic_dataspace();
+ method public static java.util.Optional<java.lang.Long> default_composition_dataspace();
+ method public static java.util.Optional<java.lang.Integer> default_composition_pixel_format();
+ method public static java.util.List<java.lang.Double> display_primary_blue();
+ method public static java.util.List<java.lang.Double> display_primary_green();
+ method public static java.util.List<java.lang.Double> display_primary_red();
+ method public static java.util.List<java.lang.Double> display_primary_white();
+ method public static java.util.Optional<java.lang.Boolean> enable_protected_contents();
+ method public static java.util.Optional<java.lang.Boolean> force_hwc_copy_for_virtual_displays();
+ method public static java.util.Optional<java.lang.Boolean> has_HDR_display();
+ method public static java.util.Optional<java.lang.Boolean> has_wide_color_display();
+ method public static java.util.Optional<java.lang.Long> max_frame_buffer_acquired_buffers();
+ method public static java.util.Optional<java.lang.Long> max_virtual_display_dimension();
+ method public static java.util.Optional<java.lang.Long> present_time_offset_from_vsync_ns();
+ method public static java.util.Optional<android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values> primary_display_orientation();
+ method public static java.util.Optional<java.lang.Boolean> refresh_rate_switching();
+ method public static java.util.Optional<java.lang.Boolean> running_without_sync_framework();
+ method public static java.util.Optional<java.lang.Integer> set_display_power_timer_ms();
+ method public static java.util.Optional<java.lang.Integer> set_idle_timer_ms();
+ method public static java.util.Optional<java.lang.Integer> set_touch_timer_ms();
+ method public static java.util.Optional<java.lang.Boolean> start_graphics_allocator_service();
+ method public static java.util.Optional<java.lang.Boolean> support_kernel_idle_timer();
+ method public static java.util.Optional<java.lang.Boolean> use_color_management();
+ method public static java.util.Optional<java.lang.Boolean> use_context_priority();
+ method public static java.util.Optional<java.lang.Boolean> use_smart_90_for_video();
+ method public static java.util.Optional<java.lang.Boolean> use_vr_flinger();
+ method public static java.util.Optional<java.lang.Long> vsync_event_phase_offset_ns();
+ method public static java.util.Optional<java.lang.Long> vsync_sf_event_phase_offset_ns();
+ method public static java.util.Optional<java.lang.Long> wcg_composition_dataspace();
+ method public static java.util.Optional<java.lang.Integer> wcg_composition_pixel_format();
+ }
+
+ public enum SurfaceFlingerProperties.primary_display_orientation_values {
+ method public String getPropValue();
+ enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_0;
+ enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_180;
+ enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_270;
+ enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_90;
+ }
+
+}
+
diff --git a/services/surfaceflinger/sysprop/api/system-removed.txt b/services/surfaceflinger/sysprop/api/system-removed.txt
new file mode 100644
index 0000000000..d802177e24
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/test-current.txt b/services/surfaceflinger/sysprop/api/test-current.txt
new file mode 100644
index 0000000000..d802177e24
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/test-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/test-removed.txt b/services/surfaceflinger/sysprop/api/test-removed.txt
new file mode 100644
index 0000000000..d802177e24
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/test-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 2feff4570e..a2c0611b1e 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -20,6 +20,8 @@ cc_test {
"libgui",
"libhardware",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"liblayers_proto",
"liblog",
"libnativewindow",
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index a892a2abd0..f9e0b6413b 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -54,11 +54,10 @@ using namespace sftest;
namespace {
// Mock test helpers
-using ::testing::_;
-using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::SetArgPointee;
+using ::testing::_;
using Transaction = SurfaceComposerClient::Transaction;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 4f8ed1ae1c..349dd3f2f1 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -125,7 +125,17 @@ public:
}
void setupScheduler() {
- mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
+ std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{{/*hwcId=*/0, 16666667}};
+ mFlinger.mutableRefreshRateConfigs() =
+ std::make_unique<scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false,
+ configs,
+ /*currentConfig=*/0);
+ mFlinger.mutableRefreshRateStats() =
+ std::make_unique<scheduler::RefreshRateStats>(*mFlinger.mutableRefreshRateConfigs(),
+ *mFlinger.mutableTimeStats(),
+ /*currentConfig=*/0,
+ /*powerMode=*/HWC_POWER_MODE_OFF);
+ mScheduler = new TestableScheduler(*mFlinger.mutableRefreshRateConfigs());
mScheduler->mutableEventControlThread().reset(mEventControlThread);
mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
EXPECT_CALL(*mEventThread.get(), registerDisplayEventConnection(_));
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 5f58e7dce9..f40996eecf 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -29,6 +29,7 @@
#include <ui/DebugUtils.h>
#include "DisplayIdentificationTest.h"
+#include "Scheduler/RefreshRateConfigs.h"
#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
@@ -179,7 +180,16 @@ DisplayTransactionTest::~DisplayTransactionTest() {
}
void DisplayTransactionTest::setupScheduler() {
- mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
+ std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{{/*hwcId=*/0, 16666667}};
+ mFlinger.mutableRefreshRateConfigs() =
+ std::make_unique<scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs,
+ /*currentConfig=*/0);
+ mFlinger.mutableRefreshRateStats() =
+ std::make_unique<scheduler::RefreshRateStats>(*mFlinger.mutableRefreshRateConfigs(),
+ *mFlinger.mutableTimeStats(),
+ /*currentConfig=*/0,
+ /*powerMode=*/HWC_POWER_MODE_OFF);
+ mScheduler = new TestableScheduler(*mFlinger.mutableRefreshRateConfigs());
mScheduler->mutableEventControlThread().reset(mEventControlThread);
mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_));
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 5067fe890b..f315a8a86c 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -23,7 +23,6 @@
#include "DisplayHardware/HWC2.h"
#include "Scheduler/RefreshRateConfigs.h"
-#include "mock/DisplayHardware/MockDisplay.h"
using namespace std::chrono_literals;
using testing::_;
@@ -50,9 +49,8 @@ protected:
ASSERT_EQ(left.configId, right.configId);
ASSERT_EQ(left.name, right.name);
ASSERT_EQ(left.fps, right.fps);
+ ASSERT_EQ(left.vsyncPeriod, right.vsyncPeriod);
}
-
- RefreshRateConfigs mConfigs;
};
RefreshRateConfigsTest::RefreshRateConfigsTest() {
@@ -71,101 +69,39 @@ namespace {
/* ------------------------------------------------------------------------
* Test cases
*/
-TEST_F(RefreshRateConfigsTest, zeroDeviceConfigs_storesPowerSavingConfig) {
- std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs;
- mConfigs.populate(displayConfigs);
-
- // We always store a configuration for screen off.
- const auto& rates = mConfigs.getRefreshRates();
- ASSERT_EQ(1, rates.size());
- const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING);
- ASSERT_NE(rates.end(), powerSavingRate);
- ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE));
- ASSERT_EQ(rates.end(), rates.find(RefreshRateType::DEFAULT));
-
- RefreshRate expectedConfig =
- RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
- assertRatesEqual(expectedConfig, *powerSavingRate->second);
-
- ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
- assertRatesEqual(expectedConfig, *mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
- ASSERT_FALSE(mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
- ASSERT_FALSE(mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
-
- // Sanity check that getRefreshRate() does not modify the underlying configs.
- ASSERT_EQ(1, mConfigs.getRefreshRates().size());
+TEST_F(RefreshRateConfigsTest, oneDeviceConfig_isRejected) {
+ std::vector<RefreshRateConfigs::InputConfig> configs{{HWC2_CONFIG_ID_60, VSYNC_60}};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfig=*/0);
+ ASSERT_FALSE(refreshRateConfigs->refreshRateSwitchingSupported());
}
-TEST_F(RefreshRateConfigsTest, oneDeviceConfig_storesDefaultConfig) {
- auto display = new Hwc2::mock::Display();
- std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs;
- auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
- config60.setVsyncPeriod(VSYNC_60);
- displayConfigs.push_back(config60.build());
- mConfigs.populate(displayConfigs);
+TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) {
+ std::vector<RefreshRateConfigs::InputConfig> configs{{HWC2_CONFIG_ID_60, VSYNC_60},
+ {HWC2_CONFIG_ID_90, VSYNC_90}};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfig=*/0);
- const auto& rates = mConfigs.getRefreshRates();
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
+ const auto& rates = refreshRateConfigs->getRefreshRateMap();
ASSERT_EQ(2, rates.size());
- const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING);
- const auto& defaultRate = rates.find(RefreshRateType::DEFAULT);
- ASSERT_NE(rates.end(), powerSavingRate);
- ASSERT_NE(rates.end(), defaultRate);
- ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE));
-
- RefreshRate expectedPowerSavingConfig =
- RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
- assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second);
- RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60, HWC2_CONFIG_ID_60};
- assertRatesEqual(expectedDefaultConfig, *defaultRate->second);
-
- ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
- assertRatesEqual(expectedPowerSavingConfig,
- *mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
- ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
- assertRatesEqual(expectedDefaultConfig, *mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
- ASSERT_FALSE(mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
-
- // Sanity check that getRefreshRate() does not modify the underlying configs.
- ASSERT_EQ(2, mConfigs.getRefreshRates().size());
-}
-
-TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesPerformanceConfig) {
- auto display = new Hwc2::mock::Display();
- std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs;
- auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
- config60.setVsyncPeriod(VSYNC_60);
- displayConfigs.push_back(config60.build());
- auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
- config90.setVsyncPeriod(VSYNC_90);
- displayConfigs.push_back(config90.build());
- mConfigs.populate(displayConfigs);
-
- const auto& rates = mConfigs.getRefreshRates();
- ASSERT_EQ(3, rates.size());
- const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING);
const auto& defaultRate = rates.find(RefreshRateType::DEFAULT);
const auto& performanceRate = rates.find(RefreshRateType::PERFORMANCE);
- ASSERT_NE(rates.end(), powerSavingRate);
ASSERT_NE(rates.end(), defaultRate);
ASSERT_NE(rates.end(), performanceRate);
- RefreshRate expectedPowerSavingConfig =
- RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
- assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second);
- RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60, HWC2_CONFIG_ID_60};
- assertRatesEqual(expectedDefaultConfig, *defaultRate->second);
- RefreshRate expectedPerformanceConfig =
- RefreshRate{CONFIG_ID_90, "90fps", 90, HWC2_CONFIG_ID_90};
- assertRatesEqual(expectedPerformanceConfig, *performanceRate->second);
-
- ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
- assertRatesEqual(expectedPowerSavingConfig,
- *mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
- ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
- assertRatesEqual(expectedDefaultConfig, *mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
- ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
+ RefreshRate expectedDefaultConfig = {CONFIG_ID_60, "60fps", 60, VSYNC_60, HWC2_CONFIG_ID_60};
+ assertRatesEqual(expectedDefaultConfig, defaultRate->second);
+ RefreshRate expectedPerformanceConfig = {CONFIG_ID_90, "90fps", 90, VSYNC_90,
+ HWC2_CONFIG_ID_90};
+ assertRatesEqual(expectedPerformanceConfig, performanceRate->second);
+
+ assertRatesEqual(expectedDefaultConfig,
+ refreshRateConfigs->getRefreshRateFromType(RefreshRateType::DEFAULT));
assertRatesEqual(expectedPerformanceConfig,
- *mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
+ refreshRateConfigs->getRefreshRateFromType(RefreshRateType::PERFORMANCE));
}
} // namespace
} // namespace scheduler
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index 411ec61770..cec0b32a6b 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -22,7 +22,6 @@
#include <thread>
#include "Scheduler/RefreshRateStats.h"
-#include "mock/DisplayHardware/MockDisplay.h"
#include "mock/MockTimeStats.h"
using namespace std::chrono_literals;
@@ -42,9 +41,18 @@ protected:
RefreshRateStatsTest();
~RefreshRateStatsTest();
+ void init(const std::vector<RefreshRateConfigs::InputConfig>& configs) {
+ mRefreshRateConfigs = std::make_unique<RefreshRateConfigs>(
+ /*refreshRateSwitching=*/true, configs, /*currentConfig=*/0);
+ mRefreshRateStats =
+ std::make_unique<RefreshRateStats>(*mRefreshRateConfigs, mTimeStats,
+ /*currentConfig=*/0,
+ /*currentPowerMode=*/HWC_POWER_MODE_OFF);
+ }
+
mock::TimeStats mTimeStats;
- RefreshRateConfigs mRefreshRateConfigs;
- RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, mTimeStats};
+ std::unique_ptr<RefreshRateConfigs> mRefreshRateConfigs;
+ std::unique_ptr<RefreshRateStats> mRefreshRateStats;
};
RefreshRateStatsTest::RefreshRateStatsTest() {
@@ -63,63 +71,46 @@ namespace {
/* ------------------------------------------------------------------------
* Test cases
*/
-TEST_F(RefreshRateStatsTest, canCreateAndDestroyTest) {
- std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
- mRefreshRateConfigs.populate(configs);
-
- // There is one default config, so the refresh rates should have one item.
- EXPECT_EQ(1, mRefreshRateStats.getTotalTimes().size());
-}
-
TEST_F(RefreshRateStatsTest, oneConfigTest) {
- auto display = new Hwc2::mock::Display();
-
- auto config = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
- config.setVsyncPeriod(VSYNC_90);
- std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
- configs.push_back(config.build());
-
- mRefreshRateConfigs.populate(configs);
+ init({{CONFIG_ID_90, VSYNC_90}});
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
- std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
- EXPECT_EQ(2, times.size());
+ std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(1, times.size());
EXPECT_NE(0u, times.count("ScreenOff"));
- EXPECT_EQ(1u, times.count("90fps"));
- EXPECT_EQ(0, times["90fps"]);
// Setting up tests on mobile harness can be flaky with time passing, so testing for
// exact time changes can result in flaxy numbers. To avoid that remember old
// numbers to make sure the correct values are increasing in the next test.
int screenOff = times["ScreenOff"];
- int ninety = times["90fps"];
// Screen is off by default.
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
- EXPECT_EQ(0, times["90fps"]);
+ EXPECT_EQ(0u, times.count("90fps"));
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
- screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
- EXPECT_LT(ninety, times["90fps"]);
+ ASSERT_EQ(1u, times.count("90fps"));
+ EXPECT_LT(0, times["90fps"]);
- mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
- ninety = mRefreshRateStats.getTotalTimes()["90fps"];
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+ int ninety = mRefreshRateStats->getTotalTimes()["90fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
// Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
// does not update refresh rates that come from the config.
EXPECT_LT(screenOff, times["ScreenOff"]);
@@ -127,93 +118,75 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) {
}
TEST_F(RefreshRateStatsTest, twoConfigsTest) {
- auto display = new Hwc2::mock::Display();
-
- auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
- config90.setVsyncPeriod(VSYNC_90);
- std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
- configs.push_back(config90.build());
-
- auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
- config60.setVsyncPeriod(VSYNC_60);
- configs.push_back(config60.build());
-
- mRefreshRateConfigs.populate(configs);
+ init({{CONFIG_ID_90, VSYNC_90}, {CONFIG_ID_60, VSYNC_60}});
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
- std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
- EXPECT_EQ(3, times.size());
+ std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(1, times.size());
EXPECT_NE(0u, times.count("ScreenOff"));
- EXPECT_EQ(1u, times.count("60fps"));
- EXPECT_EQ(0, times["60fps"]);
- EXPECT_EQ(1u, times.count("90fps"));
- EXPECT_EQ(0, times["90fps"]);
// Setting up tests on mobile harness can be flaky with time passing, so testing for
// exact time changes can result in flaxy numbers. To avoid that remember old
// numbers to make sure the correct values are increasing in the next test.
int screenOff = times["ScreenOff"];
- int sixty = times["60fps"];
- int ninety = times["90fps"];
// Screen is off by default.
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
- EXPECT_EQ(sixty, times["60fps"]);
- EXPECT_EQ(ninety, times["90fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
- screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
- EXPECT_EQ(sixty, times["60fps"]);
- EXPECT_LT(ninety, times["90fps"]);
+ ASSERT_EQ(1u, times.count("90fps"));
+ EXPECT_LT(0, times["90fps"]);
// When power mode is normal, time for configs updates.
- mRefreshRateStats.setConfigMode(CONFIG_ID_60);
- ninety = mRefreshRateStats.getTotalTimes()["90fps"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+ int ninety = mRefreshRateStats->getTotalTimes()["90fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
- EXPECT_LT(sixty, times["60fps"]);
+ ASSERT_EQ(1u, times.count("60fps"));
+ EXPECT_LT(0, times["60fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- sixty = mRefreshRateStats.getTotalTimes()["60fps"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ int sixty = mRefreshRateStats->getTotalTimes()["60fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
EXPECT_LT(ninety, times["90fps"]);
EXPECT_EQ(sixty, times["60fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_60);
- ninety = mRefreshRateStats.getTotalTimes()["90fps"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+ ninety = mRefreshRateStats->getTotalTimes()["90fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
EXPECT_LT(sixty, times["60fps"]);
// Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
// does not update refresh rates that come from the config.
- mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- sixty = mRefreshRateStats.getTotalTimes()["60fps"];
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ sixty = mRefreshRateStats->getTotalTimes()["60fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
EXPECT_EQ(sixty, times["60fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_60);
- screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+ screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
EXPECT_EQ(sixty, times["60fps"]);
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 740115ea32..571fdfd9fc 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -3,13 +3,13 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-
#include <log/log.h>
#include <mutex>
#include "Scheduler/EventControlThread.h"
#include "Scheduler/EventThread.h"
+#include "Scheduler/RefreshRateConfigs.h"
#include "Scheduler/Scheduler.h"
#include "mock/MockEventThread.h"
@@ -34,7 +34,7 @@ protected:
MOCK_METHOD0(requestNextVsync, void());
};
- scheduler::RefreshRateConfigs mRefreshRateConfigs;
+ std::unique_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
/**
* This mock Scheduler class uses implementation of mock::EventThread but keeps everything else
@@ -73,9 +73,14 @@ SchedulerTest::SchedulerTest() {
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+ std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{{/*hwcId=*/0, 16666667}};
+ mRefreshRateConfigs =
+ std::make_unique<scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs,
+ /*currentConfig=*/0);
+
std::unique_ptr<mock::EventThread> eventThread = std::make_unique<mock::EventThread>();
mEventThread = eventThread.get();
- mScheduler = std::make_unique<MockScheduler>(mRefreshRateConfigs, std::move(eventThread));
+ mScheduler = std::make_unique<MockScheduler>(*mRefreshRateConfigs, std::move(eventThread));
EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
mEventThreadConnection = new MockEventThreadConnection(mEventThread);
@@ -85,7 +90,7 @@ SchedulerTest::SchedulerTest() {
EXPECT_CALL(*mEventThread, createEventConnection(_, _))
.WillRepeatedly(Return(mEventThreadConnection));
- mConnectionHandle = mScheduler->createConnection("appConnection", 16, 16, ResyncCallback(),
+ mConnectionHandle = mScheduler->createConnection("appConnection", 16, 16,
impl::EventThread::InterceptVSyncsCallback());
EXPECT_TRUE(mConnectionHandle != nullptr);
}
@@ -107,7 +112,7 @@ TEST_F(SchedulerTest, testNullPtr) {
sp<IDisplayEventConnection> returnedValue;
ASSERT_NO_FATAL_FAILURE(
returnedValue =
- mScheduler->createDisplayEventConnection(nullptr, ResyncCallback(),
+ mScheduler->createDisplayEventConnection(nullptr,
ISurfaceComposer::
eConfigChangedSuppress));
EXPECT_TRUE(returnedValue == nullptr);
@@ -130,7 +135,7 @@ TEST_F(SchedulerTest, invalidConnectionHandle) {
sp<IDisplayEventConnection> returnedValue;
ASSERT_NO_FATAL_FAILURE(
returnedValue =
- mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback(),
+ mScheduler->createDisplayEventConnection(connectionHandle,
ISurfaceComposer::
eConfigChangedSuppress));
EXPECT_TRUE(returnedValue == nullptr);
@@ -161,7 +166,7 @@ TEST_F(SchedulerTest, validConnectionHandle) {
sp<IDisplayEventConnection> returnedValue;
ASSERT_NO_FATAL_FAILURE(
returnedValue =
- mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback(),
+ mScheduler->createDisplayEventConnection(mConnectionHandle,
ISurfaceComposer::
eConfigChangedSuppress));
EXPECT_TRUE(returnedValue != nullptr);
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 64d34ee102..1c1b0201d9 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -32,11 +32,11 @@
#include "Layer.h"
#include "NativeWindowSurface.h"
#include "Scheduler/MessageQueue.h"
+#include "Scheduler/RefreshRateConfigs.h"
#include "StartPropertySetThread.h"
#include "SurfaceFlinger.h"
#include "SurfaceFlingerFactory.h"
#include "SurfaceInterceptor.h"
-
#include "TimeStats/TimeStats.h"
namespace android {
@@ -342,6 +342,8 @@ public:
auto& mutableAppConnectionHandle() { return mFlinger->mAppConnectionHandle; }
auto& mutableSfConnectionHandle() { return mFlinger->mSfConnectionHandle; }
auto& mutableRefreshRateConfigs() { return mFlinger->mRefreshRateConfigs; }
+ auto& mutableRefreshRateStats() { return mFlinger->mRefreshRateStats; }
+ auto& mutableTimeStats() { return mFlinger->mTimeStats; }
~TestableSurfaceFlinger() {
// All these pointer and container clears help ensure that GMock does
diff --git a/services/surfaceflinger/version-script32.txt b/services/surfaceflinger/version-script32.txt
new file mode 100644
index 0000000000..2340785c42
--- /dev/null
+++ b/services/surfaceflinger/version-script32.txt
@@ -0,0 +1,12 @@
+{
+global:
+ EnsureFrontOfChain;
+ AddSpecialSignalHandlerFn;
+ RemoveSpecialSignalHandlerFn;
+ bsd_signal;
+ sigaction;
+ signal;
+ sigprocmask;
+local:
+ *;
+};
diff --git a/services/surfaceflinger/version-script64.txt b/services/surfaceflinger/version-script64.txt
new file mode 100644
index 0000000000..acf36309ea
--- /dev/null
+++ b/services/surfaceflinger/version-script64.txt
@@ -0,0 +1,11 @@
+{
+global:
+ EnsureFrontOfChain;
+ AddSpecialSignalHandlerFn;
+ RemoveSpecialSignalHandlerFn;
+ sigaction;
+ signal;
+ sigprocmask;
+local:
+ *;
+};
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index c202b5c07c..4c34b938c8 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -1,151 +1,180 @@
cc_library_shared {
- name: "libvr_hwc-hal",
-
- srcs: [
- "impl/vr_hwc.cpp",
- "impl/vr_composer_client.cpp",
- ],
-
- static_libs: [
- "libbroadcastring",
- "libdisplay",
- ],
-
- shared_libs: [
- "android.frameworks.vr.composer@1.0",
- "android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
- "libbase",
- "libbufferhubqueue",
- "libbinder",
- "libcutils",
- "libfmq",
- "libhardware",
- "libhidlbase",
- "liblog",
- "libsync",
- "libui",
- "libutils",
- "libpdx_default_transport",
- ],
-
- header_libs: [
- "android.hardware.graphics.composer@2.1-command-buffer",
- "android.hardware.graphics.composer@2.1-hal",
- ],
-
- export_header_lib_headers: [
- "android.hardware.graphics.composer@2.1-hal",
- ],
-
- export_static_lib_headers: [
- "libdisplay",
- ],
-
- export_shared_lib_headers: [
- "android.frameworks.vr.composer@1.0",
- "android.hardware.graphics.composer@2.1",
- ],
-
- export_include_dirs: ["."],
-
- cflags: [
- "-DLOG_TAG=\"vr_hwc\"",
- "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
- "-Wall",
- "-Werror",
- "-Wno-error=unused-private-field",
- // Warnings in vr_hwc.cpp to be fixed after sync of goog/master.
- "-Wno-sign-compare",
- "-Wno-unused-parameter",
- ],
+ name: "libvr_hwc-hal",
+ srcs: [
+ "impl/vr_hwc.cpp",
+ "impl/vr_composer_client.cpp",
+ ],
+
+ static_libs: [
+ "libbroadcastring",
+ "libdisplay",
+ ],
+
+ shared_libs: [
+ "android.frameworks.vr.composer@1.0",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "libbase",
+ "libbufferhubqueue",
+ "libbinder",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libsync",
+ "libui",
+ "libutils",
+ "libpdx_default_transport",
+ ],
+
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.1-hal",
+ ],
+
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.1-hal",
+ ],
+
+ export_static_lib_headers: [
+ "libdisplay",
+ ],
+
+ export_shared_lib_headers: [
+ "android.frameworks.vr.composer@1.0",
+ "android.hardware.graphics.composer@2.1",
+ ],
+
+ export_include_dirs: ["."],
+
+ cflags: [
+ "-DLOG_TAG=\"vr_hwc\"",
+ "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+ "-Wall",
+ "-Werror",
+ "-Wno-error=unused-private-field",
+ // Warnings in vr_hwc.cpp to be fixed after sync of goog/master.
+ "-Wno-sign-compare",
+ "-Wno-unused-parameter",
+ ],
+
+}
+
+cc_library_static {
+ name: "libvr_hwc-binder",
+ srcs: [
+ "aidl/android/dvr/IVrComposer.aidl",
+ "aidl/android/dvr/IVrComposerCallback.aidl",
+ "aidl/android/dvr/parcelable_composer_frame.cpp",
+ "aidl/android/dvr/parcelable_composer_layer.cpp",
+ "aidl/android/dvr/parcelable_unique_fd.cpp",
+ ],
+ aidl: {
+ include_dirs: ["frameworks/native/services/vr/hardware_composer/aidl"],
+ export_aidl_headers: true,
+ },
+ export_include_dirs: ["aidl"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libui",
+ "libutils",
+ "libvr_hwc-hal",
+ ],
}
cc_library_static {
- name: "libvr_hwc-impl",
- srcs: [
- "vr_composer.cpp",
- ],
- static_libs: [
- "libvr_hwc-binder",
- ],
- shared_libs: [
- "libbase",
- "libbinder",
- "liblog",
- "libui",
- "libutils",
- "libvr_hwc-hal",
- ],
- export_shared_lib_headers: [
- "libvr_hwc-hal",
- ],
- cflags: [
- "-DLOG_TAG=\"vr_hwc\"",
- "-Wall",
- "-Werror",
- ],
+ name: "libvr_hwc-impl",
+ srcs: [
+ "vr_composer.cpp",
+ ],
+ static_libs: [
+ "libvr_hwc-binder",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libui",
+ "libutils",
+ "libvr_hwc-hal",
+ ],
+ export_shared_lib_headers: [
+ "libvr_hwc-hal",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"vr_hwc\"",
+ "-Wall",
+ "-Werror",
+ ],
}
cc_binary {
- name: "vr_hwc",
- vintf_fragments: ["manifest_vr_hwc.xml"],
- srcs: [
- "vr_hardware_composer_service.cpp",
- ],
- static_libs: [
- "libvr_hwc-impl",
- // NOTE: This needs to be included after the *-impl lib otherwise the
- // symbols in the *-binder library get optimized out.
- "libvr_hwc-binder",
- ],
- shared_libs: [
- "android.frameworks.vr.composer@1.0",
- "android.hardware.graphics.composer@2.1",
- "libbase",
- "libbinder",
- "liblog",
- "libhardware",
- "libhidlbase",
- "libui",
- "libutils",
- "libvr_hwc-hal",
- ],
- cflags: [
- "-DLOG_TAG=\"vr_hwc\"",
- "-Wall",
- "-Werror",
- ],
- init_rc: [
- "vr_hwc.rc",
- ],
+ name: "vr_hwc",
+ vintf_fragments: ["manifest_vr_hwc.xml"],
+ srcs: [
+ "vr_hardware_composer_service.cpp"
+ ],
+ static_libs: [
+ "libvr_hwc-impl",
+ // NOTE: This needs to be included after the *-impl lib otherwise the
+ // symbols in the *-binder library get optimized out.
+ "libvr_hwc-binder",
+ ],
+ shared_libs: [
+ "android.frameworks.vr.composer@1.0",
+ "android.hardware.graphics.composer@2.1",
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libhardware",
+ "libhidlbase",
+ "libui",
+ "libutils",
+ "libvr_hwc-hal",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"vr_hwc\"",
+ "-Wall",
+ "-Werror",
+ ],
+ init_rc: [
+ "vr_hwc.rc",
+ ],
}
cc_test {
- name: "vr_hwc_test",
- gtest: true,
- srcs: ["tests/vr_composer_test.cpp"],
- static_libs: [
- "libgtest",
- "libvr_hwc-impl",
- // NOTE: This needs to be included after the *-impl lib otherwise the
- // symbols in the *-binder library get optimized out.
- "libvr_hwc-binder",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- // warnings in vr_composer_test.cpp to be fixed after merge of goog/master
- "-Wno-sign-compare",
- "-Wno-unused-parameter",
- ],
- shared_libs: [
- "libbase",
- "libbinder",
- "liblog",
- "libui",
- "libutils",
- ],
+ name: "vr_hwc_test",
+ gtest: true,
+ srcs: ["tests/vr_composer_test.cpp"],
+ static_libs: [
+ "libgtest",
+ "libvr_hwc-impl",
+ // NOTE: This needs to be included after the *-impl lib otherwise the
+ // symbols in the *-binder library get optimized out.
+ "libvr_hwc-binder",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ // warnings in vr_composer_test.cpp to be fixed after merge of goog/master
+ "-Wno-sign-compare",
+ "-Wno-unused-parameter",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libui",
+ "libutils",
+ ],
}
diff --git a/services/vr/hardware_composer/aidl/Android.bp b/services/vr/hardware_composer/aidl/Android.bp
deleted file mode 100644
index a1d5392071..0000000000
--- a/services/vr/hardware_composer/aidl/Android.bp
+++ /dev/null
@@ -1,27 +0,0 @@
-cc_library_static {
- name: "libvr_hwc-binder",
- srcs: [
- "android/dvr/IVrComposer.aidl",
- "android/dvr/IVrComposerCallback.aidl",
- "android/dvr/parcelable_composer_frame.cpp",
- "android/dvr/parcelable_composer_layer.cpp",
- "android/dvr/parcelable_unique_fd.cpp",
- ],
- aidl: {
- local_include_dirs: ["."],
- export_aidl_headers: true,
- },
- export_include_dirs: ["."],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- shared_libs: [
- "libbinder",
- "libui",
- "libutils",
- "libvr_hwc-hal",
- ],
-}
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index dcaa663160..131a306c08 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -62,7 +62,7 @@ cc_test {
service_src = [
"main.cpp",
"VirtualTouchpadService.cpp",
- ":virtualtouchpad_aidl",
+ "aidl/android/dvr/IVirtualTouchpadService.aidl",
]
service_static_libs = [
@@ -99,7 +99,7 @@ cc_binary {
client_src = [
"VirtualTouchpadClient.cpp",
"DvrVirtualTouchpadClient.cpp",
- ":virtualtouchpad_aidl",
+ "aidl/android/dvr/IVirtualTouchpadService.aidl",
]
client_shared_libs = [
@@ -122,9 +122,3 @@ cc_library {
name: "libvirtualtouchpadclient",
export_include_dirs: ["include"],
}
-
-filegroup {
- name: "virtualtouchpad_aidl",
- srcs: ["aidl/android/dvr/IVirtualTouchpadService.aidl"],
- path: "aidl",
-}
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 4d6b2be301..993b751747 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -41,13 +41,11 @@ cc_library_shared {
"-DVK_NO_PROTOTYPES",
"-fvisibility=hidden",
"-fstrict-aliasing",
- "-Wextra",
+ "-Weverything",
"-Werror",
"-Wno-padded",
- "-Wno-sign-compare",
"-Wno-switch-enum",
- "-Wno-unused-variable",
- "-Wno-unused-function",
+ "-Wno-undef",
// Have clang emit complete debug_info.
"-fstandalone-debug",
@@ -89,6 +87,7 @@ cc_library_shared {
"libbase",
"libdl_android",
"libhidlbase",
+ "libhidltransport",
"liblog",
"libui",
"libgraphicsenv",
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 3d56656896..c3b5523b9e 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -124,7 +124,7 @@ class OverrideLayerNames {
};
void AddImplicitLayers() {
- if (!is_instance_ || !driver::Debuggable())
+ if (!is_instance_)
return;
GetLayersFromSettings();
@@ -370,7 +370,8 @@ class OverrideExtensionNames {
private:
bool EnableDebugCallback() const {
- return (is_instance_ && driver::Debuggable() &&
+ return (is_instance_ &&
+ android::GraphicsEnv::getInstance().isDebuggable() &&
property_get_bool("debug.vulkan.enable_callback", false));
}
@@ -519,11 +520,7 @@ LayerChain::LayerChain(bool is_instance,
get_device_proc_addr_(nullptr),
driver_extensions_(nullptr),
driver_extension_count_(0) {
- // advertise the loader supported core Vulkan API version at vulkan::api
- for (uint32_t i = driver::ProcHook::EXTENSION_CORE_1_0;
- i != driver::ProcHook::EXTENSION_COUNT; ++i) {
- enabled_extensions_.set(i);
- }
+ enabled_extensions_.set(driver::ProcHook::EXTENSION_CORE);
}
LayerChain::~LayerChain() {
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index a5a0405f2d..bdd3573b11 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -765,19 +765,6 @@ VK_KHR_bind_memory2
{{end}}
-
-{{/*
-------------------------------------------------------------------------------
- Emits the ProcHook enum for core Vulkan API verions.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.GetProcHookEnum"}}
- {{if GetAnnotation $ "vulkan1_1"}}ProcHook::EXTENSION_CORE_1_1
- {{else}}ProcHook::EXTENSION_CORE_1_0
- {{end}}
-{{end}}
-
-
{{/*
------------------------------------------------------------------------------
Emits true if a function needs a ProcHook stub.
@@ -791,8 +778,6 @@ VK_KHR_bind_memory2
{{if $ext}}
{{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
{{end}}
-
- {{if GetAnnotation $ "vulkan1_1"}}true{{end}}
{{end}}
{{end}}
@@ -816,8 +801,7 @@ VK_KHR_bind_memory2
{{TrimPrefix "VK_" $e}},
{{end}}
- EXTENSION_CORE_1_0,
- EXTENSION_CORE_1_1,
+ EXTENSION_CORE, // valid bit
EXTENSION_COUNT,
EXTENSION_UNKNOWN,
};
@@ -854,21 +838,14 @@ VK_KHR_bind_memory2
{{AssertType $ "Function"}}
{{if (Macro "driver.NeedProcHookStub" $)}}
- {{$ext_name := Strings ("")}}
- {{$ext_hook := Strings ("")}}
{{$ext := GetAnnotation $ "extension"}}
- {{if $ext}}
- {{$ext_name = index $ext.Arguments 0}}
- {{$ext_hook = Strings ("ProcHook::") (Macro "BaseName" $ext)}}
- {{else}}
- {{$ext_name = Strings ("VK_VERSION_1_0")}}
- {{$ext_hook = (Macro "driver.GetProcHookEnum" $)}}
- {{end}}
+ {{$ext_name := index $ext.Arguments 0}}
{{$base := (Macro "BaseName" $)}}
VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
{{$p0 := index $.CallParameters 0}}
+ {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
{{if not (IsVoid $.Return.Type)}}return §{{end}}
@@ -901,7 +878,7 @@ VK_KHR_bind_memory2
{
"{{$.Name}}",
ProcHook::GLOBAL,
- {{Macro "driver.GetProcHookEnum" $}},
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
nullptr,
},
@@ -934,7 +911,7 @@ VK_KHR_bind_memory2
nullptr,
{{end}}
{{else}}
- {{Macro "driver.GetProcHookEnum" $}},
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
nullptr,
{{end}}
@@ -957,23 +934,18 @@ VK_KHR_bind_memory2
ProcHook::DEVICE,
{{$ext := GetAnnotation $ "extension"}}
- {{if or $ext (GetAnnotation $ "vulkan1_1")}}
- {{if $ext}}
- ProcHook::{{Macro "BaseName" $ext}},
- {{if Macro "IsExtensionInternal" $ext}}
- nullptr,
- nullptr,
- {{else}}
- reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
- reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
- {{end}}
+ {{if $ext}}
+ ProcHook::{{Macro "BaseName" $ext}},
+
+ {{if (Macro "IsExtensionInternal" $ext)}}
+ nullptr,
+ nullptr,
{{else}}
- {{Macro "driver.GetProcHookEnum" $}},
reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
{{end}}
{{else}}
- {{Macro "driver.GetProcHookEnum" $}},
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
nullptr,
{{end}}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 74773517ae..8ea09805ae 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -24,10 +24,7 @@
#include <dlfcn.h>
#include <algorithm>
#include <array>
-#include <climits>
#include <new>
-#include <sstream>
-#include <string>
#include <log/log.h>
@@ -107,7 +104,6 @@ class CreateInfoWrapper {
VkResult Validate();
void DowngradeApiVersion();
- void UpgradeDeviceCoreApiVersion(uint32_t api_version);
const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
@@ -156,12 +152,15 @@ class CreateInfoWrapper {
Hal Hal::hal_;
void* LoadLibrary(const android_dlextinfo& dlextinfo,
- const std::string_view subname) {
+ const char* subname,
+ int subname_len) {
ATRACE_CALL();
- std::stringstream ss;
- ss << "vulkan." << subname << ".so";
- return android_dlopen_ext(ss.str().c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ const char kLibFormat[] = "vulkan.%*s.so";
+ char* name = static_cast<char*>(
+ alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
+ sprintf(name, kLibFormat, subname_len, subname);
+ return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
}
const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
@@ -181,9 +180,8 @@ int LoadDriver(android_namespace_t* library_namespace,
char prop[PROPERTY_VALUE_MAX];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
int prop_len = property_get(key, prop, nullptr);
- if (prop_len > 0 && prop_len <= UINT_MAX) {
- std::string_view lib_name(prop, static_cast<unsigned int>(prop_len));
- so = LoadLibrary(dlextinfo, lib_name);
+ if (prop_len > 0) {
+ so = LoadLibrary(dlextinfo, prop, prop_len);
if (so)
break;
}
@@ -335,12 +333,8 @@ CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
physical_dev_(VK_NULL_HANDLE),
instance_info_(create_info),
extension_filter_() {
- // instance core versions need to match the loader api version
- for (uint32_t i = ProcHook::EXTENSION_CORE_1_0;
- i != ProcHook::EXTENSION_COUNT; ++i) {
- hook_extensions_.set(i);
- hal_extensions_.set(i);
- }
+ hook_extensions_.set(ProcHook::EXTENSION_CORE);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE);
}
CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
@@ -351,9 +345,8 @@ CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
physical_dev_(physical_dev),
dev_info_(create_info),
extension_filter_() {
- // initialize with baseline core API version
- hook_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
- hal_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
+ hook_extensions_.set(ProcHook::EXTENSION_CORE);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE);
}
CreateInfoWrapper::~CreateInfoWrapper() {
@@ -552,8 +545,7 @@ void CreateInfoWrapper::FilterExtension(const char* name) {
case ProcHook::ANDROID_external_memory_android_hardware_buffer:
case ProcHook::ANDROID_native_buffer:
case ProcHook::GOOGLE_display_timing:
- case ProcHook::EXTENSION_CORE_1_0:
- case ProcHook::EXTENSION_CORE_1_1:
+ case ProcHook::EXTENSION_CORE:
case ProcHook::EXTENSION_COUNT:
// Device and meta extensions. If we ever get here it's a bug in
// our code. But enumerating them lets us avoid having a default
@@ -601,8 +593,7 @@ void CreateInfoWrapper::FilterExtension(const char* name) {
case ProcHook::EXT_debug_report:
case ProcHook::EXT_swapchain_colorspace:
case ProcHook::ANDROID_native_buffer:
- case ProcHook::EXTENSION_CORE_1_0:
- case ProcHook::EXTENSION_CORE_1_1:
+ case ProcHook::EXTENSION_CORE:
case ProcHook::EXTENSION_COUNT:
// Instance and meta extensions. If we ever get here it's a bug
// in our code. But enumerating them lets us avoid having a
@@ -650,28 +641,6 @@ void CreateInfoWrapper::DowngradeApiVersion() {
}
}
-void CreateInfoWrapper::UpgradeDeviceCoreApiVersion(uint32_t api_version) {
- ALOG_ASSERT(!is_instance_, "Device only API called by instance wrapper.");
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wold-style-cast"
- api_version ^= VK_VERSION_PATCH(api_version);
-#pragma clang diagnostic pop
- // cap the API version to the loader supported highest version
- if (api_version > VK_API_VERSION_1_1)
- api_version = VK_API_VERSION_1_1;
- switch (api_version) {
- case VK_API_VERSION_1_1:
- hook_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
- hal_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
- [[clang::fallthrough]];
- case VK_API_VERSION_1_0:
- break;
- default:
- ALOGD("Unknown upgrade API version[%u]", api_version);
- break;
- }
-}
-
VKAPI_ATTR void* DefaultAllocate(void*,
size_t size,
size_t alignment,
@@ -755,10 +724,6 @@ void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
} // anonymous namespace
-bool Debuggable() {
- return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
-}
-
bool OpenHAL() {
return Hal::Open();
}
@@ -807,7 +772,7 @@ PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
: nullptr;
break;
case ProcHook::DEVICE:
- proc = (hook->extension == ProcHook::EXTENSION_CORE_1_0)
+ proc = (hook->extension == ProcHook::EXTENSION_CORE)
? hook->proc
: hook->checked_proc;
break;
@@ -1155,13 +1120,6 @@ VkResult CreateDevice(VkPhysicalDevice physicalDevice,
if (!data)
return VK_ERROR_OUT_OF_HOST_MEMORY;
- VkPhysicalDeviceProperties properties;
- ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
- instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
- &properties);
- ATRACE_END();
-
- wrapper.UpgradeDeviceCoreApiVersion(properties.apiVersion);
data->hook_extensions |= wrapper.GetHookExtensions();
// call into the driver
@@ -1206,6 +1164,12 @@ VkResult CreateDevice(VkPhysicalDevice physicalDevice,
return VK_ERROR_INCOMPATIBLE_DRIVER;
}
+ VkPhysicalDeviceProperties properties;
+ ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
+ instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
+ &properties);
+ ATRACE_END();
+
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
// Log that the app is hitting software Vulkan implementation
android::GraphicsEnv::getInstance().setTargetStats(
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index 047a27adc9..075a15b31a 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -67,7 +67,9 @@ struct InstanceData {
: opaque_api_data(),
allocator(alloc),
driver(),
- get_device_proc_addr(nullptr) {}
+ get_device_proc_addr(nullptr) {
+ hook_extensions.set(ProcHook::EXTENSION_CORE);
+ }
api::InstanceData opaque_api_data;
@@ -87,7 +89,9 @@ struct DeviceData {
: opaque_api_data(),
allocator(alloc),
debug_report_callbacks(debug_report_callbacks_),
- driver() {}
+ driver() {
+ hook_extensions.set(ProcHook::EXTENSION_CORE);
+ }
api::DeviceData opaque_api_data;
@@ -101,7 +105,6 @@ struct DeviceData {
uint32_t driver_version;
};
-bool Debuggable();
bool OpenHAL();
const VkAllocationCallbacks& GetDefaultAllocator();
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index aa31735eef..574c3273d0 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -31,23 +31,6 @@ namespace {
// clang-format off
-VKAPI_ATTR VkResult checkedBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
- if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
- return BindImageMemory2(device, bindInfoCount, pBindInfos);
- } else {
- Logger(device).Err(device, "VK_VERSION_1_0 not enabled. vkBindImageMemory2 not executed.");
- return VK_SUCCESS;
- }
-}
-
-VKAPI_ATTR void checkedGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
- if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
- GetDeviceQueue2(device, pQueueInfo, pQueue);
- } else {
- Logger(device).Err(device, "VK_VERSION_1_0 not enabled. vkGetDeviceQueue2 not executed.");
- }
-}
-
VKAPI_ATTR VkResult checkedCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) {
if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
return CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
@@ -191,16 +174,16 @@ const ProcHook g_proc_hooks[] = {
{
"vkAllocateCommandBuffers",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers),
nullptr,
},
{
"vkBindImageMemory2",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE_1_1,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2),
- reinterpret_cast<PFN_vkVoidFunction>(checkedBindImageMemory2),
+ nullptr,
},
{
"vkBindImageMemory2KHR",
@@ -226,14 +209,14 @@ const ProcHook g_proc_hooks[] = {
{
"vkCreateDevice",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(CreateDevice),
nullptr,
},
{
"vkCreateInstance",
ProcHook::GLOBAL,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(CreateInstance),
nullptr,
},
@@ -261,14 +244,14 @@ const ProcHook g_proc_hooks[] = {
{
"vkDestroyDevice",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice),
nullptr,
},
{
"vkDestroyInstance",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance),
nullptr,
},
@@ -289,28 +272,28 @@ const ProcHook g_proc_hooks[] = {
{
"vkEnumerateDeviceExtensionProperties",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties),
nullptr,
},
{
"vkEnumerateInstanceExtensionProperties",
ProcHook::GLOBAL,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties),
nullptr,
},
{
"vkEnumeratePhysicalDeviceGroups",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE_1_1,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroups),
nullptr,
},
{
"vkEnumeratePhysicalDevices",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices),
nullptr,
},
@@ -331,28 +314,28 @@ const ProcHook g_proc_hooks[] = {
{
"vkGetDeviceProcAddr",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr),
nullptr,
},
{
"vkGetDeviceQueue",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue),
nullptr,
},
{
"vkGetDeviceQueue2",
ProcHook::DEVICE,
- ProcHook::EXTENSION_CORE_1_1,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2),
- reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceQueue2),
+ nullptr,
},
{
"vkGetInstanceProcAddr",
ProcHook::INSTANCE,
- ProcHook::EXTENSION_CORE_1_0,
+ ProcHook::EXTENSION_CORE,
reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr),
nullptr,
},
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 831efb7026..3faf6c0e32 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -48,8 +48,7 @@ struct ProcHook {
ANDROID_external_memory_android_hardware_buffer,
KHR_bind_memory2,
- EXTENSION_CORE_1_0,
- EXTENSION_CORE_1_1,
+ EXTENSION_CORE, // valid bit
EXTENSION_COUNT,
EXTENSION_UNKNOWN,
};
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index dd917393d1..691f3b0f52 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -24,7 +24,6 @@
#include <string.h>
#include <sys/prctl.h>
-#include <memory>
#include <mutex>
#include <string>
#include <vector>
@@ -102,7 +101,9 @@ class LayerLibrary {
bool EnumerateLayers(size_t library_idx,
std::vector<Layer>& instance_layers) const;
- void* GetGPA(const Layer& layer, const std::string_view gpa_name) const;
+ void* GetGPA(const Layer& layer,
+ const char* gpa_name,
+ size_t gpa_name_len) const;
const std::string GetFilename() { return filename_; }
@@ -225,10 +226,17 @@ bool LayerLibrary::EnumerateLayers(size_t library_idx,
}
// get layer properties
- auto properties = std::make_unique<VkLayerProperties[]>(num_instance_layers + num_device_layers);
+ VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
+ (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
+ result = enumerate_instance_layers(&num_instance_layers, properties);
+ if (result != VK_SUCCESS) {
+ ALOGE("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
+ path_.c_str(), result);
+ return false;
+ }
if (num_device_layers > 0) {
result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
- properties.get() + num_instance_layers);
+ properties + num_instance_layers);
if (result != VK_SUCCESS) {
ALOGE(
"vkEnumerateDeviceLayerProperties failed for library '%s': %d",
@@ -313,11 +321,21 @@ bool LayerLibrary::EnumerateLayers(size_t library_idx,
return true;
}
-void* LayerLibrary::GetGPA(const Layer& layer, const std::string_view gpa_name) const {
- std::string layer_name { layer.properties.layerName };
- if (void* gpa = GetTrampoline((layer_name.append(gpa_name).c_str())))
- return gpa;
- return GetTrampoline((std::string {"vk"}.append(gpa_name)).c_str());
+void* LayerLibrary::GetGPA(const Layer& layer,
+ const char* gpa_name,
+ size_t gpa_name_len) const {
+ void* gpa;
+ size_t layer_name_len =
+ std::max(size_t{2}, strlen(layer.properties.layerName));
+ char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
+ strcpy(name, layer.properties.layerName);
+ strcpy(name + layer_name_len, gpa_name);
+ if (!(gpa = GetTrampoline(name))) {
+ strcpy(name, "vk");
+ strcpy(name + 2, gpa_name);
+ gpa = GetTrampoline(name);
+ }
+ return gpa;
}
// ----------------------------------------------------------------------------
@@ -370,8 +388,9 @@ void ForEachFileInZip(const std::string& zipname,
return;
}
std::string prefix(dir_in_zip + "/");
+ const ZipString prefix_str(prefix.c_str());
void* iter_cookie = nullptr;
- if ((err = StartIteration(zip, &iter_cookie, prefix, "")) != 0) {
+ if ((err = StartIteration(zip, &iter_cookie, &prefix_str, nullptr)) != 0) {
ALOGE("failed to iterate entries in apk '%s': %d", zipname.c_str(),
err);
CloseArchive(zip);
@@ -380,9 +399,11 @@ void ForEachFileInZip(const std::string& zipname,
ALOGD("searching for layers in '%s!/%s'", zipname.c_str(),
dir_in_zip.c_str());
ZipEntry entry;
- std::string name;
+ ZipString name;
while (Next(iter_cookie, &entry, &name) == 0) {
- std::string filename(name.substr(prefix.length()));
+ std::string filename(
+ reinterpret_cast<const char*>(name.name) + prefix.length(),
+ name.name_length - prefix.length());
// only enumerate direct entries of the directory, not subdirectories
if (filename.find('/') != filename.npos)
continue;
@@ -452,9 +473,10 @@ const VkExtensionProperties* FindExtension(
}
void* GetLayerGetProcAddr(const Layer& layer,
- const std::string_view gpa_name) {
+ const char* gpa_name,
+ size_t gpa_name_len) {
const LayerLibrary& library = g_layer_libraries[layer.library_idx];
- return library.GetGPA(layer, gpa_name);
+ return library.GetGPA(layer, gpa_name, gpa_name_len);
}
} // anonymous namespace
@@ -462,8 +484,7 @@ void* GetLayerGetProcAddr(const Layer& layer,
void DiscoverLayers() {
ATRACE_CALL();
- if (property_get_bool("ro.debuggable", false) &&
- prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
+ if (android::GraphicsEnv::getInstance().isDebuggable()) {
DiscoverLayersInPathList(kSystemLayerLibraryDir);
}
if (!android::GraphicsEnv::getInstance().getLayerPaths().empty())
@@ -537,13 +558,13 @@ LayerRef::LayerRef(LayerRef&& other) noexcept : layer_(other.layer_) {
PFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
- GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr"))
+ GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
: nullptr;
}
PFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
- GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr"))
+ GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
: nullptr;
}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index fbf6d0d233..a8949d36f4 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -718,6 +718,8 @@ VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev,
{VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
{VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
{VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+ {VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+ {VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
};
const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
uint32_t total_num_formats = kNumFormats;
@@ -1278,7 +1280,6 @@ VkResult CreateSwapchainKHR(VkDevice device,
VkImageCreateInfo image_create = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = &image_native_buffer,
- .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
.imageType = VK_IMAGE_TYPE_2D,
.format = create_info->imageFormat,
.extent = {0, 0, 1},
@@ -1287,6 +1288,7 @@ VkResult CreateSwapchainKHR(VkDevice device,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = create_info->imageUsage,
+ .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
.sharingMode = create_info->imageSharingMode,
.queueFamilyIndexCount = create_info->queueFamilyIndexCount,
.pQueueFamilyIndices = create_info->pQueueFamilyIndices,
@@ -1379,7 +1381,7 @@ void DestroySwapchainKHR(VkDevice device,
bool active = swapchain->surface.swapchain_handle == swapchain_handle;
ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
- if (window && swapchain->frame_timestamps_enabled) {
+ if (swapchain->frame_timestamps_enabled) {
native_window_enable_frame_timestamps(window, false);
}
for (uint32_t i = 0; i < swapchain->num_images; i++)
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
index ba025046fa..dedf419dc3 100644
--- a/vulkan/nulldrv/Android.bp
+++ b/vulkan/nulldrv/Android.bp
@@ -23,11 +23,18 @@ cc_library_shared {
"-fvisibility=hidden",
"-fstrict-aliasing",
"-DLOG_TAG=\"vknulldrv\"",
- "-Wextra",
+ "-Weverything",
"-Werror",
+ "-Wno-padded",
+ "-Wno-undef",
+ "-Wno-zero-length-array",
"-DLOG_NDEBUG=0",
],
+ cppflags: [
+ "-Wno-c++98-compat-pedantic",
+ "-Wno-c99-extensions",
+ ],
srcs: [
"null_driver.cpp",
diff --git a/vulkan/tools/Android.bp b/vulkan/tools/Android.bp
index 91d64fe1c9..2514094a15 100644
--- a/vulkan/tools/Android.bp
+++ b/vulkan/tools/Android.bp
@@ -22,8 +22,16 @@ cc_binary {
"-DLOG_TAG=\"vkinfo\"",
- "-Wextra",
+ "-Weverything",
"-Werror",
+ "-Wno-padded",
+ "-Wno-undef",
+ "-Wno-switch-enum",
+ ],
+ cppflags: [
+ "-Wno-c++98-compat-pedantic",
+ "-Wno-c99-extensions",
+ "-Wno-old-style-cast",
],
srcs: ["vkinfo.cpp"],
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
index f9e4916722..89bc926aa6 100644
--- a/vulkan/tools/vkinfo.cpp
+++ b/vulkan/tools/vkinfo.cpp
@@ -195,10 +195,10 @@ void GatherGpuInfo(VkPhysicalDevice gpu,
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &queue_create_info,
- .enabledLayerCount = (options.validate) ? num_layers : 0,
- .ppEnabledLayerNames = kValidationLayers,
.enabledExtensionCount = num_extensions,
.ppEnabledExtensionNames = extensions,
+ .enabledLayerCount = (options.validate) ? num_layers : 0,
+ .ppEnabledLayerNames = kValidationLayers,
.pEnabledFeatures = &info.features,
};
result = vkCreateDevice(gpu, &create_info, nullptr, &device);
@@ -272,10 +272,10 @@ void GatherInfo(VulkanInfo* info, const Options& options) {
const VkInstanceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &application_info,
- .enabledLayerCount = (options.validate) ? num_layers : 0,
- .ppEnabledLayerNames = kValidationLayers,
.enabledExtensionCount = num_extensions,
.ppEnabledExtensionNames = extensions,
+ .enabledLayerCount = (options.validate) ? num_layers : 0,
+ .ppEnabledLayerNames = kValidationLayers,
};
VkInstance instance;
result = vkCreateInstance(&create_info, nullptr, &instance);