summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dom/media/MediaPermissionGonk.cpp522
-rw-r--r--dom/media/MediaPermissionGonk.h39
-rw-r--r--dom/media/moz.build13
-rw-r--r--dom/media/platforms/gonk/GonkAudioDecoderManager.cpp268
-rw-r--r--dom/media/platforms/gonk/GonkAudioDecoderManager.h59
-rw-r--r--dom/media/platforms/gonk/GonkDecoderModule.cpp63
-rw-r--r--dom/media/platforms/gonk/GonkDecoderModule.h37
-rw-r--r--dom/media/platforms/gonk/GonkMediaDataDecoder.cpp385
-rw-r--r--dom/media/platforms/gonk/GonkMediaDataDecoder.h214
-rw-r--r--dom/media/platforms/gonk/GonkVideoDecoderManager.cpp772
-rw-r--r--dom/media/platforms/gonk/GonkVideoDecoderManager.h149
-rw-r--r--dom/media/platforms/gonk/moz.build39
-rw-r--r--dom/media/platforms/moz.build4
-rw-r--r--dom/secureelement/SEUtils.jsm116
-rw-r--r--dom/secureelement/gonk/ACEService.js139
-rw-r--r--dom/secureelement/gonk/ACEService.manifest2
-rw-r--r--dom/secureelement/gonk/GPAccessRulesManager.js436
-rw-r--r--dom/secureelement/gonk/GPAccessRulesManager.manifest2
-rw-r--r--dom/secureelement/gonk/SecureElement.js514
-rw-r--r--dom/secureelement/gonk/SecureElement.manifest18
-rw-r--r--dom/secureelement/gonk/UiccConnector.js360
-rw-r--r--dom/secureelement/gonk/UiccConnector.manifest17
-rw-r--r--dom/secureelement/gonk/gp_consts.js62
-rw-r--r--dom/secureelement/gonk/nsIAccessControlEnforcer.idl32
-rw-r--r--dom/secureelement/gonk/nsIAccessRulesManager.idl50
-rw-r--r--dom/secureelement/gonk/nsISecureElementConnector.idl124
-rw-r--r--dom/secureelement/gonk/se_consts.js68
-rw-r--r--dom/secureelement/moz.build24
-rw-r--r--dom/system/gonk/AudioChannelManager.cpp181
-rw-r--r--dom/system/gonk/AudioChannelManager.h87
-rw-r--r--dom/system/gonk/AudioManager.cpp1412
-rw-r--r--dom/system/gonk/AudioManager.h180
-rw-r--r--dom/system/gonk/AutoMounter.cpp1496
-rw-r--r--dom/system/gonk/AutoMounter.h101
-rw-r--r--dom/system/gonk/AutoMounterSetting.cpp284
-rw-r--r--dom/system/gonk/AutoMounterSetting.h38
-rw-r--r--dom/system/gonk/DataCallInterfaceService.js276
-rw-r--r--dom/system/gonk/DataCallInterfaceService.manifest6
-rw-r--r--dom/system/gonk/DataCallManager.js1726
-rw-r--r--dom/system/gonk/DataCallManager.manifest4
-rw-r--r--dom/system/gonk/GeolocationUtil.cpp28
-rw-r--r--dom/system/gonk/GeolocationUtil.h13
-rw-r--r--dom/system/gonk/GonkGPSGeolocationProvider.cpp706
-rw-r--r--dom/system/gonk/GonkGPSGeolocationProvider.h103
-rw-r--r--dom/system/gonk/MozMtpCommon.h56
-rw-r--r--dom/system/gonk/MozMtpDatabase.cpp1542
-rw-r--r--dom/system/gonk/MozMtpDatabase.h288
-rw-r--r--dom/system/gonk/MozMtpServer.cpp263
-rw-r--r--dom/system/gonk/MozMtpServer.h61
-rw-r--r--dom/system/gonk/MozMtpStorage.cpp135
-rw-r--r--dom/system/gonk/MozMtpStorage.h47
-rw-r--r--dom/system/gonk/NetIdManager.cpp68
-rw-r--r--dom/system/gonk/NetIdManager.h45
-rw-r--r--dom/system/gonk/NetworkInterfaceListService.js110
-rw-r--r--dom/system/gonk/NetworkInterfaceListService.manifest17
-rw-r--r--dom/system/gonk/NetworkManager.js1219
-rw-r--r--dom/system/gonk/NetworkManager.manifest3
-rw-r--r--dom/system/gonk/NetworkService.js862
-rw-r--r--dom/system/gonk/NetworkService.manifest3
-rw-r--r--dom/system/gonk/NetworkUtils.cpp2973
-rw-r--r--dom/system/gonk/NetworkUtils.h498
-rw-r--r--dom/system/gonk/NetworkWorker.cpp271
-rw-r--r--dom/system/gonk/NetworkWorker.h37
-rw-r--r--dom/system/gonk/OpenFileFinder.cpp251
-rw-r--r--dom/system/gonk/OpenFileFinder.h63
-rw-r--r--dom/system/gonk/RILSystemMessenger.jsm338
-rw-r--r--dom/system/gonk/RILSystemMessengerHelper.js169
-rw-r--r--dom/system/gonk/RILSystemMessengerHelper.manifest6
-rw-r--r--dom/system/gonk/RadioInterfaceLayer.js1324
-rw-r--r--dom/system/gonk/RadioInterfaceLayer.manifest18
-rw-r--r--dom/system/gonk/SystemProperty.cpp98
-rw-r--r--dom/system/gonk/SystemProperty.h39
-rw-r--r--dom/system/gonk/SystemWorkerManager.cpp214
-rw-r--r--dom/system/gonk/SystemWorkerManager.h75
-rw-r--r--dom/system/gonk/TetheringService.js891
-rw-r--r--dom/system/gonk/TetheringService.manifest4
-rw-r--r--dom/system/gonk/TimeZoneSettingObserver.cpp239
-rw-r--r--dom/system/gonk/TimeZoneSettingObserver.h20
-rw-r--r--dom/system/gonk/Volume.cpp596
-rw-r--r--dom/system/gonk/Volume.h157
-rw-r--r--dom/system/gonk/VolumeCommand.cpp85
-rw-r--r--dom/system/gonk/VolumeCommand.h204
-rw-r--r--dom/system/gonk/VolumeManager.cpp591
-rw-r--r--dom/system/gonk/VolumeManager.h192
-rw-r--r--dom/system/gonk/VolumeManagerLog.h27
-rw-r--r--dom/system/gonk/VolumeServiceIOThread.cpp82
-rw-r--r--dom/system/gonk/VolumeServiceIOThread.h49
-rw-r--r--dom/system/gonk/VolumeServiceTest.cpp202
-rw-r--r--dom/system/gonk/VolumeServiceTest.h19
-rw-r--r--dom/system/gonk/android_audio/AudioSystem.h1134
-rw-r--r--dom/system/gonk/android_audio/AudioTrack.h489
-rw-r--r--dom/system/gonk/android_audio/EffectApi.h798
-rw-r--r--dom/system/gonk/android_audio/IAudioFlinger.h184
-rw-r--r--dom/system/gonk/android_audio/IAudioFlingerClient.h55
-rw-r--r--dom/system/gonk/android_audio/IAudioRecord.h68
-rw-r--r--dom/system/gonk/android_audio/IAudioTrack.h89
-rw-r--r--dom/system/gonk/android_audio/IEffect.h60
-rw-r--r--dom/system/gonk/android_audio/IEffectClient.h54
-rw-r--r--dom/system/gonk/moz.build107
-rw-r--r--dom/system/gonk/mozstumbler/MozStumbler.cpp426
-rw-r--r--dom/system/gonk/mozstumbler/MozStumbler.h47
-rw-r--r--dom/system/gonk/mozstumbler/StumblerLogging.cpp13
-rw-r--r--dom/system/gonk/mozstumbler/StumblerLogging.h18
-rw-r--r--dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp151
-rw-r--r--dom/system/gonk/mozstumbler/UploadStumbleRunnable.h46
-rw-r--r--dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp321
-rw-r--r--dom/system/gonk/mozstumbler/WriteStumbleOnThread.h91
-rw-r--r--dom/system/gonk/nsIAudioManager.idl58
-rw-r--r--dom/system/gonk/nsIDataCallInterfaceService.idl268
-rw-r--r--dom/system/gonk/nsIDataCallManager.idl81
-rw-r--r--dom/system/gonk/nsIGonkDataCallInterfaceService.idl18
-rw-r--r--dom/system/gonk/nsINetworkInterface.idl108
-rw-r--r--dom/system/gonk/nsINetworkInterfaceListService.idl40
-rw-r--r--dom/system/gonk/nsINetworkManager.idl135
-rw-r--r--dom/system/gonk/nsINetworkService.idl619
-rw-r--r--dom/system/gonk/nsINetworkWorker.idl18
-rw-r--r--dom/system/gonk/nsIRadioInterfaceLayer.idl53
-rw-r--r--dom/system/gonk/nsISystemWorkerManager.idl16
-rw-r--r--dom/system/gonk/nsITetheringService.idl39
-rw-r--r--dom/system/gonk/nsIVolume.idl114
-rw-r--r--dom/system/gonk/nsIVolumeMountLock.idl12
-rw-r--r--dom/system/gonk/nsIVolumeService.idl36
-rw-r--r--dom/system/gonk/nsIVolumeStat.idl12
-rw-r--r--dom/system/gonk/nsIWorkerHolder.idl11
-rw-r--r--dom/system/gonk/nsVolume.cpp467
-rw-r--r--dom/system/gonk/nsVolume.h114
-rw-r--r--dom/system/gonk/nsVolumeMountLock.cpp171
-rw-r--r--dom/system/gonk/nsVolumeMountLock.h56
-rw-r--r--dom/system/gonk/nsVolumeService.cpp553
-rw-r--r--dom/system/gonk/nsVolumeService.h78
-rw-r--r--dom/system/gonk/nsVolumeStat.cpp33
-rw-r--r--dom/system/gonk/nsVolumeStat.h33
-rw-r--r--dom/system/gonk/ril_consts.js3338
-rw-r--r--dom/system/gonk/ril_worker.js15206
-rw-r--r--dom/system/gonk/ril_worker_buf_object.js168
-rw-r--r--dom/system/gonk/ril_worker_telephony_request_queue.js157
-rw-r--r--dom/system/gonk/systemlibs.js201
-rw-r--r--dom/system/gonk/tests/header_helpers.js217
-rw-r--r--dom/system/gonk/tests/marionette/head.js345
-rw-r--r--dom/system/gonk/tests/marionette/manifest.ini19
-rw-r--r--dom/system/gonk/tests/marionette/ril_jshint/README.md9
-rw-r--r--dom/system/gonk/tests/marionette/ril_jshint/jshint.js11096
-rw-r--r--dom/system/gonk/tests/marionette/ril_jshint/jshintrc118
-rw-r--r--dom/system/gonk/tests/marionette/test_all_network_info.js106
-rw-r--r--dom/system/gonk/tests/marionette/test_data_connection.js70
-rw-r--r--dom/system/gonk/tests/marionette/test_data_connection_proxy.js99
-rw-r--r--dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js43
-rw-r--r--dom/system/gonk/tests/marionette/test_fakevolume.js25
-rw-r--r--dom/system/gonk/tests/marionette/test_geolocation.js117
-rw-r--r--dom/system/gonk/tests/marionette/test_multiple_data_connection.js89
-rw-r--r--dom/system/gonk/tests/marionette/test_network_active_changed.js52
-rw-r--r--dom/system/gonk/tests/marionette/test_network_interface_list_service.js95
-rw-r--r--dom/system/gonk/tests/marionette/test_network_interface_mtu.js100
-rw-r--r--dom/system/gonk/tests/marionette/test_ril_code_quality.py371
-rw-r--r--dom/system/gonk/tests/marionette/test_screen_state.js47
-rw-r--r--dom/system/gonk/tests/marionette/test_timezone_changes.js135
-rw-r--r--dom/system/gonk/tests/test_ril_system_messenger.js1187
-rw-r--r--dom/system/gonk/tests/test_ril_worker_barring_password.js61
-rw-r--r--dom/system/gonk/tests/test_ril_worker_buf.js187
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js234
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js470
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cellbroadcast_gsm.js230
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cellbroadcast_umts.js105
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cf.js126
-rw-r--r--dom/system/gonk/tests/test_ril_worker_clip.js59
-rw-r--r--dom/system/gonk/tests/test_ril_worker_clir.js122
-rw-r--r--dom/system/gonk/tests/test_ril_worker_cw.js104
-rw-r--r--dom/system/gonk/tests/test_ril_worker_ecm.js168
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_BerTlvHelper.js87
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_CardLock.js282
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_CardState.js210
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_GsmPDUHelper.js79
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCContactHelper.js1042
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCIOHelper.js173
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js652
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCRecordHelper.js1080
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js326
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_IconLoader.js771
-rw-r--r--dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js1648
-rw-r--r--dom/system/gonk/tests/test_ril_worker_ruim.js328
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms.js273
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_cdma.js298
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_cdmapduhelper.js210
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_gsmpduhelper.js282
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_nl_tables.js77
-rw-r--r--dom/system/gonk/tests/test_ril_worker_sms_segment_info.js115
-rw-r--r--dom/system/gonk/tests/test_ril_worker_smsc_address.js112
-rw-r--r--dom/system/gonk/tests/test_ril_worker_ssn.js104
-rw-r--r--dom/system/gonk/tests/test_ril_worker_stk.js1698
-rw-r--r--dom/system/gonk/tests/test_ril_worker_voiceprivacy.js94
-rw-r--r--dom/system/gonk/tests/xpcshell.ini43
-rw-r--r--dom/system/gonk/worker_buf.js623
-rw-r--r--dom/system/moz.build2
-rw-r--r--hal/gonk/GonkDiskSpaceWatcher.cpp324
-rw-r--r--hal/gonk/GonkHal.cpp2045
-rw-r--r--hal/gonk/GonkSensor.cpp861
-rw-r--r--hal/gonk/GonkSensorsHelpers.cpp112
-rw-r--r--hal/gonk/GonkSensorsHelpers.h226
-rw-r--r--hal/gonk/GonkSensorsInterface.cpp494
-rw-r--r--hal/gonk/GonkSensorsInterface.h191
-rw-r--r--hal/gonk/GonkSensorsPollInterface.cpp431
-rw-r--r--hal/gonk/GonkSensorsPollInterface.h340
-rw-r--r--hal/gonk/GonkSensorsRegistryInterface.cpp213
-rw-r--r--hal/gonk/GonkSensorsRegistryInterface.h182
-rw-r--r--hal/gonk/GonkSwitch.cpp479
-rw-r--r--hal/gonk/SensorsTypes.h140
-rw-r--r--hal/gonk/SystemService.cpp131
-rw-r--r--hal/gonk/UeventPoller.cpp312
-rw-r--r--hal/gonk/UeventPoller.h49
-rw-r--r--hal/gonk/fanotify.h118
-rw-r--r--hal/gonk/nsIRecoveryService.idl39
-rw-r--r--hal/gonk/tavarua.h484
-rw-r--r--hal/moz.build52
-rw-r--r--testing/marionette/harness/marionette_harness/tests/webapi-tests.ini1
-rw-r--r--uriloader/exthandler/gonk/nsOSHelperAppService.cpp56
-rw-r--r--uriloader/exthandler/gonk/nsOSHelperAppService.h39
-rw-r--r--uriloader/exthandler/moz.build2
-rw-r--r--widget/gonk/GeckoTouchDispatcher.cpp358
-rw-r--r--widget/gonk/GeckoTouchDispatcher.h99
-rw-r--r--widget/gonk/GfxInfo.cpp194
-rw-r--r--widget/gonk/GfxInfo.h69
-rw-r--r--widget/gonk/GonkClipboardData.cpp75
-rw-r--r--widget/gonk/GonkClipboardData.h49
-rw-r--r--widget/gonk/GonkKeyMapping.h301
-rw-r--r--widget/gonk/GonkMemoryPressureMonitoring.cpp359
-rw-r--r--widget/gonk/GonkMemoryPressureMonitoring.h14
-rw-r--r--widget/gonk/GonkPermission.cpp195
-rw-r--r--widget/gonk/GonkPermission.h86
-rw-r--r--widget/gonk/HwcComposer2D.cpp971
-rw-r--r--widget/gonk/HwcComposer2D.h123
-rw-r--r--widget/gonk/HwcUtils.cpp169
-rw-r--r--widget/gonk/HwcUtils.h135
-rw-r--r--widget/gonk/OrientationObserver.cpp332
-rw-r--r--widget/gonk/OrientationObserver.h71
-rw-r--r--widget/gonk/ProcessOrientation.cpp519
-rw-r--r--widget/gonk/ProcessOrientation.h111
-rw-r--r--widget/gonk/WidgetTraceEvent.cpp96
-rw-r--r--widget/gonk/hwchal/HwcHAL.cpp214
-rw-r--r--widget/gonk/hwchal/HwcHAL.h70
-rw-r--r--widget/gonk/hwchal/HwcHALBase.h134
-rw-r--r--widget/gonk/libdisplay/BootAnimation.cpp726
-rw-r--r--widget/gonk/libdisplay/BootAnimation.h30
-rw-r--r--widget/gonk/libdisplay/DisplaySurface.h112
-rw-r--r--widget/gonk/libdisplay/FramebufferSurface.cpp207
-rw-r--r--widget/gonk/libdisplay/FramebufferSurface.h93
-rw-r--r--widget/gonk/libdisplay/GonkDisplay.h91
-rw-r--r--widget/gonk/libdisplay/GonkDisplayJB.cpp461
-rw-r--r--widget/gonk/libdisplay/GonkDisplayJB.h85
-rw-r--r--widget/gonk/libdisplay/GraphicBufferAlloc.cpp53
-rw-r--r--widget/gonk/libdisplay/GraphicBufferAlloc.h44
-rw-r--r--widget/gonk/libdisplay/VirtualDisplaySurface.cpp635
-rw-r--r--widget/gonk/libdisplay/VirtualDisplaySurface.h250
-rw-r--r--widget/gonk/libdisplay/moz.build59
-rw-r--r--widget/gonk/libui/EventHub.cpp1549
-rw-r--r--widget/gonk/libui/EventHub.h435
-rw-r--r--widget/gonk/libui/Input.cpp635
-rw-r--r--widget/gonk/libui/Input.h622
-rw-r--r--widget/gonk/libui/InputApplication.cpp42
-rw-r--r--widget/gonk/libui/InputApplication.h83
-rw-r--r--widget/gonk/libui/InputDevice.cpp184
-rw-r--r--widget/gonk/libui/InputDevice.h156
-rw-r--r--widget/gonk/libui/InputDispatcher.cpp4430
-rw-r--r--widget/gonk/libui/InputDispatcher.h1117
-rw-r--r--widget/gonk/libui/InputListener.cpp182
-rw-r--r--widget/gonk/libui/InputListener.h196
-rw-r--r--widget/gonk/libui/InputManager.cpp93
-rw-r--r--widget/gonk/libui/InputManager.h109
-rw-r--r--widget/gonk/libui/InputReader.cpp6510
-rw-r--r--widget/gonk/libui/InputReader.h1811
-rw-r--r--widget/gonk/libui/InputTransport.cpp957
-rw-r--r--widget/gonk/libui/InputTransport.h443
-rw-r--r--widget/gonk/libui/InputWindow.cpp64
-rw-r--r--widget/gonk/libui/InputWindow.h205
-rw-r--r--widget/gonk/libui/KeyCharacterMap.cpp1153
-rw-r--r--widget/gonk/libui/KeyCharacterMap.h257
-rw-r--r--widget/gonk/libui/KeyLayoutMap.cpp446
-rw-r--r--widget/gonk/libui/KeyLayoutMap.h117
-rw-r--r--widget/gonk/libui/Keyboard.cpp300
-rw-r--r--widget/gonk/libui/Keyboard.h122
-rw-r--r--widget/gonk/libui/KeycodeLabels.h380
-rw-r--r--widget/gonk/libui/PointerController.cpp604
-rw-r--r--widget/gonk/libui/PointerController.h266
-rw-r--r--widget/gonk/libui/PowerManager.h33
-rw-r--r--widget/gonk/libui/SpriteController.cpp515
-rw-r--r--widget/gonk/libui/SpriteController.h319
-rw-r--r--widget/gonk/libui/Tokenizer.cpp175
-rw-r--r--widget/gonk/libui/Tokenizer.h136
-rw-r--r--widget/gonk/libui/Trace.h64
-rw-r--r--widget/gonk/libui/VelocityControl.cpp110
-rw-r--r--widget/gonk/libui/VelocityControl.h107
-rw-r--r--widget/gonk/libui/VelocityTracker.cpp929
-rw-r--r--widget/gonk/libui/VelocityTracker.h269
-rw-r--r--widget/gonk/libui/VirtualKeyMap.cpp171
-rw-r--r--widget/gonk/libui/VirtualKeyMap.h81
-rw-r--r--widget/gonk/libui/android_input.h850
-rw-r--r--widget/gonk/libui/android_keycodes.h315
-rw-r--r--widget/gonk/libui/cutils_log.h569
-rw-r--r--widget/gonk/libui/cutils_trace.h276
-rw-r--r--widget/gonk/libui/linux_input.h1029
-rw-r--r--widget/gonk/libui/sha1.c289
-rw-r--r--widget/gonk/libui/sha1.h31
-rw-r--r--widget/gonk/moz.build96
-rw-r--r--widget/gonk/nativewindow/FakeSurfaceComposer.cpp703
-rw-r--r--widget/gonk/nativewindow/FakeSurfaceComposer.h175
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueue.h22
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueJB.cpp1036
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueJB.h653
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueKK.cpp1265
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueKK.h583
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp193
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h101
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp559
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h173
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp243
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h251
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h36
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp96
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h94
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp886
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h216
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp32
-rw-r--r--widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h132
-rw-r--r--widget/gonk/nativewindow/GonkConsumerBaseJB.cpp245
-rw-r--r--widget/gonk/nativewindow/GonkConsumerBaseJB.h239
-rw-r--r--widget/gonk/nativewindow/GonkConsumerBaseKK.cpp252
-rw-r--r--widget/gonk/nativewindow/GonkConsumerBaseKK.h240
-rw-r--r--widget/gonk/nativewindow/GonkConsumerBaseLL.cpp257
-rw-r--r--widget/gonk/nativewindow/GonkConsumerBaseLL.h245
-rw-r--r--widget/gonk/nativewindow/GonkNativeWindow.h22
-rw-r--r--widget/gonk/nativewindow/GonkNativeWindowJB.cpp180
-rw-r--r--widget/gonk/nativewindow/GonkNativeWindowJB.h133
-rw-r--r--widget/gonk/nativewindow/GonkNativeWindowKK.cpp182
-rw-r--r--widget/gonk/nativewindow/GonkNativeWindowKK.h135
-rw-r--r--widget/gonk/nativewindow/GonkNativeWindowLL.cpp204
-rw-r--r--widget/gonk/nativewindow/GonkNativeWindowLL.h133
-rw-r--r--widget/gonk/nativewindow/IGonkGraphicBufferConsumer.h20
-rw-r--r--widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.cpp480
-rw-r--r--widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.h228
-rw-r--r--widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp565
-rw-r--r--widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h337
-rw-r--r--widget/gonk/nativewindow/moz.build104
-rw-r--r--widget/gonk/nsAppShell.cpp1087
-rw-r--r--widget/gonk/nsAppShell.h112
-rw-r--r--widget/gonk/nsClipboard.cpp366
-rw-r--r--widget/gonk/nsClipboard.h27
-rw-r--r--widget/gonk/nsIdleServiceGonk.cpp33
-rw-r--r--widget/gonk/nsIdleServiceGonk.h47
-rw-r--r--widget/gonk/nsLookAndFeel.cpp465
-rw-r--r--widget/gonk/nsLookAndFeel.h40
-rw-r--r--widget/gonk/nsScreenManagerGonk.cpp1081
-rw-r--r--widget/gonk/nsScreenManagerGonk.h228
-rw-r--r--widget/gonk/nsWidgetFactory.cpp128
-rw-r--r--widget/gonk/nsWindow.cpp744
-rw-r--r--widget/gonk/nsWindow.h154
-rw-r--r--widget/moz.build6
355 files changed, 15 insertions, 139695 deletions
diff --git a/dom/media/MediaPermissionGonk.cpp b/dom/media/MediaPermissionGonk.cpp
deleted file mode 100644
index 2a9cbf331..000000000
--- a/dom/media/MediaPermissionGonk.cpp
+++ /dev/null
@@ -1,522 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MediaManager.h"
-#include "MediaPermissionGonk.h"
-
-#include "nsArray.h"
-#include "nsCOMPtr.h"
-#include "nsIContentPermissionPrompt.h"
-#include "nsIDocument.h"
-#include "nsIDOMNavigatorUserMedia.h"
-#include "nsIStringEnumerator.h"
-#include "nsJSUtils.h"
-#include "nsQueryObject.h"
-#include "nsPIDOMWindow.h"
-#include "nsTArray.h"
-#include "GetUserMediaRequest.h"
-#include "mozilla/dom/PBrowserChild.h"
-#include "mozilla/dom/MediaStreamTrackBinding.h"
-#include "mozilla/dom/MediaStreamError.h"
-#include "nsISupportsPrimitives.h"
-#include "nsServiceManagerUtils.h"
-#include "nsArrayUtils.h"
-#include "nsContentPermissionHelper.h"
-#include "mozilla/dom/PermissionMessageUtils.h"
-
-#define AUDIO_PERMISSION_NAME "audio-capture"
-#define VIDEO_PERMISSION_NAME "video-capture"
-
-using namespace mozilla::dom;
-
-namespace mozilla {
-
-static MediaPermissionManager *gMediaPermMgr = nullptr;
-
-static void
-CreateDeviceNameList(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices,
- nsTArray<nsString> &aDeviceNameList)
-{
- for (uint32_t i = 0; i < aDevices.Length(); ++i) {
- nsString name;
- nsresult rv = aDevices[i]->GetName(name);
- NS_ENSURE_SUCCESS_VOID(rv);
- aDeviceNameList.AppendElement(name);
- }
-}
-
-static already_AddRefed<nsIMediaDevice>
-FindDeviceByName(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices,
- const nsAString &aDeviceName)
-{
- for (uint32_t i = 0; i < aDevices.Length(); ++i) {
- nsCOMPtr<nsIMediaDevice> device = aDevices[i];
- nsString deviceName;
- device->GetName(deviceName);
- if (deviceName.Equals(aDeviceName)) {
- return device.forget();
- }
- }
-
- return nullptr;
-}
-
-// Helper function for notifying permission granted
-static nsresult
-NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
-{
- nsresult rv;
- nsCOMPtr<nsIMutableArray> array = nsArray::Create();
-
- for (uint32_t i = 0; i < aDevices.Length(); ++i) {
- rv = array->AppendElement(aDevices.ElementAt(i), /*weak =*/ false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
-
- return obs->NotifyObservers(array, "getUserMedia:response:allow",
- aCallID.BeginReading());
-}
-
-// Helper function for notifying permision denial or error
-static nsresult
-NotifyPermissionDeny(const nsAString &aCallID, const nsAString &aErrorMsg)
-{
- nsresult rv;
- nsCOMPtr<nsISupportsString> supportsString =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = supportsString->SetData(aErrorMsg);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
-
- return obs->NotifyObservers(supportsString, "getUserMedia:response:deny",
- aCallID.BeginReading());
-}
-
-namespace {
-
-/**
- * MediaPermissionRequest will send a prompt ipdl request to b2g process according
- * to its owned type.
- */
-class MediaPermissionRequest : public nsIContentPermissionRequest
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSICONTENTPERMISSIONREQUEST
-
- MediaPermissionRequest(RefPtr<dom::GetUserMediaRequest> &aRequest,
- nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices);
-
- already_AddRefed<nsPIDOMWindowInner> GetOwner();
-
-protected:
- virtual ~MediaPermissionRequest() {}
-
-private:
- nsresult DoAllow(const nsString &audioDevice, const nsString &videoDevice);
-
- bool mAudio; // Request for audio permission
- bool mVideo; // Request for video permission
- RefPtr<dom::GetUserMediaRequest> mRequest;
- nsTArray<nsCOMPtr<nsIMediaDevice> > mAudioDevices; // candidate audio devices
- nsTArray<nsCOMPtr<nsIMediaDevice> > mVideoDevices; // candidate video devices
- nsCOMPtr<nsIContentPermissionRequester> mRequester;
-};
-
-// MediaPermissionRequest
-NS_IMPL_ISUPPORTS(MediaPermissionRequest, nsIContentPermissionRequest)
-
-MediaPermissionRequest::MediaPermissionRequest(RefPtr<dom::GetUserMediaRequest> &aRequest,
- nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
- : mRequest(aRequest)
-{
- dom::MediaStreamConstraints constraints;
- mRequest->GetConstraints(constraints);
-
- mAudio = !constraints.mAudio.IsBoolean() || constraints.mAudio.GetAsBoolean();
- mVideo = !constraints.mVideo.IsBoolean() || constraints.mVideo.GetAsBoolean();
-
- for (uint32_t i = 0; i < aDevices.Length(); ++i) {
- nsCOMPtr<nsIMediaDevice> device(aDevices[i]);
- nsAutoString deviceType;
- device->GetType(deviceType);
- if (mAudio && deviceType.EqualsLiteral("audio")) {
- mAudioDevices.AppendElement(device);
- }
- if (mVideo && deviceType.EqualsLiteral("video")) {
- mVideoDevices.AppendElement(device);
- }
- }
-
- nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
- mRequester = new nsContentPermissionRequester(window);
-}
-
-// nsIContentPermissionRequest methods
-NS_IMETHODIMP
-MediaPermissionRequest::GetTypes(nsIArray** aTypes)
-{
- nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
- //XXX append device list
- if (mAudio) {
- nsTArray<nsString> audioDeviceNames;
- CreateDeviceNameList(mAudioDevices, audioDeviceNames);
- nsCOMPtr<nsISupports> AudioType =
- new ContentPermissionType(NS_LITERAL_CSTRING(AUDIO_PERMISSION_NAME),
- NS_LITERAL_CSTRING("unused"),
- audioDeviceNames);
- types->AppendElement(AudioType, false);
- }
- if (mVideo) {
- nsTArray<nsString> videoDeviceNames;
- CreateDeviceNameList(mVideoDevices, videoDeviceNames);
- nsCOMPtr<nsISupports> VideoType =
- new ContentPermissionType(NS_LITERAL_CSTRING(VIDEO_PERMISSION_NAME),
- NS_LITERAL_CSTRING("unused"),
- videoDeviceNames);
- types->AppendElement(VideoType, false);
- }
- NS_IF_ADDREF(*aTypes = types);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
-{
- NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
-
- nsCOMPtr<nsPIDOMWindowInner> window =
- nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID())->AsInner();
- NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
- NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
- NS_ADDREF(*aRequestingPrincipal = doc->NodePrincipal());
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::GetWindow(mozIDOMWindow** aRequestingWindow)
-{
- NS_ENSURE_ARG_POINTER(aRequestingWindow);
- nsCOMPtr<nsPIDOMWindowInner> window =
- nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID())->AsInner();
- window.forget(aRequestingWindow);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::GetElement(nsIDOMElement** aRequestingElement)
-{
- NS_ENSURE_ARG_POINTER(aRequestingElement);
- *aRequestingElement = nullptr;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::Cancel()
-{
- nsString callID;
- mRequest->GetCallID(callID);
- NotifyPermissionDeny(callID, NS_LITERAL_STRING("SecurityError"));
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::Allow(JS::HandleValue aChoices)
-{
- // check if JS object
- if (!aChoices.isObject()) {
- MOZ_ASSERT(false, "Not a correct format of PermissionChoice");
- return NS_ERROR_INVALID_ARG;
- }
- // iterate through audio-capture and video-capture
- AutoJSAPI jsapi;
- if (!jsapi.Init(&aChoices.toObject())) {
- return NS_ERROR_UNEXPECTED;
- }
- JSContext* cx = jsapi.cx();
- JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
- JS::Rooted<JS::Value> v(cx);
-
- // get selected audio device name
- nsString audioDevice;
- if (mAudio) {
- if (!JS_GetProperty(cx, obj, AUDIO_PERMISSION_NAME, &v) || !v.isString()) {
- return NS_ERROR_FAILURE;
- }
- nsAutoJSString deviceName;
- if (!deviceName.init(cx, v)) {
- MOZ_ASSERT(false, "Couldn't initialize string from aChoices");
- return NS_ERROR_FAILURE;
- }
- audioDevice = deviceName;
- }
-
- // get selected video device name
- nsString videoDevice;
- if (mVideo) {
- if (!JS_GetProperty(cx, obj, VIDEO_PERMISSION_NAME, &v) || !v.isString()) {
- return NS_ERROR_FAILURE;
- }
- nsAutoJSString deviceName;
- if (!deviceName.init(cx, v)) {
- MOZ_ASSERT(false, "Couldn't initialize string from aChoices");
- return NS_ERROR_FAILURE;
- }
- videoDevice = deviceName;
- }
-
- return DoAllow(audioDevice, videoDevice);
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
-{
- NS_ENSURE_ARG_POINTER(aRequester);
-
- nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
- requester.forget(aRequester);
- return NS_OK;
-}
-
-nsresult
-MediaPermissionRequest::DoAllow(const nsString &audioDevice,
- const nsString &videoDevice)
-{
- nsTArray<nsCOMPtr<nsIMediaDevice> > selectedDevices;
- if (mAudio) {
- nsCOMPtr<nsIMediaDevice> device =
- FindDeviceByName(mAudioDevices, audioDevice);
- if (device) {
- selectedDevices.AppendElement(device);
- }
- }
-
- if (mVideo) {
- nsCOMPtr<nsIMediaDevice> device =
- FindDeviceByName(mVideoDevices, videoDevice);
- if (device) {
- selectedDevices.AppendElement(device);
- }
- }
-
- nsString callID;
- mRequest->GetCallID(callID);
- return NotifyPermissionAllow(callID, selectedDevices);
-}
-
-already_AddRefed<nsPIDOMWindowInner>
-MediaPermissionRequest::GetOwner()
-{
- nsCOMPtr<nsPIDOMWindowInner> window =
- nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID())->AsInner();
- return window.forget();
-}
-
-// Success callback for MediaManager::GetUserMediaDevices().
-class MediaDeviceSuccessCallback: public nsIGetUserMediaDevicesSuccessCallback
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIGETUSERMEDIADEVICESSUCCESSCALLBACK
-
- explicit MediaDeviceSuccessCallback(RefPtr<dom::GetUserMediaRequest> &aRequest)
- : mRequest(aRequest) {}
-
-protected:
- virtual ~MediaDeviceSuccessCallback() {}
-
-private:
- nsresult DoPrompt(RefPtr<MediaPermissionRequest> &req);
- RefPtr<dom::GetUserMediaRequest> mRequest;
-};
-
-NS_IMPL_ISUPPORTS(MediaDeviceSuccessCallback, nsIGetUserMediaDevicesSuccessCallback)
-
-// nsIGetUserMediaDevicesSuccessCallback method
-NS_IMETHODIMP
-MediaDeviceSuccessCallback::OnSuccess(nsIVariant* aDevices)
-{
- nsIID elementIID;
- uint16_t elementType;
- void* rawArray;
- uint32_t arrayLen;
-
- nsresult rv;
- rv = aDevices->GetAsArray(&elementType, &elementIID, &arrayLen, &rawArray);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (elementType != nsIDataType::VTYPE_INTERFACE) {
- free(rawArray);
- return NS_ERROR_FAILURE;
- }
-
- // Create array for nsIMediaDevice
- nsTArray<nsCOMPtr<nsIMediaDevice> > devices;
-
- nsISupports **supportsArray = reinterpret_cast<nsISupports **>(rawArray);
- for (uint32_t i = 0; i < arrayLen; ++i) {
- nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supportsArray[i]));
- devices.AppendElement(device);
- NS_IF_RELEASE(supportsArray[i]); // explicitly decrease reference count for raw pointer
- }
- free(rawArray); // explicitly free for the memory from nsIVariant::GetAsArray
-
- // Send MediaPermissionRequest
- RefPtr<MediaPermissionRequest> req = new MediaPermissionRequest(mRequest, devices);
- rv = DoPrompt(req);
-
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-// Trigger permission prompt UI
-nsresult
-MediaDeviceSuccessCallback::DoPrompt(RefPtr<MediaPermissionRequest> &req)
-{
- nsCOMPtr<nsPIDOMWindowInner> window(req->GetOwner());
- return dom::nsContentPermissionUtils::AskPermission(req, window);
-}
-
-// Error callback for MediaManager::GetUserMediaDevices()
-class MediaDeviceErrorCallback: public nsIDOMGetUserMediaErrorCallback
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIDOMGETUSERMEDIAERRORCALLBACK
-
- explicit MediaDeviceErrorCallback(const nsAString &aCallID)
- : mCallID(aCallID) {}
-
-protected:
- virtual ~MediaDeviceErrorCallback() {}
-
-private:
- const nsString mCallID;
-};
-
-NS_IMPL_ISUPPORTS(MediaDeviceErrorCallback, nsIDOMGetUserMediaErrorCallback)
-
-// nsIDOMGetUserMediaErrorCallback method
-NS_IMETHODIMP
-MediaDeviceErrorCallback::OnError(nsISupports* aError)
-{
- RefPtr<MediaStreamError> error = do_QueryObject(aError);
- if (!error) {
- return NS_ERROR_NO_INTERFACE;
- }
-
- nsString name;
- error->GetName(name);
- return NotifyPermissionDeny(mCallID, name);
-}
-
-} // namespace anonymous
-
-// MediaPermissionManager
-NS_IMPL_ISUPPORTS(MediaPermissionManager, nsIObserver)
-
-MediaPermissionManager*
-MediaPermissionManager::GetInstance()
-{
- if (!gMediaPermMgr) {
- gMediaPermMgr = new MediaPermissionManager();
- }
-
- return gMediaPermMgr;
-}
-
-MediaPermissionManager::MediaPermissionManager()
-{
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- if (obs) {
- obs->AddObserver(this, "getUserMedia:request", false);
- obs->AddObserver(this, "xpcom-shutdown", false);
- }
-}
-
-MediaPermissionManager::~MediaPermissionManager()
-{
- this->Deinit();
-}
-
-nsresult
-MediaPermissionManager::Deinit()
-{
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- if (obs) {
- obs->RemoveObserver(this, "getUserMedia:request");
- obs->RemoveObserver(this, "xpcom-shutdown");
- }
- return NS_OK;
-}
-
-// nsIObserver method
-NS_IMETHODIMP
-MediaPermissionManager::Observe(nsISupports* aSubject, const char* aTopic,
- const char16_t* aData)
-{
- nsresult rv;
- if (!strcmp(aTopic, "getUserMedia:request")) {
- RefPtr<dom::GetUserMediaRequest> req =
- static_cast<dom::GetUserMediaRequest*>(aSubject);
- rv = HandleRequest(req);
-
- if (NS_FAILED(rv)) {
- nsString callID;
- req->GetCallID(callID);
- NotifyPermissionDeny(callID, NS_LITERAL_STRING("unable to enumerate media device"));
- }
- } else if (!strcmp(aTopic, "xpcom-shutdown")) {
- rv = this->Deinit();
- } else {
- // not reachable
- rv = NS_ERROR_FAILURE;
- }
- return rv;
-}
-
-// Handle GetUserMediaRequest, query available media device first.
-nsresult
-MediaPermissionManager::HandleRequest(RefPtr<dom::GetUserMediaRequest> &req)
-{
- nsString callID;
- req->GetCallID(callID);
- uint64_t innerWindowID = req->InnerWindowID();
-
- nsCOMPtr<nsPIDOMWindowInner> innerWindow =
- nsGlobalWindow::GetInnerWindowWithId(innerWindowID)->AsInner();
- if (!innerWindow) {
- MOZ_ASSERT(false, "No inner window");
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess =
- new MediaDeviceSuccessCallback(req);
- nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError =
- new MediaDeviceErrorCallback(callID);
-
- dom::MediaStreamConstraints constraints;
- req->GetConstraints(constraints);
-
- RefPtr<MediaManager> MediaMgr = MediaManager::GetInstance();
- nsresult rv = MediaMgr->GetUserMediaDevices(innerWindow, constraints,
- onSuccess, onError,
- innerWindowID, callID);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/dom/media/MediaPermissionGonk.h b/dom/media/MediaPermissionGonk.h
deleted file mode 100644
index 0a2fac056..000000000
--- a/dom/media/MediaPermissionGonk.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef DOM_MEDIA_MEDIAPERMISSIONGONK_H
-#define DOM_MEDIA_MEDIAPERMISSIONGONK_H
-
-#include "nsError.h"
-#include "nsIObserver.h"
-#include "nsISupportsImpl.h"
-#include "GetUserMediaRequest.h"
-
-namespace mozilla {
-
-/**
- * The observer to create the MediaPermissionMgr. This is the entry point of
- * permission request on b2g.
- */
-class MediaPermissionManager : public nsIObserver
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- static MediaPermissionManager* GetInstance();
-
-protected:
- virtual ~MediaPermissionManager();
-
-private:
- MediaPermissionManager();
- nsresult Deinit();
- nsresult HandleRequest(RefPtr<dom::GetUserMediaRequest> &req);
-};
-
-} // namespace mozilla
-
-#endif // DOM_MEDIA_MEDIAPERMISSIONGONK_H
-
diff --git a/dom/media/moz.build b/dom/media/moz.build
index d1885793b..4d036a5f6 100644
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -169,11 +169,6 @@ IPDL_SOURCES += [
'webrtc/PWebrtcGlobal.ipdl'
]
-if CONFIG['MOZ_B2G']:
- EXPORTS.mozilla += [
- 'MediaPermissionGonk.h',
- ]
-
EXPORTS.mozilla.dom += [
'AudioStreamTrack.h',
'AudioTrack.h',
@@ -270,11 +265,6 @@ UNIFIED_SOURCES += [
if CONFIG['OS_TARGET'] == 'WINNT':
SOURCES += [ 'ThreadPoolCOMListener.cpp' ]
-if CONFIG['MOZ_B2G']:
- SOURCES += [
- 'MediaPermissionGonk.cpp',
- ]
-
# DecoderTraits.cpp needs to be built separately because of Mac OS X headers.
SOURCES += [
'DecoderTraits.cpp',
@@ -325,9 +315,6 @@ else:
if CONFIG['ANDROID_VERSION'] > '15':
DEFINES['MOZ_OMX_WEBM_DECODER'] = True
-if CONFIG['MOZ_GONK_MEDIACODEC']:
- DEFINES['MOZ_GONK_MEDIACODEC'] = True
-
include('/ipc/chromium/chromium-config.mozbuild')
# Suppress some GCC warnings being treated as errors:
diff --git a/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp b/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp
deleted file mode 100644
index 0bc3fbea9..000000000
--- a/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "MediaCodecProxy.h"
-#include <OMX_IVCommon.h>
-#include <gui/Surface.h>
-#include <ICrypto.h>
-#include "GonkAudioDecoderManager.h"
-#include "MediaDecoderReader.h"
-#include "VideoUtils.h"
-#include "nsTArray.h"
-#include "mozilla/Logging.h"
-#include "stagefright/MediaBuffer.h"
-#include "stagefright/MetaData.h"
-#include "stagefright/MediaErrors.h"
-#include <stagefright/foundation/AMessage.h>
-#include <stagefright/foundation/ALooper.h>
-#include "media/openmax/OMX_Audio.h"
-#include "MediaData.h"
-#include "MediaInfo.h"
-
-#define CODECCONFIG_TIMEOUT_US 10000LL
-#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL
-
-#include <android/log.h>
-#define GADM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkAudioDecoderManager", __VA_ARGS__)
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-
-using namespace android;
-typedef android::MediaCodecProxy MediaCodecProxy;
-
-namespace mozilla {
-
-GonkAudioDecoderManager::GonkAudioDecoderManager(const AudioInfo& aConfig)
- : mAudioChannels(aConfig.mChannels)
- , mAudioRate(aConfig.mRate)
- , mAudioProfile(aConfig.mProfile)
- , mAudioCompactor(mAudioQueue)
-{
- MOZ_COUNT_CTOR(GonkAudioDecoderManager);
- MOZ_ASSERT(mAudioChannels);
- mCodecSpecificData = aConfig.mCodecSpecificConfig;
- mMimeType = aConfig.mMimeType;
-}
-
-GonkAudioDecoderManager::~GonkAudioDecoderManager()
-{
- MOZ_COUNT_DTOR(GonkAudioDecoderManager);
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-GonkAudioDecoderManager::Init()
-{
- if (InitMediaCodecProxy()) {
- return InitPromise::CreateAndResolve(TrackType::kAudioTrack, __func__);
- } else {
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-}
-
-bool
-GonkAudioDecoderManager::InitMediaCodecProxy()
-{
- status_t rv = OK;
- if (!InitLoopers(MediaData::AUDIO_DATA)) {
- return false;
- }
-
- mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false);
- if (!mDecoder.get()) {
- return false;
- }
- if (!mDecoder->AllocateAudioMediaCodec())
- {
- mDecoder = nullptr;
- return false;
- }
- sp<AMessage> format = new AMessage;
- // Fixed values
- GADM_LOG("Configure audio mime type:%s, chan no:%d, sample-rate:%d, profile:%d",
- mMimeType.get(), mAudioChannels, mAudioRate, mAudioProfile);
- format->setString("mime", mMimeType.get());
- format->setInt32("channel-count", mAudioChannels);
- format->setInt32("sample-rate", mAudioRate);
- format->setInt32("aac-profile", mAudioProfile);
- status_t err = mDecoder->configure(format, nullptr, nullptr, 0);
- if (err != OK || !mDecoder->Prepare()) {
- return false;
- }
-
- if (mMimeType.EqualsLiteral("audio/mp4a-latm")) {
- rv = mDecoder->Input(mCodecSpecificData->Elements(), mCodecSpecificData->Length(), 0,
- android::MediaCodec::BUFFER_FLAG_CODECCONFIG,
- CODECCONFIG_TIMEOUT_US);
- }
-
- if (rv == OK) {
- return true;
- } else {
- GADM_LOG("Failed to input codec specific data!");
- return false;
- }
-}
-
-nsresult
-GonkAudioDecoderManager::CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset)
-{
- if (!(aBuffer != nullptr && aBuffer->data() != nullptr)) {
- GADM_LOG("Audio Buffer is not valid!");
- return NS_ERROR_UNEXPECTED;
- }
-
- int64_t timeUs;
- if (!aBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- if (aBuffer->range_length() == 0) {
- // Some decoders may return spurious empty buffers that we just want to ignore
- // quoted from Android's AwesomePlayer.cpp
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- if (mLastTime > timeUs) {
- GADM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
- MOZ_ASSERT(false);
- return NS_ERROR_NOT_AVAILABLE;
- }
- mLastTime = timeUs;
-
- const uint8_t *data = static_cast<const uint8_t*>(aBuffer->data());
- size_t dataOffset = aBuffer->range_offset();
- size_t size = aBuffer->range_length();
-
- uint32_t frames = size / (2 * mAudioChannels);
-
- CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
- if (!duration.isValid()) {
- return NS_ERROR_UNEXPECTED;
- }
-
- typedef AudioCompactor::NativeCopy OmxCopy;
- mAudioCompactor.Push(aStreamOffset,
- timeUs,
- mAudioRate,
- frames,
- mAudioChannels,
- OmxCopy(data+dataOffset,
- size,
- mAudioChannels));
- return NS_OK;
-}
-
-nsresult
-GonkAudioDecoderManager::Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutData)
-{
- aOutData = nullptr;
- if (mAudioQueue.GetSize() > 0) {
- aOutData = mAudioQueue.PopFront();
- return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK;
- }
-
- status_t err;
- MediaBuffer* audioBuffer = nullptr;
- err = mDecoder->Output(&audioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
- AutoReleaseMediaBuffer a(audioBuffer, mDecoder.get());
-
- switch (err) {
- case OK:
- {
- nsresult rv = CreateAudioData(audioBuffer, aStreamOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- break;
- }
- case android::INFO_FORMAT_CHANGED:
- {
- // If the format changed, update our cached info.
- GADM_LOG("Decoder format changed");
- sp<AMessage> audioCodecFormat;
-
- if (mDecoder->getOutputFormat(&audioCodecFormat) != OK ||
- audioCodecFormat == nullptr) {
- return NS_ERROR_UNEXPECTED;
- }
-
- int32_t codec_channel_count = 0;
- int32_t codec_sample_rate = 0;
-
- if (!audioCodecFormat->findInt32("channel-count", &codec_channel_count) ||
- !audioCodecFormat->findInt32("sample-rate", &codec_sample_rate)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- // Update AudioInfo
- AudioConfig::ChannelLayout layout(codec_channel_count);
- if (!layout.IsValid()) {
- return NS_ERROR_FAILURE;
- }
- mAudioChannels = codec_channel_count;
- mAudioRate = codec_sample_rate;
-
- return Output(aStreamOffset, aOutData);
- }
- case android::INFO_OUTPUT_BUFFERS_CHANGED:
- {
- GADM_LOG("Info Output Buffers Changed");
- if (mDecoder->UpdateOutputBuffers()) {
- return Output(aStreamOffset, aOutData);
- }
- return NS_ERROR_FAILURE;
- }
- case -EAGAIN:
- {
- return NS_ERROR_NOT_AVAILABLE;
- }
- case android::ERROR_END_OF_STREAM:
- {
- GADM_LOG("Got EOS frame!");
- nsresult rv = CreateAudioData(audioBuffer, aStreamOffset);
- NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT);
- MOZ_ASSERT(mAudioQueue.GetSize() > 0);
- mAudioQueue.Finish();
- break;
- }
- case -ETIMEDOUT:
- {
- GADM_LOG("Timeout. can try again next time");
- return NS_ERROR_UNEXPECTED;
- }
- default:
- {
- GADM_LOG("Decoder failed, err=%d", err);
- return NS_ERROR_UNEXPECTED;
- }
- }
-
- if (mAudioQueue.GetSize() > 0) {
- aOutData = mAudioQueue.PopFront();
- // Return NS_ERROR_ABORT at the last sample.
- return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK;
- }
-
- return NS_ERROR_NOT_AVAILABLE;
-}
-
-void
-GonkAudioDecoderManager::ProcessFlush()
-{
- GADM_LOG("FLUSH<<<");
- mAudioQueue.Reset();
- GADM_LOG(">>>FLUSH");
- GonkDecoderManager::ProcessFlush();
-}
-
-void
-GonkAudioDecoderManager::ResetEOS()
-{
- GADM_LOG("ResetEOS(<<<");
- mAudioQueue.Reset();
- GADM_LOG(">>>ResetEOS(");
- GonkDecoderManager::ResetEOS();
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkAudioDecoderManager.h b/dom/media/platforms/gonk/GonkAudioDecoderManager.h
deleted file mode 100644
index aa35d620e..000000000
--- a/dom/media/platforms/gonk/GonkAudioDecoderManager.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkAudioDecoderManager_h_)
-#define GonkAudioDecoderManager_h_
-
-#include "AudioCompactor.h"
-#include "mozilla/RefPtr.h"
-#include "GonkMediaDataDecoder.h"
-
-using namespace android;
-
-namespace android {
-class MOZ_EXPORT MediaBuffer;
-} // namespace android
-
-namespace mozilla {
-
-class GonkAudioDecoderManager : public GonkDecoderManager {
-typedef android::MediaCodecProxy MediaCodecProxy;
-public:
- GonkAudioDecoderManager(const AudioInfo& aConfig);
-
- virtual ~GonkAudioDecoderManager();
-
- RefPtr<InitPromise> Init() override;
-
- nsresult Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutput) override;
-
- void ProcessFlush() override;
- virtual void ResetEOS() override;
-
- const char* GetDescriptionName() const override
- {
- return "gonk audio decoder";
- }
-
-private:
- bool InitMediaCodecProxy();
-
- nsresult CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset);
-
- uint32_t mAudioChannels;
- uint32_t mAudioRate;
- const uint32_t mAudioProfile;
-
- MediaQueue<AudioData> mAudioQueue;
-
- AudioCompactor mAudioCompactor;
-
-};
-
-} // namespace mozilla
-
-#endif // GonkAudioDecoderManager_h_
diff --git a/dom/media/platforms/gonk/GonkDecoderModule.cpp b/dom/media/platforms/gonk/GonkDecoderModule.cpp
deleted file mode 100644
index 537bc299c..000000000
--- a/dom/media/platforms/gonk/GonkDecoderModule.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "GonkDecoderModule.h"
-#include "GonkVideoDecoderManager.h"
-#include "GonkAudioDecoderManager.h"
-#include "mozilla/DebugOnly.h"
-#include "GonkMediaDataDecoder.h"
-
-namespace mozilla {
-GonkDecoderModule::GonkDecoderModule()
-{
-}
-
-GonkDecoderModule::~GonkDecoderModule()
-{
-}
-
-already_AddRefed<MediaDataDecoder>
-GonkDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
-{
- RefPtr<MediaDataDecoder> decoder =
- new GonkMediaDataDecoder(new GonkVideoDecoderManager(aParams.mImageContainer, aParams.VideoConfig()),
- aParams.mCallback);
- return decoder.forget();
-}
-
-already_AddRefed<MediaDataDecoder>
-GonkDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
-{
- RefPtr<MediaDataDecoder> decoder =
- new GonkMediaDataDecoder(new GonkAudioDecoderManager(aParams.AudioConfig()),
- aParams.mCallback);
- return decoder.forget();
-}
-
-PlatformDecoderModule::ConversionRequired
-GonkDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- if (aConfig.IsVideo()) {
- return ConversionRequired::kNeedAnnexB;
- } else {
- return ConversionRequired::kNeedNone;
- }
-}
-
-bool
-GonkDecoderModule::SupportsMimeType(const nsACString& aMimeType,
- DecoderDoctorDiagnostics* aDiagnostics) const
-{
- return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
- aMimeType.EqualsLiteral("audio/3gpp") ||
- aMimeType.EqualsLiteral("audio/amr-wb") ||
- aMimeType.EqualsLiteral("audio/mpeg") ||
- aMimeType.EqualsLiteral("video/mp4") ||
- aMimeType.EqualsLiteral("video/mp4v-es") ||
- aMimeType.EqualsLiteral("video/avc") ||
- aMimeType.EqualsLiteral("video/3gpp");
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkDecoderModule.h b/dom/media/platforms/gonk/GonkDecoderModule.h
deleted file mode 100644
index 4f29f0e75..000000000
--- a/dom/media/platforms/gonk/GonkDecoderModule.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkPlatformDecoderModule_h_)
-#define GonkPlatformDecoderModule_h_
-
-#include "PlatformDecoderModule.h"
-
-namespace mozilla {
-
-class GonkDecoderModule : public PlatformDecoderModule {
-public:
- GonkDecoderModule();
- virtual ~GonkDecoderModule();
-
- // Decode thread.
- already_AddRefed<MediaDataDecoder>
- CreateVideoDecoder(const CreateDecoderParams& aParams) override;
-
- // Decode thread.
- already_AddRefed<MediaDataDecoder>
- CreateAudioDecoder(const CreateDecoderParams& aParams) override;
-
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override;
-
- bool SupportsMimeType(const nsACString& aMimeType,
- DecoderDoctorDiagnostics* aDiagnostics) const override;
-
-};
-
-} // namespace mozilla
-
-#endif
diff --git a/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp b/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp
deleted file mode 100644
index 6d59d72e1..000000000
--- a/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp
+++ /dev/null
@@ -1,385 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "GonkMediaDataDecoder.h"
-#include "VideoUtils.h"
-#include "nsTArray.h"
-#include "MediaCodecProxy.h"
-
-#include <stagefright/foundation/ADebug.h>
-
-#include "mozilla/Logging.h"
-#include <android/log.h>
-#define GMDD_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkMediaDataDecoder", __VA_ARGS__)
-#define INPUT_TIMEOUT_US 0LL // Don't wait for buffer if none is available.
-#define MIN_QUEUED_SAMPLES 2
-
-#ifdef DEBUG
-#include <utils/AndroidThreads.h>
-#endif
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-
-using namespace android;
-
-namespace mozilla {
-
-bool
-GonkDecoderManager::InitLoopers(MediaData::Type aType)
-{
- MOZ_ASSERT(mDecodeLooper.get() == nullptr && mTaskLooper.get() == nullptr);
- MOZ_ASSERT(aType == MediaData::VIDEO_DATA || aType == MediaData::AUDIO_DATA);
-
- const char* suffix = (aType == MediaData::VIDEO_DATA ? "video" : "audio");
- mDecodeLooper = new ALooper;
- android::AString name("MediaCodecProxy/");
- name.append(suffix);
- mDecodeLooper->setName(name.c_str());
-
- mTaskLooper = new ALooper;
- name.setTo("GonkDecoderManager/");
- name.append(suffix);
- mTaskLooper->setName(name.c_str());
- mTaskLooper->registerHandler(this);
-
-#ifdef DEBUG
- sp<AMessage> findThreadId(new AMessage(kNotifyFindLooperId, id()));
- findThreadId->post();
-#endif
-
- return mDecodeLooper->start() == OK && mTaskLooper->start() == OK;
-}
-
-nsresult
-GonkDecoderManager::Input(MediaRawData* aSample)
-{
- RefPtr<MediaRawData> sample;
-
- if (aSample) {
- sample = aSample;
- } else {
- // It means EOS with empty sample.
- sample = new MediaRawData();
- }
- {
- MutexAutoLock lock(mMutex);
- mQueuedSamples.AppendElement(sample);
- }
-
- sp<AMessage> input = new AMessage(kNotifyProcessInput, id());
- if (!aSample) {
- input->setInt32("input-eos", 1);
- }
- input->post();
- return NS_OK;
-}
-
-int32_t
-GonkDecoderManager::ProcessQueuedSamples()
-{
- MOZ_ASSERT(OnTaskLooper());
-
- MutexAutoLock lock(mMutex);
- status_t rv;
- while (mQueuedSamples.Length()) {
- RefPtr<MediaRawData> data = mQueuedSamples.ElementAt(0);
- rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
- data->Size(),
- data->mTime,
- 0,
- INPUT_TIMEOUT_US);
- if (rv == OK) {
- mQueuedSamples.RemoveElementAt(0);
- mWaitOutput.AppendElement(WaitOutputInfo(data->mOffset, data->mTime,
- /* eos */ data->Data() == nullptr));
- } else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
- // In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
- // buffer on time.
- break;
- } else {
- return rv;
- }
- }
- return mQueuedSamples.Length();
-}
-
-nsresult
-GonkDecoderManager::Flush()
-{
- if (mDecoder == nullptr) {
- GMDD_LOG("Decoder is not initialized");
- return NS_ERROR_UNEXPECTED;
- }
-
- if (!mInitPromise.IsEmpty()) {
- return NS_OK;
- }
-
- {
- MutexAutoLock lock(mMutex);
- mQueuedSamples.Clear();
- }
-
- MonitorAutoLock lock(mFlushMonitor);
- mIsFlushing = true;
- sp<AMessage> flush = new AMessage(kNotifyProcessFlush, id());
- flush->post();
- while (mIsFlushing) {
- lock.Wait();
- }
- return NS_OK;
-}
-
-nsresult
-GonkDecoderManager::Shutdown()
-{
- if (mDecoder.get()) {
- mDecoder->stop();
- mDecoder->ReleaseMediaResources();
- mDecoder = nullptr;
- }
-
- mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
-
- return NS_OK;
-}
-
-size_t
-GonkDecoderManager::NumQueuedSamples()
-{
- MutexAutoLock lock(mMutex);
- return mQueuedSamples.Length();
-}
-
-void
-GonkDecoderManager::ProcessInput(bool aEndOfStream)
-{
- MOZ_ASSERT(OnTaskLooper());
-
- status_t rv = ProcessQueuedSamples();
- if (rv >= 0) {
- if (!aEndOfStream && rv <= MIN_QUEUED_SAMPLES) {
- mDecodeCallback->InputExhausted();
- }
-
- if (mToDo.get() == nullptr) {
- mToDo = new AMessage(kNotifyDecoderActivity, id());
- if (aEndOfStream) {
- mToDo->setInt32("input-eos", 1);
- }
- mDecoder->requestActivityNotification(mToDo);
- } else if (aEndOfStream) {
- mToDo->setInt32("input-eos", 1);
- }
- } else {
- GMDD_LOG("input processed: error#%d", rv);
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- }
-}
-
-void
-GonkDecoderManager::ProcessFlush()
-{
- MOZ_ASSERT(OnTaskLooper());
-
- mLastTime = INT64_MIN;
- MonitorAutoLock lock(mFlushMonitor);
- mWaitOutput.Clear();
- if (mDecoder->flush() != OK) {
- GMDD_LOG("flush error");
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- }
- mIsFlushing = false;
- lock.NotifyAll();
-}
-
-// Use output timestamp to determine which output buffer is already returned
-// and remove corresponding info, except for EOS, from the waiting list.
-// This method handles the cases that audio decoder sends multiple output
-// buffers for one input.
-void
-GonkDecoderManager::UpdateWaitingList(int64_t aForgetUpTo)
-{
- MOZ_ASSERT(OnTaskLooper());
-
- size_t i;
- for (i = 0; i < mWaitOutput.Length(); i++) {
- const auto& item = mWaitOutput.ElementAt(i);
- if (item.mEOS || item.mTimestamp > aForgetUpTo) {
- break;
- }
- }
- if (i > 0) {
- mWaitOutput.RemoveElementsAt(0, i);
- }
-}
-
-void
-GonkDecoderManager::ProcessToDo(bool aEndOfStream)
-{
- MOZ_ASSERT(OnTaskLooper());
-
- MOZ_ASSERT(mToDo.get() != nullptr);
- mToDo.clear();
-
- if (NumQueuedSamples() > 0 && ProcessQueuedSamples() < 0) {
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- return;
- }
-
- while (mWaitOutput.Length() > 0) {
- RefPtr<MediaData> output;
- WaitOutputInfo wait = mWaitOutput.ElementAt(0);
- nsresult rv = Output(wait.mOffset, output);
- if (rv == NS_OK) {
- MOZ_ASSERT(output);
- mDecodeCallback->Output(output);
- UpdateWaitingList(output->mTime);
- } else if (rv == NS_ERROR_ABORT) {
- // EOS
- MOZ_ASSERT(mQueuedSamples.IsEmpty());
- if (output) {
- mDecodeCallback->Output(output);
- UpdateWaitingList(output->mTime);
- }
- MOZ_ASSERT(mWaitOutput.Length() == 1);
- mWaitOutput.RemoveElementAt(0);
- mDecodeCallback->DrainComplete();
- ResetEOS();
- return;
- } else if (rv == NS_ERROR_NOT_AVAILABLE) {
- break;
- } else {
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- return;
- }
- }
-
- if (!aEndOfStream && NumQueuedSamples() <= MIN_QUEUED_SAMPLES) {
- mDecodeCallback->InputExhausted();
- // No need to shedule todo task this time because InputExhausted() will
- // cause Input() to be invoked and do it for us.
- return;
- }
-
- if (NumQueuedSamples() || mWaitOutput.Length() > 0) {
- mToDo = new AMessage(kNotifyDecoderActivity, id());
- if (aEndOfStream) {
- mToDo->setInt32("input-eos", 1);
- }
- mDecoder->requestActivityNotification(mToDo);
- }
-}
-
-void
-GonkDecoderManager::ResetEOS()
-{
- // After eos, android::MediaCodec needs to be flushed to receive next input
- mWaitOutput.Clear();
- if (mDecoder->flush() != OK) {
- GMDD_LOG("flush error");
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- }
-}
-
-void
-GonkDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
-{
- switch (aMessage->what()) {
- case kNotifyProcessInput:
- {
- int32_t eos = 0;
- ProcessInput(aMessage->findInt32("input-eos", &eos) && eos);
- break;
- }
- case kNotifyProcessFlush:
- {
- ProcessFlush();
- break;
- }
- case kNotifyDecoderActivity:
- {
- int32_t eos = 0;
- ProcessToDo(aMessage->findInt32("input-eos", &eos) && eos);
- break;
- }
-#ifdef DEBUG
- case kNotifyFindLooperId:
- {
- mTaskLooperId = androidGetThreadId();
- MOZ_ASSERT(mTaskLooperId);
- break;
- }
-#endif
- default:
- {
- TRESPASS();
- break;
- }
- }
-}
-
-#ifdef DEBUG
-bool
-GonkDecoderManager::OnTaskLooper()
-{
- return androidGetThreadId() == mTaskLooperId;
-}
-#endif
-
-GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
- MediaDataDecoderCallback* aCallback)
- : mManager(aManager)
-{
- MOZ_COUNT_CTOR(GonkMediaDataDecoder);
- mManager->SetDecodeCallback(aCallback);
-}
-
-GonkMediaDataDecoder::~GonkMediaDataDecoder()
-{
- MOZ_COUNT_DTOR(GonkMediaDataDecoder);
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-GonkMediaDataDecoder::Init()
-{
- return mManager->Init();
-}
-
-void
-GonkMediaDataDecoder::Shutdown()
-{
- mManager->Shutdown();
-
- // Because codec allocated runnable and init promise is at reader TaskQueue,
- // so manager needs to be destroyed at reader TaskQueue to prevent racing.
- mManager = nullptr;
-}
-
-// Inserts data into the decoder's pipeline.
-void
-GonkMediaDataDecoder::Input(MediaRawData* aSample)
-{
- mManager->Input(aSample);
-}
-
-void
-GonkMediaDataDecoder::Flush()
-{
- mManager->Flush();
-}
-
-void
-GonkMediaDataDecoder::Drain()
-{
- mManager->Input(nullptr);
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkMediaDataDecoder.h b/dom/media/platforms/gonk/GonkMediaDataDecoder.h
deleted file mode 100644
index bba2a8645..000000000
--- a/dom/media/platforms/gonk/GonkMediaDataDecoder.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkMediaDataDecoder_h_)
-#define GonkMediaDataDecoder_h_
-#include "PlatformDecoderModule.h"
-#include <stagefright/foundation/AHandler.h>
-
-namespace android {
-struct ALooper;
-class MediaBuffer;
-class MediaCodecProxy;
-} // namespace android
-
-namespace mozilla {
-class MediaRawData;
-
-// Manage the data flow from inputting encoded data and outputting decode data.
-class GonkDecoderManager : public android::AHandler {
-public:
- typedef TrackInfo::TrackType TrackType;
- typedef MediaDataDecoder::InitPromise InitPromise;
-
- virtual ~GonkDecoderManager() {}
-
- virtual RefPtr<InitPromise> Init() = 0;
- virtual const char* GetDescriptionName() const = 0;
-
- // Asynchronously send sample into mDecoder. If out of input buffer, aSample
- // will be queued for later re-send.
- nsresult Input(MediaRawData* aSample);
-
- // Flush the queued samples and signal decoder to throw all pending input/output away.
- nsresult Flush();
-
- // Shutdown decoder and rejects the init promise.
- virtual nsresult Shutdown();
-
- // How many samples are waiting for processing.
- size_t NumQueuedSamples();
-
- // Set callback for decoder events, such as requesting more input,
- // returning output, or reporting error.
- void SetDecodeCallback(MediaDataDecoderCallback* aCallback)
- {
- mDecodeCallback = aCallback;
- }
-
-protected:
- GonkDecoderManager()
- : mMutex("GonkDecoderManager")
- , mLastTime(INT64_MIN)
- , mFlushMonitor("GonkDecoderManager::Flush")
- , mIsFlushing(false)
- , mDecodeCallback(nullptr)
- {}
-
- bool InitLoopers(MediaData::Type aType);
-
- void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
-
- // Produces decoded output. It returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
- // when output is not produced yet.
- // If this returns a failure code other than NS_ERROR_NOT_AVAILABLE, an error
- // will be reported through mDecodeCallback.
- virtual nsresult Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutput) = 0;
-
- // Send queued samples to OMX. It returns how many samples are still in
- // queue after processing, or negative error code if failed.
- int32_t ProcessQueuedSamples();
-
- void ProcessInput(bool aEndOfStream);
- virtual void ProcessFlush();
- void ProcessToDo(bool aEndOfStream);
- virtual void ResetEOS();
-
- RefPtr<MediaByteBuffer> mCodecSpecificData;
-
- nsAutoCString mMimeType;
-
- // MediaCodedc's wrapper that performs the decoding.
- android::sp<android::MediaCodecProxy> mDecoder;
- // Looper for mDecoder to run on.
- android::sp<android::ALooper> mDecodeLooper;
- // Looper to run decode tasks such as processing input, output, flush, and
- // recycling output buffers.
- android::sp<android::ALooper> mTaskLooper;
- // Message codes for tasks running on mTaskLooper.
- enum {
- // Decoder will send this to indicate internal state change such as input or
- // output buffers availability. Used to run pending input & output tasks.
- kNotifyDecoderActivity = 'nda ',
- // Signal the decoder to flush.
- kNotifyProcessFlush = 'npf ',
- // Used to process queued samples when there is new input.
- kNotifyProcessInput = 'npi ',
-#ifdef DEBUG
- kNotifyFindLooperId = 'nfli',
-#endif
- };
-
- MozPromiseHolder<InitPromise> mInitPromise;
-
- Mutex mMutex; // Protects mQueuedSamples.
- // A queue that stores the samples waiting to be sent to mDecoder.
- // Empty element means EOS and there shouldn't be any sample be queued after it.
- // Samples are queued in caller's thread and dequeued in mTaskLooper.
- nsTArray<RefPtr<MediaRawData>> mQueuedSamples;
-
- // The last decoded frame presentation time. Only accessed on mTaskLooper.
- int64_t mLastTime;
-
- Monitor mFlushMonitor; // Waits for flushing to complete.
- bool mIsFlushing; // Protected by mFlushMonitor.
-
- // Remembers the notification that is currently waiting for the decoder event
- // to avoid requesting more than one notification at the time, which is
- // forbidden by mDecoder.
- android::sp<android::AMessage> mToDo;
-
- // Stores sample info for output buffer processing later.
- struct WaitOutputInfo {
- WaitOutputInfo(int64_t aOffset, int64_t aTimestamp, bool aEOS)
- : mOffset(aOffset)
- , mTimestamp(aTimestamp)
- , mEOS(aEOS)
- {}
- const int64_t mOffset;
- const int64_t mTimestamp;
- const bool mEOS;
- };
-
- nsTArray<WaitOutputInfo> mWaitOutput;
-
- MediaDataDecoderCallback* mDecodeCallback; // Reports decoder output or error.
-
-private:
- void UpdateWaitingList(int64_t aForgetUpTo);
-
-#ifdef DEBUG
- typedef void* LooperId;
-
- bool OnTaskLooper();
- LooperId mTaskLooperId;
-#endif
-};
-
-class AutoReleaseMediaBuffer
-{
-public:
- AutoReleaseMediaBuffer(android::MediaBuffer* aBuffer, android::MediaCodecProxy* aCodec)
- : mBuffer(aBuffer)
- , mCodec(aCodec)
- {}
-
- ~AutoReleaseMediaBuffer()
- {
- MOZ_ASSERT(mCodec.get());
- if (mBuffer) {
- mCodec->ReleaseMediaBuffer(mBuffer);
- }
- }
-
- android::MediaBuffer* forget()
- {
- android::MediaBuffer* tmp = mBuffer;
- mBuffer = nullptr;
- return tmp;
- }
-
-private:
- android::MediaBuffer* mBuffer;
- android::sp<android::MediaCodecProxy> mCodec;
-};
-
-// Samples are decoded using the GonkDecoder (MediaCodec)
-// created by the GonkDecoderManager. This class implements
-// the higher-level logic that drives mapping the Gonk to the async
-// MediaDataDecoder interface. The specifics of decoding the exact stream
-// type are handled by GonkDecoderManager and the GonkDecoder it creates.
-class GonkMediaDataDecoder : public MediaDataDecoder {
-public:
- GonkMediaDataDecoder(GonkDecoderManager* aDecoderManager,
- MediaDataDecoderCallback* aCallback);
-
- ~GonkMediaDataDecoder();
-
- RefPtr<InitPromise> Init() override;
-
- void Input(MediaRawData* aSample) override;
-
- void Flush() override;
-
- void Drain() override;
-
- void Shutdown() override;
-
- const char* GetDescriptionName() const override
- {
- return "gonk decoder";
- }
-
-private:
-
- android::sp<GonkDecoderManager> mManager;
-};
-
-} // namespace mozilla
-
-#endif // GonkMediaDataDecoder_h_
diff --git a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
deleted file mode 100644
index 0c7b3b6af..000000000
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
+++ /dev/null
@@ -1,772 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "MediaCodecProxy.h"
-#include <OMX_IVCommon.h>
-#include <gui/Surface.h>
-#include <ICrypto.h>
-#include "GonkVideoDecoderManager.h"
-#include "GrallocImages.h"
-#include "MediaDecoderReader.h"
-#include "ImageContainer.h"
-#include "VideoUtils.h"
-#include "nsThreadUtils.h"
-#include "Layers.h"
-#include "mozilla/Logging.h"
-#include <stagefright/MediaBuffer.h>
-#include <stagefright/MetaData.h>
-#include <stagefright/MediaErrors.h>
-#include <stagefright/foundation/AString.h>
-#include "GonkNativeWindow.h"
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/TextureClient.h"
-#include "mozilla/layers/TextureClientRecycleAllocator.h"
-#include <cutils/properties.h>
-
-#define CODECCONFIG_TIMEOUT_US 10000LL
-#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL
-
-#include <android/log.h>
-#define GVDM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkVideoDecoderManager", __VA_ARGS__)
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-using namespace mozilla::layers;
-using namespace android;
-typedef android::MediaCodecProxy MediaCodecProxy;
-
-namespace mozilla {
-
-class GonkTextureClientAllocationHelper : public layers::ITextureClientAllocationHelper
-{
-public:
- GonkTextureClientAllocationHelper(uint32_t aGrallocFormat,
- gfx::IntSize aSize)
- : ITextureClientAllocationHelper(gfx::SurfaceFormat::UNKNOWN,
- aSize,
- BackendSelector::Content,
- TextureFlags::DEALLOCATE_CLIENT,
- ALLOC_DISALLOW_BUFFERTEXTURECLIENT)
- , mGrallocFormat(aGrallocFormat)
- {}
-
- already_AddRefed<TextureClient> Allocate(KnowsCompositor* aAllocator) override
- {
- uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
- android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
- android::GraphicBuffer::USAGE_HW_TEXTURE;
-
- GrallocTextureData* texData = GrallocTextureData::Create(mSize, mGrallocFormat,
- gfx::BackendType::NONE,
- usage, aAllocator->GetTextureForwarder());
- if (!texData) {
- return nullptr;
- }
- sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
- if (!graphicBuffer.get()) {
- return nullptr;
- }
- RefPtr<TextureClient> textureClient =
- TextureClient::CreateWithData(texData, TextureFlags::DEALLOCATE_CLIENT, aAllocator->GetTextureForwarder());
- return textureClient.forget();
- }
-
- bool IsCompatible(TextureClient* aTextureClient) override
- {
- if (!aTextureClient) {
- return false;
- }
- sp<GraphicBuffer> graphicBuffer =
- static_cast<GrallocTextureData*>(aTextureClient->GetInternalData())->GetGraphicBuffer();
- if (!graphicBuffer.get() ||
- static_cast<uint32_t>(graphicBuffer->getPixelFormat()) != mGrallocFormat ||
- aTextureClient->GetSize() != mSize) {
- return false;
- }
- return true;
- }
-
-private:
- uint32_t mGrallocFormat;
-};
-
-GonkVideoDecoderManager::GonkVideoDecoderManager(
- mozilla::layers::ImageContainer* aImageContainer,
- const VideoInfo& aConfig)
- : mConfig(aConfig)
- , mImageContainer(aImageContainer)
- , mColorConverterBufferSize(0)
- , mPendingReleaseItemsLock("GonkVideoDecoderManager::mPendingReleaseItemsLock")
- , mNeedsCopyBuffer(false)
-{
- MOZ_COUNT_CTOR(GonkVideoDecoderManager);
-}
-
-GonkVideoDecoderManager::~GonkVideoDecoderManager()
-{
- MOZ_COUNT_DTOR(GonkVideoDecoderManager);
-}
-
-nsresult
-GonkVideoDecoderManager::Shutdown()
-{
- mVideoCodecRequest.DisconnectIfExists();
- return GonkDecoderManager::Shutdown();
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-GonkVideoDecoderManager::Init()
-{
- mNeedsCopyBuffer = false;
-
- uint32_t maxWidth, maxHeight;
- char propValue[PROPERTY_VALUE_MAX];
- property_get("ro.moz.omx.hw.max_width", propValue, "-1");
- maxWidth = -1 == atoi(propValue) ? MAX_VIDEO_WIDTH : atoi(propValue);
- property_get("ro.moz.omx.hw.max_height", propValue, "-1");
- maxHeight = -1 == atoi(propValue) ? MAX_VIDEO_HEIGHT : atoi(propValue) ;
-
- if (uint32_t(mConfig.mImage.width * mConfig.mImage.height) > maxWidth * maxHeight) {
- GVDM_LOG("Video resolution exceeds hw codec capability");
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- // Validate the container-reported frame and pictureRect sizes. This ensures
- // that our video frame creation code doesn't overflow.
- if (!IsValidVideoRegion(mConfig.mImage, mConfig.ImageRect(), mConfig.mDisplay)) {
- GVDM_LOG("It is not a valid region");
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- mReaderTaskQueue = AbstractThread::GetCurrent()->AsTaskQueue();
- MOZ_ASSERT(mReaderTaskQueue);
-
- if (mDecodeLooper.get() != nullptr) {
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- if (!InitLoopers(MediaData::VIDEO_DATA)) {
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- RefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
- android::sp<GonkVideoDecoderManager> self = this;
- mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper,
- mConfig.mMimeType.get(),
- false);
-
- uint32_t capability = MediaCodecProxy::kEmptyCapability;
- if (mDecoder->getCapability(&capability) == OK && (capability &
- MediaCodecProxy::kCanExposeGraphicBuffer)) {
-#if ANDROID_VERSION >= 21
- sp<IGonkGraphicBufferConsumer> consumer;
- GonkBufferQueue::createBufferQueue(&mGraphicBufferProducer, &consumer);
- mNativeWindow = new GonkNativeWindow(consumer);
-#else
- mNativeWindow = new GonkNativeWindow();
-#endif
- }
-
- mVideoCodecRequest.Begin(mDecoder->AsyncAllocateVideoMediaCodec()
- ->Then(mReaderTaskQueue, __func__,
- [self] (bool) -> void {
- self->mVideoCodecRequest.Complete();
- self->codecReserved();
- }, [self] (bool) -> void {
- self->mVideoCodecRequest.Complete();
- self->codecCanceled();
- }));
-
- return p;
-}
-
-nsresult
-GonkVideoDecoderManager::CreateVideoData(MediaBuffer* aBuffer,
- int64_t aStreamOffset,
- VideoData **v)
-{
- *v = nullptr;
- RefPtr<VideoData> data;
- int64_t timeUs;
- int32_t keyFrame;
-
- if (aBuffer == nullptr) {
- GVDM_LOG("Video Buffer is not valid!");
- return NS_ERROR_UNEXPECTED;
- }
-
- AutoReleaseMediaBuffer autoRelease(aBuffer, mDecoder.get());
-
- if (!aBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- GVDM_LOG("Decoder did not return frame time");
- return NS_ERROR_UNEXPECTED;
- }
-
- if (mLastTime > timeUs) {
- GVDM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
- return NS_ERROR_NOT_AVAILABLE;
- }
- mLastTime = timeUs;
-
- if (aBuffer->range_length() == 0) {
- // Some decoders may return spurious empty buffers that we just want to ignore
- // quoted from Android's AwesomePlayer.cpp
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- if (!aBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) {
- keyFrame = 0;
- }
-
- gfx::IntRect picture =
- mConfig.ScaledImageRect(mFrameInfo.mWidth, mFrameInfo.mHeight);
- if (aBuffer->graphicBuffer().get()) {
- data = CreateVideoDataFromGraphicBuffer(aBuffer, picture);
- if (data && !mNeedsCopyBuffer) {
- // RecycleCallback() will be responsible for release the buffer.
- autoRelease.forget();
- }
- mNeedsCopyBuffer = false;
- } else {
- data = CreateVideoDataFromDataBuffer(aBuffer, picture);
- }
-
- if (!data) {
- return NS_ERROR_UNEXPECTED;
- }
- // Fill necessary info.
- data->mOffset = aStreamOffset;
- data->mTime = timeUs;
- data->mKeyframe = keyFrame;
-
- data.forget(v);
- return NS_OK;
-}
-
-// Copy pixels from one planar YUV to another.
-static void
-CopyYUV(PlanarYCbCrData& aSource, PlanarYCbCrData& aDestination)
-{
- // Fill Y plane.
- uint8_t* srcY = aSource.mYChannel;
- gfx::IntSize ySize = aSource.mYSize;
- uint8_t* destY = aDestination.mYChannel;
- // Y plane.
- for (int i = 0; i < ySize.height; i++) {
- memcpy(destY, srcY, ySize.width);
- srcY += aSource.mYStride;
- destY += aDestination.mYStride;
- }
-
- // Fill UV plane.
- // Line start
- uint8_t* srcU = aSource.mCbChannel;
- uint8_t* srcV = aSource.mCrChannel;
- uint8_t* destU = aDestination.mCbChannel;
- uint8_t* destV = aDestination.mCrChannel;
-
- gfx::IntSize uvSize = aSource.mCbCrSize;
- for (int i = 0; i < uvSize.height; i++) {
- uint8_t* su = srcU;
- uint8_t* sv = srcV;
- uint8_t* du = destU;
- uint8_t* dv =destV;
- for (int j = 0; j < uvSize.width; j++) {
- *du++ = *su++;
- *dv++ = *sv++;
- // Move to next pixel.
- su += aSource.mCbSkip;
- sv += aSource.mCrSkip;
- du += aDestination.mCbSkip;
- dv += aDestination.mCrSkip;
- }
- // Move to next line.
- srcU += aSource.mCbCrStride;
- srcV += aSource.mCbCrStride;
- destU += aDestination.mCbCrStride;
- destV += aDestination.mCbCrStride;
- }
-}
-
-inline static int
-Align(int aX, int aAlign)
-{
- return (aX + aAlign - 1) & ~(aAlign - 1);
-}
-
-// Venus formats are doucmented in kernel/include/media/msm_media_info.h:
-// * Y_Stride : Width aligned to 128
-// * UV_Stride : Width aligned to 128
-// * Y_Scanlines: Height aligned to 32
-// * UV_Scanlines: Height/2 aligned to 16
-// * Total size = align((Y_Stride * Y_Scanlines
-// * + UV_Stride * UV_Scanlines + 4096), 4096)
-static void
-CopyVenus(uint8_t* aSrc, uint8_t* aDest, uint32_t aWidth, uint32_t aHeight)
-{
- size_t yStride = Align(aWidth, 128);
- uint8_t* s = aSrc;
- uint8_t* d = aDest;
- for (size_t i = 0; i < aHeight; i++) {
- memcpy(d, s, aWidth);
- s += yStride;
- d += yStride;
- }
- size_t uvStride = yStride;
- size_t uvLines = (aHeight + 1) / 2;
- size_t ySize = yStride * Align(aHeight, 32);
- s = aSrc + ySize;
- d = aDest + ySize;
- for (size_t i = 0; i < uvLines; i++) {
- memcpy(d, s, aWidth);
- s += uvStride;
- d += uvStride;
- }
-}
-
-static void
-CopyGraphicBuffer(sp<GraphicBuffer>& aSource, sp<GraphicBuffer>& aDestination)
-{
- void* srcPtr = nullptr;
- aSource->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &srcPtr);
- void* destPtr = nullptr;
- aDestination->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destPtr);
- MOZ_ASSERT(srcPtr && destPtr);
-
- // Build PlanarYCbCrData for source buffer.
- PlanarYCbCrData srcData;
- switch (aSource->getPixelFormat()) {
- case HAL_PIXEL_FORMAT_YV12: {
- // Android YV12 format is defined in system/core/include/system/graphics.h
- srcData.mYChannel = static_cast<uint8_t*>(srcPtr);
- srcData.mYSkip = 0;
- srcData.mYSize.width = aSource->getWidth();
- srcData.mYSize.height = aSource->getHeight();
- srcData.mYStride = aSource->getStride();
- // 4:2:0.
- srcData.mCbCrSize.width = srcData.mYSize.width / 2;
- srcData.mCbCrSize.height = srcData.mYSize.height / 2;
- srcData.mCrChannel = srcData.mYChannel + (srcData.mYStride * srcData.mYSize.height);
- // Aligned to 16 bytes boundary.
- srcData.mCbCrStride = Align(srcData.mYStride / 2, 16);
- srcData.mCrSkip = 0;
- srcData.mCbChannel = srcData.mCrChannel + (srcData.mCbCrStride * srcData.mCbCrSize.height);
- srcData.mCbSkip = 0;
-
- // Build PlanarYCbCrData for destination buffer.
- PlanarYCbCrData destData;
- destData.mYChannel = static_cast<uint8_t*>(destPtr);
- destData.mYSkip = 0;
- destData.mYSize.width = aDestination->getWidth();
- destData.mYSize.height = aDestination->getHeight();
- destData.mYStride = aDestination->getStride();
- // 4:2:0.
- destData.mCbCrSize.width = destData.mYSize.width / 2;
- destData.mCbCrSize.height = destData.mYSize.height / 2;
- destData.mCrChannel = destData.mYChannel + (destData.mYStride * destData.mYSize.height);
- // Aligned to 16 bytes boundary.
- destData.mCbCrStride = Align(destData.mYStride / 2, 16);
- destData.mCrSkip = 0;
- destData.mCbChannel = destData.mCrChannel + (destData.mCbCrStride * destData.mCbCrSize.height);
- destData.mCbSkip = 0;
-
- CopyYUV(srcData, destData);
- break;
- }
- case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
- CopyVenus(static_cast<uint8_t*>(srcPtr),
- static_cast<uint8_t*>(destPtr),
- aSource->getWidth(),
- aSource->getHeight());
- break;
- default:
- NS_ERROR("Unsupported input gralloc image type. Should never be here.");
- }
-
-
- aSource->unlock();
- aDestination->unlock();
-}
-
-already_AddRefed<VideoData>
-GonkVideoDecoderManager::CreateVideoDataFromGraphicBuffer(MediaBuffer* aSource,
- gfx::IntRect& aPicture)
-{
- sp<GraphicBuffer> srcBuffer(aSource->graphicBuffer());
- RefPtr<TextureClient> textureClient;
-
- if (mNeedsCopyBuffer) {
- // Copy buffer contents for bug 1199809.
- if (!mCopyAllocator) {
- RefPtr<layers::ImageBridgeChild> bridge = layers::ImageBridgeChild::GetSingleton();
- mCopyAllocator = new TextureClientRecycleAllocator(bridge);
- }
- if (!mCopyAllocator) {
- GVDM_LOG("Create buffer allocator failed!");
- return nullptr;
- }
-
- gfx::IntSize size(srcBuffer->getWidth(), srcBuffer->getHeight());
- GonkTextureClientAllocationHelper helper(srcBuffer->getPixelFormat(), size);
- textureClient = mCopyAllocator->CreateOrRecycle(helper);
- if (!textureClient) {
- GVDM_LOG("Copy buffer allocation failed!");
- return nullptr;
- }
-
- sp<GraphicBuffer> destBuffer =
- static_cast<GrallocTextureData*>(textureClient->GetInternalData())->GetGraphicBuffer();
-
- CopyGraphicBuffer(srcBuffer, destBuffer);
- } else {
- textureClient = mNativeWindow->getTextureClientFromBuffer(srcBuffer.get());
- textureClient->SetRecycleCallback(GonkVideoDecoderManager::RecycleCallback, this);
- static_cast<GrallocTextureData*>(textureClient->GetInternalData())->SetMediaBuffer(aSource);
- }
-
- RefPtr<VideoData> data =
- VideoData::CreateAndCopyIntoTextureClient(mConfig,
- 0, // Filled later by caller.
- 0, // Filled later by caller.
- 1, // No way to pass sample duration from muxer to
- // OMX codec, so we hardcode the duration here.
- textureClient,
- false, // Filled later by caller.
- -1,
- aPicture);
- return data.forget();
-}
-
-already_AddRefed<VideoData>
-GonkVideoDecoderManager::CreateVideoDataFromDataBuffer(MediaBuffer* aSource, gfx::IntRect& aPicture)
-{
- if (!aSource->data()) {
- GVDM_LOG("No data in Video Buffer!");
- return nullptr;
- }
- uint8_t *yuv420p_buffer = (uint8_t *)aSource->data();
- int32_t stride = mFrameInfo.mStride;
- int32_t slice_height = mFrameInfo.mSliceHeight;
-
- // Converts to OMX_COLOR_FormatYUV420Planar
- if (mFrameInfo.mColorFormat != OMX_COLOR_FormatYUV420Planar) {
- ARect crop;
- crop.top = 0;
- crop.bottom = mFrameInfo.mHeight;
- crop.left = 0;
- crop.right = mFrameInfo.mWidth;
- yuv420p_buffer = GetColorConverterBuffer(mFrameInfo.mWidth, mFrameInfo.mHeight);
- if (mColorConverter.convertDecoderOutputToI420(aSource->data(),
- mFrameInfo.mWidth, mFrameInfo.mHeight, crop, yuv420p_buffer) != OK) {
- GVDM_LOG("Color conversion failed!");
- return nullptr;
- }
- stride = mFrameInfo.mWidth;
- slice_height = mFrameInfo.mHeight;
- }
-
- size_t yuv420p_y_size = stride * slice_height;
- size_t yuv420p_u_size = ((stride + 1) / 2) * ((slice_height + 1) / 2);
- uint8_t *yuv420p_y = yuv420p_buffer;
- uint8_t *yuv420p_u = yuv420p_y + yuv420p_y_size;
- uint8_t *yuv420p_v = yuv420p_u + yuv420p_u_size;
-
- VideoData::YCbCrBuffer b;
- b.mPlanes[0].mData = yuv420p_y;
- b.mPlanes[0].mWidth = mFrameInfo.mWidth;
- b.mPlanes[0].mHeight = mFrameInfo.mHeight;
- b.mPlanes[0].mStride = stride;
- b.mPlanes[0].mOffset = 0;
- b.mPlanes[0].mSkip = 0;
-
- b.mPlanes[1].mData = yuv420p_u;
- b.mPlanes[1].mWidth = (mFrameInfo.mWidth + 1) / 2;
- b.mPlanes[1].mHeight = (mFrameInfo.mHeight + 1) / 2;
- b.mPlanes[1].mStride = (stride + 1) / 2;
- b.mPlanes[1].mOffset = 0;
- b.mPlanes[1].mSkip = 0;
-
- b.mPlanes[2].mData = yuv420p_v;
- b.mPlanes[2].mWidth =(mFrameInfo.mWidth + 1) / 2;
- b.mPlanes[2].mHeight = (mFrameInfo.mHeight + 1) / 2;
- b.mPlanes[2].mStride = (stride + 1) / 2;
- b.mPlanes[2].mOffset = 0;
- b.mPlanes[2].mSkip = 0;
-
- RefPtr<VideoData> data =
- VideoData::CreateAndCopyData(mConfig,
- mImageContainer,
- 0, // Filled later by caller.
- 0, // Filled later by caller.
- 1, // We don't know the duration.
- b,
- 0, // Filled later by caller.
- -1,
- aPicture);
-
- return data.forget();
-}
-
-bool
-GonkVideoDecoderManager::SetVideoFormat()
-{
- // read video metadata from MediaCodec
- sp<AMessage> codecFormat;
- if (mDecoder->getOutputFormat(&codecFormat) == OK) {
- AString mime;
- int32_t width = 0;
- int32_t height = 0;
- int32_t stride = 0;
- int32_t slice_height = 0;
- int32_t color_format = 0;
- int32_t crop_left = 0;
- int32_t crop_top = 0;
- int32_t crop_right = 0;
- int32_t crop_bottom = 0;
- if (!codecFormat->findString("mime", &mime) ||
- !codecFormat->findInt32("width", &width) ||
- !codecFormat->findInt32("height", &height) ||
- !codecFormat->findInt32("stride", &stride) ||
- !codecFormat->findInt32("slice-height", &slice_height) ||
- !codecFormat->findInt32("color-format", &color_format) ||
- !codecFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
- GVDM_LOG("Failed to find values");
- return false;
- }
- mFrameInfo.mWidth = width;
- mFrameInfo.mHeight = height;
- mFrameInfo.mStride = stride;
- mFrameInfo.mSliceHeight = slice_height;
- mFrameInfo.mColorFormat = color_format;
-
- nsIntSize displaySize(width, height);
- if (!IsValidVideoRegion(mConfig.mDisplay,
- mConfig.ScaledImageRect(width, height),
- displaySize)) {
- GVDM_LOG("It is not a valid region");
- return false;
- }
- return true;
- }
- GVDM_LOG("Fail to get output format");
- return false;
-}
-
-// Blocks until decoded sample is produced by the deoder.
-nsresult
-GonkVideoDecoderManager::Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutData)
-{
- aOutData = nullptr;
- status_t err;
- if (mDecoder == nullptr) {
- GVDM_LOG("Decoder is not inited");
- return NS_ERROR_UNEXPECTED;
- }
- MediaBuffer* outputBuffer = nullptr;
- err = mDecoder->Output(&outputBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
-
- switch (err) {
- case OK:
- {
- RefPtr<VideoData> data;
- nsresult rv = CreateVideoData(outputBuffer, aStreamOffset, getter_AddRefs(data));
- if (rv == NS_ERROR_NOT_AVAILABLE) {
- // Decoder outputs a empty video buffer, try again
- return NS_ERROR_NOT_AVAILABLE;
- } else if (rv != NS_OK || data == nullptr) {
- GVDM_LOG("Failed to create VideoData");
- return NS_ERROR_UNEXPECTED;
- }
- aOutData = data;
- return NS_OK;
- }
- case android::INFO_FORMAT_CHANGED:
- {
- // If the format changed, update our cached info.
- GVDM_LOG("Decoder format changed");
- if (!SetVideoFormat()) {
- return NS_ERROR_UNEXPECTED;
- }
- return Output(aStreamOffset, aOutData);
- }
- case android::INFO_OUTPUT_BUFFERS_CHANGED:
- {
- if (mDecoder->UpdateOutputBuffers()) {
- return Output(aStreamOffset, aOutData);
- }
- GVDM_LOG("Fails to update output buffers!");
- return NS_ERROR_FAILURE;
- }
- case -EAGAIN:
- {
-// GVDM_LOG("Need to try again!");
- return NS_ERROR_NOT_AVAILABLE;
- }
- case android::ERROR_END_OF_STREAM:
- {
- GVDM_LOG("Got the EOS frame!");
- RefPtr<VideoData> data;
- nsresult rv = CreateVideoData(outputBuffer, aStreamOffset, getter_AddRefs(data));
- if (rv == NS_ERROR_NOT_AVAILABLE) {
- // For EOS, no need to do any thing.
- return NS_ERROR_ABORT;
- }
- if (rv != NS_OK || data == nullptr) {
- GVDM_LOG("Failed to create video data");
- return NS_ERROR_UNEXPECTED;
- }
- aOutData = data;
- return NS_ERROR_ABORT;
- }
- case -ETIMEDOUT:
- {
- GVDM_LOG("Timeout. can try again next time");
- return NS_ERROR_UNEXPECTED;
- }
- default:
- {
- GVDM_LOG("Decoder failed, err=%d", err);
- return NS_ERROR_UNEXPECTED;
- }
- }
-
- return NS_OK;
-}
-
-void
-GonkVideoDecoderManager::codecReserved()
-{
- if (mInitPromise.IsEmpty()) {
- return;
- }
- GVDM_LOG("codecReserved");
- sp<AMessage> format = new AMessage;
- sp<Surface> surface;
- status_t rv = OK;
- // Fixed values
- GVDM_LOG("Configure video mime type: %s, width:%d, height:%d", mConfig.mMimeType.get(), mConfig.mImage.width, mConfig.mImage.height);
- format->setString("mime", mConfig.mMimeType.get());
- format->setInt32("width", mConfig.mImage.width);
- format->setInt32("height", mConfig.mImage.height);
- // Set the "moz-use-undequeued-bufs" to use the undeque buffers to accelerate
- // the video decoding.
- format->setInt32("moz-use-undequeued-bufs", 1);
- if (mNativeWindow != nullptr) {
-#if ANDROID_VERSION >= 21
- surface = new Surface(mGraphicBufferProducer);
-#else
- surface = new Surface(mNativeWindow->getBufferQueue());
-#endif
- }
- mDecoder->configure(format, surface, nullptr, 0);
- mDecoder->Prepare();
-
- if (mConfig.mMimeType.EqualsLiteral("video/mp4v-es")) {
- rv = mDecoder->Input(mConfig.mCodecSpecificConfig->Elements(),
- mConfig.mCodecSpecificConfig->Length(), 0,
- android::MediaCodec::BUFFER_FLAG_CODECCONFIG,
- CODECCONFIG_TIMEOUT_US);
- }
-
- if (rv != OK) {
- GVDM_LOG("Failed to configure codec!!!!");
- mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- return;
- }
-
- mInitPromise.Resolve(TrackType::kVideoTrack, __func__);
-}
-
-void
-GonkVideoDecoderManager::codecCanceled()
-{
- GVDM_LOG("codecCanceled");
- mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
-}
-
-// Called on GonkDecoderManager::mTaskLooper thread.
-void
-GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
-{
- switch (aMessage->what()) {
- case kNotifyPostReleaseBuffer:
- {
- ReleaseAllPendingVideoBuffers();
- break;
- }
-
- default:
- {
- GonkDecoderManager::onMessageReceived(aMessage);
- break;
- }
- }
-}
-
-uint8_t *
-GonkVideoDecoderManager::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight)
-{
- // Allocate a temporary YUV420Planer buffer.
- size_t yuv420p_y_size = aWidth * aHeight;
- size_t yuv420p_u_size = ((aWidth + 1) / 2) * ((aHeight + 1) / 2);
- size_t yuv420p_v_size = yuv420p_u_size;
- size_t yuv420p_size = yuv420p_y_size + yuv420p_u_size + yuv420p_v_size;
- if (mColorConverterBufferSize != yuv420p_size) {
- mColorConverterBuffer = MakeUnique<uint8_t[]>(yuv420p_size);
- mColorConverterBufferSize = yuv420p_size;
- }
- return mColorConverterBuffer.get();
-}
-
-/* static */
-void
-GonkVideoDecoderManager::RecycleCallback(TextureClient* aClient, void* aClosure)
-{
- MOZ_ASSERT(aClient && !aClient->IsDead());
- GonkVideoDecoderManager* videoManager = static_cast<GonkVideoDecoderManager*>(aClosure);
- GrallocTextureData* client = static_cast<GrallocTextureData*>(aClient->GetInternalData());
- aClient->ClearRecycleCallback();
- FenceHandle handle = aClient->GetAndResetReleaseFenceHandle();
- videoManager->PostReleaseVideoBuffer(client->GetMediaBuffer(), handle);
-}
-
-void GonkVideoDecoderManager::PostReleaseVideoBuffer(
- android::MediaBuffer *aBuffer,
- FenceHandle aReleaseFence)
-{
- {
- MutexAutoLock autoLock(mPendingReleaseItemsLock);
- if (aBuffer) {
- mPendingReleaseItems.AppendElement(ReleaseItem(aBuffer, aReleaseFence));
- }
- }
- sp<AMessage> notify =
- new AMessage(kNotifyPostReleaseBuffer, id());
- notify->post();
-
-}
-
-void GonkVideoDecoderManager::ReleaseAllPendingVideoBuffers()
-{
- nsTArray<ReleaseItem> releasingItems;
- {
- MutexAutoLock autoLock(mPendingReleaseItemsLock);
- releasingItems.AppendElements(mPendingReleaseItems);
- mPendingReleaseItems.Clear();
- }
-
- // Free all pending video buffers without holding mPendingReleaseItemsLock.
- size_t size = releasingItems.Length();
- for (size_t i = 0; i < size; i++) {
- RefPtr<FenceHandle::FdObj> fdObj = releasingItems[i].mReleaseFence.GetAndResetFdObj();
- sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
- fence->waitForever("GonkVideoDecoderManager");
- mDecoder->ReleaseMediaBuffer(releasingItems[i].mBuffer);
- }
- releasingItems.Clear();
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkVideoDecoderManager.h b/dom/media/platforms/gonk/GonkVideoDecoderManager.h
deleted file mode 100644
index 343bb2a5c..000000000
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkVideoDecoderManager_h_)
-#define GonkVideoDecoderManager_h_
-
-#include "nsRect.h"
-#include "GonkMediaDataDecoder.h"
-#include "mozilla/RefPtr.h"
-#include "I420ColorConverterHelper.h"
-#include "MediaCodecProxy.h"
-#include "GonkNativeWindow.h"
-#include "mozilla/layers/FenceUtils.h"
-#include "mozilla/UniquePtr.h"
-#include <ui/Fence.h>
-
-using namespace android;
-
-namespace android {
-class MediaBuffer;
-struct MOZ_EXPORT AString;
-class GonkNativeWindow;
-} // namespace android
-
-namespace mozilla {
-
-namespace layers {
-class TextureClient;
-class TextureClientRecycleAllocator;
-} // namespace mozilla::layers
-
-class GonkVideoDecoderManager : public GonkDecoderManager {
-typedef android::MediaCodecProxy MediaCodecProxy;
-typedef mozilla::layers::TextureClient TextureClient;
-
-public:
- GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
- const VideoInfo& aConfig);
-
- virtual ~GonkVideoDecoderManager();
-
- RefPtr<InitPromise> Init() override;
-
- nsresult Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutput) override;
-
- nsresult Shutdown() override;
-
- const char* GetDescriptionName() const override
- {
- return "gonk video decoder";
- }
-
- static void RecycleCallback(TextureClient* aClient, void* aClosure);
-
-protected:
- // Bug 1199809: workaround to avoid sending the graphic buffer by making a
- // copy of output buffer after calling flush(). Bug 1203859 was created to
- // reimplementing Gonk PDM on top of OpenMax IL directly. Its buffer
- // management will work better with Gecko and solve problems like this.
- void ProcessFlush() override
- {
- mNeedsCopyBuffer = true;
- GonkDecoderManager::ProcessFlush();
- }
-
-private:
- struct FrameInfo
- {
- int32_t mWidth = 0;
- int32_t mHeight = 0;
- int32_t mStride = 0;
- int32_t mSliceHeight = 0;
- int32_t mColorFormat = 0;
- int32_t mCropLeft = 0;
- int32_t mCropTop = 0;
- int32_t mCropRight = 0;
- int32_t mCropBottom = 0;
- };
-
- void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
-
- bool SetVideoFormat();
-
- nsresult CreateVideoData(MediaBuffer* aBuffer, int64_t aStreamOffset, VideoData** aOutData);
- already_AddRefed<VideoData> CreateVideoDataFromGraphicBuffer(android::MediaBuffer* aSource,
- gfx::IntRect& aPicture);
- already_AddRefed<VideoData> CreateVideoDataFromDataBuffer(android::MediaBuffer* aSource,
- gfx::IntRect& aPicture);
-
- uint8_t* GetColorConverterBuffer(int32_t aWidth, int32_t aHeight);
-
- // For codec resource management
- void codecReserved();
- void codecCanceled();
-
- void ReleaseAllPendingVideoBuffers();
- void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer,
- layers::FenceHandle mReleaseFence);
-
- VideoInfo mConfig;
-
- RefPtr<layers::ImageContainer> mImageContainer;
- RefPtr<layers::TextureClientRecycleAllocator> mCopyAllocator;
-
- MozPromiseRequestHolder<android::MediaCodecProxy::CodecPromise> mVideoCodecRequest;
- FrameInfo mFrameInfo;
-
- // color converter
- android::I420ColorConverterHelper mColorConverter;
- UniquePtr<uint8_t[]> mColorConverterBuffer;
- size_t mColorConverterBufferSize;
-
- android::sp<android::GonkNativeWindow> mNativeWindow;
-#if ANDROID_VERSION >= 21
- android::sp<android::IGraphicBufferProducer> mGraphicBufferProducer;
-#endif
-
- enum {
- kNotifyPostReleaseBuffer = 'nprb',
- };
-
- struct ReleaseItem {
- ReleaseItem(android::MediaBuffer* aBuffer, layers::FenceHandle& aFence)
- : mBuffer(aBuffer)
- , mReleaseFence(aFence) {}
- android::MediaBuffer* mBuffer;
- layers::FenceHandle mReleaseFence;
- };
- nsTArray<ReleaseItem> mPendingReleaseItems;
-
- // The lock protects mPendingReleaseItems.
- Mutex mPendingReleaseItemsLock;
-
- // This TaskQueue should be the same one in mDecodeCallback->OnReaderTaskQueue().
- // It is for codec resource mangement, decoding task should not dispatch to it.
- RefPtr<TaskQueue> mReaderTaskQueue;
-
- // Bug 1199809: do we need to make a copy of output buffer? Used only when
- // the decoder outputs graphic buffers.
- bool mNeedsCopyBuffer;
-};
-
-} // namespace mozilla
-
-#endif // GonkVideoDecoderManager_h_
diff --git a/dom/media/platforms/gonk/moz.build b/dom/media/platforms/gonk/moz.build
deleted file mode 100644
index 014594977..000000000
--- a/dom/media/platforms/gonk/moz.build
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXPORTS += [
- 'GonkAudioDecoderManager.h',
- 'GonkDecoderModule.h',
- 'GonkMediaDataDecoder.h',
- 'GonkVideoDecoderManager.h',
-]
-UNIFIED_SOURCES += [
- 'GonkAudioDecoderManager.cpp',
- 'GonkDecoderModule.cpp',
- 'GonkMediaDataDecoder.cpp',
- 'GonkVideoDecoderManager.cpp',
-]
-LOCAL_INCLUDES += [
- '/dom/media/omx/',
-]
-include('/ipc/chromium/chromium-config.mozbuild')
-
-# Suppress some GCC/clang warnings being treated as errors:
-# - about attributes on forward declarations for types that are already
-# defined, which complains about an important MOZ_EXPORT for android::AString
-# - about multi-character constants which are used in codec-related code
-if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
- CXXFLAGS += [
- '-Wno-error=attributes',
- '-Wno-error=multichar'
- ]
-
-FINAL_LIBRARY = 'xul'
-
-LOCAL_INCLUDES += [
- '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/native/opengl/include',]
-]
diff --git a/dom/media/platforms/moz.build b/dom/media/platforms/moz.build
index 310820c91..3fb0cc842 100644
--- a/dom/media/platforms/moz.build
+++ b/dom/media/platforms/moz.build
@@ -70,10 +70,6 @@ if CONFIG['MOZ_APPLEMEDIA']:
'-framework AudioToolbox',
]
-if CONFIG['MOZ_GONK_MEDIACODEC']:
- DEFINES['MOZ_GONK_MEDIACODEC'] = True
- DIRS += ['gonk']
-
include('/ipc/chromium/chromium-config.mozbuild')
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
diff --git a/dom/secureelement/SEUtils.jsm b/dom/secureelement/SEUtils.jsm
deleted file mode 100644
index d5980b19c..000000000
--- a/dom/secureelement/SEUtils.jsm
+++ /dev/null
@@ -1,116 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-"use strict";
-
-this.SEUtils = {
- byteArrayToHexString: function byteArrayToHexString(array) {
- let hexStr = "";
-
- let len = array ? array.length : 0;
- for (let i = 0; i < len; i++) {
- let hex = (array[i] & 0xff).toString(16);
- hex = (hex.length === 1) ? "0" + hex : hex;
- hexStr += hex;
- }
-
- return hexStr.toUpperCase();
- },
-
- hexStringToByteArray: function hexStringToByteArray(hexStr) {
- if (typeof hexStr !== "string" || hexStr.length % 2 !== 0) {
- return [];
- }
-
- let array = [];
- for (let i = 0, len = hexStr.length; i < len; i += 2) {
- array.push(parseInt(hexStr.substr(i, 2), 16));
- }
-
- return array;
- },
-
- arraysEqual: function arraysEqual(a1, a2) {
- if (!a1 || !a2) {
- return false;
- }
-
- if (a1.length !== a2.length) {
- return false;
- }
-
- for (let i = 0, len = a1.length; i < len; i++) {
- if (a1[i] !== a2[i]) {
- return false;
- }
- }
-
- return true;
- },
-
- ensureIsArray: function ensureIsArray(obj) {
- return Array.isArray(obj) ? obj : [obj];
- },
-
- /**
- * parseTLV is intended primarily to be used to parse Global Platform Device
- * Technology secure element access control data.
- *
- * The parsed result value is an internal format only.
- *
- * All tags will be treated as simple Tag Length Values (TLV), (i.e. with a
- * plain value, not subject to further unpacking), unless those tags are
- * listed in the containerTags array.
- *
- * @param bytes - byte array
- * @param containerTags - byte array of tags
- */
- parseTLV: function parseTLV(bytes, containerTags) {
- let result = {};
-
- if (typeof bytes === "string") {
- bytes = this.hexStringToByteArray(bytes);
- }
-
- if (!Array.isArray(bytes)) {
- debug("Passed value is not an array nor a string.");
- return null;
- }
-
- for (let pos = 0; pos < bytes.length; ) {
- let tag = bytes[pos],
- length = bytes[pos + 1],
- value = bytes.slice(pos + 2, pos + 2 + length),
- parsed = null;
-
- // Support for 0xFF padded files (GPD 7.1.2)
- if (tag === 0xFF) {
- break;
- }
-
- if (containerTags.indexOf(tag) >= 0) {
- parsed = this.parseTLV(value, containerTags);
- } else {
- parsed = value;
- }
-
- // Internal parsed format.
- if (!result[tag]) {
- result[tag] = parsed;
- } else if (Array.isArray(result[tag])) {
- result[tag].push(parsed);
- } else {
- result[tag] = [result[tag], parsed];
- }
-
- pos = pos + 2 + length;
- }
-
- return result;
- }
-};
-
-this.EXPORTED_SYMBOLS = ["SEUtils"];
diff --git a/dom/secureelement/gonk/ACEService.js b/dom/secureelement/gonk/ACEService.js
deleted file mode 100644
index b52ba5fab..000000000
--- a/dom/secureelement/gonk/ACEService.js
+++ /dev/null
@@ -1,139 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-"use strict";
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
- "resource://gre/modules/SEUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "SE", function() {
- let obj = {};
- Cu.import("resource://gre/modules/se_consts.js", obj);
- return obj;
-});
-
-var DEBUG = SE.DEBUG_ACE;
-function debug(msg) {
- if (DEBUG) {
- dump("ACEservice: " + msg + "\n");
- }
-}
-
-/**
- * Implements decision making algorithm as described in GPD specification,
- * mostly in 3.1, 3.2 and 4.2.3.
- *
- * TODO: Bug 1137533: Implement GPAccessRulesManager APDU filters
- */
-function GPAccessDecision(rules, certHash, aid) {
- this.rules = rules;
- this.certHash = certHash;
- this.aid = aid;
-}
-
-GPAccessDecision.prototype = {
- isAccessAllowed: function isAccessAllowed() {
- // GPD SE Access Control v1.1, 3.4.1, Table 3-2: (Conflict resolution)
- // If a specific rule allows, all other non-specific access is denied.
- // Conflicting specific rules will resolve to the first Allowed == "true"
- // match. Given no specific rule, the global "All" rules will determine
- // access. "Some", skips further processing if access Allowed == "true".
- //
- // Access must be decided before the SE connector openChannel, and the
- // exchangeAPDU call.
- //
- // NOTE: This implementation may change with the introduction of APDU
- // filters.
- let decision = this.rules.some(this._decideAppAccess.bind(this));
- return decision;
- },
-
- _decideAppAccess: function _decideAppAccess(rule) {
- let appMatched, appletMatched;
-
- // GPD SE AC 4.2.3: Algorithm for Applying Rules
- // Specific rule overrides global rule.
- //
- // DeviceAppID is the application hash, and the AID is SE Applet ID:
- //
- // GPD SE AC 4.2.3 A:
- // SearchRuleFor(DeviceAppID, AID)
- // GPD SE AC 4.2.3 B: If no rule fits A:
- // SearchRuleFor(<AllDeviceApplications>, AID)
- // GPD SE AC 4.2.3 C: If no rule fits A or B:
- // SearchRuleFor(DeviceAppID, <AllSEApplications>)
- // GPD SE AC 4.2.3 D: If no rule fits A, B, or C:
- // SearchRuleFor(<AllDeviceApplications>, <AllSEApplications>)
-
- // Device App
- appMatched = Array.isArray(rule.application) ?
- // GPD SE AC 4.2.3 A and 4.2.3 C (DeviceAppID rule)
- this._appCertHashMatches(rule.application) :
- // GPD SE AC 4.2.3 B and 4.2.3 D (All Device Applications)
- rule.application === Ci.nsIAccessRulesManager.ALLOW_ALL;
-
- if (!appMatched) {
- return false; // bail out early.
- }
-
- // SE Applet
- appletMatched = Array.isArray(rule.applet) ?
- // GPD SE AC 4.2.3 A and 4.2.3 B (AID rule)
- SEUtils.arraysEqual(rule.applet, this.aid) :
- // GPD SE AC 4.2.3 C and 4.2.3 D (All AID)
- rule.applet === Ci.nsIAccessRulesManager.ALL_APPLET;
-
- return appletMatched;
- },
-
- _appCertHashMatches: function _appCertHashMatches(hashArray) {
- if (!Array.isArray(hashArray)) {
- return false;
- }
-
- return !!(hashArray.find((hash) => {
- return SEUtils.arraysEqual(hash, this.certHash);
- }));
- }
-};
-
-function ACEService() {
- this._rulesManagers = new Map();
-
- this._rulesManagers.set(
- SE.TYPE_UICC,
- Cc["@mozilla.org/secureelement/access-control/rules-manager;1"]
- .createInstance(Ci.nsIAccessRulesManager));
-}
-
-ACEService.prototype = {
- _rulesManagers: null,
-
- isAccessAllowed: function isAccessAllowed(localId, seType, aid) {
- if(!Services.prefs.getBoolPref("devtools.debugger.forbid-certified-apps")) {
- debug("Certified apps debug enabled, allowing access");
- return Promise.resolve(true);
- }
-
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- _getDevCertHashForApp: function getDevCertHashForApp(manifestURL) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- classID: Components.ID("{882a7463-2ca7-4d61-a89a-10eb6fd70478}"),
- contractID: "@mozilla.org/secureelement/access-control/ace;1",
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessControlEnforcer])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ACEService]);
-
diff --git a/dom/secureelement/gonk/ACEService.manifest b/dom/secureelement/gonk/ACEService.manifest
deleted file mode 100644
index 40949c83d..000000000
--- a/dom/secureelement/gonk/ACEService.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {882a7463-2ca7-4d61-a89a-10eb6fd70478} ACEService.js
-contract @mozilla.org/secureelement/access-control/ace;1 {882a7463-2ca7-4d61-a89a-10eb6fd70478} \ No newline at end of file
diff --git a/dom/secureelement/gonk/GPAccessRulesManager.js b/dom/secureelement/gonk/GPAccessRulesManager.js
deleted file mode 100644
index dce11ec09..000000000
--- a/dom/secureelement/gonk/GPAccessRulesManager.js
+++ /dev/null
@@ -1,436 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-"use strict";
-
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyServiceGetter(this, "UiccConnector",
- "@mozilla.org/secureelement/connector/uicc;1",
- "nsISecureElementConnector");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
- "resource://gre/modules/SEUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "SE", function() {
- let obj = {};
- Cu.import("resource://gre/modules/se_consts.js", obj);
- return obj;
-});
-
-XPCOMUtils.defineLazyGetter(this, "GP", function() {
- let obj = {};
- Cu.import("resource://gre/modules/gp_consts.js", obj);
- return obj;
-});
-
-var DEBUG = SE.DEBUG_ACE;
-function debug(msg) {
- if (DEBUG) {
- dump("-*- GPAccessRulesManager " + msg);
- }
-}
-
-/**
- * Based on [1] - "GlobalPlatform Device Technology
- * Secure Element Access Control Version 1.0".
- * GPAccessRulesManager reads and parses access rules from SE file system
- * as defined in section #7 of [1]: "Structure of Access Rule Files (ARF)".
- * Rules retrieval from ARA-M applet is not implmented due to lack of
- * commercial implemenations of ARA-M.
- * @todo Bug 1137537: Implement ARA-M support according to section #4 of [1]
- */
-function GPAccessRulesManager() {}
-
-GPAccessRulesManager.prototype = {
- // source [1] section 7.1.3 PKCS#15 Selection
- PKCS_AID: "a000000063504b43532d3135",
-
- // APDUs (ISO 7816-4) for accessing rules on SE file system
- // see for more details: http://www.cardwerk.com/smartcards/
- // smartcard_standard_ISO7816-4_6_basic_interindustry_commands.aspx
- READ_BINARY: [GP.CLA_SM, GP.INS_RB, GP.P1_RB, GP.P2_RB],
- GET_RESPONSE: [GP.CLA_SM, GP.INS_GR, GP.P1_GR, GP.P2_GR],
- SELECT_BY_DF: [GP.CLA_SM, GP.INS_SF, GP.P1_SF_DF, GP.P2_SF_FCP],
-
- // Non-null if there is a channel open
- channel: null,
-
- // Refresh tag path in the acMain file as described in GPD spec,
- // sections 7.1.5 and C.1.
- REFRESH_TAG_PATH: [GP.TAG_SEQUENCE, GP.TAG_OCTETSTRING],
- refreshTag: null,
-
- // Contains rules as read from the SE
- rules: [],
-
- // Returns the latest rules. Results are cached.
- getAccessRules: function getAccessRules() {
- debug("getAccessRules");
-
- return new Promise((resolve, reject) => {
- this._readAccessRules(() => resolve(this.rules));
- });
- },
-
- _readAccessRules: Task.async(function*(done) {
- try {
- yield this._openChannel(this.PKCS_AID);
-
- let odf = yield this._readODF();
- let dodf = yield this._readDODF(odf);
-
- let acmf = yield this._readACMF(dodf);
- let refreshTag = acmf[this.REFRESH_TAG_PATH[0]]
- [this.REFRESH_TAG_PATH[1]];
-
- // Update cached rules based on refreshTag.
- if (SEUtils.arraysEqual(this.refreshTag, refreshTag)) {
- debug("_readAccessRules: refresh tag equals to the one saved.");
- yield this._closeChannel();
- return done();
- }
-
- this.refreshTag = refreshTag;
- debug("_readAccessRules: refresh tag saved: " + this.refreshTag);
-
- let acrf = yield this._readACRules(acmf);
- let accf = yield this._readACConditions(acrf);
- this.rules = yield this._parseRules(acrf, accf);
-
- DEBUG && debug("_readAccessRules: " + JSON.stringify(this.rules, 0, 2));
-
- yield this._closeChannel();
- done();
- } catch (error) {
- debug("_readAccessRules: " + error);
- this.rules = [];
- yield this._closeChannel();
- done();
- }
- }),
-
- _openChannel: function _openChannel(aid) {
- if (this.channel !== null) {
- debug("_openChannel: Channel already opened, rejecting.");
- return Promise.reject();
- }
-
- return new Promise((resolve, reject) => {
- UiccConnector.openChannel(aid, {
- notifyOpenChannelSuccess: (channel, openResponse) => {
- debug("_openChannel/notifyOpenChannelSuccess: Channel " + channel +
- " opened, open response: " + openResponse);
- this.channel = channel;
- resolve();
- },
- notifyError: (error) => {
- debug("_openChannel/notifyError: failed to open channel, error: " +
- error);
- reject(error);
- }
- });
- });
- },
-
- _closeChannel: function _closeChannel() {
- if (this.channel === null) {
- debug("_closeChannel: Channel not opened, rejecting.");
- return Promise.reject();
- }
-
- return new Promise((resolve, reject) => {
- UiccConnector.closeChannel(this.channel, {
- notifyCloseChannelSuccess: () => {
- debug("_closeChannel/notifyCloseChannelSuccess: chanel " +
- this.channel + " closed");
- this.channel = null;
- resolve();
- },
- notifyError: (error) => {
- debug("_closeChannel/notifyError: error closing channel, error" +
- error);
- reject(error);
- }
- });
- });
- },
-
- _exchangeAPDU: function _exchangeAPDU(bytes) {
- DEBUG && debug("apdu " + JSON.stringify(bytes));
-
- let apdu = this._bytesToAPDU(bytes);
- return new Promise((resolve, reject) => {
- UiccConnector.exchangeAPDU(this.channel, apdu.cla,
- apdu.ins, apdu.p1, apdu.p2, apdu.data, apdu.le,
- {
- notifyExchangeAPDUResponse: (sw1, sw2, data) => {
- debug("APDU response is " + sw1.toString(16) + sw2.toString(16) +
- " data: " + data);
-
- // 90 00 is "success"
- if (sw1 !== 0x90 && sw2 !== 0x00) {
- debug("rejecting APDU response");
- reject(new Error("Response " + sw1 + "," + sw2));
- return;
- }
-
- resolve(this._parseTLV(data));
- },
-
- notifyError: (error) => {
- debug("_exchangeAPDU/notifyError " + error);
- reject(error);
- }
- }
- );
- });
- },
-
- _readBinaryFile: function _readBinaryFile(selectResponse) {
- DEBUG && debug("Select response: " + JSON.stringify(selectResponse));
- // 0x80 tag parameter - get the elementary file (EF) length
- // without structural information.
- let fileLength = selectResponse[GP.TAG_FCP][0x80];
-
- // If file is empty, no need to attempt to read it.
- if (fileLength[0] === 0 && fileLength[1] === 0) {
- return Promise.resolve(null);
- }
-
- // TODO READ BINARY with filelength not supported
- // let readApdu = this.READ_BINARY.concat(fileLength);
- return this._exchangeAPDU(this.READ_BINARY);
- },
-
- _selectAndRead: function _selectAndRead(df) {
- return this._exchangeAPDU(this.SELECT_BY_DF.concat(df.length & 0xFF, df))
- .then((resp) => this._readBinaryFile(resp));
- },
-
- _readODF: function _readODF() {
- debug("_readODF");
- return this._selectAndRead(GP.ODF_DF);
- },
-
- _readDODF: function _readDODF(odfFile) {
- debug("_readDODF, ODF file: " + odfFile);
-
- // Data Object Directory File (DODF) is used as an entry point to the
- // Access Control data. It is specified in PKCS#15 section 6.7.6.
- // DODF is referenced by the ODF file, which looks as follows:
- // A7 06
- // 30 04
- // 04 02 XY WZ
- // where [0xXY, 0xWZ] is a DF of DODF file.
- let DODF_DF = odfFile[GP.TAG_EF_ODF][GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
- return this._selectAndRead(DODF_DF);
- },
-
- _readACMF: function _readACMF(dodfFile) {
- debug("_readACMF, DODF file: " + dodfFile);
-
- // ACMF file DF is referenced in DODF file, which looks like this:
- //
- // A1 29
- // 30 00
- // 30 0F
- // 0C 0D 47 50 20 53 45 20 41 63 63 20 43 74 6C
- // A1 14
- // 30 12
- // 06 0A 2A 86 48 86 FC 6B 81 48 01 01 <-- GPD registered OID
- // 30 04
- // 04 02 AB CD <-- ACMF DF
- // A1 2B
- // 30 00
- // 30 0F
- // 0C 0D 53 41 54 53 41 20 47 54 4F 20 31 2E 31
- // A1 16
- // 30 14
- // 06 0C 2B 06 01 04 01 2A 02 6E 03 01 01 01 <-- some other OID
- // 30 04
- // 04 02 XY WZ <-- some other file's DF
- //
- // DODF file consists of DataTypes with oidDO entries. Entry with OID
- // equal to "1.2.840.114283.200.1.1" ("2A 86 48 86 FC 6B 81 48 01 01")
- // contains DF of the ACMF. In the file above, it means that ACMF DF
- // equals to [0xAB, 0xCD], and not [0xXY, 0xWZ].
- //
- // Algorithm used to encode OID to an byte array:
- // http://www.snmpsharpnet.com/?p=153
-
- let gpdOid = [0x2A, // 1.2
- 0x86, 0x48, // 840
- 0x86, 0xFC, 0x6B, // 114283
- 0x81, 0x48, // 129
- 0x01, // 1
- 0x01]; // 1
-
- let records = SEUtils.ensureIsArray(dodfFile[GP.TAG_EXTERNALDO]);
-
- // Look for the OID registered for GPD SE.
- let gpdRecords = records.filter((record) => {
- let oid = record[GP.TAG_EXTERNALDO][GP.TAG_SEQUENCE][GP.TAG_OID];
- return SEUtils.arraysEqual(oid, gpdOid);
- });
-
- // [1] 7.1.5: "There shall be only one ACMF file per Secure Element.
- // If a Secure Element contains several ACMF files, then the security shall
- // be considered compromised and the Access Control enforcer shall forbid
- // access to all (...) apps."
- if (gpdRecords.length !== 1) {
- return Promise.reject(new Error(gpdRecords.length + " ACMF files found"));
- }
-
- let ACMain_DF = gpdRecords[0][GP.TAG_EXTERNALDO][GP.TAG_SEQUENCE]
- [GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
- return this._selectAndRead(ACMain_DF);
- },
-
- _readACRules: function _readACRules(acMainFile) {
- debug("_readACRules, ACMain file: " + acMainFile);
-
- // ACMF looks like this:
- //
- // 30 10
- // 04 08 XX XX XX XX XX XX XX XX
- // 30 04
- // 04 02 XY WZ
- //
- // where [XY, WZ] is a DF of ACRF, and XX XX XX XX XX XX XX XX is a refresh
- // tag.
-
- let ACRules_DF = acMainFile[GP.TAG_SEQUENCE][GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
- return this._selectAndRead(ACRules_DF);
- },
-
- _readACConditions: function _readACConditions(acRulesFile) {
- debug("_readACCondition, ACRules file: " + acRulesFile);
-
- let acRules = SEUtils.ensureIsArray(acRulesFile[GP.TAG_SEQUENCE]);
- if (acRules.length === 0) {
- debug("No rules found in ACRules file.");
- return Promise.reject(new Error("No rules found in ACRules file"));
- }
-
- // We first read all the condition files referenced in the ACRules file,
- // because ACRules file might reference one ACCondition file more than
- // once. Since reading it isn't exactly fast, we optimize here.
- let acReadQueue = Promise.resolve({});
-
- acRules.forEach((ruleEntry) => {
- let df = ruleEntry[GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
-
- // Promise chain read condition entries:
- let readAcCondition = (acConditionFiles) => {
- if (acConditionFiles[df] !== undefined) {
- debug("Skipping previously read acCondition df: " + df);
- return acConditionFiles;
- }
-
- return this._selectAndRead(df)
- .then((acConditionFileContents) => {
- acConditionFiles[df] = acConditionFileContents;
- return acConditionFiles;
- });
- }
-
- acReadQueue = acReadQueue.then(readAcCondition);
- });
-
- return acReadQueue;
- },
-
- _parseRules: function _parseRules(acRulesFile, acConditionFiles) {
- DEBUG && debug("_parseRules: acConditionFiles " + JSON.stringify(acConditionFiles));
- let rules = [];
-
- let acRules = SEUtils.ensureIsArray(acRulesFile[GP.TAG_SEQUENCE]);
- acRules.forEach((ruleEntry) => {
- DEBUG && debug("Parsing one rule: " + JSON.stringify(ruleEntry));
- let rule = {};
-
- // 0xA0 and 0x82 tags as per GPD spec sections C.1 - C.3. 0xA0 means
- // that rule describes access to one SE applet only (and its AID is
- // given). 0x82 means that rule describes acccess to all SE applets.
- let oneApplet = ruleEntry[GP.TAG_GPD_AID];
- let allApplets = ruleEntry[GP.TAG_GPD_ALL];
-
- if (oneApplet) {
- rule.applet = oneApplet[GP.TAG_OCTETSTRING];
- } else if (allApplets) {
- rule.applet = Ci.nsIAccessRulesManager.ALL_APPLET;
- } else {
- throw Error("Unknown applet definition");
- }
-
- let df = ruleEntry[GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING];
- let condition = acConditionFiles[df];
- if (condition === null) {
- rule.application = Ci.nsIAccessRulesManager.DENY_ALL;
- } else if (condition[GP.TAG_SEQUENCE]) {
- if (!Array.isArray(condition[GP.TAG_SEQUENCE]) &&
- !condition[GP.TAG_SEQUENCE][GP.TAG_OCTETSTRING]) {
- rule.application = Ci.nsIAccessRulesManager.ALLOW_ALL;
- } else {
- rule.application = SEUtils.ensureIsArray(condition[GP.TAG_SEQUENCE])
- .map((conditionEntry) => {
- return conditionEntry[GP.TAG_OCTETSTRING];
- });
- }
- } else {
- throw Error("Unknown application definition");
- }
-
- DEBUG && debug("Rule parsed, adding to the list: " + JSON.stringify(rule));
- rules.push(rule);
- });
-
- DEBUG && debug("All rules parsed, we have those in total: " + JSON.stringify(rules));
- return rules;
- },
-
- _parseTLV: function _parseTLV(bytes) {
- let containerTags = [
- GP.TAG_SEQUENCE,
- GP.TAG_FCP,
- GP.TAG_GPD_AID,
- GP.TAG_EXTERNALDO,
- GP.TAG_INDIRECT,
- GP.TAG_EF_ODF
- ];
- return SEUtils.parseTLV(bytes, containerTags);
- },
-
- // TODO consider removing if better format for storing
- // APDU consts will be introduced
- _bytesToAPDU: function _bytesToAPDU(arr) {
- let apdu = {
- cla: arr[0] & 0xFF,
- ins: arr[1] & 0xFF,
- p1: arr[2] & 0xFF,
- p2: arr[3] & 0xFF,
- p3: arr[4] & 0xFF,
- le: 0
- };
-
- let data = (apdu.p3 > 0) ? (arr.slice(5)) : [];
- apdu.data = (data.length) ? SEUtils.byteArrayToHexString(data) : null;
- return apdu;
- },
-
- classID: Components.ID("{3e046b4b-9e66-439a-97e0-98a69f39f55f}"),
- contractID: "@mozilla.org/secureelement/access-control/rules-manager;1",
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessRulesManager])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([GPAccessRulesManager]);
diff --git a/dom/secureelement/gonk/GPAccessRulesManager.manifest b/dom/secureelement/gonk/GPAccessRulesManager.manifest
deleted file mode 100644
index 2d7ea038b..000000000
--- a/dom/secureelement/gonk/GPAccessRulesManager.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {3e046b4b-9e66-439a-97e0-98a69f39f55f} GPAccessRulesManager.js
-contract @mozilla.org/secureelement/access-control/rules-manager;1 {3e046b4b-9e66-439a-97e0-98a69f39f55f}
diff --git a/dom/secureelement/gonk/SecureElement.js b/dom/secureelement/gonk/SecureElement.js
deleted file mode 100644
index 144c6d8d6..000000000
--- a/dom/secureelement/gonk/SecureElement.js
+++ /dev/null
@@ -1,514 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Copyright © 2014, Deutsche Telekom, Inc. */
-
-"use strict";
-
-/* globals dump, Components, XPCOMUtils, SE, Services, UiccConnector,
- SEUtils, ppmm, gMap, UUIDGenerator */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyGetter(this, "SE", () => {
- let obj = {};
- Cu.import("resource://gre/modules/se_consts.js", obj);
- return obj;
-});
-
-// set to true in se_consts.js to see debug messages
-var DEBUG = SE.DEBUG_SE;
-function debug(s) {
- if (DEBUG) {
- dump("-*- SecureElement: " + s + "\n");
- }
-}
-
-const SE_IPC_SECUREELEMENT_MSG_NAMES = [
- "SE:GetSEReaders",
- "SE:OpenChannel",
- "SE:CloseChannel",
- "SE:TransmitAPDU"
-];
-
-const SECUREELEMENTMANAGER_CONTRACTID =
- "@mozilla.org/secureelement/parent-manager;1";
-const SECUREELEMENTMANAGER_CID =
- Components.ID("{48f4e650-28d2-11e4-8c21-0800200c9a66}");
-const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageBroadcaster");
-
-XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator",
- "@mozilla.org/uuid-generator;1",
- "nsIUUIDGenerator");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
- "resource://gre/modules/SEUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "UiccConnector", () => {
- let uiccClass = Cc["@mozilla.org/secureelement/connector/uicc;1"];
- return uiccClass ? uiccClass.getService(Ci.nsISecureElementConnector) : null;
-});
-
-function getConnector(type) {
- switch (type) {
- case SE.TYPE_UICC:
- return UiccConnector;
- case SE.TYPE_ESE:
- default:
- debug("Unsupported SEConnector : " + type);
- return null;
- }
-}
-
-/**
- * 'gMap' is a nested dictionary object that manages all the information
- * pertaining to channels for a given application (appId). It manages the
- * relationship between given application and its opened channels.
- */
-XPCOMUtils.defineLazyGetter(this, "gMap", function() {
- return {
- // example structure of AppInfoMap
- // {
- // "appId1": {
- // target: target1,
- // channels: {
- // "channelToken1": {
- // seType: "uicc",
- // aid: "aid1",
- // channelNumber: 1
- // },
- // "channelToken2": { ... }
- // }
- // },
- // "appId2": { ... }
- // }
- appInfoMap: {},
-
- registerSecureElementTarget: function(appId, target) {
- if (this.isAppIdRegistered(appId)) {
- debug("AppId: " + appId + "already registered");
- return;
- }
-
- this.appInfoMap[appId] = {
- target: target,
- channels: {}
- };
-
- debug("Registered a new SE target " + appId);
- },
-
- unregisterSecureElementTarget: function(target) {
- let appId = Object.keys(this.appInfoMap).find((id) => {
- return this.appInfoMap[id].target === target;
- });
-
- if (!appId) {
- return;
- }
-
- debug("Unregistered SE Target for AppId: " + appId);
- delete this.appInfoMap[appId];
- },
-
- isAppIdRegistered: function(appId) {
- return this.appInfoMap[appId] !== undefined;
- },
-
- getChannelCountByAppIdType: function(appId, type) {
- return Object.keys(this.appInfoMap[appId].channels)
- .reduce((cnt, ch) => ch.type === type ? ++cnt : cnt, 0);
- },
-
- // Add channel to the appId. Upon successfully adding the entry
- // this function will return the 'token'
- addChannel: function(appId, type, aid, channelNumber) {
- let token = UUIDGenerator.generateUUID().toString();
- this.appInfoMap[appId].channels[token] = {
- seType: type,
- aid: aid,
- channelNumber: channelNumber
- };
- return token;
- },
-
- removeChannel: function(appId, channelToken) {
- if (this.appInfoMap[appId].channels[channelToken]) {
- debug("Deleting channel with token : " + channelToken);
- delete this.appInfoMap[appId].channels[channelToken];
- }
- },
-
- getChannel: function(appId, channelToken) {
- if (!this.appInfoMap[appId].channels[channelToken]) {
- return null;
- }
-
- return this.appInfoMap[appId].channels[channelToken];
- },
-
- getChannelsByTarget: function(target) {
- let appId = Object.keys(this.appInfoMap).find((id) => {
- return this.appInfoMap[id].target === target;
- });
-
- if (!appId) {
- return [];
- }
-
- return Object.keys(this.appInfoMap[appId].channels)
- .map(token => this.appInfoMap[appId].channels[token]);
- },
-
- getTargets: function() {
- return Object.keys(this.appInfoMap)
- .map(appId => this.appInfoMap[appId].target);
- },
- };
-});
-
-/**
- * 'SecureElementManager' is the main object that handles IPC messages from
- * child process. It interacts with other objects such as 'gMap' & 'Connector
- * instances (UiccConnector, eSEConnector)' to perform various
- * SE-related (open, close, transmit) operations.
- * @TODO: Bug 1118097 Support slot based SE/reader names
- * @TODO: Bug 1118101 Introduce SE type specific permissions
- */
-function SecureElementManager() {
- this._registerMessageListeners();
- this._registerSEListeners();
- Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
- this._acEnforcer =
- Cc["@mozilla.org/secureelement/access-control/ace;1"]
- .getService(Ci.nsIAccessControlEnforcer);
-}
-
-SecureElementManager.prototype = {
- QueryInterface: XPCOMUtils.generateQI([
- Ci.nsIMessageListener,
- Ci.nsISEListener,
- Ci.nsIObserver]),
- classID: SECUREELEMENTMANAGER_CID,
- classInfo: XPCOMUtils.generateCI({
- classID: SECUREELEMENTMANAGER_CID,
- classDescription: "SecureElementManager",
- interfaces: [Ci.nsIMessageListener,
- Ci.nsISEListener,
- Ci.nsIObserver]
- }),
-
- // Stores information about supported SE types and their presence.
- // key: secure element type, value: (Boolean) is present/accessible
- _sePresence: {},
-
- _acEnforcer: null,
-
- _shutdown: function() {
- this._acEnforcer = null;
- this.secureelement = null;
- Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
- this._unregisterMessageListeners();
- this._unregisterSEListeners();
- },
-
- _registerMessageListeners: function() {
- ppmm.addMessageListener("child-process-shutdown", this);
- for (let msgname of SE_IPC_SECUREELEMENT_MSG_NAMES) {
- ppmm.addMessageListener(msgname, this);
- }
- },
-
- _unregisterMessageListeners: function() {
- ppmm.removeMessageListener("child-process-shutdown", this);
- for (let msgname of SE_IPC_SECUREELEMENT_MSG_NAMES) {
- ppmm.removeMessageListener(msgname, this);
- }
- ppmm = null;
- },
-
- _registerSEListeners: function() {
- let connector = getConnector(SE.TYPE_UICC);
- if (!connector) {
- return;
- }
-
- this._sePresence[SE.TYPE_UICC] = false;
- connector.registerListener(this);
- },
-
- _unregisterSEListeners: function() {
- Object.keys(this._sePresence).forEach((type) => {
- let connector = getConnector(type);
- if (connector) {
- connector.unregisterListener(this);
- }
- });
-
- this._sePresence = {};
- },
-
- notifySEPresenceChanged: function(type, isPresent) {
- // we need to notify all targets, even those without open channels,
- // app could've stored the reader without actually using it
- debug("notifying DOM about SE state change");
- this._sePresence[type] = isPresent;
- gMap.getTargets().forEach(target => {
- let result = { type: type, isPresent: isPresent };
- target.sendAsyncMessage("SE:ReaderPresenceChanged", { result: result });
- });
- },
-
- _canOpenChannel: function(appId, type) {
- let opened = gMap.getChannelCountByAppIdType(appId, type);
- let limit = SE.MAX_CHANNELS_ALLOWED_PER_SESSION;
- // UICC basic channel is not accessible see comment in se_consts.js
- limit = type === SE.TYPE_UICC ? limit - 1 : limit;
- return opened < limit;
- },
-
- _handleOpenChannel: function(msg, callback) {
- if (!this._canOpenChannel(msg.appId, msg.type)) {
- debug("Max channels per session exceed");
- callback({ error: SE.ERROR_GENERIC });
- return;
- }
-
- let connector = getConnector(msg.type);
- if (!connector) {
- debug("No SE connector available");
- callback({ error: SE.ERROR_NOTPRESENT });
- return;
- }
-
- this._acEnforcer.isAccessAllowed(msg.appId, msg.type, msg.aid)
- .then((allowed) => {
- if (!allowed) {
- callback({ error: SE.ERROR_SECURITY });
- return;
- }
- connector.openChannel(SEUtils.byteArrayToHexString(msg.aid), {
-
- notifyOpenChannelSuccess: (channelNumber, openResponse) => {
- // Add the new 'channel' to the map upon success
- let channelToken =
- gMap.addChannel(msg.appId, msg.type, msg.aid, channelNumber);
- if (channelToken) {
- callback({
- error: SE.ERROR_NONE,
- channelToken: channelToken,
- isBasicChannel: (channelNumber === SE.BASIC_CHANNEL),
- openResponse: SEUtils.hexStringToByteArray(openResponse)
- });
- } else {
- callback({ error: SE.ERROR_GENERIC });
- }
- },
-
- notifyError: (reason) => {
- debug("Failed to open the channel to AID : " +
- SEUtils.byteArrayToHexString(msg.aid) +
- ", Rejected with Reason : " + reason);
- callback({ error: SE.ERROR_GENERIC, reason: reason, response: [] });
- }
- });
- })
- .catch((error) => {
- debug("Failed to get info from accessControlEnforcer " + error);
- callback({ error: SE.ERROR_SECURITY });
- });
- },
-
- _handleTransmit: function(msg, callback) {
- let channel = gMap.getChannel(msg.appId, msg.channelToken);
- if (!channel) {
- debug("Invalid token:" + msg.channelToken + ", appId: " + msg.appId);
- callback({ error: SE.ERROR_GENERIC });
- return;
- }
-
- let connector = getConnector(channel.seType);
- if (!connector) {
- debug("No SE connector available");
- callback({ error: SE.ERROR_NOTPRESENT });
- return;
- }
-
- // Bug 1137533 - ACE GPAccessRulesManager APDU filters
- connector.exchangeAPDU(channel.channelNumber, msg.apdu.cla, msg.apdu.ins,
- msg.apdu.p1, msg.apdu.p2,
- SEUtils.byteArrayToHexString(msg.apdu.data),
- msg.apdu.le, {
- notifyExchangeAPDUResponse: (sw1, sw2, response) => {
- callback({
- error: SE.ERROR_NONE,
- sw1: sw1,
- sw2: sw2,
- response: SEUtils.hexStringToByteArray(response)
- });
- },
-
- notifyError: (reason) => {
- debug("Transmit failed, rejected with Reason : " + reason);
- callback({ error: SE.ERROR_INVALIDAPPLICATION, reason: reason });
- }
- });
- },
-
- _handleCloseChannel: function(msg, callback) {
- let channel = gMap.getChannel(msg.appId, msg.channelToken);
- if (!channel) {
- debug("Invalid token:" + msg.channelToken + ", appId:" + msg.appId);
- callback({ error: SE.ERROR_GENERIC });
- return;
- }
-
- let connector = getConnector(channel.seType);
- if (!connector) {
- debug("No SE connector available");
- callback({ error: SE.ERROR_NOTPRESENT });
- return;
- }
-
- connector.closeChannel(channel.channelNumber, {
- notifyCloseChannelSuccess: () => {
- gMap.removeChannel(msg.appId, msg.channelToken);
- callback({ error: SE.ERROR_NONE });
- },
-
- notifyError: (reason) => {
- debug("Failed to close channel with token: " + msg.channelToken +
- ", reason: "+ reason);
- callback({ error: SE.ERROR_BADSTATE, reason: reason });
- }
- });
- },
-
- _handleGetSEReadersRequest: function(msg, target, callback) {
- gMap.registerSecureElementTarget(msg.appId, target);
- let readers = Object.keys(this._sePresence).map(type => {
- return { type: type, isPresent: this._sePresence[type] };
- });
- callback({ readers: readers, error: SE.ERROR_NONE });
- },
-
- _handleChildProcessShutdown: function(target) {
- let channels = gMap.getChannelsByTarget(target);
-
- let createCb = (seType, channelNumber) => {
- return {
- notifyCloseChannelSuccess: () => {
- debug("closed " + seType + ", channel " + channelNumber);
- },
-
- notifyError: (reason) => {
- debug("Failed to close " + seType + " channel " +
- channelNumber + ", reason: " + reason);
- }
- };
- };
-
- channels.forEach((channel) => {
- let connector = getConnector(channel.seType);
- if (!connector) {
- return;
- }
-
- connector.closeChannel(channel.channelNumber,
- createCb(channel.seType, channel.channelNumber));
- });
-
- gMap.unregisterSecureElementTarget(target);
- },
-
- _sendSEResponse: function(msg, result) {
- let promiseStatus = (result.error === SE.ERROR_NONE) ? "Resolved" : "Rejected";
- result.resolverId = msg.data.resolverId;
- msg.target.sendAsyncMessage(msg.name + promiseStatus, {result: result});
- },
-
- _isValidMessage: function(msg) {
- let appIdValid = gMap.isAppIdRegistered(msg.data.appId);
- return msg.name === "SE:GetSEReaders" ? true : appIdValid;
- },
-
- /**
- * nsIMessageListener interface methods.
- */
-
- receiveMessage: function(msg) {
- DEBUG && debug("Received '" + msg.name + "' message from content process" +
- ": " + JSON.stringify(msg.data));
-
- if (msg.name === "child-process-shutdown") {
- this._handleChildProcessShutdown(msg.target);
- return null;
- }
-
- if (SE_IPC_SECUREELEMENT_MSG_NAMES.indexOf(msg.name) !== -1) {
- if (!msg.target.assertPermission("secureelement-manage")) {
- debug("SecureElement message " + msg.name + " from a content process " +
- "with no 'secureelement-manage' privileges.");
- return null;
- }
- } else {
- debug("Ignoring unknown message type: " + msg.name);
- return null;
- }
-
- let callback = (result) => this._sendSEResponse(msg, result);
- if (!this._isValidMessage(msg)) {
- debug("Message not valid");
- callback({ error: SE.ERROR_GENERIC });
- return null;
- }
-
- switch (msg.name) {
- case "SE:GetSEReaders":
- this._handleGetSEReadersRequest(msg.data, msg.target, callback);
- break;
- case "SE:OpenChannel":
- this._handleOpenChannel(msg.data, callback);
- break;
- case "SE:CloseChannel":
- this._handleCloseChannel(msg.data, callback);
- break;
- case "SE:TransmitAPDU":
- this._handleTransmit(msg.data, callback);
- break;
- }
- return null;
- },
-
- /**
- * nsIObserver interface methods.
- */
-
- observe: function(subject, topic, data) {
- if (topic === NS_XPCOM_SHUTDOWN_OBSERVER_ID) {
- this._shutdown();
- }
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SecureElementManager]);
diff --git a/dom/secureelement/gonk/SecureElement.manifest b/dom/secureelement/gonk/SecureElement.manifest
deleted file mode 100644
index a76fcfc11..000000000
--- a/dom/secureelement/gonk/SecureElement.manifest
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2012 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# SecureElementManager
-component {48f4e650-28d2-11e4-8c21-0800200c9a66} SecureElement.js
-contract @mozilla.org/secureelement/parent-manager;1 {48f4e650-28d2-11e4-8c21-0800200c9a66}
-category profile-after-change SecureElementManager @mozilla.org/secureelement/parent-manager;1
diff --git a/dom/secureelement/gonk/UiccConnector.js b/dom/secureelement/gonk/UiccConnector.js
deleted file mode 100644
index 517303de2..000000000
--- a/dom/secureelement/gonk/UiccConnector.js
+++ /dev/null
@@ -1,360 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Copyright © 2014, Deutsche Telekom, Inc. */
-
-"use strict";
-
-/* globals Components, XPCOMUtils, SE, dump, libcutils, Services,
- iccService, SEUtils */
-
-const { interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyGetter(this, "SE", function() {
- let obj = {};
- Cu.import("resource://gre/modules/se_consts.js", obj);
- return obj;
-});
-
-// set to true in se_consts.js to see debug messages
-var DEBUG = SE.DEBUG_CONNECTOR;
-function debug(s) {
- if (DEBUG) {
- dump("-*- UiccConnector: " + s + "\n");
- }
-}
-
-XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
- "resource://gre/modules/SEUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "iccService",
- "@mozilla.org/icc/iccservice;1",
- "nsIIccService");
-
-const UICCCONNECTOR_CONTRACTID =
- "@mozilla.org/secureelement/connector/uicc;1";
-const UICCCONNECTOR_CID =
- Components.ID("{8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4}");
-const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
-
-// TODO: Bug 1118099 - Add multi-sim support.
-// In the Multi-sim, there is more than one client.
-// For now, use default clientID as 0. Ideally, SE parent process would like to
-// know which clients (uicc slot) are connected to CLF over SWP interface.
-const PREFERRED_UICC_CLIENTID =
- libcutils.property_get("ro.moz.se.def_client_id", "0");
-
-/**
- * 'UiccConnector' object is a wrapper over iccService's channel management
- * related interfaces that implements nsISecureElementConnector interface.
- */
-function UiccConnector() {
- this._init();
-}
-
-UiccConnector.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISecureElementConnector,
- Ci.nsIIccListener]),
- classID: UICCCONNECTOR_CID,
- classInfo: XPCOMUtils.generateCI({
- classID: UICCCONNECTOR_CID,
- contractID: UICCCONNECTOR_CONTRACTID,
- classDescription: "UiccConnector",
- interfaces: [Ci.nsISecureElementConnector,
- Ci.nsIIccListener,
- Ci.nsIObserver]
- }),
-
- _SEListeners: [],
- _isPresent: false,
-
- _init: function() {
- Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.registerListener(this);
-
- // Update the state in order to avoid race condition.
- // By this time, 'notifyCardStateChanged (with proper card state)'
- // may have occurred already before this module initialization.
- this._updatePresenceState();
- },
-
- _shutdown: function() {
- Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.unregisterListener(this);
- },
-
- _updatePresenceState: function() {
- let uiccNotReadyStates = [
- Ci.nsIIcc.CARD_STATE_UNKNOWN,
- Ci.nsIIcc.CARD_STATE_ILLEGAL,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_IN_PROGRESS,
- Ci.nsIIcc.CARD_STATE_PERMANENT_BLOCKED,
- Ci.nsIIcc.CARD_STATE_UNDETECTED
- ];
-
- let cardState = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID).cardState;
- let uiccPresent = cardState !== null &&
- uiccNotReadyStates.indexOf(cardState) == -1;
-
- if (this._isPresent === uiccPresent) {
- return;
- }
-
- debug("Uicc presence changed " + this._isPresent + " -> " + uiccPresent);
- this._isPresent = uiccPresent;
- this._SEListeners.forEach((listener) => {
- listener.notifySEPresenceChanged(SE.TYPE_UICC, this._isPresent);
- });
- },
-
- // See GP Spec, 11.1.4 Class Byte Coding
- _setChannelToCLAByte: function(cla, channel) {
- if (channel < SE.LOGICAL_CHANNEL_NUMBER_LIMIT) {
- // b7 = 0 indicates the first interindustry class byte coding
- cla = (cla & 0x9C) & 0xFF | channel;
- } else if (channel < SE.SUPPLEMENTARY_LOGICAL_CHANNEL_NUMBER_LIMIT) {
- // b7 = 1 indicates the further interindustry class byte coding
- cla = (cla & 0xB0) & 0xFF | 0x40 | (channel - SE.LOGICAL_CHANNEL_NUMBER_LIMIT);
- } else {
- debug("Channel number must be within [0..19]");
- return SE.ERROR_GENERIC;
- }
- return cla;
- },
-
- _doGetOpenResponse: function(channel, length, callback) {
- // Le value is set. It means that this is a request for all available
- // response bytes.
- let cla = this._setChannelToCLAByte(SE.CLA_GET_RESPONSE, channel);
- this.exchangeAPDU(channel, cla, SE.INS_GET_RESPONSE, 0x00, 0x00,
- null, length, {
- notifyExchangeAPDUResponse: function(sw1, sw2, response) {
- debug("GET Response : " + response);
- if (callback) {
- callback({
- error: SE.ERROR_NONE,
- sw1: sw1,
- sw2: sw2,
- response: response
- });
- }
- },
-
- notifyError: function(reason) {
- debug("Failed to get open response: " +
- ", Rejected with Reason : " + reason);
- if (callback) {
- callback({ error: SE.ERROR_INVALIDAPPLICATION, reason: reason });
- }
- }
- });
- },
-
- _doIccExchangeAPDU: function(channel, cla, ins, p1, p2, p3,
- data, appendResp, callback) {
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.iccExchangeAPDU(channel, cla & 0xFC, ins, p1, p2, p3, data, {
- notifyExchangeAPDUResponse: (sw1, sw2, response) => {
- debug("sw1 : " + sw1 + ", sw2 : " + sw2 + ", response : " + response);
-
- // According to ETSI TS 102 221 , Section 7.2.2.3.1,
- // Enforce 'Procedure bytes' checks before notifying the callback.
- // Note that 'Procedure bytes'are special cases.
- // There is no need to handle '0x60' procedure byte as it implies
- // no-action from SE stack perspective. This procedure byte is not
- // notified to application layer.
- if (sw1 === 0x6C) {
- // Use the previous command header with length as second procedure
- // byte (SW2) as received and repeat the procedure.
-
- // Recursive! and Pass empty response '' as args, since '0x6C'
- // procedure does not have to deal with appended responses.
- this._doIccExchangeAPDU(channel, cla, ins, p1, p2,
- sw2, data, "", callback);
- } else if (sw1 === 0x61) {
- // Since the terminal waited for a second procedure byte and
- // received it (sw2), send a GET RESPONSE command header to the UICC
- // with a maximum length of 'XX', where 'XX' is the value of the
- // second procedure byte (SW2).
-
- let claWithChannel = this._setChannelToCLAByte(SE.CLA_GET_RESPONSE,
- channel);
-
- // Recursive, with GET RESPONSE bytes and '0x61' procedure IS interested
- // in appended responses. Pass appended response and note that p3=sw2.
- this._doIccExchangeAPDU(channel, claWithChannel, SE.INS_GET_RESPONSE,
- 0x00, 0x00, sw2, null,
- (response ? response + appendResp : appendResp),
- callback);
- } else if (callback) {
- callback.notifyExchangeAPDUResponse(sw1, sw2, response);
- }
- },
-
- notifyError: (reason) => {
- debug("Failed to trasmit C-APDU over the channel # : " + channel +
- ", Rejected with Reason : " + reason);
- if (callback) {
- callback.notifyError(reason);
- }
- }
- });
- },
-
- /**
- * nsISecureElementConnector interface methods.
- */
-
- /**
- * Opens a channel on a default clientId
- */
- openChannel: function(aid, callback) {
- if (!this._isPresent) {
- callback.notifyError(SE.ERROR_NOTPRESENT);
- return;
- }
-
- // TODO: Bug 1118106: Handle Resource management / leaks by persisting
- // the newly opened channel in some persistent storage so that when this
- // module gets restarted (say after opening a channel) in the event of
- // some erroneous conditions such as gecko restart /, crash it can read
- // the persistent storage to check if there are any held resources
- // (opened channels) and close them.
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.iccOpenChannel(aid, {
- notifyOpenChannelSuccess: (channel) => {
- this._doGetOpenResponse(channel, 0x00, function(result) {
- if (callback) {
- callback.notifyOpenChannelSuccess(channel, result.response);
- }
- });
- },
-
- notifyError: (reason) => {
- debug("Failed to open the channel to AID : " + aid +
- ", Rejected with Reason : " + reason);
- if (callback) {
- callback.notifyError(reason);
- }
- }
- });
- },
-
- /**
- * Transmit the C-APDU (command) on default clientId.
- */
- exchangeAPDU: function(channel, cla, ins, p1, p2, data, le, callback) {
- if (!this._isPresent) {
- callback.notifyError(SE.ERROR_NOTPRESENT);
- return;
- }
-
- if (data && data.length % 2 !== 0) {
- callback.notifyError("Data should be a hex string with length % 2 === 0");
- return;
- }
-
- cla = this._setChannelToCLAByte(cla, channel);
- let lc = data ? data.length / 2 : 0;
- let p3 = lc || le;
-
- if (lc && (le !== -1)) {
- data += SEUtils.byteArrayToHexString([le]);
- }
-
- // Pass empty response '' as args as we are not interested in appended
- // responses yet!
- debug("exchangeAPDU on Channel # " + channel);
- this._doIccExchangeAPDU(channel, cla, ins, p1, p2, p3, data, "",
- callback);
- },
-
- /**
- * Closes the channel on default clientId.
- */
- closeChannel: function(channel, callback) {
- if (!this._isPresent) {
- callback.notifyError(SE.ERROR_NOTPRESENT);
- return;
- }
-
- let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID);
- icc.iccCloseChannel(channel, {
- notifyCloseChannelSuccess: function() {
- debug("closeChannel successfully closed the channel # : " + channel);
- if (callback) {
- callback.notifyCloseChannelSuccess();
- }
- },
-
- notifyError: function(reason) {
- debug("Failed to close the channel # : " + channel +
- ", Rejected with Reason : " + reason);
- if (callback) {
- callback.notifyError(reason);
- }
- }
- });
- },
-
- registerListener: function(listener) {
- if (this._SEListeners.indexOf(listener) !== -1) {
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- this._SEListeners.push(listener);
- // immediately notify listener about the current state
- listener.notifySEPresenceChanged(SE.TYPE_UICC, this._isPresent);
- },
-
- unregisterListener: function(listener) {
- let idx = this._SEListeners.indexOf(listener);
- if (idx !== -1) {
- this._SEListeners.splice(idx, 1);
- }
- },
-
- /**
- * nsIIccListener interface methods.
- */
- notifyStkCommand: function() {},
-
- notifyStkSessionEnd: function() {},
-
- notifyIccInfoChanged: function() {},
-
- notifyCardStateChanged: function() {
- debug("Card state changed, updating UICC presence.");
- this._updatePresenceState();
- },
-
- /**
- * nsIObserver interface methods.
- */
-
- observe: function(subject, topic, data) {
- if (topic === NS_XPCOM_SHUTDOWN_OBSERVER_ID) {
- this._shutdown();
- }
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([UiccConnector]);
diff --git a/dom/secureelement/gonk/UiccConnector.manifest b/dom/secureelement/gonk/UiccConnector.manifest
deleted file mode 100644
index 5ac8b3b7b..000000000
--- a/dom/secureelement/gonk/UiccConnector.manifest
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2012 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# UiccConnector
-component {8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4} UiccConnector.js
-contract @mozilla.org/secureelement/connector/uicc;1 {8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4}
diff --git a/dom/secureelement/gonk/gp_consts.js b/dom/secureelement/gonk/gp_consts.js
deleted file mode 100644
index 7c3bc7165..000000000
--- a/dom/secureelement/gonk/gp_consts.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-/* Object Directory File (ODF) is an elementary file which contain
- pointers to other EFs. It is specified in PKCS#15 section 6.7. */
-this.ODF_DF = [0x50, 0x31];
-
-/* ISO 7816-4: secure messaging */
-this.CLA_SM = 0x00;
-
-/* ISO 7816-4, 5.4.1 table 11 */
-this.INS_SF = 0xA4; // select file
-this.INS_GR = 0xC0; // get response
-this.INS_RB = 0xB0; // read binary
-
-/* ISO 7816-4: select file, see 6.11.3, table 58 & 59 */
-this.P1_SF_DF = 0x00; // select DF
-this.P2_SF_FCP = 0x04; // return FCP
-
-/* ISO 7816-4: read binary, 6.1.3. P1 and P2 describe offset of the first byte
- to be read. We always read the whole files at the moment. */
-this.P1_RB = 0x00;
-this.P2_RB = 0x00;
-
-/* ISO 7816-4: get response, 7.1.3 table 74, P1-P2 '0000' (other values RFU) */
-this.P1_GR = 0x00;
-this.P2_GR = 0x00;
-
-/* ISO 7816-4: 5.1.5 File Control Information, Table 1. For FCP and FMD. */
-this.TAG_PROPRIETARY = 0x00;
-this.TAG_NON_TLV = 0x53;
-this.TAG_BER_TLV = 0x73;
-
-/* ASN.1 tags */
-this.TAG_SEQUENCE = 0x30;
-this.TAG_OCTETSTRING = 0x04;
-this.TAG_OID = 0x06; // Object Identifier
-
-/* ISO 7816-4: 5.1.5 File Control Information, Templates. */
-this.TAG_FCP = 0x62; // File control parameters template
-this.TAG_FMD = 0x64; // File management data template
-this.TAG_FCI = 0x6F; // File control information template
-
-/* EF_DIR tags */
-this.TAG_APPLTEMPLATE = 0x61;
-this.TAG_APPLIDENTIFIER = 0x4F;
-this.TAG_APPLLABEL = 0x50;
-this.TAG_APPLPATH = 0x51;
-
-this.TAG_GPD_ALL = 0x82; // EF-ACRules - GPD spec. "all applets"
-
-/* Generic TLVs that are parsed */
-this.TAG_GPD_AID = 0xA0; // AID in the EF-ACRules - GPD spec, "one applet"
-this.TAG_EXTERNALDO = 0xA1; // External data objects - PKCS#15
-this.TAG_INDIRECT = 0xA5; // Indirect value.
-this.TAG_EF_ODF = 0xA7; // Elemenetary File Object Directory File
-
-// Allow this file to be imported via Components.utils.import().
-this.EXPORTED_SYMBOLS = Object.keys(this);
diff --git a/dom/secureelement/gonk/nsIAccessControlEnforcer.idl b/dom/secureelement/gonk/nsIAccessControlEnforcer.idl
deleted file mode 100644
index 7ad1a97f6..000000000
--- a/dom/secureelement/gonk/nsIAccessControlEnforcer.idl
+++ /dev/null
@@ -1,32 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-#include "nsISupports.idl"
-
-interface nsIVariant;
-
-[scriptable, uuid(4994a960-26d9-4d71-82dd-4505bd97bf2a)]
-interface nsIAccessControlEnforcer : nsISupports
-{
- /**
- * Determines whether application identified by its ID should be allowed
- * to access Secure Element's applet identified by its AID. Decision
- * is made according to the GPD specification.
- *
- * @param localId
- * ID of an application accessing SE
- * @param seType
- * Type of the SE.
- * @param aid
- * AID of a SE applet
- * @return Promise which is resolved to true if access should be allowed,
- * false otherwise, and rejected if the application contains
- * no developer certificate.
- */
- jsval isAccessAllowed(in unsigned long localId,
- in DOMString seType,
- in DOMString aid);
-};
diff --git a/dom/secureelement/gonk/nsIAccessRulesManager.idl b/dom/secureelement/gonk/nsIAccessRulesManager.idl
deleted file mode 100644
index 173f57c90..000000000
--- a/dom/secureelement/gonk/nsIAccessRulesManager.idl
+++ /dev/null
@@ -1,50 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Copyright © 2015, Deutsche Telekom, Inc. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(7baedd2a-3189-4b03-b2a3-34016043b5e2)]
-interface nsIAccessRulesManager : nsISupports
-{
- /* Wildcard: rule allows all applications to access an SE applet */
- const unsigned short ALLOW_ALL = 1;
- /* Wildcard: rule denies all applications to access an SE applet */
- const unsigned short DENY_ALL = 2;
- /* Wildcard: rule allows application(s) access to all SE applets */
- const unsigned short ALL_APPLET = 3;
-
- /**
- * Initiates Access Rules Manager, this should perform the initial
- * reading of rules from access rule source
- * @return Promise which is resolved if init is successful or rejected
- * otherwise
- */
- jsval init();
-
- /**
- * Retrieves all access rules.
- *
- * Rules are stored in an array. Each rule contains the following properties:
- * - applet - describes an SE applet referenced by this rule. Might equal
- * to an applet AID (as a byte array), or to a wildcard "all"
- * meaning all applets.
- * - application - describes an application referenced by this rule. Might
- * be an array of developer certificate hashes (each as
- * a byte array) in which case it lists all applications
- * allowed access. Alternatively, might equal to wildcard
- * "allowed-all" or "denied-all".
- *
- * Example rule format:
- * [{ applet: ALL_APPLET,
- * application: [[0x01, 0x02, ..., 0x20],
- * [0x20, 0x19, ...., 0x01]],
- * { applet: [0x00, 0x01, ..., 0x05],
- * application: ALLOW_ALL}}]
- *
- * @return Promise which resolves with Array containing parsed access rules
- */
- jsval getAccessRules();
-};
diff --git a/dom/secureelement/gonk/nsISecureElementConnector.idl b/dom/secureelement/gonk/nsISecureElementConnector.idl
deleted file mode 100644
index 92cc1eb2b..000000000
--- a/dom/secureelement/gonk/nsISecureElementConnector.idl
+++ /dev/null
@@ -1,124 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(1ff3f35a-1b6f-4e65-a89e-a363b8604cd7)]
-interface nsISEChannelCallback : nsISupports
-{
- /**
- * Callback function to notify on successfully opening a logical channel.
- *
- * @param channel
- * The Channel Number/Handle that is successfully opened.
- * @param openResponse
- * Response from SE for OpenChannel operation.
- */
- void notifyOpenChannelSuccess(in long channel, in DOMString openResponse);
-
- /**
- * Callback function to notify on successfully closing the logical channel.
- *
- */
- void notifyCloseChannelSuccess();
-
- /**
- * Callback function to notify the status of 'seExchangeAPDU' command.
- *
- * @param sw1
- * Response's First Status Byte
- * @param sw2
- * Response's Second Status Byte
- * @param data
- * Response's data
- */
- void notifyExchangeAPDUResponse(in octet sw1,
- in octet sw2,
- in DOMString data);
-
- /**
- * Callback function to notify error
- *
- * @param error
- * Error describing the reason for failure.
- */
- void notifyError(in DOMString error);
-};
-
-[scriptable, uuid(417f59ee-f582-45b9-9a4e-e9dcefecb4f7)]
-interface nsISEListener : nsISupports
-{
- void notifySEPresenceChanged(in DOMString seType, in boolean isPresent);
-};
-
-[scriptable, uuid(3cef313a-1d01-432d-9cd2-6610a80911f3)]
-interface nsISecureElementConnector : nsISupports
-{
- /**
- * Open a logical communication channel with the specific secure element type
- *
- * @param aid
- * Application Identifier of the Card Applet on the secure element.
- * @param callback
- * callback to notify the result of the operation.
- */
- void openChannel(in DOMString aid,
- in nsISEChannelCallback callback);
-
- /**
- * Exchanges APDU channel with the specific secure element type
- *
- * @param channel
- * Channel on which C-APDU to be transmitted.
- * @param cla
- Class Byte.
- * @param ins
- Instruction Byte
- * @param p1
- Reference parameter first byte
- * @param p2
- Reference parameter second byte
- * Refer to 3G TS 31.101 , 10.2 'Command APDU Structure' for all the cases.
- * @param data
- Sequence of C-APDU data octets
- * @param le [optional]
- * le is the length of expected response. If the response is not expected,
- it should be explicitly set to -1.
- * @param callback
- * callback to notify the result of the operation.
- */
- void exchangeAPDU(in long channel,
- in octet cla,
- in octet ins,
- in octet p1,
- in octet p2,
- in DOMString data,
- in short le,
- in nsISEChannelCallback callback);
-
- /**
- * Closes the logical communication channel to the specific secure element type
- *
- * @param channel
- * Channel to be closed.
- * @param callback
- * callback to notify the result of the operation.
- */
- void closeChannel(in long channel,
- in nsISEChannelCallback callback);
-
- /**
- * Register a Secure Element listener
- *
- * @param listener
- */
- void registerListener(in nsISEListener listener);
-
- /**
- * Unregister a Secure Element listener
- *
- * @param listener
- */
- void unregisterListener(in nsISEListener listener);
-};
diff --git a/dom/secureelement/gonk/se_consts.js b/dom/secureelement/gonk/se_consts.js
deleted file mode 100644
index 13489b7ae..000000000
--- a/dom/secureelement/gonk/se_consts.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Copyright © 2014, Deutsche Telekom, Inc. */
-
-// Set to true to debug SecureElement (SE) stack
-this.DEBUG_ALL = false;
-
-// Set individually to debug specific layers
-this.DEBUG_CONNECTOR = DEBUG_ALL || false;
-this.DEBUG_ACE = DEBUG_ALL || false ;
-this.DEBUG_SE = DEBUG_ALL || false ;
-
-// Maximun logical channels per session.
-// For 'uicc' SE type this value is 3, as opening a basic channel' : 0
-// is not allowed for security reasons. In such scenarios, possible
-// supplementary logical channels available are : [1, 2, or 3].
-// However,Other SE types may support upto max 4 (including '0').
-this.MAX_CHANNELS_ALLOWED_PER_SESSION = 4;
-
-this.BASIC_CHANNEL = 0;
-
-// According GPCardSpec 2.2
-this.MAX_APDU_LEN = 255; // including APDU header
-
-// CLA (1 byte) + INS (1 byte) + P1 (1 byte) + P2 (1 byte)
-this.APDU_HEADER_LEN = 4;
-
-this.LOGICAL_CHANNEL_NUMBER_LIMIT = 4;
-this.SUPPLEMENTARY_LOGICAL_CHANNEL_NUMBER_LIMIT = 20;
-
-this.MIN_AID_LEN = 5;
-this.MAX_AID_LEN = 16;
-
-this.CLA_GET_RESPONSE = 0x00;
-
-this.INS_SELECT = 0xA4;
-this.INS_MANAGE_CHANNEL = 0x70;
-this.INS_GET_RESPONSE = 0xC0;
-
-// Match the following errors with SecureElement.webidl's SEError enum values
-this.ERROR_NONE = "";
-this.ERROR_SECURITY = "SESecurityError";
-this.ERROR_IO = "SEIoError";
-this.ERROR_BADSTATE = "SEBadStateError";
-this.ERROR_INVALIDCHANNEL = "SEInvalidChannelError";
-this.ERROR_INVALIDAPPLICATION = "SEInvalidApplicationError";
-this.ERROR_GENERIC = "SEGenericError";
-this.ERROR_NOTPRESENT = "SENotPresentError";
-this.ERROR_ILLEGALPARAMETER = "SEIllegalParameterError";
-
-this.TYPE_UICC = "uicc";
-this.TYPE_ESE = "eSE";
-
-// Allow this file to be imported via Components.utils.import().
-this.EXPORTED_SYMBOLS = Object.keys(this);
diff --git a/dom/secureelement/moz.build b/dom/secureelement/moz.build
index a2c87b014..973000512 100644
--- a/dom/secureelement/moz.build
+++ b/dom/secureelement/moz.build
@@ -11,30 +11,6 @@ if CONFIG['MOZ_SECUREELEMENT']:
'DOMSecureElement.manifest',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_SECUREELEMENT']:
- EXTRA_COMPONENTS += [
- 'gonk/ACEService.js',
- 'gonk/ACEService.manifest',
- 'gonk/GPAccessRulesManager.js',
- 'gonk/GPAccessRulesManager.manifest',
- 'gonk/SecureElement.js',
- 'gonk/SecureElement.manifest',
- ]
- XPIDL_MODULE = 'dom_secureelement'
- XPIDL_SOURCES += [
- 'gonk/nsIAccessControlEnforcer.idl',
- 'gonk/nsIAccessRulesManager.idl',
- 'gonk/nsISecureElementConnector.idl',
- ]
- EXTRA_JS_MODULES += [
- 'gonk/gp_consts.js',
- 'gonk/se_consts.js',
- 'SEUtils.jsm'
- ]
- XPCSHELL_TESTS_MANIFESTS += [
- 'tests/unit/xpcshell.ini'
- ]
-
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
diff --git a/dom/system/gonk/AudioChannelManager.cpp b/dom/system/gonk/AudioChannelManager.cpp
deleted file mode 100644
index 977715a29..000000000
--- a/dom/system/gonk/AudioChannelManager.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDocument.h"
-#include "nsIDOMClassInfo.h"
-#include "nsIDOMEvent.h"
-#include "nsIDOMEventListener.h"
-#include "nsPIDOMWindow.h"
-#include "nsIDocShell.h"
-#include "nsIPermissionManager.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "AudioChannelManager.h"
-#include "mozilla/dom/AudioChannelManagerBinding.h"
-#include "mozilla/dom/nsBrowserElement.h"
-#include "mozilla/Services.h"
-
-namespace mozilla {
-namespace dom {
-namespace system {
-
-NS_IMPL_QUERY_INTERFACE_INHERITED(AudioChannelManager, DOMEventTargetHelper,
- nsIDOMEventListener)
-NS_IMPL_ADDREF_INHERITED(AudioChannelManager, DOMEventTargetHelper)
-NS_IMPL_RELEASE_INHERITED(AudioChannelManager, DOMEventTargetHelper)
-
-AudioChannelManager::AudioChannelManager()
- : mVolumeChannel(-1)
-{
- hal::RegisterSwitchObserver(hal::SWITCH_HEADPHONES, this);
-}
-
-AudioChannelManager::~AudioChannelManager()
-{
- hal::UnregisterSwitchObserver(hal::SWITCH_HEADPHONES, this);
-
- nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner());
- NS_ENSURE_TRUE_VOID(target);
-
- target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
- this,
- /* useCapture = */ true);
-}
-
-void
-AudioChannelManager::Init(nsPIDOMWindowInner* aWindow)
-{
- BindToOwner(aWindow);
-
- nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
- NS_ENSURE_TRUE_VOID(target);
-
- target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
- this,
- /* useCapture = */ true,
- /* wantsUntrusted = */ false);
-}
-
-JSObject*
-AudioChannelManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
- return AudioChannelManagerBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-AudioChannelManager::Notify(const hal::SwitchEvent& aEvent)
-{
- mState = Some(aEvent.status());
-
- DispatchTrustedEvent(NS_LITERAL_STRING("headphoneschange"));
-}
-
-bool
-AudioChannelManager::SetVolumeControlChannel(const nsAString& aChannel)
-{
- if (aChannel.EqualsASCII("publicnotification")) {
- return false;
- }
-
- AudioChannel newChannel = AudioChannelService::GetAudioChannel(aChannel);
-
- // Only normal channel doesn't need permission.
- if (newChannel != AudioChannel::Normal) {
- nsCOMPtr<nsIPermissionManager> permissionManager =
- services::GetPermissionManager();
- if (!permissionManager) {
- return false;
- }
- uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
- permissionManager->TestPermissionFromWindow(GetOwner(),
- nsCString(NS_LITERAL_CSTRING("audio-channel-") +
- NS_ConvertUTF16toUTF8(aChannel)).get(), &perm);
- if (perm != nsIPermissionManager::ALLOW_ACTION) {
- return false;
- }
- }
-
- if (mVolumeChannel == (int32_t)newChannel) {
- return true;
- }
-
- mVolumeChannel = (int32_t)newChannel;
-
- NotifyVolumeControlChannelChanged();
- return true;
-}
-
-bool
-AudioChannelManager::GetVolumeControlChannel(nsAString & aChannel)
-{
- if (mVolumeChannel >= 0) {
- AudioChannelService::GetAudioChannelString(
- static_cast<AudioChannel>(mVolumeChannel),
- aChannel);
- } else {
- aChannel.AssignASCII("");
- }
-
- return true;
-}
-
-void
-AudioChannelManager::NotifyVolumeControlChannelChanged()
-{
- nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
- NS_ENSURE_TRUE_VOID(docshell);
-
- bool isActive = false;
- docshell->GetIsActive(&isActive);
-
- RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
- if (!service) {
- return;
- }
-
- if (isActive) {
- service->SetDefaultVolumeControlChannel(mVolumeChannel, isActive);
- } else {
- service->SetDefaultVolumeControlChannel(-1, isActive);
- }
-}
-
-NS_IMETHODIMP
-AudioChannelManager::HandleEvent(nsIDOMEvent* aEvent)
-{
- nsAutoString type;
- aEvent->GetType(type);
-
- if (type.EqualsLiteral("visibilitychange")) {
- NotifyVolumeControlChannelChanged();
- }
- return NS_OK;
-}
-
-void
-AudioChannelManager::GetAllowedAudioChannels(
- nsTArray<RefPtr<BrowserElementAudioChannel>>& aAudioChannels,
- ErrorResult& aRv)
-{
- MOZ_ASSERT(aAudioChannels.IsEmpty());
-
- // Only main process is supported.
- if (XRE_GetProcessType() != GeckoProcessType_Default) {
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
-
- nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
- if (NS_WARN_IF(!window)) {
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
-
- nsBrowserElement::GenerateAllowedAudioChannels(window, nullptr, nullptr,
- aAudioChannels, aRv);
- NS_WARNING_ASSERTION(!aRv.Failed(), "GenerateAllowedAudioChannels failed");
-}
-
-} // namespace system
-} // namespace dom
-} // namespace mozilla
diff --git a/dom/system/gonk/AudioChannelManager.h b/dom/system/gonk/AudioChannelManager.h
deleted file mode 100644
index a460651e7..000000000
--- a/dom/system/gonk/AudioChannelManager.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_system_AudioChannelManager_h
-#define mozilla_dom_system_AudioChannelManager_h
-
-#include "mozilla/dom/BrowserElementAudioChannel.h"
-#include "mozilla/DOMEventTargetHelper.h"
-#include "mozilla/Hal.h"
-#include "mozilla/HalTypes.h"
-#include "mozilla/Maybe.h"
-#include "AudioChannelService.h"
-
-namespace mozilla {
-namespace hal {
-class SwitchEvent;
-typedef Observer<SwitchEvent> SwitchObserver;
-} // namespace hal
-
-namespace dom {
-namespace system {
-
-class AudioChannelManager final
- : public DOMEventTargetHelper
- , public hal::SwitchObserver
- , public nsIDOMEventListener
-{
-public:
- AudioChannelManager();
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIDOMEVENTLISTENER
-
- void Notify(const hal::SwitchEvent& aEvent);
-
- void Init(nsPIDOMWindowInner* aWindow);
-
- /**
- * WebIDL Interface
- */
-
- nsPIDOMWindowInner* GetParentObject() const
- {
- return GetOwner();
- }
-
- virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
- bool Headphones()
- {
- // Bug 929139 - Remove the assert check for SWITCH_STATE_UNKNOWN.
- // If any devices (ex: emulator) didn't have the corresponding sys node for
- // headset switch state then GonkSwitch will report the unknown state.
- // So it is possible to get unknown state here.
- if (mState.isNothing()) {
- mState = Some(hal::GetCurrentSwitchState(hal::SWITCH_HEADPHONES));
- }
- return mState.value() != hal::SWITCH_STATE_OFF &&
- mState.value() != hal::SWITCH_STATE_UNKNOWN;
- }
-
- bool SetVolumeControlChannel(const nsAString& aChannel);
-
- bool GetVolumeControlChannel(nsAString& aChannel);
-
- IMPL_EVENT_HANDLER(headphoneschange)
-
- void GetAllowedAudioChannels(
- nsTArray<RefPtr<mozilla::dom::BrowserElementAudioChannel>>& aAudioChannels,
- mozilla::ErrorResult& aRv);
-
-protected:
- virtual ~AudioChannelManager();
-
-private:
- void NotifyVolumeControlChannelChanged();
-
- Maybe<hal::SwitchState> mState;
- int32_t mVolumeChannel;
-};
-
-} // namespace system
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_system_AudioChannelManager_h
diff --git a/dom/system/gonk/AudioManager.cpp b/dom/system/gonk/AudioManager.cpp
deleted file mode 100644
index 88dff13f7..000000000
--- a/dom/system/gonk/AudioManager.cpp
+++ /dev/null
@@ -1,1412 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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/log.h>
-#include <cutils/properties.h>
-#include <binder/IServiceManager.h>
-
-#include "AudioChannelService.h"
-#include "AudioManager.h"
-
-#include "nsIObserverService.h"
-#include "nsISettingsService.h"
-#include "nsPrintfCString.h"
-
-#include "mozilla/Hal.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/MozPromise.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "base/message_loop.h"
-
-#include "BluetoothCommon.h"
-#include "BluetoothHfpManagerBase.h"
-
-#include "nsJSUtils.h"
-#include "nsThreadUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentUtils.h"
-#include "nsXULAppAPI.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/SettingChangeNotificationBinding.h"
-
-using namespace mozilla::dom;
-using namespace mozilla::dom::gonk;
-using namespace android;
-using namespace mozilla;
-using namespace mozilla::dom::bluetooth;
-
-#undef LOG
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args)
-
-#define HEADPHONES_STATUS_HEADSET u"headset"
-#define HEADPHONES_STATUS_HEADPHONE u"headphone"
-#define HEADPHONES_STATUS_OFF u"off"
-#define HEADPHONES_STATUS_UNKNOWN u"unknown"
-#define HEADPHONES_STATUS_CHANGED "headphones-status-changed"
-#define MOZ_SETTINGS_CHANGE_ID "mozsettings-changed"
-#define AUDIO_CHANNEL_PROCESS_CHANGED "audio-channel-process-changed"
-#define AUDIO_POLICY_SERVICE_NAME "media.audio_policy"
-#define SETTINGS_SERVICE "@mozilla.org/settingsService;1"
-
-// Refer AudioService.java from Android
-static const uint32_t sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
- 5, // voice call
- 15, // system
- 15, // ring
- 15, // music
- 15, // alarm
- 15, // notification
- 15, // BT SCO
- 15, // enforced audible
- 15, // DTMF
- 15, // TTS
-#if ANDROID_VERSION < 19
- 15, // FM
-#endif
-};
-
-static const uint32_t sDefaultStreamVolumeTbl[AUDIO_STREAM_CNT] = {
- 3, // voice call
- 8, // system
- 8, // ring
- 8, // music
- 8, // alarm
- 8, // notification
- 8, // BT SCO
- 15, // enforced audible // XXX Handle as fixed maximum audio setting
- 8, // DTMF
- 8, // TTS
-#if ANDROID_VERSION < 19
- 8, // FM
-#endif
-};
-
-static const int32_t sStreamVolumeAliasTbl[AUDIO_STREAM_CNT] = {
- AUDIO_STREAM_VOICE_CALL, // voice call
- AUDIO_STREAM_NOTIFICATION, // system
- AUDIO_STREAM_NOTIFICATION, // ring
- AUDIO_STREAM_MUSIC, // music
- AUDIO_STREAM_ALARM, // alarm
- AUDIO_STREAM_NOTIFICATION, // notification
- AUDIO_STREAM_BLUETOOTH_SCO, // BT SCO
- AUDIO_STREAM_ENFORCED_AUDIBLE,// enforced audible
- AUDIO_STREAM_DTMF, // DTMF
- AUDIO_STREAM_TTS, // TTS
-#if ANDROID_VERSION < 19
- AUDIO_STREAM_MUSIC, // FM
-#endif
-};
-
-static const uint32_t sChannelStreamTbl[NUMBER_OF_AUDIO_CHANNELS] = {
- AUDIO_STREAM_MUSIC, // AudioChannel::Normal
- AUDIO_STREAM_MUSIC, // AudioChannel::Content
- AUDIO_STREAM_NOTIFICATION, // AudioChannel::Notification
- AUDIO_STREAM_ALARM, // AudioChannel::Alarm
- AUDIO_STREAM_VOICE_CALL, // AudioChannel::Telephony
- AUDIO_STREAM_RING, // AudioChannel::Ringer
- AUDIO_STREAM_ENFORCED_AUDIBLE,// AudioChannel::Publicnotification
- AUDIO_STREAM_SYSTEM, // AudioChannel::System
-};
-
-
-struct AudioDeviceInfo {
- /** The string the value maps to */
- const char* tag;
- /** The enum value that maps to this string */
- uint32_t value;
-};
-
-// Mappings audio output devices to strings.
-static const AudioDeviceInfo kAudioDeviceInfos[] = {
- { "earpiece", AUDIO_DEVICE_OUT_EARPIECE },
- { "speaker", AUDIO_DEVICE_OUT_SPEAKER },
- { "wired_headset", AUDIO_DEVICE_OUT_WIRED_HEADSET },
- { "wired_headphone", AUDIO_DEVICE_OUT_WIRED_HEADPHONE },
- { "bt_scoheadset", AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET },
- { "bt_a2dp", AUDIO_DEVICE_OUT_BLUETOOTH_A2DP },
-};
-
-static const int kBtSampleRate = 8000;
-
-typedef MozPromise<bool, const char*, true> VolumeInitPromise;
-
-namespace mozilla {
-namespace dom {
-namespace gonk {
-
-/**
- * We have five sound volume settings from UX spec,
- * You can see more informations in Bug1068219.
- * (1) Media : music, video, FM ...
- * (2) Notification : ringer, notification ...
- * (3) Alarm : alarm
- * (4) Telephony : GSM call, WebRTC call
- * (5) Bluetooth SCO : SCO call
- **/
-struct VolumeData {
- const char* mChannelName;
- int32_t mStreamType;
-};
-
-static const VolumeData gVolumeData[] = {
- {"audio.volume.content", AUDIO_STREAM_MUSIC},
- {"audio.volume.notification", AUDIO_STREAM_NOTIFICATION},
- {"audio.volume.alarm", AUDIO_STREAM_ALARM},
- {"audio.volume.telephony", AUDIO_STREAM_VOICE_CALL},
- {"audio.volume.bt_sco", AUDIO_STREAM_BLUETOOTH_SCO}
-};
-
-class RunnableCallTask : public Runnable
-{
-public:
- explicit RunnableCallTask(nsIRunnable* aRunnable)
- : mRunnable(aRunnable) {}
-
- NS_IMETHOD Run() override
- {
- return mRunnable->Run();
- }
-protected:
- nsCOMPtr<nsIRunnable> mRunnable;
-};
-
-nsCOMPtr<nsISettingsServiceLock>
-GetSettingServiceLock()
-{
- nsresult rv;
- nsCOMPtr<nsISettingsService> service = do_GetService(SETTINGS_SERVICE, &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return nullptr;
- }
-
- nsCOMPtr<nsISettingsServiceLock> lock;
- rv = service->CreateLock(nullptr, getter_AddRefs(lock));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return nullptr;
- }
- return lock.forget();
-}
-
-#if ANDROID_VERSION >= 21
-class GonkAudioPortCallback : public AudioSystem::AudioPortCallback
-{
-public:
- virtual void onAudioPortListUpdate()
- {
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([]() {
- MOZ_ASSERT(NS_IsMainThread());
- RefPtr<AudioManager> audioManager = AudioManager::GetInstance();
- NS_ENSURE_TRUE(audioManager.get(), );
- audioManager->UpdateCachedActiveDevicesForStreams();
- audioManager->MaybeUpdateVolumeSettingToDatabase();
- });
- NS_DispatchToMainThread(runnable);
- }
- virtual void onAudioPatchListUpdate() { }
- virtual void onServiceDied() { }
-};
-#endif
-
-void
-AudioManager::HandleAudioFlingerDied()
-{
- //Disable volume change notification
- mIsVolumeInited = false;
-
- uint32_t attempt;
- for (attempt = 0; attempt < 50; attempt++) {
- if (defaultServiceManager()->checkService(String16(AUDIO_POLICY_SERVICE_NAME)) != 0) {
- break;
- }
- LOG("AudioPolicyService is dead! attempt=%d", attempt);
- usleep(1000 * 200);
- }
-
- MOZ_RELEASE_ASSERT(attempt < 50);
-
- // Indicate to audio HAL that we start the reconfiguration phase after a media
- // server crash
- AudioSystem::setParameters(0, String8("restarting=true"));
-
- // Restore device connection states
- SetAllDeviceConnectionStates();
-
- // Restore call state
-#if ANDROID_VERSION < 17
- AudioSystem::setPhoneState(mPhoneState);
-#else
- AudioSystem::setPhoneState(static_cast<audio_mode_t>(mPhoneState));
-#endif
-
- // Restore master volume
- AudioSystem::setMasterVolume(1.0);
-
- // Restore stream volumes
- for (uint32_t streamType = 0; streamType < AUDIO_STREAM_CNT; ++streamType) {
- mStreamStates[streamType]->InitStreamVolume();
- mStreamStates[streamType]->RestoreVolumeIndexToAllDevices();
- }
-
- // Indicate the end of reconfiguration phase to audio HAL
- AudioSystem::setParameters(0, String8("restarting=true"));
-
- // Enable volume change notification
- mIsVolumeInited = true;
- mAudioOutDevicesUpdated = 0;
- MaybeUpdateVolumeSettingToDatabase(true);
-}
-
-class VolumeInitCallback final : public nsISettingsServiceCallback
-{
-public:
- NS_DECL_ISUPPORTS
-
- VolumeInitCallback()
- : mInitCounter(0)
- {
- mPromise = mPromiseHolder.Ensure(__func__);
- }
-
- RefPtr<VolumeInitPromise> GetPromise() const
- {
- return mPromise;
- }
-
- NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
- {
- RefPtr<AudioManager> audioManager = AudioManager::GetInstance();
- MOZ_ASSERT(audioManager);
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- NS_ConvertASCIItoUTF16 volumeType(gVolumeData[idx].mChannelName);
- if (StringBeginsWith(aName, volumeType)) {
- uint32_t device = GetDeviceFromSettingName(aName);
- MOZ_ASSERT(device != AUDIO_DEVICE_NONE);
- if (aResult.isInt32()) {
- int32_t stream = gVolumeData[idx].mStreamType;
- uint32_t volIndex = aResult.toInt32();
- nsresult rv = audioManager->ValidateVolumeIndex(stream, volIndex);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- mPromiseHolder.Reject("Error : invalid volume index.", __func__);
- return rv;
- }
- audioManager->SetStreamVolumeForDevice(stream, volIndex, device);
- }
-
- if (++mInitCounter == MOZ_ARRAY_LENGTH(kAudioDeviceInfos) * MOZ_ARRAY_LENGTH(gVolumeData)) {
- mPromiseHolder.Resolve(true, __func__);
- }
- return NS_OK;
- }
- }
- mPromiseHolder.Reject("Error : unexpected audio init event.", __func__);
- return NS_OK;
- }
-
- NS_IMETHOD HandleError(const nsAString& aName)
- {
- mPromiseHolder.Reject(NS_ConvertUTF16toUTF8(aName).get(), __func__);
- return NS_OK;
- }
-
-protected:
- ~VolumeInitCallback() {}
-
- uint32_t GetDeviceFromSettingName(const nsAString& aName) const
- {
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(kAudioDeviceInfos); ++idx) {
- NS_ConvertASCIItoUTF16 device(kAudioDeviceInfos[idx].tag);
- if (StringEndsWith(aName, device)) {
- return kAudioDeviceInfos[idx].value;
- }
- }
- return AUDIO_DEVICE_NONE;
- }
-
- RefPtr<VolumeInitPromise> mPromise;
- MozPromiseHolder<VolumeInitPromise> mPromiseHolder;
- uint32_t mInitCounter;
-};
-
-NS_IMPL_ISUPPORTS(VolumeInitCallback, nsISettingsServiceCallback)
-
-static void
-BinderDeadCallback(status_t aErr)
-{
- if (aErr != DEAD_OBJECT) {
- return;
- }
-
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([]() {
- MOZ_ASSERT(NS_IsMainThread());
- RefPtr<AudioManager> audioManager = AudioManager::GetInstance();
- NS_ENSURE_TRUE(audioManager.get(), );
- audioManager->HandleAudioFlingerDied();
- });
-
- NS_DispatchToMainThread(runnable);
-}
-
-bool
-AudioManager::IsFmOutConnected()
-{
- return mConnectedDevices.Get(AUDIO_DEVICE_OUT_FM, nullptr);
-}
-
-NS_IMPL_ISUPPORTS(AudioManager, nsIAudioManager, nsIObserver)
-
-void
-AudioManager::AudioOutDeviceUpdated(uint32_t aDevice)
-{
- MOZ_ASSERT(audio_is_output_device(aDevice));
- mAudioOutDevicesUpdated |= aDevice;
-}
-
-void
-AudioManager::UpdateHeadsetConnectionState(hal::SwitchState aState)
-{
- bool headphoneConnected = mConnectedDevices.Get(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
- nullptr);
- bool headsetConnected = mConnectedDevices.Get(AUDIO_DEVICE_OUT_WIRED_HEADSET,
- nullptr);
- if (aState == hal::SWITCH_STATE_HEADSET) {
- UpdateDeviceConnectionState(true,
- AUDIO_DEVICE_OUT_WIRED_HEADSET,
- NS_LITERAL_CSTRING(""));
- } else if (aState == hal::SWITCH_STATE_HEADPHONE) {
- UpdateDeviceConnectionState(true,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
- NS_LITERAL_CSTRING(""));
- } else if (aState == hal::SWITCH_STATE_OFF) {
- if (headsetConnected) {
- UpdateDeviceConnectionState(false,
- AUDIO_DEVICE_OUT_WIRED_HEADSET,
- NS_LITERAL_CSTRING(""));
- }
- if (headphoneConnected) {
- UpdateDeviceConnectionState(false,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
- NS_LITERAL_CSTRING(""));
- }
- }
-}
-
-void
-AudioManager::UpdateDeviceConnectionState(bool aIsConnected, uint32_t aDevice, const nsCString& aDeviceName)
-{
-#if ANDROID_VERSION >= 15
- bool isConnected = mConnectedDevices.Get(aDevice, nullptr);
- if (isConnected && !aIsConnected) {
- AudioSystem::setDeviceConnectionState(static_cast<audio_devices_t>(aDevice),
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- aDeviceName.get());
- mConnectedDevices.Remove(aDevice);
- } else if(!isConnected && aIsConnected) {
- AudioSystem::setDeviceConnectionState(static_cast<audio_devices_t>(aDevice),
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- aDeviceName.get());
- mConnectedDevices.Put(aDevice, aDeviceName);
- }
-#if ANDROID_VERSION < 21
- // Manually call it, since AudioPortCallback is not supported.
- // Current volumes might be changed by updating active devices in android
- // AudioPolicyManager.
- MaybeUpdateVolumeSettingToDatabase();
-#endif
-#else
- NS_NOTREACHED("Doesn't support audio routing on GB version");
-#endif
-}
-
-void
-AudioManager::SetAllDeviceConnectionStates()
-{
- for (auto iter = mConnectedDevices.Iter(); !iter.Done(); iter.Next()) {
- const uint32_t& device = iter.Key();
- nsCString& deviceAddress = iter.Data();
- AudioSystem::setDeviceConnectionState(static_cast<audio_devices_t>(device),
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- deviceAddress.get());
- }
-#if ANDROID_VERSION < 21
- // Manually call it, since AudioPortCallback is not supported.
- // Current volumes might be changed by updating active devices in android
- // AudioPolicyManager.
- MaybeUpdateVolumeSettingToDatabase(true);
-#endif
-}
-
-void
-AudioManager::HandleBluetoothStatusChanged(nsISupports* aSubject,
- const char* aTopic,
- const nsCString aAddress)
-{
-#ifdef MOZ_B2G_BT
- bool isConnected = false;
- if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
- BluetoothHfpManagerBase* hfp =
- static_cast<BluetoothHfpManagerBase*>(aSubject);
- isConnected = hfp->IsScoConnected();
- } else {
- BluetoothProfileManagerBase* profile =
- static_cast<BluetoothProfileManagerBase*>(aSubject);
- isConnected = profile->IsConnected();
- }
-
- if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
- if (isConnected) {
- String8 cmd;
- cmd.appendFormat("bt_samplerate=%d", kBtSampleRate);
- AudioSystem::setParameters(0, cmd);
- SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_BT_SCO);
- } else {
- int32_t force;
- GetForceForUse(nsIAudioManager::USE_COMMUNICATION, &force);
- if (force == nsIAudioManager::FORCE_BT_SCO) {
- SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE);
- }
- }
- } else if (!strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID)) {
- if (!isConnected && mA2dpSwitchDone) {
- RefPtr<AudioManager> self = this;
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([self, isConnected, aAddress]() {
- if (self->mA2dpSwitchDone) {
- return;
- }
- self->UpdateDeviceConnectionState(isConnected,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
- aAddress);
-
- String8 cmd("bluetooth_enabled=false");
- AudioSystem::setParameters(0, cmd);
- cmd.setTo("A2dpSuspended=true");
- AudioSystem::setParameters(0, cmd);
- self->mA2dpSwitchDone = true;
- });
- MessageLoop::current()->PostDelayedTask(
- MakeAndAddRef<RunnableCallTask>(runnable), 1000);
-
- mA2dpSwitchDone = false;
- } else {
- UpdateDeviceConnectionState(isConnected,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
- aAddress);
- String8 cmd("bluetooth_enabled=true");
- AudioSystem::setParameters(0, cmd);
- cmd.setTo("A2dpSuspended=false");
- AudioSystem::setParameters(0, cmd);
- mA2dpSwitchDone = true;
-#if ANDROID_VERSION >= 17
- if (AudioSystem::getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_NO_BT_A2DP) {
- SetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_NONE);
- }
-#endif
- }
- mBluetoothA2dpEnabled = isConnected;
- } else if (!strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
- UpdateDeviceConnectionState(isConnected,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
- aAddress);
- UpdateDeviceConnectionState(isConnected,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
- aAddress);
- } else if (!strcmp(aTopic, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID)) {
- String8 cmd;
- BluetoothHfpManagerBase* hfp =
- static_cast<BluetoothHfpManagerBase*>(aSubject);
- if (hfp->IsNrecEnabled()) {
- cmd.setTo("bt_headset_name=<unknown>;bt_headset_nrec=on");
- AudioSystem::setParameters(0, cmd);
- } else {
- cmd.setTo("bt_headset_name=<unknown>;bt_headset_nrec=off");
- AudioSystem::setParameters(0, cmd);
- }
- }
-#endif
-}
-
-void
-AudioManager::HandleAudioChannelProcessChanged()
-{
- // Note: If the user answers a VoIP call (e.g. WebRTC calls) during the
- // telephony call (GSM/CDMA calls) the audio manager won't set the
- // PHONE_STATE_IN_COMMUNICATION audio state. Once the telephony call finishes
- // the RIL plumbing sets the PHONE_STATE_NORMAL audio state. This seems to be
- // an issue for the VoIP call but it is not. Once the RIL plumbing sets the
- // the PHONE_STATE_NORMAL audio state the AudioManager::mPhoneAudioAgent
- // member will call the NotifyStoppedPlaying() method causing that this function will
- // be called again and therefore the audio manager sets the
- // PHONE_STATE_IN_COMMUNICATION audio state.
-
- if ((mPhoneState == PHONE_STATE_IN_CALL) ||
- (mPhoneState == PHONE_STATE_RINGTONE)) {
- return;
- }
-
- RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
- bool telephonyChannelIsActive = service && service->TelephonyChannelIsActive();
- telephonyChannelIsActive ? SetPhoneState(PHONE_STATE_IN_COMMUNICATION) :
- SetPhoneState(PHONE_STATE_NORMAL);
-}
-
-nsresult
-AudioManager::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- if ((strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID) == 0) ||
- (strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID) == 0) ||
- (strcmp(aTopic, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID) == 0) ||
- (strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID) == 0)) {
- nsCString address = NS_ConvertUTF16toUTF8(nsDependentString(aData));
- if (address.IsEmpty()) {
- NS_WARNING(nsPrintfCString("Invalid address of %s", aTopic).get());
- return NS_ERROR_FAILURE;
- }
-
- HandleBluetoothStatusChanged(aSubject, aTopic, address);
- return NS_OK;
- }
-
- else if (!strcmp(aTopic, AUDIO_CHANNEL_PROCESS_CHANGED)) {
- HandleAudioChannelProcessChanged();
- return NS_OK;
- }
-
- // To process the volume control on each volume categories according to
- // change of settings
- else if (!strcmp(aTopic, MOZ_SETTINGS_CHANGE_ID)) {
- RootedDictionary<dom::SettingChangeNotification> setting(RootingCx());
- if (!WrappedJSToDictionary(aSubject, setting)) {
- return NS_OK;
- }
- if (!StringBeginsWith(setting.mKey, NS_LITERAL_STRING("audio.volume."))) {
- return NS_OK;
- }
- if (!setting.mValue.isNumber()) {
- return NS_OK;
- }
-
- uint32_t volIndex = setting.mValue.toNumber();
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- if (setting.mKey.EqualsASCII(gVolumeData[idx].mChannelName)) {
- SetStreamVolumeIndex(gVolumeData[idx].mStreamType, volIndex);
- return NS_OK;
- }
- }
- }
-
- NS_WARNING("Unexpected topic in AudioManager");
- return NS_ERROR_FAILURE;
-}
-
-static void
-NotifyHeadphonesStatus(hal::SwitchState aState)
-{
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (obs) {
- if (aState == hal::SWITCH_STATE_HEADSET) {
- obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_HEADSET);
- } else if (aState == hal::SWITCH_STATE_HEADPHONE) {
- obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_HEADPHONE);
- } else if (aState == hal::SWITCH_STATE_OFF) {
- obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_OFF);
- } else {
- obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_UNKNOWN);
- }
- }
-}
-
-class HeadphoneSwitchObserver : public hal::SwitchObserver
-{
-public:
- void Notify(const hal::SwitchEvent& aEvent) {
- RefPtr<AudioManager> audioManager = AudioManager::GetInstance();
- MOZ_ASSERT(audioManager);
- audioManager->HandleHeadphoneSwitchEvent(aEvent);
- }
-};
-
-void
-AudioManager::HandleHeadphoneSwitchEvent(const hal::SwitchEvent& aEvent)
-{
- NotifyHeadphonesStatus(aEvent.status());
- // When user pulled out the headset, a delay of routing here can avoid the leakage of audio from speaker.
- if (aEvent.status() == hal::SWITCH_STATE_OFF && mSwitchDone) {
-
- RefPtr<AudioManager> self = this;
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([self]() {
- if (self->mSwitchDone) {
- return;
- }
- self->UpdateHeadsetConnectionState(hal::SWITCH_STATE_OFF);
- self->mSwitchDone = true;
- });
- MessageLoop::current()->PostDelayedTask(
- MakeAndAddRef<RunnableCallTask>(runnable), 1000);
- mSwitchDone = false;
- } else if (aEvent.status() != hal::SWITCH_STATE_OFF) {
- UpdateHeadsetConnectionState(aEvent.status());
- mSwitchDone = true;
- }
- // Handle the coexistence of a2dp / headset device, latest one wins.
-#if ANDROID_VERSION >= 17
- int32_t forceUse = 0;
- GetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, &forceUse);
- if (aEvent.status() != hal::SWITCH_STATE_OFF && mBluetoothA2dpEnabled) {
- SetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_NO_BT_A2DP);
- } else if (forceUse == AUDIO_POLICY_FORCE_NO_BT_A2DP) {
- SetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_NONE);
- }
-#endif
-}
-
-AudioManager::AudioManager()
- : mPhoneState(PHONE_STATE_CURRENT)
- , mIsVolumeInited(false)
- , mAudioOutDevicesUpdated(0)
- , mSwitchDone(true)
-#if defined(MOZ_B2G_BT) || ANDROID_VERSION >= 17
- , mBluetoothA2dpEnabled(false)
-#endif
-#ifdef MOZ_B2G_BT
- , mA2dpSwitchDone(true)
-#endif
- , mObserver(new HeadphoneSwitchObserver())
-{
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(kAudioDeviceInfos); ++idx) {
- mAudioDeviceTableIdMaps.Put(kAudioDeviceInfos[idx].value, idx);
- }
-
- AudioSystem::setErrorCallback(BinderDeadCallback);
-#if ANDROID_VERSION >= 21
- android::sp<GonkAudioPortCallback> callback = new GonkAudioPortCallback();
- AudioSystem::setAudioPortCallback(callback);
-#endif
-
- // Create VolumeStreamStates
- for (uint32_t loop = 0; loop < AUDIO_STREAM_CNT; ++loop) {
- VolumeStreamState* streamState =
- new VolumeStreamState(*this, static_cast<audio_stream_type_t>(loop));
- mStreamStates.AppendElement(streamState);
- }
- // Initialize stream volumes with default values
- for (int32_t streamType = 0; streamType < AUDIO_STREAM_MAX; streamType++) {
- uint32_t volIndex = sDefaultStreamVolumeTbl[streamType];
- SetStreamVolumeForDevice(streamType, volIndex, AUDIO_DEVICE_OUT_DEFAULT);
- }
- UpdateCachedActiveDevicesForStreams();
-
- RegisterSwitchObserver(hal::SWITCH_HEADPHONES, mObserver);
- // Initialize headhone/heaset status
- UpdateHeadsetConnectionState(hal::GetCurrentSwitchState(hal::SWITCH_HEADPHONES));
- NotifyHeadphonesStatus(hal::GetCurrentSwitchState(hal::SWITCH_HEADPHONES));
-
- // Get the initial volume index from settings DB during boot up.
- InitVolumeFromDatabase();
-
- // Gecko only control stream volume not master so set to default value
- // directly.
- AudioSystem::setMasterVolume(1.0);
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- NS_ENSURE_TRUE_VOID(obs);
- if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_SCO_STATUS_CHANGED_ID, false))) {
- NS_WARNING("Failed to add bluetooth sco status changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_A2DP_STATUS_CHANGED_ID, false))) {
- NS_WARNING("Failed to add bluetooth a2dp status changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_HFP_STATUS_CHANGED_ID, false))) {
- NS_WARNING("Failed to add bluetooth hfp status changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID, false))) {
- NS_WARNING("Failed to add bluetooth hfp NREC status changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, MOZ_SETTINGS_CHANGE_ID, false))) {
- NS_WARNING("Failed to add mozsettings-changed observer!");
- }
- if (NS_FAILED(obs->AddObserver(this, AUDIO_CHANNEL_PROCESS_CHANGED, false))) {
- NS_WARNING("Failed to add audio-channel-process-changed observer!");
- }
-
-}
-
-AudioManager::~AudioManager() {
- AudioSystem::setErrorCallback(nullptr);
-#if ANDROID_VERSION >= 21
- AudioSystem::setAudioPortCallback(nullptr);
-#endif
- hal::UnregisterSwitchObserver(hal::SWITCH_HEADPHONES, mObserver);
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- NS_ENSURE_TRUE_VOID(obs);
- if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_SCO_STATUS_CHANGED_ID))) {
- NS_WARNING("Failed to remove bluetooth sco status changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_A2DP_STATUS_CHANGED_ID))) {
- NS_WARNING("Failed to remove bluetooth a2dp status changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_HFP_STATUS_CHANGED_ID))) {
- NS_WARNING("Failed to remove bluetooth hfp status changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID))) {
- NS_WARNING("Failed to remove bluetooth hfp NREC status changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, MOZ_SETTINGS_CHANGE_ID))) {
- NS_WARNING("Failed to remove mozsettings-changed observer!");
- }
- if (NS_FAILED(obs->RemoveObserver(this, AUDIO_CHANNEL_PROCESS_CHANGED))) {
- NS_WARNING("Failed to remove audio-channel-process-changed!");
- }
-}
-
-static StaticRefPtr<AudioManager> sAudioManager;
-
-already_AddRefed<AudioManager>
-AudioManager::GetInstance()
-{
- // Avoid createing AudioManager from content process.
- if (!XRE_IsParentProcess()) {
- MOZ_CRASH("Non-chrome processes should not get here.");
- }
-
- // Avoid createing multiple AudioManager instance inside main process.
- if (!sAudioManager) {
- sAudioManager = new AudioManager();
- ClearOnShutdown(&sAudioManager);
- }
-
- RefPtr<AudioManager> audioMgr = sAudioManager.get();
- return audioMgr.forget();
-}
-
-NS_IMETHODIMP
-AudioManager::GetMicrophoneMuted(bool* aMicrophoneMuted)
-{
-
- if (AudioSystem::isMicrophoneMuted(aMicrophoneMuted)) {
- return NS_ERROR_FAILURE;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-AudioManager::SetMicrophoneMuted(bool aMicrophoneMuted)
-{
- if (!AudioSystem::muteMicrophone(aMicrophoneMuted)) {
- return NS_OK;
- }
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-AudioManager::GetPhoneState(int32_t* aState)
-{
- *aState = mPhoneState;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-AudioManager::SetPhoneState(int32_t aState)
-{
- if (mPhoneState == aState) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- if (obs) {
- nsString state;
- state.AppendInt(aState);
- obs->NotifyObservers(nullptr, "phone-state-changed", state.get());
- }
-
-#if ANDROID_VERSION < 17
- if (AudioSystem::setPhoneState(aState)) {
-#else
- if (AudioSystem::setPhoneState(static_cast<audio_mode_t>(aState))) {
-#endif
- return NS_ERROR_FAILURE;
- }
-
-#if ANDROID_VERSION < 21
- // Manually call it, since AudioPortCallback is not supported.
- // Current volumes might be changed by updating active devices in android
- // AudioPolicyManager.
- MaybeUpdateVolumeSettingToDatabase();
-#endif
- mPhoneState = aState;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-AudioManager::SetForceForUse(int32_t aUsage, int32_t aForce)
-{
-#if ANDROID_VERSION >= 15
- status_t status = AudioSystem::setForceUse(
- (audio_policy_force_use_t)aUsage,
- (audio_policy_forced_cfg_t)aForce);
-#if ANDROID_VERSION < 21
- // Manually call it, since AudioPortCallback is not supported.
- // Current volumes might be changed by updating active devices in android
- // AudioPolicyManager.
- MaybeUpdateVolumeSettingToDatabase();
-#endif
- return status ? NS_ERROR_FAILURE : NS_OK;
-#else
- NS_NOTREACHED("Doesn't support force routing on GB version");
- return NS_ERROR_UNEXPECTED;
-#endif
-}
-
-NS_IMETHODIMP
-AudioManager::GetForceForUse(int32_t aUsage, int32_t* aForce) {
-#if ANDROID_VERSION >= 15
- *aForce = AudioSystem::getForceUse((audio_policy_force_use_t)aUsage);
- return NS_OK;
-#else
- NS_NOTREACHED("Doesn't support force routing on GB version");
- return NS_ERROR_UNEXPECTED;
-#endif
-}
-
-NS_IMETHODIMP
-AudioManager::SetAudioChannelVolume(uint32_t aChannel, uint32_t aIndex)
-{
- if (aChannel >= NUMBER_OF_AUDIO_CHANNELS) {
- return NS_ERROR_INVALID_ARG;
- }
-
- return SetStreamVolumeIndex(sChannelStreamTbl[aChannel], aIndex);
-}
-
-NS_IMETHODIMP
-AudioManager::GetAudioChannelVolume(uint32_t aChannel, uint32_t* aIndex)
-{
- if (aChannel >= NUMBER_OF_AUDIO_CHANNELS) {
- return NS_ERROR_INVALID_ARG;
- }
-
- if (!aIndex) {
- return NS_ERROR_NULL_POINTER;
- }
-
- return GetStreamVolumeIndex(sChannelStreamTbl[aChannel], aIndex);
-}
-
-NS_IMETHODIMP
-AudioManager::GetMaxAudioChannelVolume(uint32_t aChannel, uint32_t* aMaxIndex)
-{
- if (aChannel >= NUMBER_OF_AUDIO_CHANNELS) {
- return NS_ERROR_INVALID_ARG;
- }
-
- if (!aMaxIndex) {
- return NS_ERROR_NULL_POINTER;
- }
-
- *aMaxIndex = mStreamStates[sChannelStreamTbl[aChannel]]->GetMaxIndex();
- return NS_OK;
-}
-
-nsresult
-AudioManager::ValidateVolumeIndex(int32_t aStream, uint32_t aIndex) const
-{
- if (aStream <= AUDIO_STREAM_DEFAULT || aStream >= AUDIO_STREAM_MAX) {
- return NS_ERROR_INVALID_ARG;
- }
-
- uint32_t maxIndex = mStreamStates[aStream]->GetMaxIndex();
- if (aIndex > maxIndex) {
- return NS_ERROR_FAILURE;
- }
- return NS_OK;
-}
-
-nsresult
-AudioManager::SetStreamVolumeForDevice(int32_t aStream,
- uint32_t aIndex,
- uint32_t aDevice)
-{
- if (aStream <= AUDIO_STREAM_DEFAULT || aStream >= AUDIO_STREAM_MAX) {
- return NS_ERROR_INVALID_ARG;
- }
-
- int32_t streamAlias = sStreamVolumeAliasTbl[aStream];
- VolumeStreamState* streamState = mStreamStates[streamAlias].get();
- return streamState->SetVolumeIndexToAliasStreams(aIndex, aDevice);
-}
-
-nsresult
-AudioManager::SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex)
-{
- if (aStream <= AUDIO_STREAM_DEFAULT || aStream >= AUDIO_STREAM_MAX) {
- return NS_ERROR_INVALID_ARG;
- }
-
- int32_t streamAlias = sStreamVolumeAliasTbl[aStream];
-
- nsresult rv;
- for (int32_t streamType = 0; streamType < AUDIO_STREAM_MAX; streamType++) {
- if (streamAlias == sStreamVolumeAliasTbl[streamType]) {
- rv = mStreamStates[streamType]->SetVolumeIndexToActiveDevices(aIndex);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- // AUDIO_STREAM_FM is not used on recent gonk.
- // AUDIO_STREAM_MUSIC is used for FM radio volume control.
-#if ANDROID_VERSION < 19
- if (streamAlias == AUDIO_STREAM_MUSIC && IsFmOutConnected()) {
- rv = mStreamStates[AUDIO_STREAM_FM]->
- SetVolumeIndex(aIndex, AUDIO_DEVICE_OUT_FM);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
-#endif
-
- MaybeUpdateVolumeSettingToDatabase();
- return NS_OK;
-}
-
-nsresult
-AudioManager::GetStreamVolumeIndex(int32_t aStream, uint32_t *aIndex)
-{
- if (!aIndex) {
- return NS_ERROR_INVALID_ARG;
- }
-
- if (aStream <= AUDIO_STREAM_DEFAULT || aStream >= AUDIO_STREAM_MAX) {
- return NS_ERROR_INVALID_ARG;
- }
-
- *aIndex = mStreamStates[aStream]->GetVolumeIndex();
- return NS_OK;
-}
-
-nsAutoCString
-AudioManager::AppendDeviceToVolumeSetting(const char* aName, uint32_t aDevice)
-{
- nsAutoCString topic;
- topic.Assign(aName);
- topic.Append(".");
- uint32_t index = 0;
- DebugOnly<bool> exist = mAudioDeviceTableIdMaps.Get(aDevice, &index);
- MOZ_ASSERT(exist);
- topic.Append(kAudioDeviceInfos[index].tag);
- return topic;
-}
-
-void
-AudioManager::InitVolumeFromDatabase()
-{
- nsresult rv;
- nsCOMPtr<nsISettingsService> service = do_GetService(SETTINGS_SERVICE, &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- nsCOMPtr<nsISettingsServiceLock> lock;
- rv = service->CreateLock(nullptr, getter_AddRefs(lock));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- RefPtr<VolumeInitCallback> callback = new VolumeInitCallback();
- MOZ_ASSERT(callback);
- callback->GetPromise()->Then(AbstractThread::MainThread(), __func__, this,
- &AudioManager::InitDeviceVolumeSucceeded,
- &AudioManager::InitDeviceVolumeFailed);
-
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- for (uint32_t idx2 = 0; idx2 < MOZ_ARRAY_LENGTH(kAudioDeviceInfos); ++idx2) {
- lock->Get(AppendDeviceToVolumeSetting(gVolumeData[idx].mChannelName,
- kAudioDeviceInfos[idx2].value).get(),
- callback);
- }
- }
-}
-
-void
-AudioManager::InitDeviceVolumeSucceeded()
-{
- mIsVolumeInited = true;
- MaybeUpdateVolumeSettingToDatabase(true);
-}
-
-void
-AudioManager::InitDeviceVolumeFailed(const char* aError)
-{
- // Default volume of AUDIO_DEVICE_OUT_DEFAULT is already set.
- mIsVolumeInited = true;
- MaybeUpdateVolumeSettingToDatabase(true);
- NS_WARNING(aError);
-}
-
-void
-AudioManager::MaybeUpdateVolumeSettingToDatabase(bool aForce)
-{
- if (!mIsVolumeInited) {
- return;
- }
-
- nsCOMPtr<nsISettingsServiceLock> lock = GetSettingServiceLock();
- if (NS_WARN_IF(!lock)) {
- return;
- }
-
- // Send events to update the Gaia volumes
- JS::Rooted<JS::Value> value(RootingCx());
- uint32_t volume = 0;
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- int32_t streamType = gVolumeData[idx].mStreamType;
- VolumeStreamState* streamState = mStreamStates[streamType].get();
- if(!aForce && !streamState->IsDevicesChanged()) {
- continue;
- }
- // Get volume index of active device.
- volume = streamState->GetVolumeIndex();
- value.setInt32(volume);
- lock->Set(gVolumeData[idx].mChannelName, value, nullptr, nullptr);
- }
-
- // For reducing the code dependency, Gaia doesn't need to know the
- // device volume, it only need to care about different volume categories.
- // However, we need to send the setting volume to the permanent database,
- // so that we can store the volume setting even if the phone reboots.
-
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- int32_t streamType = gVolumeData[idx].mStreamType;
- VolumeStreamState* streamState = mStreamStates[streamType].get();
-
- if(!streamState->IsVolumeIndexesChanged()) {
- continue;
- }
-
- uint32_t remainingDevices = mAudioOutDevicesUpdated;
- for (uint32_t i = 0; remainingDevices != 0; i++) {
- uint32_t device = (1 << i);
- if ((device & remainingDevices) == 0) {
- continue;
- }
- remainingDevices &= ~device;
- if (!mAudioDeviceTableIdMaps.Get(device, nullptr)) {
- continue;
- }
- volume = streamState->GetVolumeIndex(device);
- value.setInt32(volume);
- lock->Set(AppendDeviceToVolumeSetting(gVolumeData[idx].mChannelName,
- device).get(),
- value, nullptr, nullptr);
- }
- }
-
- // Clear changed flags
- for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
- int32_t streamType = gVolumeData[idx].mStreamType;
- mStreamStates[streamType]->ClearDevicesChanged();
- mStreamStates[streamType]->ClearVolumeIndexesChanged();
- }
- // Clear mAudioOutDevicesUpdated
- mAudioOutDevicesUpdated = 0;
-}
-
-void
-AudioManager::UpdateCachedActiveDevicesForStreams()
-{
- // This function updates cached active devices for streams.
- // It is used for optimization of GetDevicesForStream() since L.
- // AudioManager could know when active devices
- // are changed in AudioPolicyManager by onAudioPortListUpdate().
- // Except it, AudioManager normally do not need to ask AuidoPolicyManager
- // about current active devices of streams and could use cached values.
- // Before L, onAudioPortListUpdate() does not exist and GetDevicesForStream()
- // does not use the cache. Therefore this function do nothing.
-#if ANDROID_VERSION >= 21
- for (int32_t streamType = 0; streamType < AUDIO_STREAM_MAX; streamType++) {
- // Update cached active devices of stream
- mStreamStates[streamType]->IsDevicesChanged(false /* aFromCache */);
- }
-#endif
-}
-
-uint32_t
-AudioManager::GetDevicesForStream(int32_t aStream, bool aFromCache)
-{
-#if ANDROID_VERSION >= 21
- // Since Lollipop, devices update could be notified by AudioPortCallback.
- // Cached values can be used if there is no update.
- if (aFromCache) {
- return mStreamStates[aStream]->GetLastDevices();
- }
-#endif
-
-#if ANDROID_VERSION >= 17
- audio_devices_t devices =
- AudioSystem::getDevicesForStream(static_cast<audio_stream_type_t>(aStream));
-
- return static_cast<uint32_t>(devices);
-#else
- // Per audio out device volume is not supported.
- // Use AUDIO_DEVICE_OUT_SPEAKER just to store audio volume to DB.
- return AUDIO_DEVICE_OUT_SPEAKER;
-#endif
-}
-
-uint32_t
-AudioManager::GetDeviceForStream(int32_t aStream)
-{
- uint32_t devices =
- GetDevicesForStream(static_cast<audio_stream_type_t>(aStream));
- uint32_t device = SelectDeviceFromDevices(devices);
- return device;
-}
-
-/* static */ uint32_t
-AudioManager::SelectDeviceFromDevices(uint32_t aOutDevices)
-{
- uint32_t device = aOutDevices;
-
- // See android AudioService.getDeviceForStream().
- // AudioPolicyManager expects it.
- // See also android AudioPolicyManager::getDeviceForVolume().
- if ((device & (device - 1)) != 0) {
- // Multiple device selection.
- if ((device & AUDIO_DEVICE_OUT_SPEAKER) != 0) {
- device = AUDIO_DEVICE_OUT_SPEAKER;
-#if ANDROID_VERSION >= 21
- } else if ((device & AUDIO_DEVICE_OUT_HDMI_ARC) != 0) {
- device = AUDIO_DEVICE_OUT_HDMI_ARC;
- } else if ((device & AUDIO_DEVICE_OUT_SPDIF) != 0) {
- device = AUDIO_DEVICE_OUT_SPDIF;
- } else if ((device & AUDIO_DEVICE_OUT_AUX_LINE) != 0) {
- device = AUDIO_DEVICE_OUT_AUX_LINE;
-#endif
- } else {
- device &= AUDIO_DEVICE_OUT_ALL_A2DP;
- }
- }
- MOZ_ASSERT(audio_is_output_device(device));
- return device;
-}
-AudioManager::VolumeStreamState::VolumeStreamState(AudioManager& aManager,
- int32_t aStreamType)
- : mManager(aManager)
- , mStreamType(aStreamType)
- , mLastDevices(0)
- , mIsDevicesChanged(true)
- , mIsVolumeIndexesChanged(true)
-{
- InitStreamVolume();
-}
-
-bool
-AudioManager::VolumeStreamState::IsDevicesChanged(bool aFromCache)
-{
- uint32_t devices = mManager.GetDevicesForStream(mStreamType, aFromCache);
- if (devices != mLastDevices) {
- mLastDevices = devices;
- mIsDevicesChanged = true;
- }
- return mIsDevicesChanged;
-}
-
-void
-AudioManager::VolumeStreamState::ClearDevicesChanged()
-{
- mIsDevicesChanged = false;
-}
-
-bool
-AudioManager::VolumeStreamState::IsVolumeIndexesChanged()
-{
- return mIsVolumeIndexesChanged;
-}
-
-void
-AudioManager::VolumeStreamState::ClearVolumeIndexesChanged()
-{
- mIsVolumeIndexesChanged = false;
-}
-
-void
-AudioManager::VolumeStreamState::InitStreamVolume()
-{
- AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(mStreamType),
- 0,
- GetMaxIndex());
-}
-
-uint32_t
-AudioManager::VolumeStreamState::GetMaxIndex()
-{
- return sMaxStreamVolumeTbl[mStreamType];
-}
-
-uint32_t
-AudioManager::VolumeStreamState::GetDefaultIndex()
-{
- return sDefaultStreamVolumeTbl[mStreamType];
-}
-
-uint32_t
-AudioManager::VolumeStreamState::GetVolumeIndex()
-{
- uint32_t device = mManager.GetDeviceForStream(mStreamType);
- return GetVolumeIndex(device);
-}
-
-uint32_t
-AudioManager::VolumeStreamState::GetVolumeIndex(uint32_t aDevice)
-{
- uint32_t index = 0;
- bool ret = mVolumeIndexes.Get(aDevice, &index);
- if (!ret) {
- index = mVolumeIndexes.Get(AUDIO_DEVICE_OUT_DEFAULT);
- }
- return index;
-}
-
-nsresult
-AudioManager::VolumeStreamState::SetVolumeIndexToActiveDevices(uint32_t aIndex)
-{
- uint32_t device = mManager.GetDeviceForStream(mStreamType);
-
- // Update volume index for device
- uint32_t oldVolumeIndex = 0;
- bool exist = mVolumeIndexes.Get(device, &oldVolumeIndex);
- if (exist && aIndex == oldVolumeIndex) {
- // No update
- return NS_OK;
- }
-
- // AudioPolicyManager::setStreamVolumeIndex() set volumes of all active
- // devices for stream.
- nsresult rv;
- rv = SetVolumeIndexToConsistentDeviceIfNeeded(aIndex, device);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- return NS_OK;
-}
-
-nsresult
-AudioManager::VolumeStreamState::SetVolumeIndexToAliasStreams(uint32_t aIndex,
- uint32_t aDevice)
-{
- uint32_t oldVolumeIndex = 0;
- bool exist = mVolumeIndexes.Get(aDevice, &oldVolumeIndex);
- if (exist && aIndex == oldVolumeIndex) {
- // No update
- return NS_OK;
- }
-
- nsresult rv = SetVolumeIndexToConsistentDeviceIfNeeded(aIndex, aDevice);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- for (int32_t streamType = 0; streamType < AUDIO_STREAM_MAX; streamType++) {
- if ((streamType != mStreamType) &&
- sStreamVolumeAliasTbl[streamType] == mStreamType) {
- // Rescaling of index is not necessary.
- rv = mManager.mStreamStates[streamType]->
- SetVolumeIndexToAliasStreams(aIndex, aDevice);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-AudioManager::VolumeStreamState::SetVolumeIndexToConsistentDeviceIfNeeded(uint32_t aIndex, uint32_t aDevice)
-{
- nsresult rv;
- if (aDevice == AUDIO_DEVICE_OUT_SPEAKER || aDevice == AUDIO_DEVICE_OUT_EARPIECE) {
- // Set AUDIO_DEVICE_OUT_SPEAKER and AUDIO_DEVICE_OUT_EARPIECE to same volume.
- rv = SetVolumeIndex(aIndex, AUDIO_DEVICE_OUT_SPEAKER);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- rv = SetVolumeIndex(aIndex, AUDIO_DEVICE_OUT_EARPIECE);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- // No alias device
- rv = SetVolumeIndex(aIndex, aDevice);
- }
- return rv;
-}
-
-nsresult
-AudioManager::VolumeStreamState::SetVolumeIndex(uint32_t aIndex,
- uint32_t aDevice,
- bool aUpdateCache)
-{
- status_t rv;
-#if ANDROID_VERSION >= 17
- if (aUpdateCache) {
- mVolumeIndexes.Put(aDevice, aIndex);
- mIsVolumeIndexesChanged = true;
- mManager.AudioOutDeviceUpdated(aDevice);
- }
-
- rv = AudioSystem::setStreamVolumeIndex(
- static_cast<audio_stream_type_t>(mStreamType),
- aIndex,
- aDevice);
- return rv ? NS_ERROR_FAILURE : NS_OK;
-#else
- if (aUpdateCache) {
- // Per audio out device volume is not supported.
- // Use AUDIO_DEVICE_OUT_SPEAKER just to store audio volume to DB.
- mVolumeIndexes.Put(AUDIO_DEVICE_OUT_SPEAKER, aIndex);
- mIsVolumeIndexesChanged = true;
- mManager.AudioOutDeviceUpdated(AUDIO_DEVICE_OUT_SPEAKER);
- }
- rv = AudioSystem::setStreamVolumeIndex(
- static_cast<audio_stream_type_t>(mStreamType),
- aIndex);
- return rv ? NS_ERROR_FAILURE : NS_OK;
-#endif
-}
-
-void
-AudioManager::VolumeStreamState::RestoreVolumeIndexToAllDevices()
-{
- for (auto iter = mVolumeIndexes.Iter(); !iter.Done(); iter.Next()) {
- const uint32_t& key = iter.Key();
- uint32_t& index = iter.Data();
- SetVolumeIndex(key, index, /* aUpdateCache */ false);
- }
-}
-
-} /* namespace gonk */
-} /* namespace dom */
-} /* namespace mozilla */
diff --git a/dom/system/gonk/AudioManager.h b/dom/system/gonk/AudioManager.h
deleted file mode 100644
index f56eaad6c..000000000
--- a/dom/system/gonk/AudioManager.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 mozilla_dom_system_b2g_audiomanager_h__
-#define mozilla_dom_system_b2g_audiomanager_h__
-
-#include "mozilla/HalTypes.h"
-#include "mozilla/Observer.h"
-#include "mozilla/UniquePtr.h"
-#include "nsAutoPtr.h"
-#include "nsDataHashtable.h"
-#include "nsIAudioManager.h"
-#include "nsIObserver.h"
-#include "android_audio/AudioSystem.h"
-
-// {b2b51423-502d-4d77-89b3-7786b562b084}
-#define NS_AUDIOMANAGER_CID {0x94f6fd70, 0x7615, 0x4af9, \
- {0x89, 0x10, 0xf9, 0x3c, 0x55, 0xe6, 0x62, 0xec}}
-#define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"
-
-class nsISettingsServiceLock;
-
-namespace mozilla {
-namespace hal {
-class SwitchEvent;
-typedef Observer<SwitchEvent> SwitchObserver;
-} // namespace hal
-
-namespace dom {
-namespace gonk {
-
-class VolumeInitCallback;
-
-class AudioManager final : public nsIAudioManager
- , public nsIObserver
-{
-public:
- static already_AddRefed<AudioManager> GetInstance();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIAUDIOMANAGER
- NS_DECL_NSIOBSERVER
-
- // Validate whether the volume index is within the range
- nsresult ValidateVolumeIndex(int32_t aStream, uint32_t aIndex) const;
-
- // Called when android AudioFlinger in mediaserver is died
- void HandleAudioFlingerDied();
-
- void HandleHeadphoneSwitchEvent(const hal::SwitchEvent& aEvent);
-
- class VolumeStreamState {
- public:
- explicit VolumeStreamState(AudioManager& aManager, int32_t aStreamType);
- int32_t GetStreamType()
- {
- return mStreamType;
- }
- bool IsDevicesChanged(bool aFromCache = true);
- void ClearDevicesChanged();
- uint32_t GetLastDevices()
- {
- return mLastDevices;
- }
- bool IsVolumeIndexesChanged();
- void ClearVolumeIndexesChanged();
- void InitStreamVolume();
- uint32_t GetMaxIndex();
- uint32_t GetDefaultIndex();
- uint32_t GetVolumeIndex();
- uint32_t GetVolumeIndex(uint32_t aDevice);
- void ClearCurrentVolumeUpdated();
- // Set volume index to all active devices.
- // Active devices are chosen by android AudioPolicyManager.
- nsresult SetVolumeIndexToActiveDevices(uint32_t aIndex);
- // Set volume index to all alias streams for device. Alias streams have same volume.
- nsresult SetVolumeIndexToAliasStreams(uint32_t aIndex, uint32_t aDevice);
- nsresult SetVolumeIndexToConsistentDeviceIfNeeded(uint32_t aIndex, uint32_t aDevice);
- nsresult SetVolumeIndex(uint32_t aIndex, uint32_t aDevice, bool aUpdateCache = true);
- // Restore volume index to all devices. Called when AudioFlinger is restarted.
- void RestoreVolumeIndexToAllDevices();
- private:
- AudioManager& mManager;
- const int32_t mStreamType;
- uint32_t mLastDevices;
- bool mIsDevicesChanged;
- bool mIsVolumeIndexesChanged;
- nsDataHashtable<nsUint32HashKey, uint32_t> mVolumeIndexes;
- };
-
-protected:
- int32_t mPhoneState;
-
- bool mIsVolumeInited;
-
- // A bitwise variable for volume update of audio output devices,
- // clear it after store the value into database.
- uint32_t mAudioOutDevicesUpdated;
-
- // Connected devices that are controlled by setDeviceConnectionState()
- nsDataHashtable<nsUint32HashKey, nsCString> mConnectedDevices;
-
- nsDataHashtable<nsUint32HashKey, uint32_t> mAudioDeviceTableIdMaps;
-
- bool mSwitchDone;
-
-#if defined(MOZ_B2G_BT) || ANDROID_VERSION >= 17
- bool mBluetoothA2dpEnabled;
-#endif
-#ifdef MOZ_B2G_BT
- bool mA2dpSwitchDone;
-#endif
- nsTArray<UniquePtr<VolumeStreamState> > mStreamStates;
- uint32_t mLastChannelVolume[AUDIO_STREAM_CNT];
-
- bool IsFmOutConnected();
-
- nsresult SetStreamVolumeForDevice(int32_t aStream,
- uint32_t aIndex,
- uint32_t aDevice);
- nsresult SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex);
- nsresult GetStreamVolumeIndex(int32_t aStream, uint32_t* aIndex);
-
- void UpdateCachedActiveDevicesForStreams();
- uint32_t GetDevicesForStream(int32_t aStream, bool aFromCache = true);
- uint32_t GetDeviceForStream(int32_t aStream);
- // Choose one device as representative of active devices.
- static uint32_t SelectDeviceFromDevices(uint32_t aOutDevices);
-
-private:
- nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
-
- void HandleBluetoothStatusChanged(nsISupports* aSubject,
- const char* aTopic,
- const nsCString aAddress);
- void HandleAudioChannelProcessChanged();
-
- // Append the audio output device to the volume setting string.
- nsAutoCString AppendDeviceToVolumeSetting(const char* aName,
- uint32_t aDevice);
-
- // We store the volume setting in the database, these are related functions.
- void InitVolumeFromDatabase();
- void MaybeUpdateVolumeSettingToDatabase(bool aForce = false);
-
- // Promise functions.
- void InitDeviceVolumeSucceeded();
- void InitDeviceVolumeFailed(const char* aError);
-
- void AudioOutDeviceUpdated(uint32_t aDevice);
-
- void UpdateHeadsetConnectionState(hal::SwitchState aState);
- void UpdateDeviceConnectionState(bool aIsConnected, uint32_t aDevice, const nsCString& aDeviceName);
- void SetAllDeviceConnectionStates();
-
- AudioManager();
- ~AudioManager();
-
- friend class VolumeInitCallback;
- friend class VolumeStreamState;
- friend class GonkAudioPortCallback;
-};
-
-} /* namespace gonk */
-} /* namespace dom */
-} /* namespace mozilla */
-
-#endif // mozilla_dom_system_b2g_audiomanager_h__
diff --git a/dom/system/gonk/AutoMounter.cpp b/dom/system/gonk/AutoMounter.cpp
deleted file mode 100644
index 52c4554fb..000000000
--- a/dom/system/gonk/AutoMounter.cpp
+++ /dev/null
@@ -1,1496 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <signal.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-#include <sys/statfs.h>
-
-#include <arpa/inet.h>
-#include <linux/types.h>
-#include <linux/netlink.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <android/log.h>
-#include <cutils/properties.h>
-
-#include "AutoMounter.h"
-#include "nsVolumeService.h"
-#include "AutoMounterSetting.h"
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "mozilla/AutoRestore.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/Hal.h"
-#include "mozilla/StaticPtr.h"
-#include "MozMtpServer.h"
-#include "MozMtpStorage.h"
-#include "nsCharSeparatedTokenizer.h"
-#include "nsMemory.h"
-#include "nsString.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-#include "OpenFileFinder.h"
-#include "Volume.h"
-#include "VolumeManager.h"
-#include "nsIStatusReporter.h"
-
-USING_MTP_NAMESPACE
-
-/**************************************************************************
-*
-* The following "switch" files are available for monitoring usb
-* connections:
-*
-* /sys/devices/virtual/switch/usb_connected/state
-* /sys/devices/virtual/switch/usb_configuration/state
-*
-* Under gingerbread, only the usb_configuration seems to be available.
-* Starting with honeycomb, usb_connected was also added.
-*
-* When a cable insertion/removal occurs, then a uevent similar to the
-* following will be generted:
-*
-* change@/devices/virtual/switch/usb_configuration
-* ACTION=change
-* DEVPATH=/devices/virtual/switch/usb_configuration
-* SUBSYSTEM=switch
-* SWITCH_NAME=usb_configuration
-* SWITCH_STATE=0
-* SEQNUM=5038
-*
-* SWITCH_STATE will be 0 after a removal and 1 after an insertion
-*
-**************************************************************************/
-
-#define USB_CONFIGURATION_SWITCH_NAME NS_LITERAL_STRING("usb_configuration")
-
-#define GB_SYS_UMS_ENABLE "/sys/devices/virtual/usb_composite/usb_mass_storage/enable"
-#define GB_SYS_USB_CONFIGURED "/sys/devices/virtual/switch/usb_configuration/state"
-
-#define ICS_SYS_USB_FUNCTIONS "/sys/devices/virtual/android_usb/android0/functions"
-#define ICS_SYS_UMS_DIRECTORY "/sys/devices/virtual/android_usb/android0/f_mass_storage"
-#define ICS_SYS_MTP_DIRECTORY "/sys/devices/virtual/android_usb/android0/f_mtp"
-#define ICS_SYS_USB_STATE "/sys/devices/virtual/android_usb/android0/state"
-
-#undef USE_DEBUG // MozMtpDatabase.h also defines USE_DEBUG
-#define USE_DEBUG 0
-
-#undef LOG
-#undef LOGW
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AutoMounter", ## args)
-#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "AutoMounter", ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "AutoMounter", ## args)
-
-#undef DBG
-#if USE_DEBUG
-#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "AutoMounter" , ## args)
-#else
-#define DBG(args...)
-#endif
-
-namespace mozilla {
-namespace system {
-
-#define SYS_USB_CONFIG "sys.usb.config"
-#define PERSIST_SYS_USB_CONFIG "persist.sys.usb.config"
-
-#define USB_FUNC_ADB "adb"
-#define USB_FUNC_MTP "mtp"
-#define USB_FUNC_NONE "none"
-#define USB_FUNC_RNDIS "rndis"
-#define USB_FUNC_UMS "mass_storage"
-#define USB_FUNC_DEFAULT "default"
-
-class AutoMounter;
-
-static void SetAutoMounterStatus(int32_t aStatus);
-
-/***************************************************************************/
-
-inline const char* SwitchStateStr(const hal::SwitchEvent& aEvent)
-{
- return aEvent.status() == hal::SWITCH_STATE_ON ? "plugged" : "unplugged";
-}
-
-/***************************************************************************/
-
-static bool
-IsUsbCablePluggedIn()
-{
-#if 0
- // Use this code when bug 745078 gets fixed (or use whatever the
- // appropriate method is)
- return GetCurrentSwitchEvent(SWITCH_USB) == hal::SWITCH_STATE_ON;
-#else
- // Until then, just go read the file directly
- if (access(ICS_SYS_USB_STATE, F_OK) == 0) {
- char usbState[20];
- if (ReadSysFile(ICS_SYS_USB_STATE, usbState, sizeof(usbState))) {
- DBG("IsUsbCablePluggedIn: state = '%s'", usbState);
- return strcmp(usbState, "CONFIGURED") == 0 ||
- strcmp(usbState, "CONNECTED") == 0;
- }
- ERR("Error reading file '%s': %s", ICS_SYS_USB_STATE, strerror(errno));
- return false;
- }
- bool configured;
- if (ReadSysFile(GB_SYS_USB_CONFIGURED, &configured)) {
- return configured;
- }
- ERR("Error reading file '%s': %s", GB_SYS_USB_CONFIGURED, strerror(errno));
- return false;
-#endif
-}
-
-static bool
-IsUsbConfigured()
-{
- if (access(ICS_SYS_USB_STATE, F_OK) == 0) {
- char usbState[20];
- if (ReadSysFile(ICS_SYS_USB_STATE, usbState, sizeof(usbState))) {
- DBG("IsUsbConfigured: state = '%s'", usbState);
- return strcmp(usbState, "CONFIGURED") == 0;
- }
- ERR("Error reading file '%s': %s", ICS_SYS_USB_STATE, strerror(errno));
- return false;
- }
- bool configured;
- if (ReadSysFile(GB_SYS_USB_CONFIGURED, &configured)) {
- return configured;
- }
- ERR("Error reading file '%s': %s", GB_SYS_USB_CONFIGURED, strerror(errno));
- return false;
-}
-
-/***************************************************************************/
-
-// The AutoVolumeManagerStateObserver allows the AutoMounter to know when
-// the volume manager changes state (i.e. it has finished initialization)
-class AutoVolumeManagerStateObserver : public VolumeManager::StateObserver
-{
-public:
- virtual void Notify(const VolumeManager::StateChangedEvent& aEvent);
-};
-
-// The AutoVolumeEventObserver allows the AutoMounter to know about card
-// insertion and removal, as well as state changes in the volume.
-class AutoVolumeEventObserver : public Volume::EventObserver
-{
-public:
- virtual void Notify(Volume* const& aEvent);
-};
-
-class AutoMounterResponseCallback : public VolumeResponseCallback
-{
-public:
- AutoMounterResponseCallback()
- : mErrorCount(0)
- {
- }
-
-protected:
- virtual void ResponseReceived(const VolumeCommand* aCommand);
-
-private:
- const static int kMaxErrorCount = 3; // Max number of errors before we give up
-
- int mErrorCount;
-};
-
-/***************************************************************************/
-
-class AutoMounter
-{
-public:
- NS_INLINE_DECL_REFCOUNTING(AutoMounter)
-
- typedef nsTArray<RefPtr<Volume>> VolumeArray;
-
- AutoMounter()
- : mState(STATE_IDLE),
- mResponseCallback(new AutoMounterResponseCallback),
- mMode(AUTOMOUNTER_DISABLE)
- {
- VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
- Volume::RegisterVolumeObserver(&mVolumeEventObserver, "AutoMounter");
-
- // It's possible that the VolumeManager is already in the READY state,
- // so we call CheckVolumeSettings here to cover that case. Otherwise,
- // we'll pick it up when the VolumeManage state changes to VOLUMES_READY.
- CheckVolumeSettings();
-
- DBG("Calling UpdateState from constructor");
- UpdateState();
- }
-
- void CheckVolumeSettings()
- {
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- DBG("CheckVolumeSettings: VolumeManager is NOT READY yet");
- return;
- }
- DBG("CheckVolumeSettings: VolumeManager is READY");
-
- // The VolumeManager knows about all of the volumes from vold. We now
- // know the names of all of the volumes, so we can find out what the
- // initial sharing settings are set to.
-
- VolumeManager::VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- VolumeManager::VolumeArray::index_type i;
- for (i = 0; i < numVolumes; i++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(i);
- if (vol) {
- // We need to pick up the intial value of the
- // ums.volume.NAME.enabled setting.
- AutoMounterSetting::CheckVolumeSettings(vol->Name());
-
- // Note: eventually CheckVolumeSettings will call
- // AutoMounter::SetSharingMode, which will in turn call
- // UpdateState if needed.
- }
- }
- }
-
- void UpdateState();
- void GetStatus(bool& umsAvail, bool& umsConfigured, bool& umsEnabled, bool& mtpAvail,
- bool& mtpConfigured, bool& mtpEnabled, bool& rndisConfigured);
-
- nsresult Dump(nsACString& desc);
-
- void ConfigureUsbFunction(const char* aUsbFunc);
-
- bool StartMtpServer();
- void StopMtpServer();
-
- void StartUmsSharing();
- void StopUmsSharing();
-
-
- const char* ModeStr(int32_t aMode)
- {
- switch (aMode) {
- case AUTOMOUNTER_DISABLE: return "Disable";
- case AUTOMOUNTER_ENABLE_UMS: return "Enable-UMS";
- case AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED: return "DisableWhenUnplugged";
- case AUTOMOUNTER_ENABLE_MTP: return "Enable-MTP";
- }
- return "??? Unknown ???";
- }
-
- bool IsModeEnabled(int32_t aMode)
- {
- return aMode == AUTOMOUNTER_ENABLE_MTP ||
- aMode == AUTOMOUNTER_ENABLE_UMS;
- }
-
- void SetMode(int32_t aMode)
- {
- if ((aMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) &&
- (mMode == AUTOMOUNTER_DISABLE)) {
- // If it's already disabled, then leave it as disabled.
- // AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED implies "enabled until unplugged"
- aMode = AUTOMOUNTER_DISABLE;
- }
-
- if (aMode == AUTOMOUNTER_DISABLE &&
- mMode == AUTOMOUNTER_ENABLE_UMS && IsUsbCablePluggedIn()) {
- // On many devices (esp non-Samsung), we can't force the disable, so we
- // need to defer until the USB cable is actually unplugged.
- // See bug 777043.
- //
- // Otherwise our attempt to disable it will fail, and we'll wind up in a bad
- // state where the AutoMounter thinks that Sharing has been turned off, but
- // the files are actually still being Shared because the attempt to unshare
- // failed.
- LOG("Attempting to disable UMS. Deferring until USB cable is unplugged.");
- aMode = AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED;
- }
-
- if (aMode != mMode) {
- LOG("Changing mode from '%s' to '%s'", ModeStr(mMode), ModeStr(aMode));
- mMode = aMode;
- DBG("Calling UpdateState due to mode set to %d", mMode);
- UpdateState();
- }
- }
-
- void SetSharingMode(const nsACString& aVolumeName, bool aAllowSharing)
- {
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol) {
- return;
- }
- if (vol->IsSharingEnabled() == aAllowSharing) {
- return;
- }
- vol->SetUnmountRequested(false);
- vol->SetMountRequested(false);
- vol->SetSharingEnabled(aAllowSharing);
- DBG("Calling UpdateState due to volume %s sharing set to %d",
- vol->NameStr(), (int)aAllowSharing);
- UpdateState();
- }
-
- void FormatVolume(const nsACString& aVolumeName)
- {
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol) {
- return;
- }
- if (vol->IsFormatRequested()) {
- return;
- }
- vol->SetUnmountRequested(false);
- vol->SetMountRequested(false);
- vol->SetFormatRequested(true);
- DBG("Calling UpdateState due to volume %s formatting set to %d",
- vol->NameStr(), (int)vol->IsFormatRequested());
- UpdateState();
- }
-
- void MountVolume(const nsACString& aVolumeName)
- {
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol) {
- return;
- }
- vol->SetUnmountRequested(false);
- if (vol->IsMountRequested() || vol->mState == nsIVolume::STATE_MOUNTED) {
- return;
- }
- vol->SetMountRequested(true);
- DBG("Calling UpdateState due to volume %s mounting set to %d",
- vol->NameStr(), (int)vol->IsMountRequested());
- UpdateState();
- }
-
- void UnmountVolume(const nsACString& aVolumeName)
- {
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol) {
- return;
- }
- if (vol->IsUnmountRequested()) {
- return;
- }
- vol->SetMountRequested(false);
- vol->SetUnmountRequested(true);
- DBG("Calling UpdateState due to volume %s unmounting set to %d",
- vol->NameStr(), (int)vol->IsUnmountRequested());
- UpdateState();
- }
-
-protected:
- ~AutoMounter()
- {
- Volume::UnregisterVolumeObserver(&mVolumeEventObserver, "AutoMounter");
- VolumeManager::UnregisterStateObserver(&mVolumeManagerStateObserver);
- }
-
-private:
-
- enum STATE
- {
- // IDLE - Nothing is being shared
- STATE_IDLE,
-
- // We've detected that conditions are right to enable mtp. So we've
- // set sys.usb.config to include mtp, and we're waiting for the USB
- // subsystem to be "configured". Once mtp shows up in
- // then we know
- // that its been configured and we can open /dev/mtp_usb
- STATE_MTP_CONFIGURING,
-
- // mtp has been configured (i.e. mtp now shows up in
- // /sys/devices/virtual/android_usb/android0/functions so we can start
- // the mtp server.
- STATE_MTP_STARTED,
-
- // The mtp server has reported sessionStarted. We'll leave this state
- // when we receive sessionEnded.
- STATE_MTP_CONNECTED,
-
- // We've added mass_storage (aka UMS) to sys.usb.config and we're waiting for
- // mass_storage to appear in /sys/devices/virtual/android_usb/android0/functions
- STATE_UMS_CONFIGURING,
-
- // mass_storage has been configured and we can start sharing once the user
- // enables it.
- STATE_UMS_CONFIGURED,
-
- // USB Tethering is enabled
- STATE_RNDIS_CONFIGURED,
- };
-
- const char *StateStr(STATE aState)
- {
- switch (aState) {
- case STATE_IDLE: return "IDLE";
- case STATE_MTP_CONFIGURING: return "MTP_CONFIGURING";
- case STATE_MTP_CONNECTED: return "MTP_CONNECTED";
- case STATE_MTP_STARTED: return "MTP_STARTED";
- case STATE_UMS_CONFIGURING: return "UMS_CONFIGURING";
- case STATE_UMS_CONFIGURED: return "UMS_CONFIGURED";
- case STATE_RNDIS_CONFIGURED: return "RNDIS_CONFIGURED";
- }
- return "STATE_???";
- }
-
- void SetState(STATE aState)
- {
- const char *oldStateStr = StateStr(mState);
- mState = aState;
- const char *newStateStr = StateStr(mState);
- LOG("AutoMounter state changed from %s to %s", oldStateStr, newStateStr);
- }
-
- STATE mState;
-
- AutoVolumeEventObserver mVolumeEventObserver;
- AutoVolumeManagerStateObserver mVolumeManagerStateObserver;
- RefPtr<VolumeResponseCallback> mResponseCallback;
- int32_t mMode;
- MozMtpStorage::Array mMozMtpStorage;
-};
-
-static StaticRefPtr<AutoMounter> sAutoMounter;
-static StaticRefPtr<MozMtpServer> sMozMtpServer;
-
-// The following is for status reporter
-enum STATE_REPORTER_STATE
-{
- REPORTER_UNREGISTERED,
- REPORTER_REGISTERED
-};
-
-static int status_reporter_progress = REPORTER_UNREGISTERED;
-nsresult getState(nsACString &desc)
-{
- sAutoMounter->Dump(desc);
- return NS_OK;
-}
-NS_STATUS_REPORTER_IMPLEMENT(AutoMounter, "AutoMounter", getState);
-
-/***************************************************************************/
-
-void
-AutoVolumeManagerStateObserver::Notify(const VolumeManager::StateChangedEvent &)
-{
- LOG("VolumeManager state changed event: %s", VolumeManager::StateStr());
-
- if (!sAutoMounter) {
- return;
- }
-
- // In the event that the VolumeManager just entered the VOLUMES_READY state,
- // we call CheckVolumeSettings here (it's possible that this method never
- // gets called if the VolumeManager was already in the VOLUMES_READY state
- // by the time the AutoMounter was constructed).
- sAutoMounter->CheckVolumeSettings();
-
- DBG("Calling UpdateState due to VolumeManagerStateObserver");
- sAutoMounter->UpdateState();
-}
-
-void
-AutoVolumeEventObserver::Notify(Volume * const &)
-{
- if (!sAutoMounter) {
- return;
- }
- DBG("Calling UpdateState due to VolumeEventStateObserver");
- sAutoMounter->UpdateState();
-}
-
-void
-AutoMounterResponseCallback::ResponseReceived(const VolumeCommand* aCommand)
-{
-
- if (WasSuccessful()) {
- DBG("Calling UpdateState due to Volume::OnSuccess");
- mErrorCount = 0;
- sAutoMounter->UpdateState();
- return;
- }
- ERR("Command '%s' failed: %d '%s'",
- aCommand->CmdStr(), ResponseCode(), ResponseStr().get());
-
- if (++mErrorCount < kMaxErrorCount) {
- DBG("Calling UpdateState due to VolumeResponseCallback::OnError");
- sAutoMounter->UpdateState();
- }
-}
-
-static bool
-IsUsbFunctionEnabled(const char* aConfig, const char* aUsbFunc)
-{
- nsAutoCString config(aConfig);
- nsCCharSeparatedTokenizer tokenizer(config, ',');
-
- while (tokenizer.hasMoreTokens()) {
- nsAutoCString token(tokenizer.nextToken());
- if (token.Equals(aUsbFunc)) {
- DBG("IsUsbFunctionEnabled('%s', '%s'): returning true", aConfig, aUsbFunc);
- return true;
- }
- }
- DBG("IsUsbFunctionEnabled('%s', '%s'): returning false", aConfig, aUsbFunc);
- return false;
-}
-
-static void
-SetUsbFunction(const char* aUsbFunc)
-{
- char oldSysUsbConfig[PROPERTY_VALUE_MAX];
- property_get(SYS_USB_CONFIG, oldSysUsbConfig, "");
-
- if (strcmp(oldSysUsbConfig, USB_FUNC_NONE) == 0) {
- // It's quite possible that sys.usb.config may have the value "none". We
- // convert that to an empty string here, and at the end we convert the
- // empty string back to "none".
- oldSysUsbConfig[0] = '\0';
- }
-
- if (IsUsbFunctionEnabled(oldSysUsbConfig, aUsbFunc)) {
- // The function is already configured. Nothing else to do.
- DBG("SetUsbFunction('%s') - already set - nothing to do", aUsbFunc);
- return;
- }
-
- char newSysUsbConfig[PROPERTY_VALUE_MAX];
-
- if (strcmp(aUsbFunc, USB_FUNC_MTP) == 0) {
- // We're enabling MTP. For this we'll wind up using mtp, or mtp,adb
- strlcpy(newSysUsbConfig, USB_FUNC_MTP, sizeof(newSysUsbConfig));
- } else if (strcmp(aUsbFunc, USB_FUNC_UMS) == 0) {
- // We're enabling UMS. For this we make the assumption that the persisted
- // property has mass_storage enabled.
- property_get(PERSIST_SYS_USB_CONFIG, newSysUsbConfig, "");
- } else if (strcmp(aUsbFunc, USB_FUNC_DEFAULT) == 0) {
- // Set the property as PERSIST_SYS_USB_CONFIG
- property_get(PERSIST_SYS_USB_CONFIG, newSysUsbConfig, "");
- } else {
- printf_stderr("AutoMounter::SetUsbFunction Unrecognized aUsbFunc '%s'\n", aUsbFunc);
- MOZ_ASSERT(0);
- return;
- }
-
- // Make sure the new value that we write into sys.usb.config keeps the adb
- // (or non-adb) of the current string.
-
- if (IsUsbFunctionEnabled(oldSysUsbConfig, USB_FUNC_ADB)) {
- // ADB was turned on - keep it on.
- if (!IsUsbFunctionEnabled(newSysUsbConfig, USB_FUNC_ADB)) {
- // Add adb to the new string
- strlcat(newSysUsbConfig, ",", sizeof(newSysUsbConfig));
- strlcat(newSysUsbConfig, USB_FUNC_ADB, sizeof(newSysUsbConfig));
- }
- } else {
- // ADB was turned off - keep it off
- if (IsUsbFunctionEnabled(newSysUsbConfig, USB_FUNC_ADB)) {
- // Remove ADB from the new string.
- if (strcmp(newSysUsbConfig, USB_FUNC_ADB) == 0) {
- newSysUsbConfig[0] = '\0';
- } else {
- nsAutoCString withoutAdb(newSysUsbConfig);
- withoutAdb.ReplaceSubstring( "," USB_FUNC_ADB, "");
- strlcpy(newSysUsbConfig, withoutAdb.get(), sizeof(newSysUsbConfig));
- }
- }
- }
-
- // If the persisted function didn't have mass_storage (this happens on
- // the nexus 4/5, then we can get to here and have oldSysUsbConfig equal
- // to newSysUsbConfig. So we need to check for that.
-
- if (strcmp(oldSysUsbConfig, newSysUsbConfig) == 0) {
- DBG("SetUsbFunction('%s') %s is already set to '%s' - nothing to do",
- aUsbFunc, SYS_USB_CONFIG, newSysUsbConfig);
- return;
- }
-
- if (newSysUsbConfig[0] == '\0') {
- // Convert the empty string back to the string "none"
- strlcpy(newSysUsbConfig, USB_FUNC_NONE, sizeof(newSysUsbConfig));
- }
- LOG("SetUsbFunction(%s) %s from '%s' to '%s'", aUsbFunc, SYS_USB_CONFIG,
- oldSysUsbConfig, newSysUsbConfig);
- property_set(SYS_USB_CONFIG, newSysUsbConfig);
-}
-
-bool
-AutoMounter::StartMtpServer()
-{
- if (sMozMtpServer) {
- // Mtp Server is already running - nothing to do
- return true;
- }
- LOG("Starting MtpServer");
-
- // For debugging, Change the #if 0 to #if 1, and then attach gdb during
- // the 5 second interval below. Otherwise, configuring MTP will cause adb
- // (and thus gdb) to get bounced.
-#if 0
- LOG("Sleeping");
- PRTime now = PR_Now();
- PRTime stopTime = now + 5000000;
- while (PR_Now() < stopTime) {
- LOG("Sleeping...");
- sleep(1);
- }
- LOG("Sleep done");
-#endif
-
- sMozMtpServer = new MozMtpServer();
- if (!sMozMtpServer->Init()) {
- sMozMtpServer = nullptr;
- return false;
- }
-
- VolumeArray::index_type volIndex;
- VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- RefPtr<MozMtpStorage> storage = new MozMtpStorage(vol, sMozMtpServer);
- mMozMtpStorage.AppendElement(storage);
- }
-
- sMozMtpServer->Run();
- return true;
-}
-
-void
-AutoMounter::StopMtpServer()
-{
- LOG("Stopping MtpServer");
-
- mMozMtpStorage.Clear();
- sMozMtpServer = nullptr;
-}
-
-/***************************************************************************/
-
-void
-AutoMounter::UpdateState()
-{
- static bool inUpdateState = false;
- if (inUpdateState) {
- // When UpdateState calls SetISharing, this causes a volume state
- // change to occur, which would normally cause UpdateState to be called
- // again. We want the volume state change to go out (so that device
- // storage will see the change in sharing state), but since we're
- // already in UpdateState we just want to prevent recursion from screwing
- // things up.
- return;
- }
- AutoRestore<bool> inUpdateStateDetector(inUpdateState);
- inUpdateState = true;
-
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // If the following preconditions are met:
- // - UMS is available (i.e. compiled into the kernel)
- // - UMS is enabled
- // - AutoMounter is enabled
- // - USB cable is plugged in
- // then we will try to unmount and share
- // otherwise we will try to unshare and mount.
-
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- // The volume manager isn't in a ready state, so there
- // isn't anything else that we can do.
- LOG("UpdateState: VolumeManager not ready yet");
- return;
- }
-
- if (mResponseCallback->IsPending()) {
- // We only deal with one outstanding volume command at a time,
- // so we need to wait for it to finish.
- return;
- }
-
- // Calling setprop sys.usb.config mtp,adb (or adding mass_storage) will
- // cause /sys/devices/virtual/android_usb/android0/state to go:
- // CONFIGURED -> DISCONNECTED -> CONNECTED -> CONFIGURED
- //
- // Since IsUsbCablePluggedIn returns state == CONFIGURED, it will look
- // like a cable pull and replugin.
- bool umsAvail, umsConfigured, umsEnabled;
- bool mtpAvail, mtpConfigured, mtpEnabled;
- bool rndisConfigured;
- bool usbCablePluggedIn = IsUsbCablePluggedIn();
- GetStatus(umsAvail, umsConfigured, umsEnabled, mtpAvail,
- mtpConfigured, mtpEnabled, rndisConfigured);
- bool enabled = mtpEnabled || umsEnabled;
-
- if (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) {
- // DISABLE_WHEN_UNPLUGGED implies already enabled.
- enabled = usbCablePluggedIn;
- if (!usbCablePluggedIn) {
- mMode = AUTOMOUNTER_DISABLE;
- mtpEnabled = false;
- umsEnabled = false;
- }
- }
-
- DBG("UpdateState: ums:A%dC%dE%d mtp:A%dC%dE%d rndis:%d mode:%d usb:%d mState:%s",
- umsAvail, umsConfigured, umsEnabled,
- mtpAvail, mtpConfigured, mtpEnabled, rndisConfigured,
- mMode, usbCablePluggedIn, StateStr(mState));
-
- switch (mState) {
-
- case STATE_IDLE:
- if (!usbCablePluggedIn) {
- // Stay in the IDLE state. We'll get a CONNECTED or CONFIGURED
- // UEvent when the usb cable is plugged in.
- break;
- }
- if (rndisConfigured) {
- // USB Tethering uses RNDIS. We'll just wait until its turned off.
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- if (mtpEnabled) {
- if (mtpConfigured) {
- // The USB layer has already been configured. Now we can go ahead
- // and start the MTP server. This particular codepath will not
- // normally be taken, but it could happen if you stop and restart
- // b2g while sys.usb.config is set to enable mtp.
- if (StartMtpServer()) {
- SetState(STATE_MTP_STARTED);
- } else {
- if (umsAvail) {
- // Unable to start MTP. Go back to UMS.
- LOG("UpdateState: StartMtpServer failed, switch to UMS");
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- } else {
- LOG("UpdateState: StartMtpServer failed, keep idle state");
- SetUsbFunction(USB_FUNC_DEFAULT);
- }
- }
- } else {
- // We need to configure USB to use mtp. Wait for it to be configured
- // before we start the MTP server.
- SetUsbFunction(USB_FUNC_MTP);
- SetState(STATE_MTP_CONFIGURING);
- }
- } else if (umsConfigured) {
- // UMS is already configured.
- SetState(STATE_UMS_CONFIGURED);
- } else if (umsAvail) {
- // We do this whether or not UMS is enabled. With UMS, it's the
- // sharing of the volume which is significant. What is important
- // is that we don't leave it in MTP mode when MTP isn't enabled.
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- }
- break;
-
- case STATE_MTP_CONFIGURING:
- // While configuring, the USB configuration state will change from
- // CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
- // so we don't check for cable unplugged here.
- if (mtpEnabled && mtpConfigured) {
- // The USB layer has been configured. Now we can go ahead and start
- // the MTP server.
- if (StartMtpServer()) {
- SetState(STATE_MTP_STARTED);
- } else {
- // Unable to start MTP. Go back to UMS.
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- }
- break;
- }
- if (rndisConfigured) {
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- break;
-
- case STATE_MTP_STARTED:
- if (usbCablePluggedIn && mtpConfigured && mtpEnabled) {
- // Everything is still good. Leave the MTP server running
- break;
- }
- DBG("STATE_MTP_STARTED: About to StopMtpServer "
- "mtpConfigured = %d mtpEnabled = %d usbCablePluggedIn: %d",
- mtpConfigured, mtpEnabled, usbCablePluggedIn);
- StopMtpServer();
- if (rndisConfigured) {
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- if (umsAvail) {
- // Switch back to UMS
- SetUsbFunction(USB_FUNC_UMS);
- SetState(STATE_UMS_CONFIGURING);
- break;
- }
-
- // if ums/rndis is not available and mtp is disable,
- // restore the usb function as PERSIST_SYS_USB_CONFIG.
- SetUsbFunction(USB_FUNC_DEFAULT);
- SetState(STATE_IDLE);
- break;
-
- case STATE_UMS_CONFIGURING:
- if (mtpEnabled) {
- // MTP was enabled. Start reconfiguring.
- SetState(STATE_MTP_CONFIGURING);
- SetUsbFunction(USB_FUNC_MTP);
- break;
- }
- if (rndisConfigured) {
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- // While configuring, the USB configuration state will change from
- // CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
- // so we don't check for cable unplugged here. However, having said
- // that, we'll often sit in this state while the cable is unplugged,
- // since we might not get any events until the cable gets plugged back
- // in. This is why we need to check for mtpEnabled once we get the
- // configured event.
- if (umsConfigured) {
- SetState(STATE_UMS_CONFIGURED);
- }
- break;
-
- case STATE_UMS_CONFIGURED:
- if (usbCablePluggedIn) {
- if (mtpEnabled) {
- // MTP was enabled. Start reconfiguring.
- SetState(STATE_MTP_CONFIGURING);
- SetUsbFunction(USB_FUNC_MTP);
- break;
- }
- if (umsConfigured && umsEnabled) {
- // This is the normal state when UMS is enabled.
- break;
- }
- }
- if (rndisConfigured) {
- SetState(STATE_RNDIS_CONFIGURED);
- break;
- }
- SetState(STATE_IDLE);
- break;
-
- case STATE_RNDIS_CONFIGURED:
- if (usbCablePluggedIn && rndisConfigured) {
- // Normal state when RNDIS is enabled.
- break;
- }
- SetState(STATE_IDLE);
- break;
-
- default:
- SetState(STATE_IDLE);
- break;
- }
-
- bool tryToShare = umsEnabled && usbCablePluggedIn;
- LOG("UpdateState: ums:A%dC%dE%d mtp:A%dC%dE%d mode:%d usb:%d tryToShare:%d state:%s",
- umsAvail, umsConfigured, umsEnabled,
- mtpAvail, mtpConfigured, mtpEnabled,
- mMode, usbCablePluggedIn, tryToShare, StateStr(mState));
-
- bool filesOpen = false;
- static unsigned filesOpenDelayCount = 0;
- VolumeArray::index_type volIndex;
- VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- Volume::STATE volState = vol->State();
-
- if (vol->State() == nsIVolume::STATE_MOUNTED) {
- LOG("UpdateState: Volume %s is %s and %s @ %s gen %d locked %d sharing %s",
- vol->NameStr(), vol->StateStr(),
- vol->MediaPresent() ? "inserted" : "missing",
- vol->MountPoint().get(), vol->MountGeneration(),
- (int)vol->IsMountLocked(),
- vol->CanBeShared() ? (vol->IsSharingEnabled() ?
- (vol->IsSharing() ? "en-y" : "en-n") : "dis") : "x");
- if (vol->IsSharing() && !usbCablePluggedIn) {
- // We call SetIsSharing(true) below to indicate intent to share. This
- // causes a state change which notifys apps, and they'll close any
- // open files, which will initiate the change away from the mounted
- // state and into the sharing state. Normally, when the volume
- // transitions back to the mounted state, then vol->mIsSharing gets set
- // to false. However, if the user pulls the USB cable before we
- // actually start sharing, then the volume never actually leaves
- // the mounted state (and hence never transitions from
- // sharing -> mounted), and mIsSharing never gets set back to false.
- // So we clear mIsSharing here.
- vol->SetIsSharing(false);
- }
- } else {
- LOG("UpdateState: Volume %s is %s and %s", vol->NameStr(), vol->StateStr(),
- vol->MediaPresent() ? "inserted" : "missing");
- }
- if (!vol->MediaPresent()) {
- // No media - nothing we can do
- continue;
- }
-
- if (vol->State() == nsIVolume::STATE_CHECKMNT) {
- // vold reports the volume is "Mounted". Need to check if the volume is
- // accessible by statfs(). Once it can be accessed, set the volume as
- // STATE_MOUNTED, otherwise, post a delay task of UpdateState to check it
- // again.
- struct statfs fsbuf;
- int rc = MOZ_TEMP_FAILURE_RETRY(statfs(vol->MountPoint().get(), &fsbuf));
- if (rc == -1) {
- // statfs() failed. Stay in STATE_CHECKMNT. Any failures here
- // are probably non-recoverable, so we need to wait until
- // something else changes the state back to IDLE/UNMOUNTED, etc.
- ERR("statfs failed for '%s': errno = %d (%s)", vol->NameStr(), errno, strerror(errno));
- continue;
- }
- static int delay = 250;
- if (fsbuf.f_blocks == 0) {
- if (delay <= 4000) {
- LOG("UpdateState: Volume '%s' is inaccessible, checking again in %d msec", vol->NameStr(), delay);
- MessageLoopForIO::current()->
- PostDelayedTask(NewRunnableMethod(this, &AutoMounter::UpdateState),
- delay);
- delay *= 2;
- } else {
- LOG("UpdateState: Volume '%s' is inaccessible, giving up", vol->NameStr());
- }
- continue;
- } else {
- delay = 250;
- vol->SetState(nsIVolume::STATE_MOUNTED);
- }
- }
-
- if ((tryToShare && vol->IsSharingEnabled()) ||
- vol->IsFormatRequested() ||
- vol->IsUnmountRequested()) {
- switch (volState) {
- // We're going to try to unmount the volume
- case nsIVolume::STATE_MOUNTED: {
- if (vol->IsMountLocked()) {
- // The volume is currently locked, so leave it in the mounted
- // state.
- LOGW("UpdateState: Mounted volume %s is locked, not sharing or formatting",
- vol->NameStr());
- break;
- }
-
- // Mark the volume as if we've started sharing/formatting/unmmounting.
- // This will cause apps which watch device storage notifications to see
- // the volume go into the different state, and prompt them to close any
- // open files that they might have.
- if (tryToShare && vol->IsSharingEnabled()) {
- vol->SetIsSharing(true);
- } else if (vol->IsFormatRequested()){
- vol->SetIsFormatting(true);
- } else if (vol->IsUnmountRequested()){
- vol->SetIsUnmounting(true);
- }
-
- // Check to see if there are any open files on the volume and
- // don't initiate the unmount while there are open files.
- OpenFileFinder::Info fileInfo;
- OpenFileFinder fileFinder(vol->MountPoint());
- if (fileFinder.First(&fileInfo)) {
- LOGW("The following files are open under '%s'",
- vol->MountPoint().get());
- do {
- LOGW(" PID: %d file: '%s' app: '%s' comm: '%s' exe: '%s'\n",
- fileInfo.mPid,
- fileInfo.mFileName.get(),
- fileInfo.mAppName.get(),
- fileInfo.mComm.get(),
- fileInfo.mExe.get());
- } while (fileFinder.Next(&fileInfo));
- LOGW("UpdateState: Mounted volume %s has open files, not sharing or formatting",
- vol->NameStr());
-
- // Check again in a few seconds to see if the files are closed.
- // Since we're trying to share the volume, this implies that we're
- // plugged into the PC via USB and this in turn implies that the
- // battery is charging, so we don't need to be too concerned about
- // wasting battery here.
- //
- // If we just detected that there were files open, then we use
- // a short timer. We will have told the apps that we're trying
- // trying to share, and they'll be closing their files. This makes
- // the sharing more responsive. If after a few seconds, the apps
- // haven't closed their files, then we back off.
-
- int delay = 1000;
- if (filesOpenDelayCount > 10) {
- delay = 5000;
- }
- MessageLoopForIO::current()->
- PostDelayedTask(NewRunnableMethod(this, &AutoMounter::UpdateState),
- delay);
- filesOpen = true;
- break;
- }
-
- // Volume is mounted, we need to unmount before
- // we can share.
- LOG("UpdateState: Unmounting %s", vol->NameStr());
- vol->StartUnmount(mResponseCallback);
- return; // UpdateState will be called again when the Unmount command completes
- }
- case nsIVolume::STATE_IDLE:
- case nsIVolume::STATE_MOUNT_FAIL: {
- LOG("UpdateState: Volume %s is %s", vol->NameStr(), vol->StateStr());
- if (vol->IsFormatting() && !vol->IsFormatRequested()) {
- vol->SetFormatRequested(false);
- if (!(tryToShare && vol->IsSharingEnabled()) && volState == nsIVolume::STATE_IDLE) {
- LOG("UpdateState: Mounting %s", vol->NameStr());
- vol->StartMount(mResponseCallback);
- break;
- }
- }
-
- // If there are format and share requests in the same time,
- // we should do format first then share.
- if (vol->IsFormatRequested()) {
- // Volume is unmounted. We can go ahead and format.
- LOG("UpdateState: Formatting %s", vol->NameStr());
- vol->StartFormat(mResponseCallback);
- } else if (tryToShare && vol->IsSharingEnabled() && volState == nsIVolume::STATE_IDLE) {
- // Volume is unmounted. We can go ahead and share.
- LOG("UpdateState: Sharing %s", vol->NameStr());
- vol->StartShare(mResponseCallback);
- }
- return; // UpdateState will be called again when the Share/Format command completes
- }
- default: {
- // Not in a state that we can do anything about.
- break;
- }
- }
- } else {
- // We're going to try and unshare and remount the volumes
- switch (volState) {
- case nsIVolume::STATE_SHARED: {
- // Volume is shared. We can go ahead and unshare.
- LOG("UpdateState: Unsharing %s", vol->NameStr());
- vol->StartUnshare(mResponseCallback);
- return; // UpdateState will be called again when the Unshare command completes
- }
- case nsIVolume::STATE_IDLE: {
- if (!vol->IsUnmountRequested()) {
- // Volume is unmounted and mount-requested, try to mount.
-
- LOG("UpdateState: Mounting %s", vol->NameStr());
- vol->StartMount(mResponseCallback);
- }
- return; // UpdateState will be called again when Mount command completes
- }
- default: {
- // Not in a state that we can do anything about.
- break;
- }
- }
- }
- }
-
- int32_t status = AUTOMOUNTER_STATUS_DISABLED;
- if (filesOpen) {
- filesOpenDelayCount++;
- status = AUTOMOUNTER_STATUS_FILES_OPEN;
- } else if (enabled) {
- filesOpenDelayCount = 0;
- status = AUTOMOUNTER_STATUS_ENABLED;
- }
- SetAutoMounterStatus(status);
-}
-
-/***************************************************************************/
-
-void AutoMounter::GetStatus(bool& umsAvail, bool& umsConfigured, bool& umsEnabled,
- bool& mtpAvail, bool& mtpConfigured, bool& mtpEnabled,
- bool& rndisConfigured)
-{
- umsAvail = false;
- umsConfigured = false;
- umsEnabled = false;
- mtpAvail = false;
- mtpConfigured = false;
- mtpEnabled = false;
- rndisConfigured = false;
-
- if (access(ICS_SYS_USB_FUNCTIONS, F_OK) != 0) {
- return;
- }
-
- char functionsStr[60];
- if (!ReadSysFile(ICS_SYS_USB_FUNCTIONS, functionsStr, sizeof(functionsStr))) {
- ERR("Error reading file '%s': %s", ICS_SYS_USB_FUNCTIONS, strerror(errno));
- functionsStr[0] = '\0';
- }
- DBG("GetStatus: USB functions: '%s'", functionsStr);
-
- bool usbConfigured = IsUsbConfigured();
-
- // On the Nexus 4/5, it advertises that the UMS usb function is available,
- // but we have a further requirement that mass_storage be in the
- // persist.sys.usb.config property.
- char persistSysUsbConfig[PROPERTY_VALUE_MAX];
- property_get(PERSIST_SYS_USB_CONFIG, persistSysUsbConfig, "");
- if (IsUsbFunctionEnabled(persistSysUsbConfig, USB_FUNC_UMS)) {
- umsAvail = (access(ICS_SYS_UMS_DIRECTORY, F_OK) == 0);
- }
- if (umsAvail) {
- umsConfigured = usbConfigured && strstr(functionsStr, USB_FUNC_UMS) != nullptr;
- umsEnabled = (mMode == AUTOMOUNTER_ENABLE_UMS) ||
- ((mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) && umsConfigured);
- } else {
- umsConfigured = false;
- umsEnabled = false;
- }
-
- mtpAvail = (access(ICS_SYS_MTP_DIRECTORY, F_OK) == 0);
- if (mtpAvail) {
- mtpConfigured = usbConfigured && strstr(functionsStr, USB_FUNC_MTP) != nullptr;
- mtpEnabled = (mMode == AUTOMOUNTER_ENABLE_MTP) ||
- ((mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) && mtpConfigured);
- } else {
- mtpConfigured = false;
- mtpEnabled = false;
- }
-
- rndisConfigured = strstr(functionsStr, USB_FUNC_RNDIS) != nullptr;
-}
-
-
-nsresult AutoMounter::Dump(nsACString& desc)
-{
- DBG("GetState!");
- bool umsAvail, umsConfigured, umsEnabled;
- bool mtpAvail, mtpConfigured, mtpEnabled;
- bool rndisConfigured;
- GetStatus(umsAvail, umsConfigured, umsEnabled, mtpAvail,
- mtpConfigured, mtpEnabled, rndisConfigured);
- if (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) {
- // DISABLE_WHEN_UNPLUGGED implies already enabled.
- if (!IsUsbCablePluggedIn()) {
- mMode = AUTOMOUNTER_DISABLE;
- mtpEnabled = false;
- umsEnabled = false;
- }
- }
-
- // Automounter information
- desc += "Current Mode:";
- desc += ModeStr(mMode);
- desc += "|";
-
-
- desc += "Current State:";
- desc += StateStr(mState);
- desc += "|";
-
- desc += "UMS Status:";
- if (umsAvail) {
- desc += "Available";
- } else {
- desc += "UnAvailable";
- }
- desc += ",";
- if (umsConfigured) {
- desc += "Configured";
- } else {
- desc += "Un-Configured";
- }
- desc += ",";
- if (umsEnabled) {
- desc += "Enabled";
- } else {
- desc += "Disabled";
- }
- desc += "|";
-
-
- desc += "MTP Status:";
- if (mtpAvail) {
- desc += "Available";
- } else {
- desc += "UnAvailable";
- }
- desc += ",";
- if (mtpConfigured) {
- desc += "Configured";
- } else {
- desc += "Un-Configured";
- }
- desc += ",";
- if (mtpEnabled) {
- desc += "Enabled";
- } else {
- desc += "Disabled";
- }
-
-
- // Volume information
- VolumeArray::index_type volIndex;
- VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
-
- desc += "|";
- desc += vol->NameStr();
- desc += ":";
- desc += vol->StateStr();
- desc += "@";
- desc += vol->MountPoint().get();
-
- if (!vol->MediaPresent()) {
- continue;
- }
-
- if (vol->CanBeShared()) {
- desc += ",CanBeShared";
- }
- if (vol->CanBeFormatted()) {
- desc += ",CanBeFormatted";
- }
- if (vol->CanBeMounted()) {
- desc += ",CanBeMounted";
- }
- if (vol->IsRemovable()) {
- desc += ",Removable";
- }
- if (vol->IsHotSwappable()) {
- desc += ",HotSwappable";
- }
- }
-
- return NS_OK;
-}
-
-
-static void
-InitAutoMounterIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(!sAutoMounter);
-
- sAutoMounter = new AutoMounter();
-}
-
-static void
-ShutdownAutoMounterIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- sAutoMounter = nullptr;
- ShutdownVolumeManager();
-}
-
-static void
-SetAutoMounterModeIOThread(const int32_t& aMode)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->SetMode(aMode);
-}
-
-static void
-SetAutoMounterSharingModeIOThread(const nsCString& aVolumeName, const bool& aAllowSharing)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->SetSharingMode(aVolumeName, aAllowSharing);
-}
-
-static void
-AutoMounterFormatVolumeIOThread(const nsCString& aVolumeName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->FormatVolume(aVolumeName);
-}
-
-static void
-AutoMounterMountVolumeIOThread(const nsCString& aVolumeName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->MountVolume(aVolumeName);
-}
-
-static void
-AutoMounterUnmountVolumeIOThread(const nsCString& aVolumeName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sAutoMounter);
-
- sAutoMounter->UnmountVolume(aVolumeName);
-}
-
-static void
-UsbCableEventIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (!sAutoMounter) {
- return;
- }
- DBG("Calling UpdateState due to USBCableEvent");
- sAutoMounter->UpdateState();
-}
-
-/**************************************************************************
-*
-* Public API
-*
-* Since the AutoMounter runs in IO Thread context, we need to switch
-* to IOThread context before we can do anything.
-*
-**************************************************************************/
-
-class UsbCableObserver final : public hal::SwitchObserver
-{
- ~UsbCableObserver()
- {
- hal::UnregisterSwitchObserver(hal::SWITCH_USB, this);
- }
-
-public:
- NS_INLINE_DECL_REFCOUNTING(UsbCableObserver)
-
- UsbCableObserver()
- {
- hal::RegisterSwitchObserver(hal::SWITCH_USB, this);
- }
-
- virtual void Notify(const hal::SwitchEvent& aEvent)
- {
- DBG("UsbCable switch device: %d state: %s\n",
- aEvent.device(), SwitchStateStr(aEvent));
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(UsbCableEventIOThread));
- }
-};
-
-static StaticRefPtr<UsbCableObserver> sUsbCableObserver;
-static StaticRefPtr<AutoMounterSetting> sAutoMounterSetting;
-
-void
-InitAutoMounter()
-{
- InitVolumeManager();
- sAutoMounterSetting = new AutoMounterSetting();
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(InitAutoMounterIOThread));
-
- // Switch Observers need to run on the main thread, so we need to
- // start it here and have it send events to the AutoMounter running
- // on the IO Thread.
- sUsbCableObserver = new UsbCableObserver();
-
- // Register status reporter into reporter manager
- if(status_reporter_progress == REPORTER_UNREGISTERED) {
- NS_RegisterStatusReporter(new NS_STATUS_REPORTER_NAME(AutoMounter));
- }
- status_reporter_progress = REPORTER_REGISTERED;
-}
-
-int32_t
-GetAutoMounterStatus()
-{
- if (sAutoMounterSetting) {
- return sAutoMounterSetting->GetStatus();
- }
- return AUTOMOUNTER_STATUS_DISABLED;
-}
-
-//static
-void
-SetAutoMounterStatus(int32_t aStatus)
-{
- if (sAutoMounterSetting) {
- sAutoMounterSetting->SetStatus(aStatus);
- }
-}
-
-void
-SetAutoMounterMode(int32_t aMode)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(SetAutoMounterModeIOThread, aMode));
-}
-
-void
-SetAutoMounterSharingMode(const nsCString& aVolumeName, bool aAllowSharing)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(SetAutoMounterSharingModeIOThread,
- aVolumeName, aAllowSharing));
-}
-
-void
-AutoMounterFormatVolume(const nsCString& aVolumeName)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(AutoMounterFormatVolumeIOThread,
- aVolumeName));
-}
-
-void
-AutoMounterMountVolume(const nsCString& aVolumeName)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(AutoMounterMountVolumeIOThread,
- aVolumeName));
-}
-
-void
-AutoMounterUnmountVolume(const nsCString& aVolumeName)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(AutoMounterUnmountVolumeIOThread,
- aVolumeName));
-}
-
-void
-ShutdownAutoMounter()
-{
- if (sAutoMounter) {
- DBG("ShutdownAutoMounter: About to StopMtpServer");
- sAutoMounter->StopMtpServer();
- // Unregister status reporter into reporter manager
- if(status_reporter_progress == REPORTER_REGISTERED) {
- NS_UnregisterStatusReporter(new NS_STATUS_REPORTER_NAME(AutoMounter));
- }
- status_reporter_progress = REPORTER_UNREGISTERED;
- }
- sAutoMounterSetting = nullptr;
- sUsbCableObserver = nullptr;
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(ShutdownAutoMounterIOThread));
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/AutoMounter.h b/dom/system/gonk/AutoMounter.h
deleted file mode 100644
index ea98cadf1..000000000
--- a/dom/system/gonk/AutoMounter.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_automounter_h__
-#define mozilla_system_automounter_h__
-
-#include <stdint.h>
-
-class nsCString;
-
-namespace mozilla {
-namespace system {
-
-// AutoMounter modes
-#define AUTOMOUNTER_DISABLE 0
-#define AUTOMOUNTER_ENABLE_UMS 1
-#define AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED 2
-#define AUTOMOUNTER_ENABLE_MTP 3
-
-// Automounter statuses
-#define AUTOMOUNTER_STATUS_DISABLED 0
-#define AUTOMOUNTER_STATUS_ENABLED 1
-#define AUTOMOUNTER_STATUS_FILES_OPEN 2
-
-/**
- * Initialize the automounter. This causes some of the phone's
- * directories to show up on the host when the phone is plugged
- * into the host via USB.
- *
- * When the AutoMounter starts, it will poll the current state
- * of affairs (usb cable plugged in, automounter enabled, etc)
- * and try to make the state of the volumes match.
- */
-void
-InitAutoMounter();
-
-/**
- * Sets the enabled state of the automounter.
- *
- * This will in turn cause the automounter to re-evaluate
- * whether it should mount/unmount/share/unshare volumes.
- */
-void
-SetAutoMounterMode(int32_t aMode);
-
-/**
- * Reports the status of the automounter.
- */
-int32_t
-GetAutoMounterStatus();
-
-/**
- * Sets the sharing mode of an individual volume.
- *
- * If a volume is enabled for sharing, and the autmounter
- * is in a state to share, then the volume will be shared
- * with the PC.
- */
-void
-SetAutoMounterSharingMode(const nsCString& aVolumeName, bool aAllowSharing);
-
-/**
- * Formats the volume with specified volume name.
- *
- * If the volume is ready to format, automounter
- * will unmount it, format it and then mount it again.
- */
-void
-AutoMounterFormatVolume(const nsCString& aVolumeName);
-
-/**
- * Mounts the volume with specified volume name.
- *
- * If the volume is already unmounted, automounter
- * will mount it. Otherwise automounter will skip this.
- */
-void
-AutoMounterMountVolume(const nsCString& aVolumeName);
-
-/**
- * Unmounts the volume with specified volume name.
- *
- * If the volume is already mounted, automounter
- * will unmount it. Otherwise automounter will skip this.
- */
-void
-AutoMounterUnmountVolume(const nsCString& aVolumeName);
-
-/**
- * Shuts down the automounter.
- *
- * This leaves the volumes in whatever state they're in.
- */
-void
-ShutdownAutoMounter();
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_automounter_h__
diff --git a/dom/system/gonk/AutoMounterSetting.cpp b/dom/system/gonk/AutoMounterSetting.cpp
deleted file mode 100644
index 606bcce04..000000000
--- a/dom/system/gonk/AutoMounterSetting.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "AutoMounter.h"
-#include "AutoMounterSetting.h"
-
-#include "base/message_loop.h"
-#include "jsapi.h"
-#include "mozilla/Services.h"
-#include "nsCOMPtr.h"
-#include "nsContentUtils.h"
-#include "nsDebug.h"
-#include "nsIObserverService.h"
-#include "nsISettingsService.h"
-#include "nsJSUtils.h"
-#include "nsPrintfCString.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-#include "nsThreadUtils.h"
-#include "xpcpublic.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/SettingChangeNotificationBinding.h"
-
-#undef LOG
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AutoMounterSetting" , ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "AutoMounterSetting" , ## args)
-
-#define UMS_MODE "ums.mode"
-#define UMS_STATUS "ums.status"
-#define UMS_VOLUME_ENABLED_PREFIX "ums.volume."
-#define UMS_VOLUME_ENABLED_SUFFIX ".enabled"
-#define MOZSETTINGS_CHANGED "mozsettings-changed"
-
-using namespace mozilla::dom;
-
-namespace mozilla {
-namespace system {
-
-class SettingsServiceCallback final : public nsISettingsServiceCallback
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
-
- SettingsServiceCallback() {}
-
- NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
- {
- if (aResult.isInt32()) {
- int32_t mode = aResult.toInt32();
- SetAutoMounterMode(mode);
- }
- return NS_OK;
- }
-
- NS_IMETHOD HandleError(const nsAString& aName)
- {
- ERR("SettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
- return NS_OK;
- }
-
-protected:
- ~SettingsServiceCallback() {}
-};
-
-NS_IMPL_ISUPPORTS(SettingsServiceCallback, nsISettingsServiceCallback)
-
-class CheckVolumeSettingsCallback final : public nsISettingsServiceCallback
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
-
- CheckVolumeSettingsCallback(const nsACString& aVolumeName)
- : mVolumeName(aVolumeName) {}
-
- NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
- {
- if (aResult.isBoolean()) {
- bool isSharingEnabled = aResult.toBoolean();
- SetAutoMounterSharingMode(mVolumeName, isSharingEnabled);
- }
- return NS_OK;
- }
-
- NS_IMETHOD HandleError(const nsAString& aName)
- {
- ERR("CheckVolumeSettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
- return NS_OK;
- }
-
-protected:
- ~CheckVolumeSettingsCallback() {}
-
-private:
- nsCString mVolumeName;
-};
-
-NS_IMPL_ISUPPORTS(CheckVolumeSettingsCallback, nsISettingsServiceCallback)
-
-AutoMounterSetting::AutoMounterSetting()
- : mStatus(AUTOMOUNTER_STATUS_DISABLED)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- // Setup an observer to watch changes to the setting
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (!observerService) {
- ERR("GetObserverService failed");
- return;
- }
- nsresult rv;
- rv = observerService->AddObserver(this, MOZSETTINGS_CHANGED, false);
- if (NS_FAILED(rv)) {
- ERR("AddObserver failed");
- return;
- }
-
- // Force ums.mode to be 0 initially. We do this because settings are persisted.
- // We don't want UMS to be enabled until such time as the phone is unlocked,
- // and gaia/apps/system/js/storage.js takes care of detecting when the phone
- // becomes unlocked and changes ums.mode appropriately.
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- if (!settingsService) {
- ERR("Failed to get settingsLock service!");
- return;
- }
- nsCOMPtr<nsISettingsServiceLock> lock;
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- nsCOMPtr<nsISettingsServiceCallback> callback = new SettingsServiceCallback();
- JS::Rooted<JS::Value> value(RootingCx());
- value.setInt32(AUTOMOUNTER_DISABLE);
- lock->Set(UMS_MODE, value, callback, nullptr);
- value.setInt32(mStatus);
- lock->Set(UMS_STATUS, value, nullptr, nullptr);
-}
-
-AutoMounterSetting::~AutoMounterSetting()
-{
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (observerService) {
- observerService->RemoveObserver(this, MOZSETTINGS_CHANGED);
- }
-}
-
-NS_IMPL_ISUPPORTS(AutoMounterSetting, nsIObserver)
-
-const char *
-AutoMounterSetting::StatusStr(int32_t aStatus)
-{
- switch (aStatus) {
- case AUTOMOUNTER_STATUS_DISABLED: return "Disabled";
- case AUTOMOUNTER_STATUS_ENABLED: return "Enabled";
- case AUTOMOUNTER_STATUS_FILES_OPEN: return "FilesOpen";
- }
- return "??? Unknown ???";
-}
-
-class CheckVolumeSettingsRunnable : public Runnable
-{
-public:
- CheckVolumeSettingsRunnable(const nsACString& aVolumeName)
- : mVolumeName(aVolumeName) {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- NS_ENSURE_TRUE(settingsService, NS_ERROR_FAILURE);
- nsCOMPtr<nsISettingsServiceLock> lock;
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- nsCOMPtr<nsISettingsServiceCallback> callback =
- new CheckVolumeSettingsCallback(mVolumeName);
- nsPrintfCString setting(UMS_VOLUME_ENABLED_PREFIX "%s" UMS_VOLUME_ENABLED_SUFFIX,
- mVolumeName.get());
- lock->Get(setting.get(), callback);
- return NS_OK;
- }
-
-private:
- nsCString mVolumeName;
-};
-
-//static
-void
-AutoMounterSetting::CheckVolumeSettings(const nsACString& aVolumeName)
-{
- NS_DispatchToMainThread(new CheckVolumeSettingsRunnable(aVolumeName));
-}
-
-class SetStatusRunnable : public Runnable
-{
-public:
- SetStatusRunnable(int32_t aStatus) : mStatus(aStatus) {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- NS_ENSURE_TRUE(settingsService, NS_ERROR_FAILURE);
- nsCOMPtr<nsISettingsServiceLock> lock;
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- // lock may be null if this gets called during shutdown.
- if (lock) {
- JS::Rooted<JS::Value> value(RootingCx(),
- JS::Int32Value(mStatus));
- lock->Set(UMS_STATUS, value, nullptr, nullptr);
- }
- return NS_OK;
- }
-
-private:
- int32_t mStatus;
-};
-
-//static
-void
-AutoMounterSetting::SetStatus(int32_t aStatus)
-{
- if (aStatus != mStatus) {
- LOG("Changing status from '%s' to '%s'",
- StatusStr(mStatus), StatusStr(aStatus));
- mStatus = aStatus;
- NS_DispatchToMainThread(new SetStatusRunnable(aStatus));
- }
-}
-
-NS_IMETHODIMP
-AutoMounterSetting::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
- return NS_OK;
- }
-
- // Note that this function gets called for any and all settings changes,
- // so we need to carefully check if we have the one we're interested in.
- //
- // The string that we're interested in will be a JSON string that looks like:
- // {"key":"ums.autoMount","value":true}
-
- RootedDictionary<SettingChangeNotification> setting(RootingCx());
- if (!WrappedJSToDictionary(aSubject, setting)) {
- return NS_OK;
- }
-
- // Check for ums.mode changes
- if (setting.mKey.EqualsASCII(UMS_MODE)) {
- if (!setting.mValue.isInt32()) {
- return NS_OK;
- }
- int32_t mode = setting.mValue.toInt32();
- SetAutoMounterMode(mode);
- return NS_OK;
- }
-
- // Check for ums.volume.NAME.enabled
- if (StringBeginsWith(setting.mKey, NS_LITERAL_STRING(UMS_VOLUME_ENABLED_PREFIX)) &&
- StringEndsWith(setting.mKey, NS_LITERAL_STRING(UMS_VOLUME_ENABLED_SUFFIX))) {
- if (!setting.mValue.isBoolean()) {
- return NS_OK;
- }
- const size_t prefixLen = sizeof(UMS_VOLUME_ENABLED_PREFIX) - 1;
- const size_t suffixLen = sizeof(UMS_VOLUME_ENABLED_SUFFIX) - 1;
- nsDependentSubstring volumeName =
- Substring(setting.mKey, prefixLen, setting.mKey.Length() - prefixLen - suffixLen);
- bool isSharingEnabled = setting.mValue.toBoolean();
- SetAutoMounterSharingMode(NS_LossyConvertUTF16toASCII(volumeName), isSharingEnabled);
- return NS_OK;
- }
-
- return NS_OK;
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/AutoMounterSetting.h b/dom/system/gonk/AutoMounterSetting.h
deleted file mode 100644
index 7972de379..000000000
--- a/dom/system/gonk/AutoMounterSetting.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_automountersetting_h__
-#define mozilla_system_automountersetting_h__
-
-#include "nsIObserver.h"
-
-namespace mozilla {
-namespace system {
-
-class AutoMounterSetting : public nsIObserver
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- AutoMounterSetting();
-
- static void CheckVolumeSettings(const nsACString& aVolumeName);
-
- int32_t GetStatus() { return mStatus; }
- void SetStatus(int32_t aStatus);
- const char *StatusStr(int32_t aStatus);
-
-protected:
- virtual ~AutoMounterSetting();
-
-private:
- int32_t mStatus;
-};
-
-} // namespace system
-} // namespace mozilla
-
-#endif // mozilla_system_automountersetting_h__
-
diff --git a/dom/system/gonk/DataCallInterfaceService.js b/dom/system/gonk/DataCallInterfaceService.js
deleted file mode 100644
index 0f0e7101c..000000000
--- a/dom/system/gonk/DataCallInterfaceService.js
+++ /dev/null
@@ -1,276 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const DATACALLINTERFACE_CONTRACTID = "@mozilla.org/datacall/interface;1";
-const DATACALLINTERFACESERVICE_CONTRACTID =
- "@mozilla.org/datacall/interfaceservice;1";
-const DATACALLINTERFACE_CID =
- Components.ID("{ff669306-4390-462a-989b-ba37fc42153f}");
-const DATACALLINTERFACESERVICE_CID =
- Components.ID("{e23e9337-592d-40b9-8cef-7bd47c28b72e}");
-
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const PREF_RIL_DEBUG_ENABLED = "ril.debugging.enabled";
-
-XPCOMUtils.defineLazyGetter(this, "RIL", function () {
- let obj = {};
- Cu.import("resource://gre/modules/ril_consts.js", obj);
- return obj;
-});
-
-XPCOMUtils.defineLazyServiceGetter(this, "gRil",
- "@mozilla.org/ril;1",
- "nsIRadioInterfaceLayer");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
- "@mozilla.org/mobileconnection/mobileconnectionservice;1",
- "nsIMobileConnectionService");
-
-var DEBUG = RIL.DEBUG_RIL;
-
-function updateDebugFlag() {
- // Read debug setting from pref
- let debugPref;
- try {
- debugPref = Services.prefs.getBoolPref(PREF_RIL_DEBUG_ENABLED);
- } catch (e) {
- debugPref = false;
- }
- DEBUG = debugPref || RIL.DEBUG_RIL;
-}
-updateDebugFlag();
-
-function DataCall(aAttributes) {
- for (let key in aAttributes) {
- if (key === "pdpType") {
- // Convert pdp type into constant int value.
- this[key] = RIL.RIL_DATACALL_PDP_TYPES.indexOf(aAttributes[key]);
- continue;
- }
-
- this[key] = aAttributes[key];
- }
-}
-DataCall.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCall]),
-
- failCause: Ci.nsIDataCallInterface.DATACALL_FAIL_NONE,
- suggestedRetryTime: -1,
- cid: -1,
- active: -1,
- pdpType: -1,
- ifname: null,
- addreses: null,
- dnses: null,
- gateways: null,
- pcscf: null,
- mtu: -1
-};
-
-function DataCallInterfaceService() {
- this._dataCallInterfaces = [];
-
- let numClients = gRil.numRadioInterfaces;
- for (let i = 0; i < numClients; i++) {
- this._dataCallInterfaces.push(new DataCallInterface(i));
- }
-
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
- Services.prefs.addObserver(PREF_RIL_DEBUG_ENABLED, this, false);
-}
-DataCallInterfaceService.prototype = {
- classID: DATACALLINTERFACESERVICE_CID,
- classInfo: XPCOMUtils.generateCI({
- classID: DATACALLINTERFACESERVICE_CID,
- contractID: DATACALLINTERFACESERVICE_CONTRACTID,
- classDescription: "Data Call Interface Service",
- interfaces: [Ci.nsIDataCallInterfaceService,
- Ci.nsIGonkDataCallInterfaceService]
- }),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallInterfaceService,
- Ci.nsIGonkDataCallInterfaceService],
- Ci.nsIObserver),
-
- // An array of DataCallInterface instances.
- _dataCallInterfaces: null,
-
- debug: function(aMessage) {
- dump("-*- DataCallInterfaceService: " + aMessage + "\n");
- },
-
- // nsIDataCallInterfaceService
-
- getDataCallInterface: function(aClientId) {
- let dataCallInterface = this._dataCallInterfaces[aClientId];
- if (!dataCallInterface) {
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- return dataCallInterface;
- },
-
- // nsIGonkDataCallInterfaceService
-
- notifyDataCallListChanged: function(aClientId, aCount, aDataCalls) {
- let dataCallInterface = this.getDataCallInterface(aClientId);
- dataCallInterface.handleDataCallListChanged(aCount, aDataCalls);
- },
-
- // nsIObserver
-
- observe: function(aSubject, aTopic, aData) {
- switch (aTopic) {
- case TOPIC_PREF_CHANGED:
- if (aData === PREF_RIL_DEBUG_ENABLED) {
- updateDebugFlag();
- }
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- Services.prefs.removeObserver(PREF_RIL_DEBUG_ENABLED, this);
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- break;
- }
- },
-};
-
-function DataCallInterface(aClientId) {
- this._clientId = aClientId;
- this._radioInterface = gRil.getRadioInterface(aClientId);
- this._listeners = [];
-
- if (DEBUG) this.debug("DataCallInterface: " + aClientId);
-}
-DataCallInterface.prototype = {
- classID: DATACALLINTERFACE_CID,
- classInfo: XPCOMUtils.generateCI({classID: DATACALLINTERFACE_CID,
- contractID: DATACALLINTERFACE_CONTRACTID,
- classDescription: "Data Call Interface",
- interfaces: [Ci.nsIDataCallInterface]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallInterface]),
-
- debug: function(aMessage) {
- dump("-*- DataCallInterface[" + this._clientId + "]: " + aMessage + "\n");
- },
-
- _clientId: -1,
-
- _radioInterface: null,
-
- _listeners: null,
-
- // nsIDataCallInterface
-
- setupDataCall: function(aApn, aUsername, aPassword, aAuthType, aPdpType,
- aCallback) {
- let connection =
- gMobileConnectionService.getItemByServiceId(this._clientId);
- let dataInfo = connection && connection.data;
- let radioTechType = dataInfo.type;
- let radioTechnology = RIL.GECKO_RADIO_TECH.indexOf(radioTechType);
- // Convert pdp type into string value.
- let pdpType = RIL.RIL_DATACALL_PDP_TYPES[aPdpType];
-
- this._radioInterface.sendWorkerMessage("setupDataCall", {
- radioTech: radioTechnology,
- apn: aApn,
- user: aUsername,
- passwd: aPassword,
- chappap: aAuthType,
- pdptype: pdpType
- }, (aResponse) => {
- if (aResponse.errorMsg) {
- aCallback.notifyError(aResponse.errorMsg);
- } else {
- let dataCall = new DataCall(aResponse);
- aCallback.notifySetupDataCallSuccess(dataCall);
- }
- });
- },
-
- deactivateDataCall: function(aCid, aReason, aCallback) {
- this._radioInterface.sendWorkerMessage("deactivateDataCall", {
- cid: aCid,
- reason: aReason
- }, (aResponse) => {
- if (aResponse.errorMsg) {
- aCallback.notifyError(aResponse.errorMsg);
- } else {
- aCallback.notifySuccess();
- }
- });
- },
-
- getDataCallList: function(aCallback) {
- this._radioInterface.sendWorkerMessage("getDataCallList", null,
- (aResponse) => {
- if (aResponse.errorMsg) {
- aCallback.notifyError(aResponse.errorMsg);
- } else {
- let dataCalls = aResponse.datacalls.map(
- dataCall => new DataCall(dataCall));
- aCallback.notifyGetDataCallListSuccess(dataCalls.length, dataCalls);
- }
- });
- },
-
- setDataRegistration: function(aAttach, aCallback) {
- this._radioInterface.sendWorkerMessage("setDataRegistration", {
- attach: aAttach
- }, (aResponse) => {
- if (aResponse.errorMsg) {
- aCallback.notifyError(aResponse.errorMsg);
- } else {
- aCallback.notifySuccess();
- }
- });
- },
-
- handleDataCallListChanged: function(aCount, aDataCalls) {
- this._notifyAllListeners("notifyDataCallListChanged", [aCount, aDataCalls]);
- },
-
- _notifyAllListeners: function(aMethodName, aArgs) {
- let listeners = this._listeners.slice();
- for (let listener of listeners) {
- if (this._listeners.indexOf(listener) == -1) {
- // Listener has been unregistered in previous run.
- continue;
- }
-
- let handler = listener[aMethodName];
- try {
- handler.apply(listener, aArgs);
- } catch (e) {
- if (DEBUG) {
- this.debug("listener for " + aMethodName + " threw an exception: " + e);
- }
- }
- }
- },
-
- registerListener: function(aListener) {
- if (this._listeners.indexOf(aListener) >= 0) {
- return;
- }
-
- this._listeners.push(aListener);
- },
-
- unregisterListener: function(aListener) {
- let index = this._listeners.indexOf(aListener);
- if (index >= 0) {
- this._listeners.splice(index, 1);
- }
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataCallInterfaceService]); \ No newline at end of file
diff --git a/dom/system/gonk/DataCallInterfaceService.manifest b/dom/system/gonk/DataCallInterfaceService.manifest
deleted file mode 100644
index bf062c7e9..000000000
--- a/dom/system/gonk/DataCallInterfaceService.manifest
+++ /dev/null
@@ -1,6 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-component {e23e9337-592d-40b9-8cef-7bd47c28b72e} DataCallInterfaceService.js
-contract @mozilla.org/datacall/interfaceservice;1 {e23e9337-592d-40b9-8cef-7bd47c28b72e} \ No newline at end of file
diff --git a/dom/system/gonk/DataCallManager.js b/dom/system/gonk/DataCallManager.js
deleted file mode 100644
index 5411987cd..000000000
--- a/dom/system/gonk/DataCallManager.js
+++ /dev/null
@@ -1,1726 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
- "@mozilla.org/mobileconnection/mobileconnectionservice;1",
- "nsIMobileConnectionService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
- "@mozilla.org/icc/iccservice;1",
- "nsIIccService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gDataCallInterfaceService",
- "@mozilla.org/datacall/interfaceservice;1",
- "nsIDataCallInterfaceService");
-
-XPCOMUtils.defineLazyGetter(this, "RIL", function() {
- let obj = {};
- Cu.import("resource://gre/modules/ril_consts.js", obj);
- return obj;
-});
-
-// Ril quirk to attach data registration on demand.
-var RILQUIRKS_DATA_REGISTRATION_ON_DEMAND =
- libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true";
-
-// Ril quirk to control the uicc/data subscription.
-var RILQUIRKS_SUBSCRIPTION_CONTROL =
- libcutils.property_get("ro.moz.ril.subscription_control", "false") == "true";
-
-// Ril quirk to enable IPv6 protocol/roaming protocol in APN settings.
-var RILQUIRKS_HAVE_IPV6 =
- libcutils.property_get("ro.moz.ril.ipv6", "false") == "true";
-
-const DATACALLMANAGER_CID =
- Components.ID("{35b9efa2-e42c-45ce-8210-0a13e6f4aadc}");
-const DATACALLHANDLER_CID =
- Components.ID("{132b650f-c4d8-4731-96c5-83785cb31dee}");
-const RILNETWORKINTERFACE_CID =
- Components.ID("{9574ee84-5d0d-4814-b9e6-8b279e03dcf4}");
-const RILNETWORKINFO_CID =
- Components.ID("{dd6cf2f0-f0e3-449f-a69e-7c34fdcb8d4b}");
-
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed";
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const TOPIC_DATA_CALL_ERROR = "data-call-error";
-const PREF_RIL_DEBUG_ENABLED = "ril.debugging.enabled";
-
-const NETWORK_TYPE_UNKNOWN = Ci.nsINetworkInfo.NETWORK_TYPE_UNKNOWN;
-const NETWORK_TYPE_WIFI = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
-const NETWORK_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
-const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS;
-const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL;
-const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS;
-const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN;
-const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA;
-
-const NETWORK_STATE_UNKNOWN = Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN;
-const NETWORK_STATE_CONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTING;
-const NETWORK_STATE_CONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
-const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTING;
-const NETWORK_STATE_DISCONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
-
-const INT32_MAX = 2147483647;
-
-// set to true in ril_consts.js to see debug messages
-var DEBUG = RIL.DEBUG_RIL;
-
-function updateDebugFlag() {
- // Read debug setting from pref
- let debugPref;
- try {
- debugPref = Services.prefs.getBoolPref(PREF_RIL_DEBUG_ENABLED);
- } catch (e) {
- debugPref = false;
- }
- DEBUG = debugPref || RIL.DEBUG_RIL;
-}
-updateDebugFlag();
-
-function DataCallManager() {
- this._connectionHandlers = [];
-
- let numRadioInterfaces = gMobileConnectionService.numItems;
- for (let clientId = 0; clientId < numRadioInterfaces; clientId++) {
- this._connectionHandlers.push(new DataCallHandler(clientId));
- }
-
- let lock = gSettingsService.createLock();
- // Read the APN data from the settings DB.
- lock.get("ril.data.apnSettings", this);
- // Read the data enabled setting from DB.
- lock.get("ril.data.enabled", this);
- lock.get("ril.data.roaming_enabled", this);
- // Read the default client id for data call.
- lock.get("ril.data.defaultServiceId", this);
-
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
- Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false);
- Services.prefs.addObserver(PREF_RIL_DEBUG_ENABLED, this, false);
-}
-DataCallManager.prototype = {
- classID: DATACALLMANAGER_CID,
- classInfo: XPCOMUtils.generateCI({classID: DATACALLMANAGER_CID,
- classDescription: "Data Call Manager",
- interfaces: [Ci.nsIDataCallManager]}),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallManager,
- Ci.nsIObserver,
- Ci.nsISettingsServiceCallback]),
-
- _connectionHandlers: null,
-
- // Flag to determine the data state to start with when we boot up. It
- // corresponds to the 'ril.data.enabled' setting from the UI.
- _dataEnabled: false,
-
- // Flag to record the default client id for data call. It corresponds to
- // the 'ril.data.defaultServiceId' setting from the UI.
- _dataDefaultClientId: -1,
-
- // Flag to record the current default client id for data call.
- // It differs from _dataDefaultClientId in that it is set only when
- // the switch of client id process is done.
- _currentDataClientId: -1,
-
- // Pending function to execute when we are notified that another data call has
- // been disconnected.
- _pendingDataCallRequest: null,
-
- debug: function(aMsg) {
- dump("-*- DataCallManager: " + aMsg + "\n");
- },
-
- get dataDefaultServiceId() {
- return this._dataDefaultClientId;
- },
-
- getDataCallHandler: function(aClientId) {
- let handler = this._connectionHandlers[aClientId]
- if (!handler) {
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- return handler;
- },
-
- _setDataRegistration: function(aDataCallInterface, aAttach) {
- return new Promise(function(aResolve, aReject) {
- let callback = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallCallback]),
- notifySuccess: function() {
- aResolve();
- },
- notifyError: function(aErrorMsg) {
- aReject(aErrorMsg);
- }
- };
-
- aDataCallInterface.setDataRegistration(aAttach, callback);
- });
- },
-
- _handleDataClientIdChange: function(aNewClientId) {
- if (this._dataDefaultClientId === aNewClientId) {
- return;
- }
- this._dataDefaultClientId = aNewClientId;
-
- // This is to handle boot up stage.
- if (this._currentDataClientId == -1) {
- this._currentDataClientId = this._dataDefaultClientId;
- let connHandler = this._connectionHandlers[this._currentDataClientId];
- let dcInterface = connHandler.dataCallInterface;
- if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
- RILQUIRKS_SUBSCRIPTION_CONTROL) {
- this._setDataRegistration(dcInterface, true);
- }
- if (this._dataEnabled) {
- let settings = connHandler.dataCallSettings;
- settings.oldEnabled = settings.enabled;
- settings.enabled = true;
- connHandler.updateRILNetworkInterface();
- }
- return;
- }
-
- let oldConnHandler = this._connectionHandlers[this._currentDataClientId];
- let oldIface = oldConnHandler.dataCallInterface;
- let oldSettings = oldConnHandler.dataCallSettings;
- let newConnHandler = this._connectionHandlers[this._dataDefaultClientId];
- let newIface = newConnHandler.dataCallInterface;
- let newSettings = newConnHandler.dataCallSettings;
-
- let applyPendingDataSettings = () => {
- if (DEBUG) {
- this.debug("Apply pending data registration and settings.");
- }
-
- if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
- RILQUIRKS_SUBSCRIPTION_CONTROL) {
- this._setDataRegistration(oldIface, false).then(() => {
- if (this._dataEnabled) {
- newSettings.oldEnabled = newSettings.enabled;
- newSettings.enabled = true;
- }
- this._currentDataClientId = this._dataDefaultClientId;
-
- this._setDataRegistration(newIface, true).then(() => {
- newConnHandler.updateRILNetworkInterface();
- });
- });
- return;
- }
-
- if (this._dataEnabled) {
- newSettings.oldEnabled = newSettings.enabled;
- newSettings.enabled = true;
- }
-
- this._currentDataClientId = this._dataDefaultClientId;
- newConnHandler.updateRILNetworkInterface();
- };
-
- if (this._dataEnabled) {
- oldSettings.oldEnabled = oldSettings.enabled;
- oldSettings.enabled = false;
- }
-
- oldConnHandler.deactivateDataCallsAndWait().then(() => {
- applyPendingDataSettings();
- });
- },
-
- _shutdown: function() {
- for (let handler of this._connectionHandlers) {
- handler.shutdown();
- }
- this._connectionHandlers = null;
- Services.prefs.removeObserver(PREF_RIL_DEBUG_ENABLED, this);
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED);
- },
-
- /**
- * nsISettingsServiceCallback
- */
- handle: function(aName, aResult) {
- switch (aName) {
- case "ril.data.apnSettings":
- if (DEBUG) {
- this.debug("'ril.data.apnSettings' is now " +
- JSON.stringify(aResult));
- }
- if (!aResult) {
- break;
- }
- for (let clientId in this._connectionHandlers) {
- let handler = this._connectionHandlers[clientId];
- let apnSetting = aResult[clientId];
- if (handler && apnSetting) {
- handler.updateApnSettings(apnSetting);
- }
- }
- break;
- case "ril.data.enabled":
- if (DEBUG) {
- this.debug("'ril.data.enabled' is now " + aResult);
- }
- if (this._dataEnabled === aResult) {
- break;
- }
- this._dataEnabled = aResult;
-
- if (DEBUG) {
- this.debug("Default id for data call: " + this._dataDefaultClientId);
- }
- if (this._dataDefaultClientId === -1) {
- // We haven't got the default id for data from db.
- break;
- }
-
- let connHandler = this._connectionHandlers[this._dataDefaultClientId];
- let settings = connHandler.dataCallSettings;
- settings.oldEnabled = settings.enabled;
- settings.enabled = aResult;
- connHandler.updateRILNetworkInterface();
- break;
- case "ril.data.roaming_enabled":
- if (DEBUG) {
- this.debug("'ril.data.roaming_enabled' is now " + aResult);
- this.debug("Default id for data call: " + this._dataDefaultClientId);
- }
- for (let clientId = 0; clientId < this._connectionHandlers.length; clientId++) {
- let connHandler = this._connectionHandlers[clientId];
- let settings = connHandler.dataCallSettings;
- settings.roamingEnabled = Array.isArray(aResult) ? aResult[clientId]
- : aResult;
- }
- if (this._dataDefaultClientId === -1) {
- // We haven't got the default id for data from db.
- break;
- }
- this._connectionHandlers[this._dataDefaultClientId].updateRILNetworkInterface();
- break;
- case "ril.data.defaultServiceId":
- aResult = aResult || 0;
- if (DEBUG) {
- this.debug("'ril.data.defaultServiceId' is now " + aResult);
- }
- this._handleDataClientIdChange(aResult);
- break;
- }
- },
-
- handleError: function(aErrorMessage) {
- if (DEBUG) {
- this.debug("There was an error while reading RIL settings.");
- }
- },
-
- /**
- * nsIObserver interface methods.
- */
- observe: function(aSubject, aTopic, aData) {
- switch (aTopic) {
- case TOPIC_MOZSETTINGS_CHANGED:
- if ("wrappedJSObject" in aSubject) {
- aSubject = aSubject.wrappedJSObject;
- }
- this.handle(aSubject.key, aSubject.value);
- break;
- case TOPIC_PREF_CHANGED:
- if (aData === PREF_RIL_DEBUG_ENABLED) {
- updateDebugFlag();
- }
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- this._shutdown();
- break;
- }
- },
-};
-
-function DataCallHandler(aClientId) {
- // Initial owning attributes.
- this.clientId = aClientId;
- this.dataCallSettings = {
- oldEnabled: false,
- enabled: false,
- roamingEnabled: false
- };
- this._dataCalls = [];
- this._listeners = [];
-
- // This map is used to collect all the apn types and its corresponding
- // RILNetworkInterface.
- this.dataNetworkInterfaces = new Map();
-
- this.dataCallInterface = gDataCallInterfaceService.getDataCallInterface(aClientId);
- this.dataCallInterface.registerListener(this);
-
- let mobileConnection = gMobileConnectionService.getItemByServiceId(aClientId);
- mobileConnection.registerListener(this);
-
- this._dataInfo = {
- state: mobileConnection.data.state,
- type: mobileConnection.data.type,
- roaming: mobileConnection.data.roaming
- }
-}
-DataCallHandler.prototype = {
- classID: DATACALLHANDLER_CID,
- classInfo: XPCOMUtils.generateCI({classID: DATACALLHANDLER_CID,
- classDescription: "Data Call Handler",
- interfaces: [Ci.nsIDataCallHandler]}),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallHandler,
- Ci.nsIDataCallInterfaceListener,
- Ci.nsIMobileConnectionListener]),
-
- clientId: 0,
- dataCallInterface: null,
- dataCallSettings: null,
- dataNetworkInterfaces: null,
- _dataCalls: null,
- _dataInfo: null,
-
- // Apn settings to be setup after data call are cleared.
- _pendingApnSettings: null,
-
- debug: function(aMsg) {
- dump("-*- DataCallHandler[" + this.clientId + "]: " + aMsg + "\n");
- },
-
- shutdown: function() {
- // Shutdown all RIL network interfaces
- this.dataNetworkInterfaces.forEach(function(networkInterface) {
- gNetworkManager.unregisterNetworkInterface(networkInterface);
- networkInterface.shutdown();
- networkInterface = null;
- });
- this.dataNetworkInterfaces.clear();
- this._dataCalls = [];
- this.clientId = null;
-
- this.dataCallInterface.unregisterListener(this);
- this.dataCallInterface = null;
-
- let mobileConnection =
- gMobileConnectionService.getItemByServiceId(this.clientId);
- mobileConnection.unregisterListener(this);
- },
-
- /**
- * Check if we get all necessary APN data.
- */
- _validateApnSetting: function(aApnSetting) {
- return (aApnSetting &&
- aApnSetting.apn &&
- aApnSetting.types &&
- aApnSetting.types.length);
- },
-
- _convertApnType: function(aApnType) {
- switch (aApnType) {
- case "default":
- return NETWORK_TYPE_MOBILE;
- case "mms":
- return NETWORK_TYPE_MOBILE_MMS;
- case "supl":
- return NETWORK_TYPE_MOBILE_SUPL;
- case "ims":
- return NETWORK_TYPE_MOBILE_IMS;
- case "dun":
- return NETWORK_TYPE_MOBILE_DUN;
- case "fota":
- return NETWORK_TYPE_MOBILE_FOTA;
- default:
- return NETWORK_TYPE_UNKNOWN;
- }
- },
-
- _compareDataCallOptions: function(aDataCall, aNewDataCall) {
- return aDataCall.apnProfile.apn == aNewDataCall.apnProfile.apn &&
- aDataCall.apnProfile.user == aNewDataCall.apnProfile.user &&
- aDataCall.apnProfile.password == aNewDataCall.apnProfile.passwd &&
- aDataCall.apnProfile.authType == aNewDataCall.apnProfile.authType &&
- aDataCall.apnProfile.protocol == aNewDataCall.apnProfile.protocol &&
- aDataCall.apnProfile.roaming_protocol == aNewDataCall.apnProfile.roaming_protocol;
- },
-
- /**
- * This function will do the following steps:
- * 1. Clear the cached APN settings in the RIL.
- * 2. Combine APN, user name, and password as the key of |byApn| object to
- * refer to the corresponding APN setting.
- * 3. Use APN type as the index of |byType| object to refer to the
- * corresponding APN setting.
- * 4. Create RilNetworkInterface for each APN setting created at step 2.
- */
- _setupApnSettings: function(aNewApnSettings) {
- if (!aNewApnSettings) {
- return;
- }
- if (DEBUG) this.debug("setupApnSettings: " + JSON.stringify(aNewApnSettings));
-
- // Shutdown all network interfaces and clear data calls.
- this.dataNetworkInterfaces.forEach(function(networkInterface) {
- gNetworkManager.unregisterNetworkInterface(networkInterface);
- networkInterface.shutdown();
- networkInterface = null;
- });
- this.dataNetworkInterfaces.clear();
- this._dataCalls = [];
-
- // Cache the APN settings by APNs and by types in the RIL.
- for (let inputApnSetting of aNewApnSettings) {
- if (!this._validateApnSetting(inputApnSetting)) {
- continue;
- }
-
- // Use APN type as the key of dataNetworkInterfaces to refer to the
- // corresponding RILNetworkInterface.
- for (let i = 0; i < inputApnSetting.types.length; i++) {
- let apnType = inputApnSetting.types[i];
- let networkType = this._convertApnType(apnType);
- if (networkType === NETWORK_TYPE_UNKNOWN) {
- if (DEBUG) this.debug("Invalid apn type: " + apnType);
- continue;
- }
-
- if (DEBUG) this.debug("Preparing RILNetworkInterface for type: " + apnType);
- // Create DataCall for RILNetworkInterface or reuse one that is shareable.
- let dataCall;
- for (let i = 0; i < this._dataCalls.length; i++) {
- if (this._dataCalls[i].canHandleApn(inputApnSetting)) {
- if (DEBUG) this.debug("Found shareable DataCall, reusing it.");
- dataCall = this._dataCalls[i];
- break;
- }
- }
-
- if (!dataCall) {
- if (DEBUG) this.debug("No shareable DataCall found, creating one.");
- dataCall = new DataCall(this.clientId, inputApnSetting, this);
- this._dataCalls.push(dataCall);
- }
-
- try {
- let networkInterface = new RILNetworkInterface(this, networkType,
- inputApnSetting,
- dataCall);
- gNetworkManager.registerNetworkInterface(networkInterface);
- this.dataNetworkInterfaces.set(networkType, networkInterface);
- } catch (e) {
- if (DEBUG) {
- this.debug("Error setting up RILNetworkInterface for type " +
- apnType + ": " + e);
- }
- }
- }
- }
- },
-
- /**
- * Check if all data is disconnected.
- */
- allDataDisconnected: function() {
- for (let i = 0; i < this._dataCalls.length; i++) {
- let dataCall = this._dataCalls[i];
- if (dataCall.state != NETWORK_STATE_UNKNOWN &&
- dataCall.state != NETWORK_STATE_DISCONNECTED) {
- return false;
- }
- }
- return true;
- },
-
- deactivateDataCallsAndWait: function() {
- return new Promise((aResolve, aReject) => {
- this.deactivateDataCalls({
- notifyDataCallsDisconnected: function() {
- aResolve();
- }
- });
- });
- },
-
- updateApnSettings: function(aNewApnSettings) {
- if (!aNewApnSettings) {
- return;
- }
- if (this._pendingApnSettings) {
- // Change of apn settings in process, just update to the newest.
- this._pengingApnSettings = aNewApnSettings;
- return;
- }
-
- this._pendingApnSettings = aNewApnSettings;
- this.deactivateDataCallsAndWait().then(() => {
- this._setupApnSettings(this._pendingApnSettings);
- this._pendingApnSettings = null;
- this.updateRILNetworkInterface();
- });
- },
-
- updateRILNetworkInterface: function() {
- let networkInterface = this.dataNetworkInterfaces.get(NETWORK_TYPE_MOBILE);
- if (!networkInterface) {
- if (DEBUG) {
- this.debug("No network interface for default data.");
- }
- return;
- }
-
- let connection =
- gMobileConnectionService.getItemByServiceId(this.clientId);
-
- // This check avoids data call connection if the radio is not ready
- // yet after toggling off airplane mode.
- let radioState = connection && connection.radioState;
- if (radioState != Ci.nsIMobileConnection.MOBILE_RADIO_STATE_ENABLED) {
- if (DEBUG) {
- this.debug("RIL is not ready for data connection: radio's not ready");
- }
- return;
- }
-
- // We only watch at "ril.data.enabled" flag changes for connecting or
- // disconnecting the data call. If the value of "ril.data.enabled" is
- // true and any of the remaining flags change the setting application
- // should turn this flag to false and then to true in order to reload
- // the new values and reconnect the data call.
- if (this.dataCallSettings.oldEnabled === this.dataCallSettings.enabled) {
- if (DEBUG) {
- this.debug("No changes for ril.data.enabled flag. Nothing to do.");
- }
- return;
- }
-
- let dataInfo = connection && connection.data;
- let isRegistered =
- dataInfo &&
- dataInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
- let haveDataConnection =
- dataInfo &&
- dataInfo.type != RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
- if (!isRegistered || !haveDataConnection) {
- if (DEBUG) {
- this.debug("RIL is not ready for data connection: Phone's not " +
- "registered or doesn't have data connection.");
- }
- return;
- }
- let wifi_active = false;
- if (gNetworkManager.activeNetworkInfo &&
- gNetworkManager.activeNetworkInfo.type == NETWORK_TYPE_WIFI) {
- wifi_active = true;
- }
-
- let defaultDataCallConnected = networkInterface.connected;
-
- // We have moved part of the decision making into DataCall, the rest will be
- // moved after Bug 904514 - [meta] NetworkManager enhancement.
- if (networkInterface.enabled &&
- (!this.dataCallSettings.enabled ||
- (dataInfo.roaming && !this.dataCallSettings.roamingEnabled))) {
- if (DEBUG) {
- this.debug("Data call settings: disconnect data call.");
- }
- networkInterface.disconnect();
- return;
- }
-
- if (networkInterface.enabled && wifi_active) {
- if (DEBUG) {
- this.debug("Disconnect data call when Wifi is connected.");
- }
- networkInterface.disconnect();
- return;
- }
-
- if (!this.dataCallSettings.enabled || defaultDataCallConnected) {
- if (DEBUG) {
- this.debug("Data call settings: nothing to do.");
- }
- return;
- }
- if (dataInfo.roaming && !this.dataCallSettings.roamingEnabled) {
- if (DEBUG) {
- this.debug("We're roaming, but data roaming is disabled.");
- }
- return;
- }
- if (wifi_active) {
- if (DEBUG) {
- this.debug("Don't connect data call when Wifi is connected.");
- }
- return;
- }
- if (this._pendingApnSettings) {
- if (DEBUG) this.debug("We're changing apn settings, ignore any changes.");
- return;
- }
-
- if (this._deactivatingDataCalls) {
- if (DEBUG) this.debug("We're deactivating all data calls, ignore any changes.");
- return;
- }
-
- if (DEBUG) {
- this.debug("Data call settings: connect data call.");
- }
- networkInterface.connect();
- },
-
- _isMobileNetworkType: function(aNetworkType) {
- if (aNetworkType === NETWORK_TYPE_MOBILE ||
- aNetworkType === NETWORK_TYPE_MOBILE_MMS ||
- aNetworkType === NETWORK_TYPE_MOBILE_SUPL ||
- aNetworkType === NETWORK_TYPE_MOBILE_IMS ||
- aNetworkType === NETWORK_TYPE_MOBILE_DUN ||
- aNetworkType === NETWORK_TYPE_MOBILE_FOTA) {
- return true;
- }
-
- return false;
- },
-
- getDataCallStateByType: function(aNetworkType) {
- if (!this._isMobileNetworkType(aNetworkType)) {
- if (DEBUG) this.debug(aNetworkType + " is not a mobile network type!");
- throw Cr.NS_ERROR_INVALID_ARG;
- }
-
- let networkInterface = this.dataNetworkInterfaces.get(aNetworkType);
- if (!networkInterface) {
- return NETWORK_STATE_UNKNOWN;
- }
- return networkInterface.info.state;
- },
-
- setupDataCallByType: function(aNetworkType) {
- if (DEBUG) {
- this.debug("setupDataCallByType: " + aNetworkType);
- }
-
- if (!this._isMobileNetworkType(aNetworkType)) {
- if (DEBUG) this.debug(aNetworkType + " is not a mobile network type!");
- throw Cr.NS_ERROR_INVALID_ARG;
- }
-
- let networkInterface = this.dataNetworkInterfaces.get(aNetworkType);
- if (!networkInterface) {
- if (DEBUG) {
- this.debug("No network interface for type: " + aNetworkType);
- }
- return;
- }
-
- networkInterface.connect();
- },
-
- deactivateDataCallByType: function(aNetworkType) {
- if (DEBUG) {
- this.debug("deactivateDataCallByType: " + aNetworkType);
- }
-
- if (!this._isMobileNetworkType(aNetworkType)) {
- if (DEBUG) this.debug(aNetworkType + " is not a mobile network type!");
- throw Cr.NS_ERROR_INVALID_ARG;
- }
-
- let networkInterface = this.dataNetworkInterfaces.get(aNetworkType);
- if (!networkInterface) {
- if (DEBUG) {
- this.debug("No network interface for type: " + aNetworkType);
- }
- return;
- }
-
- networkInterface.disconnect();
- },
-
- _deactivatingDataCalls: false,
-
- deactivateDataCalls: function(aCallback) {
- let dataDisconnecting = false;
- this.dataNetworkInterfaces.forEach(function(networkInterface) {
- if (networkInterface.enabled) {
- if (networkInterface.info.state != NETWORK_STATE_UNKNOWN &&
- networkInterface.info.state != NETWORK_STATE_DISCONNECTED) {
- dataDisconnecting = true;
- }
- networkInterface.disconnect();
- }
- });
-
- this._deactivatingDataCalls = dataDisconnecting;
- if (!dataDisconnecting) {
- aCallback.notifyDataCallsDisconnected();
- return;
- }
-
- let callback = {
- notifyAllDataDisconnected: () => {
- this._unregisterListener(callback);
- aCallback.notifyDataCallsDisconnected();
- }
- };
- this._registerListener(callback);
- },
-
- _listeners: null,
-
- _notifyListeners: function(aMethodName, aArgs) {
- let listeners = this._listeners.slice();
- for (let listener of listeners) {
- if (this._listeners.indexOf(listener) == -1) {
- // Listener has been unregistered in previous run.
- continue;
- }
-
- let handler = listener[aMethodName];
- try {
- handler.apply(listener, aArgs);
- } catch (e) {
- this.debug("listener for " + aMethodName + " threw an exception: " + e);
- }
- }
- },
-
- _registerListener: function(aListener) {
- if (this._listeners.indexOf(aListener) >= 0) {
- return;
- }
-
- this._listeners.push(aListener);
- },
-
- _unregisterListener: function(aListener) {
- let index = this._listeners.indexOf(aListener);
- if (index >= 0) {
- this._listeners.splice(index, 1);
- }
- },
-
- _findDataCallByCid: function(aCid) {
- if (aCid === undefined || aCid < 0) {
- return -1;
- }
-
- for (let i = 0; i < this._dataCalls.length; i++) {
- let datacall = this._dataCalls[i];
- if (datacall.linkInfo.cid != null &&
- datacall.linkInfo.cid == aCid) {
- return i;
- }
- }
-
- return -1;
- },
-
- /**
- * Notify about data call setup error, called from DataCall.
- */
- notifyDataCallError: function(aDataCall, aErrorMsg) {
- // Notify data call error only for data APN
- let networkInterface = this.dataNetworkInterfaces.get(NETWORK_TYPE_MOBILE);
- if (networkInterface && networkInterface.enabled) {
- let dataCall = networkInterface.dataCall;
- if (this._compareDataCallOptions(dataCall, aDataCall)) {
- Services.obs.notifyObservers(networkInterface.info,
- TOPIC_DATA_CALL_ERROR, aErrorMsg);
- }
- }
- },
-
- /**
- * Notify about data call changed, called from DataCall.
- */
- notifyDataCallChanged: function(aUpdatedDataCall) {
- // Process pending radio power off request after all data calls
- // are disconnected.
- if (aUpdatedDataCall.state == NETWORK_STATE_DISCONNECTED ||
- aUpdatedDataCall.state == NETWORK_STATE_UNKNOWN &&
- this.allDataDisconnected() && this._deactivatingDataCalls) {
- this._deactivatingDataCalls = false;
- this._notifyListeners("notifyAllDataDisconnected", {
- clientId: this.clientId
- });
- }
- },
-
- // nsIDataCallInterfaceListener
-
- notifyDataCallListChanged: function(aCount, aDataCallList) {
- let currentDataCalls = this._dataCalls.slice();
- for (let i = 0; i < aDataCallList.length; i++) {
- let dataCall = aDataCallList[i];
- let index = this._findDataCallByCid(dataCall.cid);
- if (index == -1) {
- if (DEBUG) {
- this.debug("Unexpected new data call: " + JSON.stringify(dataCall));
- }
- continue;
- }
- currentDataCalls[index].onDataCallChanged(dataCall);
- currentDataCalls[index] = null;
- }
-
- // If there is any CONNECTED DataCall left in currentDataCalls, means that
- // it is missing in dataCallList, we should send a DISCONNECTED event to
- // notify about this.
- for (let i = 0; i < currentDataCalls.length; i++) {
- let currentDataCall = currentDataCalls[i];
- if (currentDataCall && currentDataCall.linkInfo.cid != null &&
- currentDataCall.state == NETWORK_STATE_CONNECTED) {
- if (DEBUG) {
- this.debug("Expected data call missing: " + JSON.stringify(
- currentDataCall.apnProfile) + ", must have been DISCONNECTED.");
- }
- currentDataCall.onDataCallChanged({
- state: NETWORK_STATE_DISCONNECTED
- });
- }
- }
- },
-
- // nsIMobileConnectionListener
-
- notifyVoiceChanged: function() {},
-
- notifyDataChanged: function () {
- let connection = gMobileConnectionService.getItemByServiceId(this.clientId);
- let newDataInfo = connection.data;
-
- if (this._dataInfo.state == newDataInfo.state &&
- this._dataInfo.type == newDataInfo.type &&
- this._dataInfo.roaming == newDataInfo.roaming) {
- return;
- }
-
- this._dataInfo.state = newDataInfo.state;
- this._dataInfo.type = newDataInfo.type;
- this._dataInfo.roaming = newDataInfo.roaming;
- this.updateRILNetworkInterface();
- },
-
- notifyDataError: function (aMessage) {},
-
- notifyCFStateChanged: function(aAction, aReason, aNumber, aTimeSeconds, aServiceClass) {},
-
- notifyEmergencyCbModeChanged: function(aActive, aTimeoutMs) {},
-
- notifyOtaStatusChanged: function(aStatus) {},
-
- notifyRadioStateChanged: function() {},
-
- notifyClirModeChanged: function(aMode) {},
-
- notifyLastKnownNetworkChanged: function() {},
-
- notifyLastKnownHomeNetworkChanged: function() {},
-
- notifyNetworkSelectionModeChanged: function() {},
-
- notifyDeviceIdentitiesChanged: function() {}
-};
-
-function DataCall(aClientId, aApnSetting, aDataCallHandler) {
- this.clientId = aClientId;
- this.dataCallHandler = aDataCallHandler;
- this.apnProfile = {
- apn: aApnSetting.apn,
- user: aApnSetting.user,
- password: aApnSetting.password,
- authType: aApnSetting.authtype,
- protocol: aApnSetting.protocol,
- roaming_protocol: aApnSetting.roaming_protocol
- };
- this.linkInfo = {
- cid: null,
- ifname: null,
- addresses: [],
- dnses: [],
- gateways: [],
- pcscf: [],
- mtu: null
- };
- this.state = NETWORK_STATE_UNKNOWN;
- this.requestedNetworkIfaces = [];
-}
-DataCall.prototype = {
- /**
- * Standard values for the APN connection retry process
- * Retry funcion: time(secs) = A * numer_of_retries^2 + B
- */
- NETWORK_APNRETRY_FACTOR: 8,
- NETWORK_APNRETRY_ORIGIN: 3,
- NETWORK_APNRETRY_MAXRETRIES: 10,
-
- dataCallHandler: null,
-
- // Event timer for connection retries
- timer: null,
-
- // APN failed connections. Retry counter
- apnRetryCounter: 0,
-
- // Array to hold RILNetworkInterfaces that requested this DataCall.
- requestedNetworkIfaces: null,
-
- /**
- * @return "deactivate" if <ifname> changes or one of the aCurrentDataCall
- * addresses is missing in updatedDataCall, or "identical" if no
- * changes found, or "changed" otherwise.
- */
- _compareDataCallLink: function(aUpdatedDataCall, aCurrentDataCall) {
- // If network interface is changed, report as "deactivate".
- if (aUpdatedDataCall.ifname != aCurrentDataCall.ifname) {
- return "deactivate";
- }
-
- // If any existing address is missing, report as "deactivate".
- for (let i = 0; i < aCurrentDataCall.addresses.length; i++) {
- let address = aCurrentDataCall.addresses[i];
- if (aUpdatedDataCall.addresses.indexOf(address) < 0) {
- return "deactivate";
- }
- }
-
- if (aCurrentDataCall.addresses.length != aUpdatedDataCall.addresses.length) {
- // Since now all |aCurrentDataCall.addresses| are found in
- // |aUpdatedDataCall.addresses|, this means one or more new addresses are
- // reported.
- return "changed";
- }
-
- let fields = ["gateways", "dnses"];
- for (let i = 0; i < fields.length; i++) {
- // Compare <datacall>.<field>.
- let field = fields[i];
- let lhs = aUpdatedDataCall[field], rhs = aCurrentDataCall[field];
- if (lhs.length != rhs.length) {
- return "changed";
- }
- for (let i = 0; i < lhs.length; i++) {
- if (lhs[i] != rhs[i]) {
- return "changed";
- }
- }
- }
-
- if (aCurrentDataCall.mtu != aUpdatedDataCall.mtu) {
- return "changed";
- }
-
- return "identical";
- },
-
- _getGeckoDataCallState:function (aDataCall) {
- if (aDataCall.active == Ci.nsIDataCallInterface.DATACALL_STATE_ACTIVE_UP ||
- aDataCall.active == Ci.nsIDataCallInterface.DATACALL_STATE_ACTIVE_DOWN) {
- return NETWORK_STATE_CONNECTED;
- }
-
- return NETWORK_STATE_DISCONNECTED;
- },
-
- onSetupDataCallResult: function(aDataCall) {
- this.debug("onSetupDataCallResult: " + JSON.stringify(aDataCall));
- let errorMsg = aDataCall.errorMsg;
- if (aDataCall.failCause &&
- aDataCall.failCause != Ci.nsIDataCallInterface.DATACALL_FAIL_NONE) {
- errorMsg =
- RIL.RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[aDataCall.failCause];
- }
-
- if (errorMsg) {
- if (DEBUG) {
- this.debug("SetupDataCall error for apn " + this.apnProfile.apn + ": " +
- errorMsg + " (" + aDataCall.failCause + "), retry time: " +
- aDataCall.suggestedRetryTime);
- }
-
- this.state = NETWORK_STATE_DISCONNECTED;
-
- if (this.requestedNetworkIfaces.length === 0) {
- if (DEBUG) this.debug("This DataCall is not requested anymore.");
- return;
- }
-
- // Let DataCallHandler notify MobileConnectionService
- this.dataCallHandler.notifyDataCallError(this, errorMsg);
-
- // For suggestedRetryTime, the value of INT32_MAX(0x7fffffff) means no retry.
- if (aDataCall.suggestedRetryTime === INT32_MAX ||
- this.isPermanentFail(aDataCall.failCause, errorMsg)) {
- if (DEBUG) this.debug("Data call error: no retry needed.");
- return;
- }
-
- this.retry(aDataCall.suggestedRetryTime);
- return;
- }
-
- this.apnRetryCounter = 0;
- this.linkInfo.cid = aDataCall.cid;
-
- if (this.requestedNetworkIfaces.length === 0) {
- if (DEBUG) {
- this.debug("State is connected, but no network interface requested" +
- " this DataCall");
- }
- this.deactivate();
- return;
- }
-
- this.linkInfo.ifname = aDataCall.ifname;
- this.linkInfo.addresses = aDataCall.addresses ? aDataCall.addresses.split(" ") : [];
- this.linkInfo.gateways = aDataCall.gateways ? aDataCall.gateways.split(" ") : [];
- this.linkInfo.dnses = aDataCall.dnses ? aDataCall.dnses.split(" ") : [];
- this.linkInfo.pcscf = aDataCall.pcscf ? aDataCall.pcscf.split(" ") : [];
- this.linkInfo.mtu = aDataCall.mtu > 0 ? aDataCall.mtu : 0;
- this.state = this._getGeckoDataCallState(aDataCall);
-
- // Notify DataCallHandler about data call connected.
- this.dataCallHandler.notifyDataCallChanged(this);
-
- for (let i = 0; i < this.requestedNetworkIfaces.length; i++) {
- this.requestedNetworkIfaces[i].notifyRILNetworkInterface();
- }
- },
-
- onDeactivateDataCallResult: function() {
- if (DEBUG) this.debug("onDeactivateDataCallResult");
-
- this.reset();
-
- if (this.requestedNetworkIfaces.length > 0) {
- if (DEBUG) {
- this.debug("State is disconnected/unknown, but this DataCall is" +
- " requested.");
- }
- this.setup();
- return;
- }
-
- // Notify DataCallHandler about data call disconnected.
- this.dataCallHandler.notifyDataCallChanged(this);
- },
-
- onDataCallChanged: function(aUpdatedDataCall) {
- if (DEBUG) {
- this.debug("onDataCallChanged: " + JSON.stringify(aUpdatedDataCall));
- }
-
- if (this.state == NETWORK_STATE_CONNECTING ||
- this.state == NETWORK_STATE_DISCONNECTING) {
- if (DEBUG) {
- this.debug("We are in connecting/disconnecting state, ignore any " +
- "unsolicited event for now.");
- }
- return;
- }
-
- let dataCallState = this._getGeckoDataCallState(aUpdatedDataCall);
- if (this.state == dataCallState &&
- dataCallState != NETWORK_STATE_CONNECTED) {
- return;
- }
-
- let newLinkInfo = {
- ifname: aUpdatedDataCall.ifname,
- addresses: aUpdatedDataCall.addresses ? aUpdatedDataCall.addresses.split(" ") : [],
- dnses: aUpdatedDataCall.dnses ? aUpdatedDataCall.dnses.split(" ") : [],
- gateways: aUpdatedDataCall.gateways ? aUpdatedDataCall.gateways.split(" ") : [],
- pcscf: aUpdatedDataCall.pcscf ? aUpdatedDataCall.pcscf.split(" ") : [],
- mtu: aUpdatedDataCall.mtu > 0 ? aUpdatedDataCall.mtu : 0
- };
-
- switch (dataCallState) {
- case NETWORK_STATE_CONNECTED:
- if (this.state == NETWORK_STATE_CONNECTED) {
- let result =
- this._compareDataCallLink(newLinkInfo, this.linkInfo);
-
- if (result == "identical") {
- if (DEBUG) this.debug("No changes in data call.");
- return;
- }
- if (result == "deactivate") {
- if (DEBUG) this.debug("Data link changed, cleanup.");
- this.deactivate();
- return;
- }
- // Minor change, just update and notify.
- if (DEBUG) {
- this.debug("Data link minor change, just update and notify.");
- }
-
- this.linkInfo.addresses = newLinkInfo.addresses.slice();
- this.linkInfo.gateways = newLinkInfo.gateways.slice();
- this.linkInfo.dnses = newLinkInfo.dnses.slice();
- this.linkInfo.pcscf = newLinkInfo.pcscf.slice();
- this.linkInfo.mtu = newLinkInfo.mtu;
- }
- break;
- case NETWORK_STATE_DISCONNECTED:
- case NETWORK_STATE_UNKNOWN:
- if (this.state == NETWORK_STATE_CONNECTED) {
- // Notify first on unexpected data call disconnection.
- this.state = dataCallState;
- for (let i = 0; i < this.requestedNetworkIfaces.length; i++) {
- this.requestedNetworkIfaces[i].notifyRILNetworkInterface();
- }
- }
- this.reset();
-
- if (this.requestedNetworkIfaces.length > 0) {
- if (DEBUG) {
- this.debug("State is disconnected/unknown, but this DataCall is" +
- " requested.");
- }
- this.setup();
- return;
- }
- break;
- }
-
- this.state = dataCallState;
-
- // Notify DataCallHandler about data call changed.
- this.dataCallHandler.notifyDataCallChanged(this);
-
- for (let i = 0; i < this.requestedNetworkIfaces.length; i++) {
- this.requestedNetworkIfaces[i].notifyRILNetworkInterface();
- }
- },
-
- // Helpers
-
- debug: function(aMsg) {
- dump("-*- DataCall[" + this.clientId + ":" + this.apnProfile.apn + "]: " +
- aMsg + "\n");
- },
-
- get connected() {
- return this.state == NETWORK_STATE_CONNECTED;
- },
-
- isPermanentFail: function(aDataFailCause, aErrorMsg) {
- // Check ril.h for 'no retry' data call fail causes.
- if (aErrorMsg === RIL.GECKO_ERROR_RADIO_NOT_AVAILABLE ||
- aErrorMsg === RIL.GECKO_ERROR_INVALID_PARAMETER ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_OPERATOR_BARRED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_MISSING_UKNOWN_APN ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_UNKNOWN_PDP_ADDRESS_TYPE ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_USER_AUTHENTICATION ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_ACTIVATION_REJECT_GGSN ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_SERVICE_OPTION_NOT_SUPPORTED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_NSAPI_IN_USE ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_ONLY_IPV4_ALLOWED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_ONLY_IPV6_ALLOWED ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_PROTOCOL_ERRORS ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_RADIO_POWER_OFF ||
- aDataFailCause === Ci.nsIDataCallInterface.DATACALL_FAIL_TETHERED_CALL_ACTIVE) {
- return true;
- }
-
- return false;
- },
-
- inRequestedTypes: function(aType) {
- for (let i = 0; i < this.requestedNetworkIfaces.length; i++) {
- if (this.requestedNetworkIfaces[i].info.type == aType) {
- return true;
- }
- }
- return false;
- },
-
- canHandleApn: function(aApnSetting) {
- let isIdentical = this.apnProfile.apn == aApnSetting.apn &&
- (this.apnProfile.user || '') == (aApnSetting.user || '') &&
- (this.apnProfile.password || '') == (aApnSetting.password || '') &&
- (this.apnProfile.authType || '') == (aApnSetting.authtype || '');
-
- if (RILQUIRKS_HAVE_IPV6) {
- isIdentical = isIdentical &&
- (this.apnProfile.protocol || '') == (aApnSetting.protocol || '') &&
- (this.apnProfile.roaming_protocol || '') == (aApnSetting.roaming_protocol || '');
- }
-
- return isIdentical;
- },
-
- resetLinkInfo: function() {
- this.linkInfo.cid = null;
- this.linkInfo.ifname = null;
- this.linkInfo.addresses = [];
- this.linkInfo.dnses = [];
- this.linkInfo.gateways = [];
- this.linkInfo.pcscf = [];
- this.linkInfo.mtu = null;
- },
-
- reset: function() {
- this.resetLinkInfo();
-
- this.state = NETWORK_STATE_UNKNOWN;
- },
-
- connect: function(aNetworkInterface) {
- if (DEBUG) this.debug("connect: " + aNetworkInterface.info.type);
-
- if (this.requestedNetworkIfaces.indexOf(aNetworkInterface) == -1) {
- this.requestedNetworkIfaces.push(aNetworkInterface);
- }
-
- if (this.state == NETWORK_STATE_CONNECTING ||
- this.state == NETWORK_STATE_DISCONNECTING) {
- return;
- }
- if (this.state == NETWORK_STATE_CONNECTED) {
- // This needs to run asynchronously, to behave the same way as the case of
- // non-shared apn, see bug 1059110.
- Services.tm.currentThread.dispatch(() => {
- // Do not notify if state changed while this event was being dispatched,
- // the state probably was notified already or need not to be notified.
- if (aNetworkInterface.info.state == RIL.GECKO_NETWORK_STATE_CONNECTED) {
- aNetworkInterface.notifyRILNetworkInterface();
- }
- }, Ci.nsIEventTarget.DISPATCH_NORMAL);
- return;
- }
-
- // If retry mechanism is running on background, stop it since we are going
- // to setup data call now.
- if (this.timer) {
- this.timer.cancel();
- }
-
- this.setup();
- },
-
- setup: function() {
- if (DEBUG) {
- this.debug("Going to set up data connection with APN " +
- this.apnProfile.apn);
- }
-
- let connection =
- gMobileConnectionService.getItemByServiceId(this.clientId);
- let dataInfo = connection && connection.data;
- if (dataInfo == null ||
- dataInfo.state != RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED ||
- dataInfo.type == RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN) {
- return;
- }
-
- let radioTechType = dataInfo.type;
- let radioTechnology = RIL.GECKO_RADIO_TECH.indexOf(radioTechType);
- let authType = RIL.RIL_DATACALL_AUTH_TO_GECKO.indexOf(this.apnProfile.authType);
- // Use the default authType if the value in database is invalid.
- // For the case that user might not select the authentication type.
- if (authType == -1) {
- if (DEBUG) {
- this.debug("Invalid authType '" + this.apnProfile.authtype +
- "', using '" + RIL.GECKO_DATACALL_AUTH_DEFAULT + "'");
- }
- authType = RIL.RIL_DATACALL_AUTH_TO_GECKO.indexOf(RIL.GECKO_DATACALL_AUTH_DEFAULT);
- }
-
- let pdpType = Ci.nsIDataCallInterface.DATACALL_PDP_TYPE_IPV4;
- if (RILQUIRKS_HAVE_IPV6) {
- pdpType = !dataInfo.roaming
- ? RIL.RIL_DATACALL_PDP_TYPES.indexOf(this.apnProfile.protocol)
- : RIL.RIL_DATACALL_PDP_TYPES.indexOf(this.apnProfile.roaming_protocol);
- if (pdpType == -1) {
- if (DEBUG) {
- this.debug("Invalid pdpType '" + (!dataInfo.roaming
- ? this.apnProfile.protocol
- : this.apnProfile.roaming_protocol) +
- "', using '" + RIL.GECKO_DATACALL_PDP_TYPE_DEFAULT + "'");
- }
- pdpType = RIL.RIL_DATACALL_PDP_TYPES.indexOf(RIL.GECKO_DATACALL_PDP_TYPE_DEFAULT);
- }
- }
-
- let dcInterface = this.dataCallHandler.dataCallInterface;
- dcInterface.setupDataCall(
- this.apnProfile.apn, this.apnProfile.user, this.apnProfile.password,
- authType, pdpType, {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallCallback]),
- notifySetupDataCallSuccess: (aDataCall) => {
- this.onSetupDataCallResult(aDataCall);
- },
- notifyError: (aErrorMsg) => {
- this.onSetupDataCallResult({errorMsg: aErrorMsg});
- }
- });
- this.state = NETWORK_STATE_CONNECTING;
- },
-
- retry: function(aSuggestedRetryTime) {
- let apnRetryTimer;
-
- // We will retry the connection in increasing times
- // based on the function: time = A * numer_of_retries^2 + B
- if (this.apnRetryCounter >= this.NETWORK_APNRETRY_MAXRETRIES) {
- this.apnRetryCounter = 0;
- this.timer = null;
- if (DEBUG) this.debug("Too many APN Connection retries - STOP retrying");
- return;
- }
-
- // If there is a valid aSuggestedRetryTime, override the retry timer.
- if (aSuggestedRetryTime !== undefined && aSuggestedRetryTime >= 0) {
- apnRetryTimer = aSuggestedRetryTime / 1000;
- } else {
- apnRetryTimer = this.NETWORK_APNRETRY_FACTOR *
- (this.apnRetryCounter * this.apnRetryCounter) +
- this.NETWORK_APNRETRY_ORIGIN;
- }
- this.apnRetryCounter++;
- if (DEBUG) {
- this.debug("Data call - APN Connection Retry Timer (secs-counter): " +
- apnRetryTimer + "-" + this.apnRetryCounter);
- }
-
- if (this.timer == null) {
- // Event timer for connection retries
- this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- }
- this.timer.initWithCallback(this, apnRetryTimer * 1000,
- Ci.nsITimer.TYPE_ONE_SHOT);
- },
-
- disconnect: function(aNetworkInterface) {
- if (DEBUG) this.debug("disconnect: " + aNetworkInterface.info.type);
-
- let index = this.requestedNetworkIfaces.indexOf(aNetworkInterface);
- if (index != -1) {
- this.requestedNetworkIfaces.splice(index, 1);
-
- if (this.state == NETWORK_STATE_DISCONNECTED ||
- this.state == NETWORK_STATE_UNKNOWN) {
- if (this.timer) {
- this.timer.cancel();
- }
- this.reset();
- return;
- }
-
- // Notify the DISCONNECTED event immediately after network interface is
- // removed from requestedNetworkIfaces, to make the DataCall, shared or
- // not, to have the same behavior.
- Services.tm.currentThread.dispatch(() => {
- // Do not notify if state changed while this event was being dispatched,
- // the state probably was notified already or need not to be notified.
- if (aNetworkInterface.info.state == RIL.GECKO_NETWORK_STATE_DISCONNECTED) {
- aNetworkInterface.notifyRILNetworkInterface();
-
- // Clear link info after notifying NetworkManager.
- if (this.requestedNetworkIfaces.length === 0) {
- this.resetLinkInfo();
- }
- }
- }, Ci.nsIEventTarget.DISPATCH_NORMAL);
- }
-
- // Only deactivate data call if no more network interface needs this
- // DataCall and if state is CONNECTED, for other states, we simply remove
- // the network interface from requestedNetworkIfaces.
- if (this.requestedNetworkIfaces.length > 0 ||
- this.state != NETWORK_STATE_CONNECTED) {
- return;
- }
-
- this.deactivate();
- },
-
- deactivate: function() {
- let reason = Ci.nsIDataCallInterface.DATACALL_DEACTIVATE_NO_REASON;
- if (DEBUG) {
- this.debug("Going to disconnect data connection cid " + this.linkInfo.cid);
- }
-
- let dcInterface = this.dataCallHandler.dataCallInterface;
- dcInterface.deactivateDataCall(this.linkInfo.cid, reason, {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallCallback]),
- notifySuccess: () => {
- this.onDeactivateDataCallResult();
- },
- notifyError: (aErrorMsg) => {
- this.onDeactivateDataCallResult();
- }
- });
-
- this.state = NETWORK_STATE_DISCONNECTING;
- },
-
- // Entry method for timer events. Used to reconnect to a failed APN
- notify: function(aTimer) {
- this.setup();
- },
-
- shutdown: function() {
- if (this.timer) {
- this.timer.cancel();
- this.timer = null;
- }
- }
-};
-
-function RILNetworkInfo(aClientId, aType, aNetworkInterface)
-{
- this.serviceId = aClientId;
- this.type = aType;
-
- this.networkInterface = aNetworkInterface;
-}
-RILNetworkInfo.prototype = {
- classID: RILNETWORKINFO_CID,
- classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINFO_CID,
- classDescription: "RILNetworkInfo",
- interfaces: [Ci.nsINetworkInfo,
- Ci.nsIRilNetworkInfo]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo,
- Ci.nsIRilNetworkInfo]),
-
- networkInterface: null,
-
- getDataCall: function() {
- return this.networkInterface.dataCall;
- },
-
- getApnSetting: function() {
- return this.networkInterface.apnSetting;
- },
-
- debug: function(aMsg) {
- dump("-*- RILNetworkInfo[" + this.serviceId + ":" + this.type + "]: " +
- aMsg + "\n");
- },
-
- /**
- * nsINetworkInfo Implementation
- */
- get state() {
- let dataCall = this.getDataCall();
- if (!dataCall.inRequestedTypes(this.type)) {
- return NETWORK_STATE_DISCONNECTED;
- }
- return dataCall.state;
- },
-
- type: null,
-
- get name() {
- return this.getDataCall().linkInfo.ifname;
- },
-
- getAddresses: function(aIps, aPrefixLengths) {
- let addresses = this.getDataCall().linkInfo.addresses;
-
- let ips = [];
- let prefixLengths = [];
- for (let i = 0; i < addresses.length; i++) {
- let [ip, prefixLength] = addresses[i].split("/");
- ips.push(ip);
- prefixLengths.push(prefixLength);
- }
-
- aIps.value = ips.slice();
- aPrefixLengths.value = prefixLengths.slice();
-
- return ips.length;
- },
-
- getGateways: function(aCount) {
- let linkInfo = this.getDataCall().linkInfo;
-
- if (aCount) {
- aCount.value = linkInfo.gateways.length;
- }
-
- return linkInfo.gateways.slice();
- },
-
- getDnses: function(aCount) {
- let linkInfo = this.getDataCall().linkInfo;
-
- if (aCount) {
- aCount.value = linkInfo.dnses.length;
- }
-
- return linkInfo.dnses.slice();
- },
-
- /**
- * nsIRilNetworkInfo Implementation
- */
-
- serviceId: 0,
-
- get iccId() {
- let icc = gIccService.getIccByServiceId(this.serviceId);
- let iccInfo = icc && icc.iccInfo;
-
- return iccInfo && iccInfo.iccid;
- },
-
- get mmsc() {
- if (this.type != NETWORK_TYPE_MOBILE_MMS) {
- if (DEBUG) this.debug("Error! Only MMS network can get MMSC.");
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- return this.getApnSetting().mmsc || "";
- },
-
- get mmsProxy() {
- if (this.type != NETWORK_TYPE_MOBILE_MMS) {
- if (DEBUG) this.debug("Error! Only MMS network can get MMS proxy.");
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- return this.getApnSetting().mmsproxy || "";
- },
-
- get mmsPort() {
- if (this.type != NETWORK_TYPE_MOBILE_MMS) {
- if (DEBUG) this.debug("Error! Only MMS network can get MMS port.");
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- // Note: Port 0 is reserved, so we treat it as invalid as well.
- // See http://www.iana.org/assignments/port-numbers
- return this.getApnSetting().mmsport || -1;
- },
-
- getPcscf: function(aCount) {
- if (this.type != NETWORK_TYPE_MOBILE_IMS) {
- if (DEBUG) this.debug("Error! Only IMS network can get pcscf.");
- throw Cr.NS_ERROR_UNEXPECTED;
- }
-
- let linkInfo = this.getDataCall().linkInfo;
-
- if (aCount) {
- aCount.value = linkInfo.pcscf.length;
- }
- return linkInfo.pcscf.slice();
- },
-};
-
-function RILNetworkInterface(aDataCallHandler, aType, aApnSetting, aDataCall) {
- if (!aDataCall) {
- throw new Error("No dataCall for RILNetworkInterface: " + type);
- }
-
- this.dataCallHandler = aDataCallHandler;
- this.enabled = false;
- this.dataCall = aDataCall;
- this.apnSetting = aApnSetting;
-
- this.info = new RILNetworkInfo(aDataCallHandler.clientId, aType, this);
-}
-
-RILNetworkInterface.prototype = {
- classID: RILNETWORKINTERFACE_CID,
- classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINTERFACE_CID,
- classDescription: "RILNetworkInterface",
- interfaces: [Ci.nsINetworkInterface]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
-
- // If this RILNetworkInterface type is enabled or not.
- enabled: null,
-
- apnSetting: null,
-
- dataCall: null,
-
- /**
- * nsINetworkInterface Implementation
- */
-
- info: null,
-
- get httpProxyHost() {
- return this.apnSetting.proxy || "";
- },
-
- get httpProxyPort() {
- return this.apnSetting.port || "";
- },
-
- get mtu() {
- // Value provided by network has higher priority than apn settings.
- return this.dataCall.linkInfo.mtu || this.apnSetting.mtu || -1;
- },
-
- // Helpers
-
- debug: function(aMsg) {
- dump("-*- RILNetworkInterface[" + this.dataCallHandler.clientId + ":" +
- this.info.type + "]: " + aMsg + "\n");
- },
-
- get connected() {
- return this.info.state == NETWORK_STATE_CONNECTED;
- },
-
- notifyRILNetworkInterface: function() {
- if (DEBUG) {
- this.debug("notifyRILNetworkInterface type: " + this.info.type +
- ", state: " + this.info.state);
- }
-
- gNetworkManager.updateNetworkInterface(this);
- },
-
- connect: function() {
- this.enabled = true;
-
- this.dataCall.connect(this);
- },
-
- disconnect: function() {
- if (!this.enabled) {
- return;
- }
- this.enabled = false;
-
- this.dataCall.disconnect(this);
- },
-
- shutdown: function() {
- this.dataCall.shutdown();
- this.dataCall = null;
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataCallManager]); \ No newline at end of file
diff --git a/dom/system/gonk/DataCallManager.manifest b/dom/system/gonk/DataCallManager.manifest
deleted file mode 100644
index 2a982415e..000000000
--- a/dom/system/gonk/DataCallManager.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-# DataCallManager.js
-component {35b9efa2-e42c-45ce-8210-0a13e6f4aadc} DataCallManager.js
-contract @mozilla.org/datacall/manager;1 {35b9efa2-e42c-45ce-8210-0a13e6f4aadc}
-category profile-after-change DataCallManager @mozilla.org/datacall/manager;1 \ No newline at end of file
diff --git a/dom/system/gonk/GeolocationUtil.cpp b/dom/system/gonk/GeolocationUtil.cpp
deleted file mode 100644
index 99d484a19..000000000
--- a/dom/system/gonk/GeolocationUtil.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GeolocationUtil.h"
-
-double CalculateDeltaInMeter(double aLat, double aLon, double aLastLat, double aLastLon)
-{
- // Use spherical law of cosines to calculate difference
- // Not quite as correct as the Haversine but simpler and cheaper
- const double radsInDeg = M_PI / 180.0;
- const double rNewLat = aLat * radsInDeg;
- const double rNewLon = aLon * radsInDeg;
- const double rOldLat = aLastLat * radsInDeg;
- const double rOldLon = aLastLon * radsInDeg;
- // WGS84 equatorial radius of earth = 6378137m
- double cosDelta = (sin(rNewLat) * sin(rOldLat)) +
- (cos(rNewLat) * cos(rOldLat) * cos(rOldLon - rNewLon));
- if (cosDelta > 1.0) {
- cosDelta = 1.0;
- } else if (cosDelta < -1.0) {
- cosDelta = -1.0;
- }
- return acos(cosDelta) * 6378137;
-}
-
diff --git a/dom/system/gonk/GeolocationUtil.h b/dom/system/gonk/GeolocationUtil.h
deleted file mode 100644
index fde337fb8..000000000
--- a/dom/system/gonk/GeolocationUtil.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef GEOLOCATIONUTIL_H
-#define GEOLOCATIONUTIL_H
-
-double CalculateDeltaInMeter(double aLat, double aLon, double aLastLat, double aLastLon);
-
-#endif
-
diff --git a/dom/system/gonk/GonkGPSGeolocationProvider.cpp b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
deleted file mode 100644
index 9ce6ce2e5..000000000
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ /dev/null
@@ -1,706 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "GonkGPSGeolocationProvider.h"
-
-#include <cmath>
-#include <pthread.h>
-#include <hardware/gps.h>
-
-#include "base/task.h"
-#include "GeolocationUtil.h"
-#include "mozstumbler/MozStumbler.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Services.h"
-#include "nsContentUtils.h"
-#include "nsGeoPosition.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsINetworkInterface.h"
-#include "nsIObserverService.h"
-#include "nsJSUtils.h"
-#include "nsPrintfCString.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "prtime.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/SettingChangeNotificationBinding.h"
-
-#ifdef AGPS_TYPE_INVALID
-#define AGPS_HAVE_DUAL_APN
-#endif
-
-#define FLUSH_AIDE_DATA 0
-
-#undef LOG
-#undef ERR
-#undef DBG
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GonkGPSGeolocationProvider", ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "GonkGPSGeolocationProvider", ## args)
-#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "GonkGPSGeolocationProvider" , ## args)
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-static const int kDefaultPeriod = 1000; // ms
-static bool gDebug_isLoggingEnabled = false;
-static bool gDebug_isGPSLocationIgnored = false;
-static const char* kMozSettingsChangedTopic = "mozsettings-changed";
-// Both of these settings can be toggled in the Gaia Developer settings screen.
-static const char* kSettingDebugEnabled = "geolocation.debugging.enabled";
-static const char* kSettingDebugGpsIgnored = "geolocation.debugging.gps-locations-ignored";
-
-// While most methods of GonkGPSGeolocationProvider should only be
-// called from main thread, we deliberately put the Init and ShutdownGPS
-// methods off main thread to avoid blocking.
-NS_IMPL_ISUPPORTS(GonkGPSGeolocationProvider,
- nsIGeolocationProvider,
- nsIObserver,
- nsISettingsServiceCallback)
-
-/* static */ GonkGPSGeolocationProvider* GonkGPSGeolocationProvider::sSingleton = nullptr;
-GpsCallbacks GonkGPSGeolocationProvider::mCallbacks;
-
-
-void
-GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location)
-{
- if (gDebug_isGPSLocationIgnored) {
- return;
- }
-
- class UpdateLocationEvent : public Runnable {
- public:
- UpdateLocationEvent(nsGeoPosition* aPosition)
- : mPosition(aPosition)
- {}
- NS_IMETHOD Run() override {
- RefPtr<GonkGPSGeolocationProvider> provider =
- GonkGPSGeolocationProvider::GetSingleton();
- nsCOMPtr<nsIGeolocationUpdate> callback = provider->mLocationCallback;
- provider->mLastGPSPosition = mPosition;
- if (callback) {
- callback->Update(mPosition);
- }
- return NS_OK;
- }
- private:
- RefPtr<nsGeoPosition> mPosition;
- };
-
- MOZ_ASSERT(location);
-
- const float kImpossibleAccuracy_m = 0.001;
- if (location->accuracy < kImpossibleAccuracy_m) {
- return;
- }
-
- RefPtr<nsGeoPosition> somewhere = new nsGeoPosition(location->latitude,
- location->longitude,
- location->altitude,
- location->accuracy,
- location->accuracy,
- location->bearing,
- location->speed,
- PR_Now() / PR_USEC_PER_MSEC);
- // Note above: Can't use location->timestamp as the time from the satellite is a
- // minimum of 16 secs old (see http://leapsecond.com/java/gpsclock.htm).
- // All code from this point on expects the gps location to be timestamped with the
- // current time, most notably: the geolocation service which respects maximumAge
- // set in the DOM JS.
-
- if (gDebug_isLoggingEnabled) {
- DBG("geo: GPS got a fix (%f, %f). accuracy: %f",
- location->latitude,
- location->longitude,
- location->accuracy);
- }
-
- RefPtr<UpdateLocationEvent> event = new UpdateLocationEvent(somewhere);
- NS_DispatchToMainThread(event);
-
-}
-
-class NotifyObserversGPSTask final : public Runnable
-{
-public:
- explicit NotifyObserversGPSTask(const char16_t* aData)
- : mData(aData)
- {}
- NS_IMETHOD Run() override {
- RefPtr<nsIGeolocationProvider> provider =
- GonkGPSGeolocationProvider::GetSingleton();
- nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
- obsService->NotifyObservers(provider, "geolocation-device-events", mData);
- return NS_OK;
- }
-private:
- const char16_t* mData;
-};
-
-void
-GonkGPSGeolocationProvider::StatusCallback(GpsStatus* status)
-{
- const char* msgStream=0;
- switch (status->status) {
- case GPS_STATUS_NONE:
- msgStream = "geo: GPS_STATUS_NONE\n";
- break;
- case GPS_STATUS_SESSION_BEGIN:
- msgStream = "geo: GPS_STATUS_SESSION_BEGIN\n";
- break;
- case GPS_STATUS_SESSION_END:
- msgStream = "geo: GPS_STATUS_SESSION_END\n";
- break;
- case GPS_STATUS_ENGINE_ON:
- msgStream = "geo: GPS_STATUS_ENGINE_ON\n";
- NS_DispatchToMainThread(new NotifyObserversGPSTask(u"GPSStarting"));
- break;
- case GPS_STATUS_ENGINE_OFF:
- msgStream = "geo: GPS_STATUS_ENGINE_OFF\n";
- NS_DispatchToMainThread(new NotifyObserversGPSTask(u"GPSShutdown"));
- break;
- default:
- msgStream = "geo: Unknown GPS status\n";
- break;
- }
- if (gDebug_isLoggingEnabled){
- DBG("%s", msgStream);
- }
-}
-
-void
-GonkGPSGeolocationProvider::SvStatusCallback(GpsSvStatus* sv_info)
-{
- if (gDebug_isLoggingEnabled) {
- static int numSvs = 0;
- static uint32_t numEphemeris = 0;
- static uint32_t numAlmanac = 0;
- static uint32_t numUsedInFix = 0;
-
- unsigned int i = 1;
- uint32_t svAlmanacCount = 0;
- for (i = 1; i > 0; i <<= 1) {
- if (i & sv_info->almanac_mask) {
- svAlmanacCount++;
- }
- }
-
- uint32_t svEphemerisCount = 0;
- for (i = 1; i > 0; i <<= 1) {
- if (i & sv_info->ephemeris_mask) {
- svEphemerisCount++;
- }
- }
-
- uint32_t svUsedCount = 0;
- for (i = 1; i > 0; i <<= 1) {
- if (i & sv_info->used_in_fix_mask) {
- svUsedCount++;
- }
- }
-
- // Log the message only if the the status changed.
- if (sv_info->num_svs != numSvs ||
- svAlmanacCount != numAlmanac ||
- svEphemerisCount != numEphemeris ||
- svUsedCount != numUsedInFix) {
-
- LOG(
- "geo: Number of SVs have (visibility, almanac, ephemeris): (%d, %d, %d)."
- " %d of these SVs were used in fix.\n",
- sv_info->num_svs, svAlmanacCount, svEphemerisCount, svUsedCount);
-
- numSvs = sv_info->num_svs;
- numAlmanac = svAlmanacCount;
- numEphemeris = svEphemerisCount;
- numUsedInFix = svUsedCount;
- }
- }
-}
-
-void
-GonkGPSGeolocationProvider::NmeaCallback(GpsUtcTime timestamp, const char* nmea, int length)
-{
- if (gDebug_isLoggingEnabled) {
- DBG("NMEA: timestamp:\t%lld, length: %d, %s", timestamp, length, nmea);
- }
-}
-
-void
-GonkGPSGeolocationProvider::SetCapabilitiesCallback(uint32_t capabilities)
-{
- class UpdateCapabilitiesEvent : public Runnable {
- public:
- UpdateCapabilitiesEvent(uint32_t aCapabilities)
- : mCapabilities(aCapabilities)
- {}
- NS_IMETHOD Run() override {
- RefPtr<GonkGPSGeolocationProvider> provider =
- GonkGPSGeolocationProvider::GetSingleton();
-
- provider->mSupportsScheduling = mCapabilities & GPS_CAPABILITY_SCHEDULING;
- provider->mSupportsSingleShot = mCapabilities & GPS_CAPABILITY_SINGLE_SHOT;
-#ifdef GPS_CAPABILITY_ON_DEMAND_TIME
- provider->mSupportsTimeInjection = mCapabilities & GPS_CAPABILITY_ON_DEMAND_TIME;
-#endif
- return NS_OK;
- }
- private:
- uint32_t mCapabilities;
- };
-
- NS_DispatchToMainThread(new UpdateCapabilitiesEvent(capabilities));
-}
-
-void
-GonkGPSGeolocationProvider::AcquireWakelockCallback()
-{
-}
-
-void
-GonkGPSGeolocationProvider::ReleaseWakelockCallback()
-{
-}
-
-typedef void *(*pthread_func)(void *);
-
-/** Callback for creating a thread that can call into the JS codes.
- */
-pthread_t
-GonkGPSGeolocationProvider::CreateThreadCallback(const char* name, void (*start)(void *), void* arg)
-{
- pthread_t thread;
- pthread_attr_t attr;
-
- pthread_attr_init(&attr);
-
- /* Unfortunately pthread_create and the callback disagreed on what
- * start function should return.
- */
- pthread_create(&thread, &attr, reinterpret_cast<pthread_func>(start), arg);
-
- return thread;
-}
-
-void
-GonkGPSGeolocationProvider::RequestUtcTimeCallback()
-{
-}
-
-GonkGPSGeolocationProvider::GonkGPSGeolocationProvider()
- : mStarted(false)
- , mSupportsScheduling(false)
- , mObservingSettingsChange(false)
- , mSupportsSingleShot(false)
- , mSupportsTimeInjection(false)
- , mGpsInterface(nullptr)
-{
-}
-
-GonkGPSGeolocationProvider::~GonkGPSGeolocationProvider()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!mStarted, "Must call Shutdown before destruction");
-
- sSingleton = nullptr;
-}
-
-already_AddRefed<GonkGPSGeolocationProvider>
-GonkGPSGeolocationProvider::GetSingleton()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!sSingleton)
- sSingleton = new GonkGPSGeolocationProvider();
-
- RefPtr<GonkGPSGeolocationProvider> provider = sSingleton;
- return provider.forget();
-}
-
-const GpsInterface*
-GonkGPSGeolocationProvider::GetGPSInterface()
-{
- hw_module_t* module;
-
- if (hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module))
- return nullptr;
-
- hw_device_t* device;
- if (module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device))
- return nullptr;
-
- gps_device_t* gps_device = (gps_device_t *)device;
- const GpsInterface* result = gps_device->get_gps_interface(gps_device);
-
- if (result->size != sizeof(GpsInterface)) {
- return nullptr;
- }
- return result;
-}
-
-void
-GonkGPSGeolocationProvider::RequestSettingValue(const char* aKey)
-{
- MOZ_ASSERT(aKey);
- nsCOMPtr<nsISettingsService> ss = do_GetService("@mozilla.org/settingsService;1");
- if (!ss) {
- MOZ_ASSERT(ss);
- return;
- }
-
- nsCOMPtr<nsISettingsServiceLock> lock;
- nsresult rv = ss->CreateLock(nullptr, getter_AddRefs(lock));
- if (NS_FAILED(rv)) {
- ERR("error while createLock setting '%s': %d\n", aKey, uint32_t(rv));
- return;
- }
-
- rv = lock->Get(aKey, this);
- if (NS_FAILED(rv)) {
- ERR("error while get setting '%s': %d\n", aKey, uint32_t(rv));
- return;
- }
-}
-
-void
-GonkGPSGeolocationProvider::InjectLocation(double latitude,
- double longitude,
- float accuracy)
-{
- if (gDebug_isLoggingEnabled) {
- DBG("injecting location (%f, %f) accuracy: %f", latitude, longitude, accuracy);
- }
-
- MOZ_ASSERT(NS_IsMainThread());
- if (!mGpsInterface) {
- return;
- }
-
- mGpsInterface->inject_location(latitude, longitude, accuracy);
-}
-
-void
-GonkGPSGeolocationProvider::Init()
-{
- // Must not be main thread. Some GPS driver's first init takes very long.
- MOZ_ASSERT(!NS_IsMainThread());
-
- mGpsInterface = GetGPSInterface();
- if (!mGpsInterface) {
- return;
- }
-
- if (!mCallbacks.size) {
- mCallbacks.size = sizeof(GpsCallbacks);
- mCallbacks.location_cb = LocationCallback;
- mCallbacks.status_cb = StatusCallback;
- mCallbacks.sv_status_cb = SvStatusCallback;
- mCallbacks.nmea_cb = NmeaCallback;
- mCallbacks.set_capabilities_cb = SetCapabilitiesCallback;
- mCallbacks.acquire_wakelock_cb = AcquireWakelockCallback;
- mCallbacks.release_wakelock_cb = ReleaseWakelockCallback;
- mCallbacks.create_thread_cb = CreateThreadCallback;
-
-#ifdef GPS_CAPABILITY_ON_DEMAND_TIME
- mCallbacks.request_utc_time_cb = RequestUtcTimeCallback;
-#endif
-
- }
-
- if (mGpsInterface->init(&mCallbacks) != 0) {
- return;
- }
-
- NS_DispatchToMainThread(NewRunnableMethod(this, &GonkGPSGeolocationProvider::StartGPS));
-}
-
-void
-GonkGPSGeolocationProvider::StartGPS()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(mGpsInterface);
-
- int32_t update = Preferences::GetInt("geo.default.update", kDefaultPeriod);
-
- int positionMode = GPS_POSITION_MODE_STANDALONE;
-
- if (!mSupportsScheduling) {
- update = kDefaultPeriod;
- }
-
- mGpsInterface->set_position_mode(positionMode,
- GPS_POSITION_RECURRENCE_PERIODIC,
- update, 0, 0);
-#if FLUSH_AIDE_DATA
- // Delete cached data
- mGpsInterface->delete_aiding_data(GPS_DELETE_ALL);
-#endif
-
- mGpsInterface->start();
-}
-
-
-NS_IMPL_ISUPPORTS(GonkGPSGeolocationProvider::NetworkLocationUpdate,
- nsIGeolocationUpdate)
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::NetworkLocationUpdate::Update(nsIDOMGeoPosition *position)
-{
- RefPtr<GonkGPSGeolocationProvider> provider =
- GonkGPSGeolocationProvider::GetSingleton();
-
- nsCOMPtr<nsIDOMGeoPositionCoords> coords;
- position->GetCoords(getter_AddRefs(coords));
- if (!coords) {
- return NS_ERROR_FAILURE;
- }
-
- double lat, lon, acc;
- coords->GetLatitude(&lat);
- coords->GetLongitude(&lon);
- coords->GetAccuracy(&acc);
-
- double delta = -1.0;
-
- static double sLastMLSPosLat = 0;
- static double sLastMLSPosLon = 0;
-
- if (0 != sLastMLSPosLon || 0 != sLastMLSPosLat) {
- delta = CalculateDeltaInMeter(lat, lon, sLastMLSPosLat, sLastMLSPosLon);
- }
-
- sLastMLSPosLat = lat;
- sLastMLSPosLon = lon;
-
- // if the MLS coord change is smaller than this arbitrarily small value
- // assume the MLS coord is unchanged, and stick with the GPS location
- const double kMinMLSCoordChangeInMeters = 10;
-
- DOMTimeStamp time_ms = 0;
- if (provider->mLastGPSPosition) {
- provider->mLastGPSPosition->GetTimestamp(&time_ms);
- }
- const int64_t diff_ms = (PR_Now() / PR_USEC_PER_MSEC) - time_ms;
-
- // We want to distinguish between the GPS being inactive completely
- // and temporarily inactive. In the former case, we would use a low
- // accuracy network location; in the latter, we only want a network
- // location that appears to updating with movement.
-
- const bool isGPSFullyInactive = diff_ms > 1000 * 60 * 2; // two mins
- const bool isGPSTempInactive = diff_ms > 1000 * 10; // 10 secs
-
- if (provider->mLocationCallback) {
- if (isGPSFullyInactive ||
- (isGPSTempInactive && delta > kMinMLSCoordChangeInMeters))
- {
- if (gDebug_isLoggingEnabled) {
- DBG("Using MLS, GPS age:%fs, MLS Delta:%fm\n", diff_ms / 1000.0, delta);
- }
- provider->mLocationCallback->Update(position);
- } else if (provider->mLastGPSPosition) {
- if (gDebug_isLoggingEnabled) {
- DBG("Using old GPS age:%fs\n", diff_ms / 1000.0);
- }
-
- // This is a fallback case so that the GPS provider responds with its last
- // location rather than waiting for a more recent GPS or network location.
- // The service decides if the location is too old, not the provider.
- provider->mLocationCallback->Update(provider->mLastGPSPosition);
- }
- }
- provider->InjectLocation(lat, lon, acc);
- return NS_OK;
-}
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::NetworkLocationUpdate::NotifyError(uint16_t error)
-{
- return NS_OK;
-}
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Startup()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (mStarted) {
- return NS_OK;
- }
-
- RequestSettingValue(kSettingDebugEnabled);
- RequestSettingValue(kSettingDebugGpsIgnored);
-
- // Setup an observer to watch changes to the setting.
- nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
- if (observerService) {
- MOZ_ASSERT(!mObservingSettingsChange);
- nsresult rv = observerService->AddObserver(this, kMozSettingsChangedTopic, false);
- if (NS_FAILED(rv)) {
- NS_WARNING("geo: Gonk GPS AddObserver failed");
- } else {
- mObservingSettingsChange = true;
- }
- }
-
- if (!mInitThread) {
- nsresult rv = NS_NewThread(getter_AddRefs(mInitThread));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- mInitThread->Dispatch(NewRunnableMethod(this, &GonkGPSGeolocationProvider::Init),
- NS_DISPATCH_NORMAL);
-
- mNetworkLocationProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1");
- if (mNetworkLocationProvider) {
- nsresult rv = mNetworkLocationProvider->Startup();
- if (NS_SUCCEEDED(rv)) {
- RefPtr<NetworkLocationUpdate> update = new NetworkLocationUpdate();
- mNetworkLocationProvider->Watch(update);
- }
- }
-
- mStarted = true;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Watch(nsIGeolocationUpdate* aCallback)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mLocationCallback = aCallback;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Shutdown()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!mStarted) {
- return NS_OK;
- }
-
- mStarted = false;
- if (mNetworkLocationProvider) {
- mNetworkLocationProvider->Shutdown();
- mNetworkLocationProvider = nullptr;
- }
-
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- if (obs) {
- nsresult rv;
- rv = obs->RemoveObserver(this, kMozSettingsChangedTopic);
- if (NS_FAILED(rv)) {
- NS_WARNING("geo: Gonk GPS mozsettings RemoveObserver failed");
- } else {
- mObservingSettingsChange = false;
- }
- }
-
- mInitThread->Dispatch(NewRunnableMethod(this, &GonkGPSGeolocationProvider::ShutdownGPS),
- NS_DISPATCH_NORMAL);
-
- return NS_OK;
-}
-
-void
-GonkGPSGeolocationProvider::ShutdownGPS()
-{
- MOZ_ASSERT(!mStarted, "Should only be called after Shutdown");
-
- if (mGpsInterface) {
- mGpsInterface->stop();
- mGpsInterface->cleanup();
- }
-}
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::SetHighAccuracy(bool)
-{
- return NS_OK;
-}
-
-namespace {
-int
-ConvertToGpsNetworkType(int aNetworkInterfaceType)
-{
- switch (aNetworkInterfaceType) {
- case nsINetworkInfo::NETWORK_TYPE_WIFI:
- return AGPS_RIL_NETWORK_TYPE_WIFI;
- case nsINetworkInfo::NETWORK_TYPE_MOBILE:
- return AGPS_RIL_NETWORK_TYPE_MOBILE;
- case nsINetworkInfo::NETWORK_TYPE_MOBILE_MMS:
- return AGPS_RIL_NETWORK_TYPE_MOBILE_MMS;
- case nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL:
- return AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL;
- case nsINetworkInfo::NETWORK_TYPE_MOBILE_DUN:
- return AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN;
- default:
- NS_WARNING(nsPrintfCString("Unknown network type mapping %d",
- aNetworkInterfaceType).get());
- return -1;
- }
-}
-} // namespace
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!strcmp(aTopic, kMozSettingsChangedTopic)) {
- // Read changed setting value
- RootedDictionary<SettingChangeNotification> setting(RootingCx());
- if (!WrappedJSToDictionary(aSubject, setting)) {
- return NS_OK;
- }
-
- if (setting.mKey.EqualsASCII(kSettingDebugGpsIgnored)) {
- LOG("received mozsettings-changed: ignoring\n");
- gDebug_isGPSLocationIgnored =
- setting.mValue.isBoolean() ? setting.mValue.toBoolean() : false;
- if (gDebug_isLoggingEnabled) {
- DBG("GPS ignored %d\n", gDebug_isGPSLocationIgnored);
- }
- return NS_OK;
- } else if (setting.mKey.EqualsASCII(kSettingDebugEnabled)) {
- LOG("received mozsettings-changed: logging\n");
- gDebug_isLoggingEnabled =
- setting.mValue.isBoolean() ? setting.mValue.toBoolean() : false;
- return NS_OK;
- }
- }
-
- return NS_OK;
-}
-
-/** nsISettingsServiceCallback **/
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::Handle(const nsAString& aName,
- JS::Handle<JS::Value> aResult)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GonkGPSGeolocationProvider::HandleError(const nsAString& aErrorMessage)
-{
- return NS_OK;
-}
diff --git a/dom/system/gonk/GonkGPSGeolocationProvider.h b/dom/system/gonk/GonkGPSGeolocationProvider.h
deleted file mode 100644
index 514398edf..000000000
--- a/dom/system/gonk/GonkGPSGeolocationProvider.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 GonkGPSGeolocationProvider_h
-#define GonkGPSGeolocationProvider_h
-
-#include <hardware/gps.h> // for GpsInterface
-#include "nsCOMPtr.h"
-#include "nsIGeolocationProvider.h"
-#include "nsIObserver.h"
-#include "nsIDOMGeoPosition.h"
-#include "nsISettingsService.h"
-
-class nsIThread;
-
-#define GONK_GPS_GEOLOCATION_PROVIDER_CID \
-{ 0x48525ec5, 0x5a7f, 0x490a, { 0x92, 0x77, 0xba, 0x66, 0xe0, 0xd2, 0x2c, 0x8b } }
-
-#define GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID \
-"@mozilla.org/gonk-gps-geolocation-provider;1"
-
-class GonkGPSGeolocationProvider : public nsIGeolocationProvider
- , public nsIObserver
- , public nsISettingsServiceCallback
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIGEOLOCATIONPROVIDER
- NS_DECL_NSIOBSERVER
- NS_DECL_NSISETTINGSSERVICECALLBACK
-
- static already_AddRefed<GonkGPSGeolocationProvider> GetSingleton();
-
-private:
-
- /* Client should use GetSingleton() to get the provider instance. */
- GonkGPSGeolocationProvider();
- GonkGPSGeolocationProvider(const GonkGPSGeolocationProvider &);
- GonkGPSGeolocationProvider & operator = (const GonkGPSGeolocationProvider &);
- virtual ~GonkGPSGeolocationProvider();
-
- static void LocationCallback(GpsLocation* location);
- static void StatusCallback(GpsStatus* status);
- static void SvStatusCallback(GpsSvStatus* sv_info);
- static void NmeaCallback(GpsUtcTime timestamp, const char* nmea, int length);
- static void SetCapabilitiesCallback(uint32_t capabilities);
- static void AcquireWakelockCallback();
- static void ReleaseWakelockCallback();
- static pthread_t CreateThreadCallback(const char* name, void (*start)(void*), void* arg);
- static void RequestUtcTimeCallback();
-
- static GpsCallbacks mCallbacks;
-
- void Init();
- void StartGPS();
- void ShutdownGPS();
- void InjectLocation(double latitude, double longitude, float accuracy);
- void RequestSettingValue(const char* aKey);
-
- const GpsInterface* GetGPSInterface();
-
- static GonkGPSGeolocationProvider* sSingleton;
-
- bool mStarted;
-
- bool mSupportsScheduling;
- bool mObservingSettingsChange;
- bool mSupportsSingleShot;
- bool mSupportsTimeInjection;
-
- const GpsInterface* mGpsInterface;
- nsCOMPtr<nsIGeolocationUpdate> mLocationCallback;
- nsCOMPtr<nsIThread> mInitThread;
- nsCOMPtr<nsIGeolocationProvider> mNetworkLocationProvider;
- nsCOMPtr<nsIDOMGeoPosition> mLastGPSPosition;
-
- class NetworkLocationUpdate : public nsIGeolocationUpdate
- {
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIGEOLOCATIONUPDATE
-
- NetworkLocationUpdate() {}
-
- private:
- virtual ~NetworkLocationUpdate() {}
- };
-};
-
-#endif /* GonkGPSGeolocationProvider_h */
diff --git a/dom/system/gonk/MozMtpCommon.h b/dom/system/gonk/MozMtpCommon.h
deleted file mode 100644
index 81c0a3a74..000000000
--- a/dom/system/gonk/MozMtpCommon.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozmtpcommon_h__
-#define mozilla_system_mozmtpcommon_h__
-
-#include "mozilla/Types.h"
-#include <android/log.h>
-
-#define USE_DEBUG 0
-
-#if USE_DEBUG
-#define MTP_DBG(msg, ...) \
- __android_log_print(ANDROID_LOG_DEBUG, "MozMtp", \
- "%s: " msg, __FUNCTION__, ##__VA_ARGS__)
-#else
-#define MTP_DBG(msg, ...)
-#endif
-
-#define MTP_LOG(msg, ...) \
- __android_log_print(ANDROID_LOG_INFO, "MozMtp", \
- "%s: " msg, __FUNCTION__, ##__VA_ARGS__)
-
-#define MTP_ERR(msg, ...) \
- __android_log_print(ANDROID_LOG_ERROR, "MozMtp", \
- "%s: " msg, __FUNCTION__, ##__VA_ARGS__)
-
-#define BEGIN_MTP_NAMESPACE \
- namespace mozilla { namespace system { namespace mtp {
-#define END_MTP_NAMESPACE \
- } /* namespace mtp */ } /* namespace system */ } /* namespace mozilla */
-#define USING_MTP_NAMESPACE \
- using namespace mozilla::system::mtp;
-
-namespace android {
- class MOZ_EXPORT MtpServer;
- class MOZ_EXPORT MtpStorage;
- class MOZ_EXPORT MtpStringBuffer;
- class MOZ_EXPORT MtpDatabase;
- class MOZ_EXPORT MtpDataPacket;
- class MOZ_EXPORT MtpProperty;
-}
-
-#include <mtp.h>
-#include <MtpDatabase.h>
-#include <MtpObjectInfo.h>
-#include <MtpProperty.h>
-#include <MtpServer.h>
-#include <MtpStorage.h>
-#include <MtpStringBuffer.h>
-#include <MtpTypes.h>
-
-#endif // mozilla_system_mtpcommon_h__
diff --git a/dom/system/gonk/MozMtpDatabase.cpp b/dom/system/gonk/MozMtpDatabase.cpp
deleted file mode 100644
index 29fe23e8d..000000000
--- a/dom/system/gonk/MozMtpDatabase.cpp
+++ /dev/null
@@ -1,1542 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MozMtpDatabase.h"
-#include "MozMtpServer.h"
-
-#include "base/message_loop.h"
-#include "DeviceStorage.h"
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/AutoRestore.h"
-#include "mozilla/Scoped.h"
-#include "mozilla/Services.h"
-#include "nsIFile.h"
-#include "nsIObserverService.h"
-#include "nsPrintfCString.h"
-#include "nsString.h"
-#include "prio.h"
-
-#include <dirent.h>
-#include <libgen.h>
-#include <utime.h>
-#include <sys/stat.h>
-
-using namespace android;
-using namespace mozilla;
-
-namespace mozilla {
-MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCloseDir, PRDir, PR_CloseDir)
-}
-
-BEGIN_MTP_NAMESPACE
-
-static const char* kMtpWatcherNotify = "mtp-watcher-notify";
-
-#if 0
-// Some debug code for figuring out deadlocks, if you happen to run into
-// that scenario
-
-class DebugMutexAutoLock: public MutexAutoLock
-{
-public:
- DebugMutexAutoLock(mozilla::Mutex& aMutex)
- : MutexAutoLock(aMutex)
- {
- MTP_LOG("Mutex acquired");
- }
-
- ~DebugMutexAutoLock()
- {
- MTP_LOG("Releasing mutex");
- }
-};
-#define MutexAutoLock MTP_LOG("About to enter mutex"); DebugMutexAutoLock
-
-#endif
-
-static const char *
-ObjectPropertyAsStr(MtpObjectProperty aProperty)
-{
- switch (aProperty) {
- case MTP_PROPERTY_STORAGE_ID: return "MTP_PROPERTY_STORAGE_ID";
- case MTP_PROPERTY_OBJECT_FORMAT: return "MTP_PROPERTY_OBJECT_FORMAT";
- case MTP_PROPERTY_PROTECTION_STATUS: return "MTP_PROPERTY_PROTECTION_STATUS";
- case MTP_PROPERTY_OBJECT_SIZE: return "MTP_PROPERTY_OBJECT_SIZE";
- case MTP_PROPERTY_OBJECT_FILE_NAME: return "MTP_PROPERTY_OBJECT_FILE_NAME";
- case MTP_PROPERTY_DATE_CREATED: return "MTP_PROPERTY_DATE_CREATED";
- case MTP_PROPERTY_DATE_MODIFIED: return "MTP_PROPERTY_DATE_MODIFIED";
- case MTP_PROPERTY_PARENT_OBJECT: return "MTP_PROPERTY_PARENT_OBJECT";
- case MTP_PROPERTY_PERSISTENT_UID: return "MTP_PROPERTY_PERSISTENT_UID";
- case MTP_PROPERTY_NAME: return "MTP_PROPERTY_NAME";
- case MTP_PROPERTY_DATE_ADDED: return "MTP_PROPERTY_DATE_ADDED";
- case MTP_PROPERTY_WIDTH: return "MTP_PROPERTY_WIDTH";
- case MTP_PROPERTY_HEIGHT: return "MTP_PROPERTY_HEIGHT";
- case MTP_PROPERTY_IMAGE_BIT_DEPTH: return "MTP_PROPERTY_IMAGE_BIT_DEPTH";
- case MTP_PROPERTY_DISPLAY_NAME: return "MTP_PROPERTY_DISPLAY_NAME";
- }
- return "MTP_PROPERTY_???";
-}
-
-static char*
-FormatDate(time_t aTime, char *aDateStr, size_t aDateStrSize)
-{
- struct tm tm;
- localtime_r(&aTime, &tm);
- MTP_LOG("(%ld) tm_zone = %s off = %ld", aTime, tm.tm_zone, tm.tm_gmtoff);
- strftime(aDateStr, aDateStrSize, "%Y%m%dT%H%M%S", &tm);
- return aDateStr;
-}
-
-MozMtpDatabase::MozMtpDatabase()
- : mMutex("MozMtpDatabase::mMutex"),
- mDb(mMutex),
- mStorage(mMutex),
- mBeginSendObjectCalled(false)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // We use the index into the array as the handle. Since zero isn't a valid
- // index, we stick a dummy entry there.
-
- RefPtr<DbEntry> dummy;
-
- MutexAutoLock lock(mMutex);
- mDb.AppendElement(dummy);
-}
-
-//virtual
-MozMtpDatabase::~MozMtpDatabase()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-}
-
-void
-MozMtpDatabase::AddEntry(DbEntry *entry)
-{
- MutexAutoLock lock(mMutex);
-
- entry->mHandle = GetNextHandle();
- MOZ_ASSERT(mDb.Length() == entry->mHandle);
- mDb.AppendElement(entry);
-
- MTP_DBG("Handle: 0x%08x Parent: 0x%08x Path:'%s'",
- entry->mHandle, entry->mParent, entry->mPath.get());
-}
-
-void
-MozMtpDatabase::AddEntryAndNotify(DbEntry* entry, RefCountedMtpServer* aMtpServer)
-{
- AddEntry(entry);
- aMtpServer->sendObjectAdded(entry->mHandle);
-}
-
-void
-MozMtpDatabase::DumpEntries(const char* aLabel)
-{
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- MTP_LOG("%s: numEntries = %d", aLabel, numEntries);
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry) {
- MTP_LOG("%s: mDb[%d]: mHandle: 0x%08x mParent: 0x%08x StorageID: 0x%08x path: '%s'",
- aLabel, entryIndex, entry->mHandle, entry->mParent, entry->mStorageID, entry->mPath.get());
- } else {
- MTP_LOG("%s: mDb[%2d]: entry is NULL", aLabel, entryIndex);
- }
- }
-}
-
-MtpObjectHandle
-MozMtpDatabase::FindEntryByPath(const nsACString& aPath)
-{
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry && entry->mPath.Equals(aPath)) {
- return entryIndex;
- }
- }
- return 0;
-}
-
-already_AddRefed<MozMtpDatabase::DbEntry>
-MozMtpDatabase::GetEntry(MtpObjectHandle aHandle)
-{
- MutexAutoLock lock(mMutex);
-
- RefPtr<DbEntry> entry;
-
- if (aHandle > 0 && aHandle < mDb.Length()) {
- entry = mDb[aHandle];
- }
- return entry.forget();
-}
-
-void
-MozMtpDatabase::RemoveEntry(MtpObjectHandle aHandle)
-{
- MutexAutoLock lock(mMutex);
- if (!IsValidHandle(aHandle)) {
- return;
- }
-
- RefPtr<DbEntry> removedEntry = mDb[aHandle];
- mDb[aHandle] = nullptr;
- MTP_DBG("0x%08x removed", aHandle);
- // if the entry is not a folder, just return.
- if (removedEntry->mObjectFormat != MTP_FORMAT_ASSOCIATION) {
- return;
- }
-
- // Find out and remove the children of aHandle.
- // Since the index for a directory will always be less than the index of any of its children,
- // we can remove the entire subtree in one pass.
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = aHandle+1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry && IsValidHandle(entry->mParent) && !mDb[entry->mParent]) {
- mDb[entryIndex] = nullptr;
- MTP_DBG("0x%08x removed", aHandle);
- }
- }
-}
-
-void
-MozMtpDatabase::RemoveEntryAndNotify(MtpObjectHandle aHandle, RefCountedMtpServer* aMtpServer)
-{
- RemoveEntry(aHandle);
- aMtpServer->sendObjectRemoved(aHandle);
-}
-
-void
-MozMtpDatabase::UpdateEntryAndNotify(MtpObjectHandle aHandle, DeviceStorageFile* aFile, RefCountedMtpServer* aMtpServer)
-{
- UpdateEntry(aHandle, aFile);
- aMtpServer->sendObjectAdded(aHandle);
-}
-
-
-void
-MozMtpDatabase::UpdateEntry(MtpObjectHandle aHandle, DeviceStorageFile* aFile)
-{
- MutexAutoLock lock(mMutex);
-
- RefPtr<DbEntry> entry = mDb[aHandle];
-
- int64_t fileSize = 0;
- aFile->mFile->GetFileSize(&fileSize);
- entry->mObjectSize = fileSize;
-
- PRTime dateModifiedMsecs;
- // GetLastModifiedTime returns msecs
- aFile->mFile->GetLastModifiedTime(&dateModifiedMsecs);
- entry->mDateModified = dateModifiedMsecs / PR_MSEC_PER_SEC;
- entry->mDateCreated = entry->mDateModified;
- entry->mDateAdded = entry->mDateModified;
-
- #if USE_DEBUG
- char dateStr[20];
- MTP_DBG("UpdateEntry (0x%08x file %s) modified (%ld) %s",
- entry->mHandle, entry->mPath.get(),
- entry->mDateModified,
- FormatDate(entry->mDateModified, dateStr, sizeof(dateStr)));
- #endif
-}
-
-
-class MtpWatcherNotifyRunnable final : public Runnable
-{
-public:
- MtpWatcherNotifyRunnable(nsACString& aStorageName,
- nsACString& aPath,
- const char* aEventType)
- : mStorageName(aStorageName),
- mPath(aPath),
- mEventType(aEventType)
- {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- NS_ConvertUTF8toUTF16 storageName(mStorageName);
- NS_ConvertUTF8toUTF16 path(mPath);
-
- RefPtr<DeviceStorageFile> dsf(
- new DeviceStorageFile(NS_LITERAL_STRING(DEVICESTORAGE_SDCARD),
- storageName, path));
- NS_ConvertUTF8toUTF16 eventType(mEventType);
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-
- MTP_DBG("Sending mtp-watcher-notify %s %s %s",
- mEventType.get(), mStorageName.get(), mPath.get());
-
- obs->NotifyObservers(dsf, kMtpWatcherNotify, eventType.get());
- return NS_OK;
- }
-
-private:
- nsCString mStorageName;
- nsCString mPath;
- nsCString mEventType;
-};
-
-// MtpWatcherNotify is used to tell DeviceStorage when a file was changed
-// through the MTP server.
-void
-MozMtpDatabase::MtpWatcherNotify(DbEntry* aEntry, const char* aEventType)
-{
- // This function gets called from the MozMtpServer::mServerThread
- MOZ_ASSERT(!NS_IsMainThread());
-
- MTP_DBG("file: %s %s", aEntry->mPath.get(), aEventType);
-
- // Tell interested parties that a file was created, deleted, or modified.
-
- RefPtr<StorageEntry> storageEntry;
- {
- MutexAutoLock lock(mMutex);
-
- // FindStorage and the mStorage[] access both need to have the mutex held.
- StorageArray::index_type storageIndex = FindStorage(aEntry->mStorageID);
- if (storageIndex == StorageArray::NoIndex) {
- return;
- }
- storageEntry = mStorage[storageIndex];
- }
-
- // DeviceStorage wants the storageName and the path relative to the root
- // of the storage area, so we need to strip off the storagePath
-
- nsAutoCString relPath(Substring(aEntry->mPath,
- storageEntry->mStoragePath.Length() + 1));
-
- RefPtr<MtpWatcherNotifyRunnable> r =
- new MtpWatcherNotifyRunnable(storageEntry->mStorageName, relPath, aEventType);
- DebugOnly<nsresult> rv = NS_DispatchToMainThread(r);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-}
-
-// Called to tell the MTP server about new or deleted files,
-void
-MozMtpDatabase::MtpWatcherUpdate(RefCountedMtpServer* aMtpServer,
- DeviceStorageFile* aFile,
- const nsACString& aEventType)
-{
- // Runs on the MtpWatcherUpdate->mIOThread (see MozMtpServer.cpp)
- MOZ_ASSERT(!NS_IsMainThread());
-
- // Figure out which storage the belongs to (if any)
-
- if (!aFile->mFile) {
- // No path - don't bother looking.
- return;
- }
- nsString wideFilePath;
- aFile->mFile->GetPath(wideFilePath);
- NS_ConvertUTF16toUTF8 filePath(wideFilePath);
-
- nsCString evtType(aEventType);
- MTP_LOG("file %s %s", filePath.get(), evtType.get());
-
- MtpObjectHandle entryHandle = FindEntryByPath(filePath);
-
- if (aEventType.EqualsLiteral("modified")) {
- // To update the file information to the newest, we remove the entry for
- // the existing file, then re-add the entry for the file.
-
- if (entryHandle != 0) {
- // Update entry for the file and tell MTP.
- MTP_LOG("About to update handle 0x%08x file %s", entryHandle, filePath.get());
- UpdateEntryAndNotify(entryHandle, aFile, aMtpServer);
- }
- else {
- // Create entry for the file and tell MTP.
- CreateEntryForFileAndNotify(filePath, aFile, aMtpServer);
- }
- return;
- }
-
- if (aEventType.EqualsLiteral("deleted")) {
- if (entryHandle == 0) {
- // The entry has already been removed. We can't tell MTP.
- return;
- }
- MTP_LOG("About to call sendObjectRemoved Handle 0x%08x file %s", entryHandle, filePath.get());
- RemoveEntryAndNotify(entryHandle, aMtpServer);
- return;
- }
-}
-
-nsCString
-MozMtpDatabase::BaseName(const nsCString& path)
-{
- nsCOMPtr<nsIFile> file;
- NS_NewNativeLocalFile(path, false, getter_AddRefs(file));
- if (file) {
- nsCString leafName;
- file->GetNativeLeafName(leafName);
- return leafName;
- }
- return path;
-}
-
-static nsCString
-GetPathWithoutFileName(const nsCString& aFullPath)
-{
- nsCString path;
-
- int32_t offset = aFullPath.RFindChar('/');
- if (offset != kNotFound) {
- // The trailing slash will be as part of 'path'
- path = StringHead(aFullPath, offset + 1);
- }
-
- MTP_LOG("returning '%s'", path.get());
-
- return path;
-}
-
-void
-MozMtpDatabase::CreateEntryForFileAndNotify(const nsACString& aPath,
- DeviceStorageFile* aFile,
- RefCountedMtpServer* aMtpServer)
-{
- // Find the StorageID that this path corresponds to.
-
- nsCString remainder;
- MtpStorageID storageID = FindStorageIDFor(aPath, remainder);
- if (storageID == 0) {
- // The path in question isn't for a storage area we're monitoring.
- nsCString path(aPath);
- return;
- }
-
- bool exists = false;
- aFile->mFile->Exists(&exists);
- if (!exists) {
- // File doesn't exist, no sense telling MTP about it.
- // This could happen if Device Storage created and deleted a file right
- // away. Since the notifications wind up being async, the file might
- // not exist any more.
- return;
- }
-
- // Now walk the remaining directories, finding or creating as required.
-
- MtpObjectHandle parent = MTP_PARENT_ROOT;
- bool doFind = true;
- int32_t offset = aPath.Length() - remainder.Length();
- int32_t slash;
-
- do {
- nsDependentCSubstring component;
- slash = aPath.FindChar('/', offset);
- if (slash == kNotFound) {
- component.Rebind(aPath, 0, aPath.Length());
- } else {
- component.Rebind(aPath, 0 , slash);
- }
- if (doFind) {
- MtpObjectHandle entryHandle = FindEntryByPath(component);
- if (entryHandle != 0) {
- // We found an entry.
- parent = entryHandle;
- offset = slash + 1 ;
- continue;
- }
- }
-
- // We've got a directory component that doesn't exist. This means that all
- // further subdirectories won't exist either, so we can skip searching
- // for them.
- doFind = false;
-
- // This directory and the file don't exist, create them
-
- RefPtr<DbEntry> entry = new DbEntry;
-
- entry->mStorageID = storageID;
- entry->mObjectName = Substring(aPath, offset, slash - offset);
- entry->mParent = parent;
- entry->mDisplayName = entry->mObjectName;
- entry->mPath = component;
-
- if (slash == kNotFound) {
- // No slash - this is the file component
- entry->mObjectFormat = MTP_FORMAT_DEFINED;
-
- int64_t fileSize = 0;
- aFile->mFile->GetFileSize(&fileSize);
- entry->mObjectSize = fileSize;
-
- // Note: Even though PRTime records usec, GetLastModifiedTime returns
- // msecs.
- PRTime dateModifiedMsecs;
- aFile->mFile->GetLastModifiedTime(&dateModifiedMsecs);
- entry->mDateModified = dateModifiedMsecs / PR_MSEC_PER_SEC;
- } else {
- // Found a slash, this makes this a directory component
- entry->mObjectFormat = MTP_FORMAT_ASSOCIATION;
- entry->mObjectSize = 0;
- time(&entry->mDateModified);
- }
- entry->mDateCreated = entry->mDateModified;
- entry->mDateAdded = entry->mDateModified;
-
- AddEntryAndNotify(entry, aMtpServer);
- MTP_LOG("About to call sendObjectAdded Handle 0x%08x file %s", entry->mHandle, entry->mPath.get());
-
- parent = entry->mHandle;
- offset = slash + 1;
- } while (slash != kNotFound);
-
- return;
-}
-
-void
-MozMtpDatabase::AddDirectory(MtpStorageID aStorageID,
- const char* aPath,
- MtpObjectHandle aParent)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- ScopedCloseDir dir;
-
- if (!(dir = PR_OpenDir(aPath))) {
- MTP_ERR("Unable to open directory '%s'", aPath);
- return;
- }
-
- PRDirEntry* dirEntry;
- while ((dirEntry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
- nsPrintfCString filename("%s/%s", aPath, dirEntry->name);
- PRFileInfo64 fileInfo;
- if (PR_GetFileInfo64(filename.get(), &fileInfo) != PR_SUCCESS) {
- MTP_ERR("Unable to retrieve file information for '%s'", filename.get());
- continue;
- }
-
- RefPtr<DbEntry> entry = new DbEntry;
-
- entry->mStorageID = aStorageID;
- entry->mParent = aParent;
- entry->mObjectName = dirEntry->name;
- entry->mDisplayName = dirEntry->name;
- entry->mPath = filename;
-
- // PR_GetFileInfo64 returns timestamps in usecs
- entry->mDateModified = fileInfo.modifyTime / PR_USEC_PER_SEC;
- entry->mDateCreated = fileInfo.creationTime / PR_USEC_PER_SEC;
- time(&entry->mDateAdded);
-
- if (fileInfo.type == PR_FILE_FILE) {
- entry->mObjectFormat = MTP_FORMAT_DEFINED;
- //TODO: Check how 64-bit filesize are dealt with
- entry->mObjectSize = fileInfo.size;
- AddEntry(entry);
- } else if (fileInfo.type == PR_FILE_DIRECTORY) {
- entry->mObjectFormat = MTP_FORMAT_ASSOCIATION;
- entry->mObjectSize = 0;
- AddEntry(entry);
- AddDirectory(aStorageID, filename.get(), entry->mHandle);
- }
- }
-}
-
-MozMtpDatabase::StorageArray::index_type
-MozMtpDatabase::FindStorage(MtpStorageID aStorageID)
-{
- // Currently, this routine is called from MozMtpDatabase::RemoveStorage
- // and MozMtpDatabase::MtpWatcherNotify, which both hold mMutex.
-
- StorageArray::size_type numStorages = mStorage.Length();
- StorageArray::index_type storageIndex;
-
- for (storageIndex = 0; storageIndex < numStorages; storageIndex++) {
- RefPtr<StorageEntry> storage = mStorage[storageIndex];
- if (storage->mStorageID == aStorageID) {
- return storageIndex;
- }
- }
- return StorageArray::NoIndex;
-}
-
-// Find the storage ID for the storage area that contains aPath.
-MtpStorageID
-MozMtpDatabase::FindStorageIDFor(const nsACString& aPath, nsCSubstring& aRemainder)
-{
- MutexAutoLock lock(mMutex);
-
- aRemainder.Truncate();
-
- StorageArray::size_type numStorages = mStorage.Length();
- StorageArray::index_type storageIndex;
-
- for (storageIndex = 0; storageIndex < numStorages; storageIndex++) {
- RefPtr<StorageEntry> storage = mStorage[storageIndex];
- if (StringHead(aPath, storage->mStoragePath.Length()).Equals(storage->mStoragePath)) {
- if (aPath.Length() == storage->mStoragePath.Length()) {
- return storage->mStorageID;
- }
- if (aPath[storage->mStoragePath.Length()] == '/') {
- aRemainder = Substring(aPath, storage->mStoragePath.Length() + 1);
- return storage->mStorageID;
- }
- }
- }
- return 0;
-}
-
-void
-MozMtpDatabase::AddStorage(MtpStorageID aStorageID,
- const char* aPath,
- const char* aName)
-{
- // This is called on the IOThread from MozMtpStorage::StorageAvailable
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- MTP_DBG("StorageID: 0x%08x aPath: '%s' aName: '%s'",
- aStorageID, aPath, aName);
-
- PRFileInfo fileInfo;
- if (PR_GetFileInfo(aPath, &fileInfo) != PR_SUCCESS) {
- MTP_ERR("'%s' doesn't exist", aPath);
- return;
- }
- if (fileInfo.type != PR_FILE_DIRECTORY) {
- MTP_ERR("'%s' isn't a directory", aPath);
- return;
- }
-
- RefPtr<StorageEntry> storageEntry = new StorageEntry;
-
- storageEntry->mStorageID = aStorageID;
- storageEntry->mStoragePath = aPath;
- storageEntry->mStorageName = aName;
- {
- MutexAutoLock lock(mMutex);
- mStorage.AppendElement(storageEntry);
- }
-
- AddDirectory(aStorageID, aPath, MTP_PARENT_ROOT);
- {
- MutexAutoLock lock(mMutex);
- MTP_LOG("added %d items from tree '%s'", mDb.Length(), aPath);
- }
-}
-
-void
-MozMtpDatabase::RemoveStorage(MtpStorageID aStorageID)
-{
- MutexAutoLock lock(mMutex);
-
- // This is called on the IOThread from MozMtpStorage::StorageAvailable
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry && entry->mStorageID == aStorageID) {
- mDb[entryIndex] = nullptr;
- }
- }
- StorageArray::index_type storageIndex = FindStorage(aStorageID);
- if (storageIndex != StorageArray::NoIndex) {
- mStorage.RemoveElementAt(storageIndex);
- }
-}
-
-// called from SendObjectInfo to reserve a database entry for the incoming file
-//virtual
-MtpObjectHandle
-MozMtpDatabase::beginSendObject(const char* aPath,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent,
- MtpStorageID aStorageID,
- uint64_t aSize,
- time_t aModified)
-{
- // If MtpServer::doSendObjectInfo receives a request with a parent of
- // MTP_PARENT_ROOT, then it fills in aPath with the fully qualified path
- // and then passes in a parent of zero.
-
- if (aParent == 0) {
- // Undo what doSendObjectInfo did
- aParent = MTP_PARENT_ROOT;
- }
-
- RefPtr<DbEntry> entry = new DbEntry;
-
- entry->mStorageID = aStorageID;
- entry->mParent = aParent;
- entry->mPath = aPath;
- entry->mObjectName = BaseName(entry->mPath);
- entry->mDisplayName = entry->mObjectName;
- entry->mObjectFormat = aFormat;
- entry->mObjectSize = aSize;
-
- if (aModified != 0) {
- // Currently, due to the way that parseDateTime is coded in
- // frameworks/av/media/mtp/MtpUtils.cpp, aModified winds up being the number
- // of seconds from the epoch in local time, rather than UTC time. So we
- // need to convert it back to being relative to UTC since that's what linux
- // expects time_t to contain.
- //
- // In more concrete testable terms, if the host parses 2015-08-02 02:22:00
- // as a local time in the Pacific timezone, aModified will come to us as
- // 1438482120.
- //
- // What we want is what mktime would pass us with the same date. Using python
- // (because its simple) with the current timezone set to be America/Vancouver:
- //
- // >>> import time
- // >>> time.mktime((2015, 8, 2, 2, 22, 0, 0, 0, -1))
- // 1438507320.0
- // >>> time.localtime(1438507320)
- // time.struct_time(tm_year=2015, tm_mon=8, tm_mday=2, tm_hour=2, tm_min=22, tm_sec=0, tm_wday=6, tm_yday=214, tm_isdst=1)
- //
- // Currently, when a file has a modification time of 2015-08-22 02:22:00 PDT
- // then aModified will come in as 1438482120 which corresponds to
- // 2015-08-22 02:22:00 UTC
-
- struct tm tm;
- if (gmtime_r(&aModified, &tm) != NULL) {
- // GMT always comes back with tm_isdst = 0, so we set it to -1 in order
- // to have mktime figure out dst based on the date.
- tm.tm_isdst = -1;
- aModified = mktime(&tm);
- if (aModified == (time_t)-1) {
- aModified = 0;
- }
- } else {
- aModified = 0;
- }
- }
- if (aModified == 0) {
- // The ubuntu host doesn't pass in the modified/created times in the
- // SENDOBJECT packet, so aModified winds up being zero. About the best
- // we can do with that is to use the current time.
- time(&aModified);
- }
-
- // And just an FYI for anybody else looking at timestamps. Under OSX you
- // need to use the Android File Transfer program to copy files into the
- // phone. That utility passes in both date modified and date created
- // timestamps, but they're both equal to the time that the file was copied
- // and not the times that are associated with the files.
-
- // Now we have aModified in a traditional time_t format, which is the number
- // of seconds from the UTC epoch.
-
- entry->mDateModified = aModified;
- entry->mDateCreated = entry->mDateModified;
- entry->mDateAdded = entry->mDateModified;
-
- AddEntry(entry);
-
- #if USE_DEBUG
- char dateStr[20];
- MTP_LOG("Handle: 0x%08x Parent: 0x%08x Path: '%s' aModified %ld %s",
- entry->mHandle, aParent, aPath, aModified,
- FormatDate(entry->mDateModified, dateStr, sizeof(dateStr)));
- #endif
-
- mBeginSendObjectCalled = true;
- return entry->mHandle;
-}
-
-// called to report success or failure of the SendObject file transfer
-// success should signal a notification of the new object's creation,
-// failure should remove the database entry created in beginSendObject
-
-//virtual
-void
-MozMtpDatabase::endSendObject(const char* aPath,
- MtpObjectHandle aHandle,
- MtpObjectFormat aFormat,
- bool aSucceeded)
-{
- MTP_LOG("Handle: 0x%08x Path: '%s'", aHandle, aPath);
-
- if (aSucceeded) {
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (entry) {
- // The android MTP server only copies the data in, it doesn't set the
- // modified timestamp, so we do that here.
-
- struct utimbuf new_times;
- struct stat sb;
-
- char dateStr[20];
- MTP_LOG("Path: '%s' setting modified time to (%ld) %s",
- entry->mPath.get(), entry->mDateModified,
- FormatDate(entry->mDateModified, dateStr, sizeof(dateStr)));
-
- stat(entry->mPath.get(), &sb);
- new_times.actime = sb.st_atime; // Preserve atime
- new_times.modtime = entry->mDateModified;
- utime(entry->mPath.get(), &new_times);
-
- MtpWatcherNotify(entry, "modified");
- }
- } else {
- RemoveEntry(aHandle);
- }
- mBeginSendObjectCalled = false;
-}
-
-//virtual
-MtpObjectHandleList*
-MozMtpDatabase::getObjectList(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent)
-{
- MTP_LOG("StorageID: 0x%08x Format: 0x%04x Parent: 0x%08x",
- aStorageID, aFormat, aParent);
-
- // aStorageID == 0xFFFFFFFF for all storage
- // aFormat == 0 for all formats
- // aParent == 0xFFFFFFFF for objects with no parents
- // aParent == 0 for all objects
-
- //TODO: Optimize
-
- UniquePtr<MtpObjectHandleList> list(new MtpObjectHandleList());
-
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry &&
- (aStorageID == 0xFFFFFFFF || entry->mStorageID == aStorageID) &&
- (aFormat == 0 || entry->mObjectFormat == aFormat) &&
- (aParent == 0 || entry->mParent == aParent)) {
- list->push(entry->mHandle);
- }
- }
- MTP_LOG(" returning %d items", list->size());
- return list.release();
-}
-
-//virtual
-int
-MozMtpDatabase::getNumObjects(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent)
-{
- MTP_LOG("");
-
- // aStorageID == 0xFFFFFFFF for all storage
- // aFormat == 0 for all formats
- // aParent == 0xFFFFFFFF for objects with no parents
- // aParent == 0 for all objects
-
- int count = 0;
-
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIndex;
- for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
- RefPtr<DbEntry> entry = mDb[entryIndex];
- if (entry &&
- (aStorageID == 0xFFFFFFFF || entry->mStorageID == aStorageID) &&
- (aFormat == 0 || entry->mObjectFormat == aFormat) &&
- (aParent == 0 || entry->mParent == aParent)) {
- count++;
- }
- }
-
- MTP_LOG(" returning %d items", count);
- return count;
-}
-
-//virtual
-MtpObjectFormatList*
-MozMtpDatabase::getSupportedPlaybackFormats()
-{
- static const uint16_t init_data[] = {MTP_FORMAT_UNDEFINED, MTP_FORMAT_ASSOCIATION,
- MTP_FORMAT_TEXT, MTP_FORMAT_HTML, MTP_FORMAT_WAV,
- MTP_FORMAT_MP3, MTP_FORMAT_MPEG, MTP_FORMAT_EXIF_JPEG,
- MTP_FORMAT_TIFF_EP, MTP_FORMAT_BMP, MTP_FORMAT_GIF,
- MTP_FORMAT_PNG, MTP_FORMAT_TIFF, MTP_FORMAT_WMA,
- MTP_FORMAT_OGG, MTP_FORMAT_AAC, MTP_FORMAT_MP4_CONTAINER,
- MTP_FORMAT_MP2, MTP_FORMAT_3GP_CONTAINER, MTP_FORMAT_FLAC};
-
- MtpObjectFormatList *list = new MtpObjectFormatList();
- list->appendArray(init_data, MOZ_ARRAY_LENGTH(init_data));
-
- MTP_LOG("returning Supported Playback Formats");
- return list;
-}
-
-//virtual
-MtpObjectFormatList*
-MozMtpDatabase::getSupportedCaptureFormats()
-{
- static const uint16_t init_data[] = {MTP_FORMAT_ASSOCIATION, MTP_FORMAT_PNG};
-
- MtpObjectFormatList *list = new MtpObjectFormatList();
- list->appendArray(init_data, MOZ_ARRAY_LENGTH(init_data));
- MTP_LOG("returning MTP_FORMAT_ASSOCIATION, MTP_FORMAT_PNG");
- return list;
-}
-
-static const MtpObjectProperty sSupportedObjectProperties[] =
-{
- MTP_PROPERTY_STORAGE_ID,
- MTP_PROPERTY_OBJECT_FORMAT,
- MTP_PROPERTY_PROTECTION_STATUS, // UINT16 - always 0
- MTP_PROPERTY_OBJECT_SIZE,
- MTP_PROPERTY_OBJECT_FILE_NAME, // just the filename - no directory
- MTP_PROPERTY_NAME,
- MTP_PROPERTY_DATE_CREATED,
- MTP_PROPERTY_DATE_MODIFIED,
- MTP_PROPERTY_PARENT_OBJECT,
- MTP_PROPERTY_PERSISTENT_UID,
- MTP_PROPERTY_DATE_ADDED,
-};
-
-//virtual
-MtpObjectPropertyList*
-MozMtpDatabase::getSupportedObjectProperties(MtpObjectFormat aFormat)
-{
- MTP_LOG("");
- MtpObjectPropertyList *list = new MtpObjectPropertyList();
- list->appendArray(sSupportedObjectProperties,
- MOZ_ARRAY_LENGTH(sSupportedObjectProperties));
- return list;
-}
-
-//virtual
-MtpDevicePropertyList*
-MozMtpDatabase::getSupportedDeviceProperties()
-{
- MTP_LOG("");
- static const uint16_t init_data[] = { MTP_DEVICE_PROPERTY_UNDEFINED };
-
- MtpDevicePropertyList *list = new MtpDevicePropertyList();
- list->appendArray(init_data, MOZ_ARRAY_LENGTH(init_data));
- return list;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket)
-{
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Invalid Handle: 0x%08x", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MTP_LOG("Handle: 0x%08x '%s' Property: %s 0x%08x",
- aHandle, entry->mDisplayName.get(), ObjectPropertyAsStr(aProperty), aProperty);
-
- switch (aProperty)
- {
- case MTP_PROPERTY_STORAGE_ID: aPacket.putUInt32(entry->mStorageID); break;
- case MTP_PROPERTY_PARENT_OBJECT: aPacket.putUInt32(entry->mParent); break;
- case MTP_PROPERTY_OBJECT_FORMAT: aPacket.putUInt16(entry->mObjectFormat); break;
- case MTP_PROPERTY_OBJECT_SIZE: aPacket.putUInt64(entry->mObjectSize); break;
- case MTP_PROPERTY_DISPLAY_NAME: aPacket.putString(entry->mDisplayName.get()); break;
- case MTP_PROPERTY_PERSISTENT_UID:
- // the same as aPacket.putUInt128
- aPacket.putUInt64(entry->mHandle);
- aPacket.putUInt64(entry->mStorageID);
- break;
- case MTP_PROPERTY_NAME: aPacket.putString(entry->mDisplayName.get()); break;
-
- default:
- MTP_LOG("Invalid Property: 0x%08x", aProperty);
- return MTP_RESPONSE_INVALID_OBJECT_PROP_CODE;
- }
-
- return MTP_RESPONSE_OK;
-}
-
-static int
-GetTypeOfObjectProp(MtpObjectProperty aProperty)
-{
- struct PropertyTableEntry {
- MtpObjectProperty property;
- int type;
- };
-
- static const PropertyTableEntry kObjectPropertyTable[] = {
- {MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
- {MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
- {MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
- {MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
- {MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
- {MTP_PROPERTY_DATE_CREATED, MTP_TYPE_STR },
- {MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
- {MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
- {MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
- {MTP_PROPERTY_NAME, MTP_TYPE_STR },
- {MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
- {MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
- };
-
- int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
- const PropertyTableEntry* entryProp = kObjectPropertyTable;
- int type = 0;
-
- for (int i = 0; i < count; ++i, ++entryProp) {
- if (entryProp->property == aProperty) {
- type = entryProp->type;
- break;
- }
- }
-
- return type;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::setObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket)
-{
- MTP_LOG("Handle: 0x%08x Property: 0x%08x", aHandle, aProperty);
-
- // Only support file name change
- if (aProperty != MTP_PROPERTY_OBJECT_FILE_NAME) {
- MTP_ERR("property 0x%x not supported", aProperty);
- return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
- }
-
- if (GetTypeOfObjectProp(aProperty) != MTP_TYPE_STR) {
- MTP_ERR("property type 0x%x not supported", GetTypeOfObjectProp(aProperty));
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Invalid Handle: 0x%08x", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MtpStringBuffer buf;
- aPacket.getString(buf);
-
- nsDependentCString newFileName(buf);
- nsCString newFileFullPath(GetPathWithoutFileName(entry->mPath) + newFileName);
-
- if (PR_Rename(entry->mPath.get(), newFileFullPath.get()) != PR_SUCCESS) {
- MTP_ERR("Failed to rename '%s' to '%s'",
- entry->mPath.get(), newFileFullPath.get());
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- MTP_LOG("renamed '%s' to '%s'", entry->mPath.get(), newFileFullPath.get());
-
- entry->mPath = newFileFullPath;
- entry->mObjectName = BaseName(entry->mPath);
- entry->mDisplayName = entry->mObjectName;
-
- return MTP_RESPONSE_OK;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket)
-{
- MTP_LOG("(GENERAL ERROR)");
- return MTP_RESPONSE_GENERAL_ERROR;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::setDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket)
-{
- MTP_LOG("(NOT SUPPORTED)");
- return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::resetDeviceProperty(MtpDeviceProperty aProperty)
-{
- MTP_LOG("(NOT SUPPORTED)");
- return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
-}
-
-void
-MozMtpDatabase::QueryEntries(MozMtpDatabase::MatchType aMatchType,
- uint32_t aMatchField1,
- uint32_t aMatchField2,
- UnprotectedDbArray &result)
-{
- MutexAutoLock lock(mMutex);
-
- ProtectedDbArray::size_type numEntries = mDb.Length();
- ProtectedDbArray::index_type entryIdx;
- RefPtr<DbEntry> entry;
-
- result.Clear();
-
- switch (aMatchType) {
-
- case MatchAll:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- if (mDb[entryIdx]) {
- result.AppendElement(mDb[entryIdx]);
- }
- }
- break;
-
- case MatchHandle:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mHandle == aMatchField1) {
- result.AppendElement(entry);
- // Handles are unique - return the one that we found.
- return;
- }
- }
- break;
-
- case MatchParent:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mParent == aMatchField1) {
- result.AppendElement(entry);
- }
- }
- break;
-
- case MatchFormat:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mObjectFormat == aMatchField1) {
- result.AppendElement(entry);
- }
- }
- break;
-
- case MatchHandleFormat:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mHandle == aMatchField1) {
- if (entry->mObjectFormat == aMatchField2) {
- result.AppendElement(entry);
- }
- // Only 1 entry can match my aHandle. So we can return early.
- return;
- }
- }
- break;
-
- case MatchParentFormat:
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- entry = mDb[entryIdx];
- if (entry && entry->mParent == aMatchField1 && entry->mObjectFormat == aMatchField2) {
- result.AppendElement(entry);
- }
- }
- break;
-
- default:
- MOZ_ASSERT(!"Invalid MatchType");
- }
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getObjectPropertyList(MtpObjectHandle aHandle,
- uint32_t aFormat,
- uint32_t aProperty,
- int aGroupCode,
- int aDepth,
- MtpDataPacket& aPacket)
-{
- MTP_LOG("Handle: 0x%08x Format: 0x%08x aProperty: 0x%08x aGroupCode: %d aDepth %d",
- aHandle, aFormat, aProperty, aGroupCode, aDepth);
-
- if (aDepth > 1) {
- return MTP_RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED;
- }
- if (aGroupCode != 0) {
- return MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED;
- }
-
- MatchType matchType = MatchAll;
- uint32_t matchField1 = 0;
- uint32_t matchField2 = 0;
-
- // aHandle == 0 implies all objects at the root level
- // further specificed by aFormat and/or aDepth
-
- if (aFormat == 0) {
- if (aHandle == 0xffffffff) {
- // select all objects
- matchType = MatchAll;
- } else {
- if (aDepth == 1) {
- // select objects whose Parent matches aHandle
- matchType = MatchParent;
- matchField1 = aHandle;
- } else {
- // select object whose handle matches aHandle
- matchType = MatchHandle;
- matchField1 = aHandle;
- }
- }
- } else {
- if (aHandle == 0xffffffff) {
- // select all objects whose format matches aFormat
- matchType = MatchFormat;
- matchField1 = aFormat;
- } else {
- if (aDepth == 1) {
- // select objects whose Parent is aHandle and format matches aFormat
- matchType = MatchParentFormat;
- matchField1 = aHandle;
- matchField2 = aFormat;
- } else {
- // select objects whose handle is aHandle and format matches aFormat
- matchType = MatchHandleFormat;
- matchField1 = aHandle;
- matchField2 = aFormat;
- }
- }
- }
-
- UnprotectedDbArray result;
- QueryEntries(matchType, matchField1, matchField2, result);
-
- const MtpObjectProperty *objectPropertyList;
- size_t numObjectProperties = 0;
- MtpObjectProperty objectProperty;
-
- if (aProperty == 0xffffffff) {
- // return all supported properties
- numObjectProperties = MOZ_ARRAY_LENGTH(sSupportedObjectProperties);
- objectPropertyList = sSupportedObjectProperties;
- } else {
- // return property indicated by aProperty
- numObjectProperties = 1;
- objectProperty = aProperty;
- objectPropertyList = &objectProperty;
- }
-
- UnprotectedDbArray::size_type numEntries = result.Length();
- UnprotectedDbArray::index_type entryIdx;
-
- char dateStr[20];
-
- aPacket.putUInt32(numObjectProperties * numEntries);
- for (entryIdx = 0; entryIdx < numEntries; entryIdx++) {
- RefPtr<DbEntry> entry = result[entryIdx];
-
- for (size_t propertyIdx = 0; propertyIdx < numObjectProperties; propertyIdx++) {
- aPacket.putUInt32(entry->mHandle);
- MtpObjectProperty prop = objectPropertyList[propertyIdx];
- aPacket.putUInt16(prop);
- switch (prop) {
-
- case MTP_PROPERTY_STORAGE_ID:
- aPacket.putUInt16(MTP_TYPE_UINT32);
- aPacket.putUInt32(entry->mStorageID);
- break;
-
- case MTP_PROPERTY_PARENT_OBJECT:
- aPacket.putUInt16(MTP_TYPE_UINT32);
- aPacket.putUInt32(entry->mParent);
- break;
-
- case MTP_PROPERTY_PERSISTENT_UID:
- aPacket.putUInt16(MTP_TYPE_UINT128);
- // the same as aPacket.putUInt128
- aPacket.putUInt64(entry->mHandle);
- aPacket.putUInt64(entry->mStorageID);
- break;
-
- case MTP_PROPERTY_OBJECT_FORMAT:
- aPacket.putUInt16(MTP_TYPE_UINT16);
- aPacket.putUInt16(entry->mObjectFormat);
- break;
-
- case MTP_PROPERTY_OBJECT_SIZE:
- aPacket.putUInt16(MTP_TYPE_UINT64);
- aPacket.putUInt64(entry->mObjectSize);
- break;
-
- case MTP_PROPERTY_OBJECT_FILE_NAME:
- case MTP_PROPERTY_NAME:
- aPacket.putUInt16(MTP_TYPE_STR);
- aPacket.putString(entry->mObjectName.get());
- break;
-
- case MTP_PROPERTY_PROTECTION_STATUS:
- aPacket.putUInt16(MTP_TYPE_UINT16);
- aPacket.putUInt16(0); // 0 = No Protection
- break;
-
- case MTP_PROPERTY_DATE_CREATED: {
- aPacket.putUInt16(MTP_TYPE_STR);
- aPacket.putString(FormatDate(entry->mDateCreated, dateStr, sizeof(dateStr)));
- MTP_LOG("mDateCreated: (%ld) %s", entry->mDateCreated, dateStr);
- break;
- }
-
- case MTP_PROPERTY_DATE_MODIFIED: {
- aPacket.putUInt16(MTP_TYPE_STR);
- aPacket.putString(FormatDate(entry->mDateModified, dateStr, sizeof(dateStr)));
- MTP_LOG("mDateModified: (%ld) %s", entry->mDateModified, dateStr);
- break;
- }
-
- case MTP_PROPERTY_DATE_ADDED: {
- aPacket.putUInt16(MTP_TYPE_STR);
- aPacket.putString(FormatDate(entry->mDateAdded, dateStr, sizeof(dateStr)));
- MTP_LOG("mDateAdded: (%ld) %s", entry->mDateAdded, dateStr);
- break;
- }
-
- default:
- MTP_ERR("Unrecognized property code: %u", prop);
- return MTP_RESPONSE_GENERAL_ERROR;
- }
- }
- }
- return MTP_RESPONSE_OK;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getObjectInfo(MtpObjectHandle aHandle,
- MtpObjectInfo& aInfo)
-{
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Handle 0x%08x is invalid", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MTP_LOG("Handle: 0x%08x Display:'%s' Object:'%s'", aHandle, entry->mDisplayName.get(), entry->mObjectName.get());
-
- aInfo.mHandle = aHandle;
- aInfo.mStorageID = entry->mStorageID;
- aInfo.mFormat = entry->mObjectFormat;
- aInfo.mProtectionStatus = 0x0;
-
- if (entry->mObjectSize > 0xFFFFFFFFuLL) {
- aInfo.mCompressedSize = 0xFFFFFFFFuLL;
- } else {
- aInfo.mCompressedSize = entry->mObjectSize;
- }
-
- aInfo.mThumbFormat = MTP_FORMAT_UNDEFINED;
- aInfo.mThumbCompressedSize = 0;
- aInfo.mThumbPixWidth = 0;
- aInfo.mThumbPixHeight = 0;
- aInfo.mImagePixWidth = 0;
- aInfo.mImagePixHeight = 0;
- aInfo.mImagePixDepth = 0;
- aInfo.mParent = entry->mParent;
- aInfo.mAssociationType = 0;
- aInfo.mAssociationDesc = 0;
- aInfo.mSequenceNumber = 0;
- aInfo.mName = ::strdup(entry->mObjectName.get());
- aInfo.mDateCreated = entry->mDateCreated;
- aInfo.mDateModified = entry->mDateModified;
-
- MTP_LOG("aInfo.mDateCreated = %ld entry->mDateCreated = %ld",
- aInfo.mDateCreated, entry->mDateCreated);
- MTP_LOG("aInfo.mDateModified = %ld entry->mDateModified = %ld",
- aInfo.mDateModified, entry->mDateModified);
-
- aInfo.mKeywords = ::strdup("fxos,touch");
-
- return MTP_RESPONSE_OK;
-}
-
-//virtual
-void*
-MozMtpDatabase::getThumbnail(MtpObjectHandle aHandle, size_t& aOutThumbSize)
-{
- MTP_LOG("Handle: 0x%08x (returning nullptr)", aHandle);
-
- aOutThumbSize = 0;
-
- return nullptr;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::getObjectFilePath(MtpObjectHandle aHandle,
- MtpString& aOutFilePath,
- int64_t& aOutFileLength,
- MtpObjectFormat& aOutFormat)
-{
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Handle 0x%08x is invalid", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MTP_LOG("Handle: 0x%08x FilePath: '%s'", aHandle, entry->mPath.get());
-
- aOutFilePath = entry->mPath.get();
- aOutFileLength = entry->mObjectSize;
- aOutFormat = entry->mObjectFormat;
-
- return MTP_RESPONSE_OK;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::deleteFile(MtpObjectHandle aHandle)
-{
- RefPtr<DbEntry> entry = GetEntry(aHandle);
- if (!entry) {
- MTP_ERR("Invalid Handle: 0x%08x", aHandle);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-
- MTP_LOG("Handle: 0x%08x '%s'", aHandle, entry->mPath.get());
-
- // File deletion will happen in lower level implementation.
- // The only thing we need to do is removing the entry from the db.
- RemoveEntry(aHandle);
-
- // Tell Device Storage that the file is gone.
- MtpWatcherNotify(entry, "deleted");
-
- return MTP_RESPONSE_OK;
-}
-
-#if 0
-//virtual
-MtpResponseCode
-MozMtpDatabase::moveFile(MtpObjectHandle aHandle, MtpObjectHandle aNewParent)
-{
- MTP_LOG("Handle: 0x%08x NewParent: 0x%08x", aHandle, aNewParent);
-
- // change parent
-
- return MTP_RESPONSE_OK
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::copyFile(MtpObjectHandle aHandle, MtpObjectHandle aNewParent)
-{
- MTP_LOG("Handle: 0x%08x NewParent: 0x%08x", aHandle, aNewParent);
-
- // duplicate DbEntry
- // change parent
-
- return MTP_RESPONSE_OK
-}
-#endif
-
-//virtual
-MtpObjectHandleList*
-MozMtpDatabase::getObjectReferences(MtpObjectHandle aHandle)
-{
- MTP_LOG("Handle: 0x%08x (returning nullptr)", aHandle);
- return nullptr;
-}
-
-//virtual
-MtpResponseCode
-MozMtpDatabase::setObjectReferences(MtpObjectHandle aHandle,
- MtpObjectHandleList* aReferences)
-{
- MTP_LOG("Handle: 0x%08x (NOT SUPPORTED)", aHandle);
- return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
-}
-
-//virtual
-MtpProperty*
-MozMtpDatabase::getObjectPropertyDesc(MtpObjectProperty aProperty,
- MtpObjectFormat aFormat)
-{
- MTP_LOG("Property: %s 0x%08x", ObjectPropertyAsStr(aProperty), aProperty);
-
- MtpProperty* result = nullptr;
- switch (aProperty)
- {
- case MTP_PROPERTY_PROTECTION_STATUS:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT16);
- break;
- case MTP_PROPERTY_OBJECT_FORMAT:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT16, false, aFormat);
- break;
- case MTP_PROPERTY_STORAGE_ID:
- case MTP_PROPERTY_PARENT_OBJECT:
- case MTP_PROPERTY_WIDTH:
- case MTP_PROPERTY_HEIGHT:
- case MTP_PROPERTY_IMAGE_BIT_DEPTH:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT32);
- break;
- case MTP_PROPERTY_OBJECT_SIZE:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT64);
- break;
- case MTP_PROPERTY_DISPLAY_NAME:
- case MTP_PROPERTY_NAME:
- result = new MtpProperty(aProperty, MTP_TYPE_STR);
- break;
- case MTP_PROPERTY_OBJECT_FILE_NAME:
- result = new MtpProperty(aProperty, MTP_TYPE_STR, true);
- break;
- case MTP_PROPERTY_DATE_CREATED:
- case MTP_PROPERTY_DATE_MODIFIED:
- case MTP_PROPERTY_DATE_ADDED:
- result = new MtpProperty(aProperty, MTP_TYPE_STR);
- result->setFormDateTime();
- break;
- case MTP_PROPERTY_PERSISTENT_UID:
- result = new MtpProperty(aProperty, MTP_TYPE_UINT128);
- break;
- default:
- break;
- }
-
- return result;
-}
-
-//virtual
-MtpProperty*
-MozMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty aProperty)
-{
- MTP_LOG("(returning MTP_DEVICE_PROPERTY_UNDEFINED)");
- return new MtpProperty(MTP_DEVICE_PROPERTY_UNDEFINED, MTP_TYPE_UNDEFINED);
-}
-
-//virtual
-void
-MozMtpDatabase::sessionStarted()
-{
- MTP_LOG("");
-}
-
-//virtual
-void
-MozMtpDatabase::sessionEnded()
-{
- MTP_LOG("");
-}
-
-END_MTP_NAMESPACE
diff --git a/dom/system/gonk/MozMtpDatabase.h b/dom/system/gonk/MozMtpDatabase.h
deleted file mode 100644
index 8b308762e..000000000
--- a/dom/system/gonk/MozMtpDatabase.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozmtpdatabase_h__
-#define mozilla_system_mozmtpdatabase_h__
-
-#include "MozMtpCommon.h"
-
-#include "mozilla/Mutex.h"
-#include "mozilla/RefPtr.h"
-#include "nsCOMPtr.h"
-#include "nsString.h"
-#include "nsIThread.h"
-#include "nsTArray.h"
-
-class DeviceStorageFile;
-
-BEGIN_MTP_NAMESPACE // mozilla::system::mtp
-
-class RefCountedMtpServer;
-
-using namespace android;
-
-class MozMtpDatabase final : public MtpDatabase
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpDatabase)
-
- MozMtpDatabase();
-
- // called from SendObjectInfo to reserve a database entry for the incoming file
- virtual MtpObjectHandle beginSendObject(const char* aPath,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent,
- MtpStorageID aStorageID,
- uint64_t aSize,
- time_t aModified);
-
- // called to report success or failure of the SendObject file transfer
- // success should signal a notification of the new object's creation,
- // failure should remove the database entry created in beginSendObject
- virtual void endSendObject(const char* aPath,
- MtpObjectHandle aHandle,
- MtpObjectFormat aFormat,
- bool aSucceeded);
-
- virtual MtpObjectHandleList* getObjectList(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent);
-
- virtual int getNumObjects(MtpStorageID aStorageID,
- MtpObjectFormat aFormat,
- MtpObjectHandle aParent);
-
- virtual MtpObjectFormatList* getSupportedPlaybackFormats();
-
- virtual MtpObjectFormatList* getSupportedCaptureFormats();
-
- virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat aFormat);
-
- virtual MtpDevicePropertyList* getSupportedDeviceProperties();
-
- virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle aHandle,
- MtpObjectProperty aProperty,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty aProperty,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty aProperty);
-
- virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle aHandle,
- uint32_t aFormat,
- uint32_t aProperty,
- int aGroupCode,
- int aDepth,
- MtpDataPacket& aPacket);
-
- virtual MtpResponseCode getObjectInfo(MtpObjectHandle aHandle,
- MtpObjectInfo& aInfo);
-
- virtual void* getThumbnail(MtpObjectHandle aHandle, size_t& aOutThumbSize);
-
- virtual MtpResponseCode getObjectFilePath(MtpObjectHandle aHandle,
- MtpString& aOutFilePath,
- int64_t& aOutFileLength,
- MtpObjectFormat& aOutFormat);
-
- virtual MtpResponseCode deleteFile(MtpObjectHandle aHandle);
-
- virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle aHandle);
-
- virtual MtpResponseCode setObjectReferences(MtpObjectHandle aHandle,
- MtpObjectHandleList* aReferences);
-
- virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty aProperty,
- MtpObjectFormat aFormat);
-
- virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty aProperty);
-
- virtual void sessionStarted();
-
- virtual void sessionEnded();
-
- void AddStorage(MtpStorageID aStorageID, const char* aPath, const char *aName);
- void RemoveStorage(MtpStorageID aStorageID);
-
- void MtpWatcherUpdate(RefCountedMtpServer* aMtpServer,
- DeviceStorageFile* aFile,
- const nsACString& aEventType);
-
-protected:
- virtual ~MozMtpDatabase();
-
-private:
-
- struct DbEntry final
- {
- DbEntry()
- : mHandle(0),
- mStorageID(0),
- mObjectFormat(MTP_FORMAT_DEFINED),
- mParent(0),
- mObjectSize(0),
- mDateCreated(0),
- mDateModified(0),
- mDateAdded(0) {}
-
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DbEntry)
-
- MtpObjectHandle mHandle; // uint32_t
- MtpStorageID mStorageID; // uint32_t
- nsCString mObjectName;
- MtpObjectFormat mObjectFormat; // uint16_t
- MtpObjectHandle mParent; // uint32_t
- uint64_t mObjectSize;
- nsCString mDisplayName;
- nsCString mPath;
- time_t mDateCreated;
- time_t mDateModified;
- time_t mDateAdded;
-
- protected:
- ~DbEntry() {}
- };
-
- template<class T>
- class ProtectedTArray : private nsTArray<T>
- {
- public:
- typedef T elem_type;
- typedef typename nsTArray<T>::size_type size_type;
- typedef typename nsTArray<T>::index_type index_type;
- typedef nsTArray<T> base_type;
-
- static const index_type NoIndex = base_type::NoIndex;
-
- ProtectedTArray(mozilla::Mutex& aMutex)
- : mMutex(aMutex)
- {}
-
- size_type Length() const
- {
- // GRR - This assert prints to stderr and won't show up in logcat.
- mMutex.AssertCurrentThreadOwns();
- return base_type::Length();
- }
-
- template <class Item>
- elem_type* AppendElement(const Item& aItem)
- {
- mMutex.AssertCurrentThreadOwns();
- return base_type::AppendElement(aItem);
- }
-
- void Clear()
- {
- mMutex.AssertCurrentThreadOwns();
- base_type::Clear();
- }
-
- void RemoveElementAt(index_type aIndex)
- {
- mMutex.AssertCurrentThreadOwns();
- base_type::RemoveElementAt(aIndex);
- }
-
- elem_type& operator[](index_type aIndex)
- {
- mMutex.AssertCurrentThreadOwns();
- return base_type::ElementAt(aIndex);
- }
-
- const elem_type& operator[](index_type aIndex) const
- {
- mMutex.AssertCurrentThreadOwns();
- return base_type::ElementAt(aIndex);
- }
-
- private:
- mozilla::Mutex& mMutex;
- };
- typedef nsTArray<RefPtr<DbEntry> > UnprotectedDbArray;
- typedef ProtectedTArray<RefPtr<DbEntry> > ProtectedDbArray;
-
- struct StorageEntry final
- {
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StorageEntry)
-
- MtpStorageID mStorageID;
- nsCString mStoragePath;
- nsCString mStorageName;
-
- protected:
- ~StorageEntry() {}
- };
- typedef ProtectedTArray<RefPtr<StorageEntry> > StorageArray;
-
- enum MatchType
- {
- MatchAll,
- MatchHandle,
- MatchParent,
- MatchFormat,
- MatchHandleFormat,
- MatchParentFormat,
- };
-
- bool IsValidHandle(MtpObjectHandle aHandle)
- {
- return aHandle > 0 && aHandle < mDb.Length();
- }
-
- void AddEntry(DbEntry* aEntry);
- void AddEntryAndNotify(DbEntry* aEntr, RefCountedMtpServer* aMtpServer);
- void DumpEntries(const char* aLabel);
- MtpObjectHandle FindEntryByPath(const nsACString& aPath);
- already_AddRefed<DbEntry> GetEntry(MtpObjectHandle aHandle);
- void RemoveEntry(MtpObjectHandle aHandle);
- void RemoveEntryAndNotify(MtpObjectHandle aHandle, RefCountedMtpServer* aMtpServer);
- void UpdateEntry(MtpObjectHandle aHandle, DeviceStorageFile* aFile);
- void UpdateEntryAndNotify(MtpObjectHandle aHandle, DeviceStorageFile* aFile,
- RefCountedMtpServer* aMtpServer);
- void QueryEntries(MatchType aMatchType, uint32_t aMatchField1,
- uint32_t aMatchField2, UnprotectedDbArray& aResult);
-
- nsCString BaseName(const nsCString& aPath);
-
-
- MtpObjectHandle GetNextHandle()
- {
- return mDb.Length();
- }
-
- void AddDirectory(MtpStorageID aStorageID, const char *aPath, MtpObjectHandle aParent);
-
- void CreateEntryForFileAndNotify(const nsACString& aPath,
- DeviceStorageFile* aFile,
- RefCountedMtpServer* aMtpServer);
-
- StorageArray::index_type FindStorage(MtpStorageID aStorageID);
- MtpStorageID FindStorageIDFor(const nsACString& aPath, nsCSubstring& aRemainder);
- void MtpWatcherNotify(DbEntry* aEntry, const char* aEventType);
-
- // We need a mutex to protext mDb and mStorage. The MTP server runs on a
- // dedicated thread, and it updates/accesses mDb. When files are updated
- // through DeviceStorage, we need to update/access mDb and mStorage as well
- // (from a non-MTP server thread).
- mozilla::Mutex mMutex;
- ProtectedDbArray mDb;
- StorageArray mStorage;
-
- bool mBeginSendObjectCalled;
-};
-
-END_MTP_NAMESPACE
-
-#endif // mozilla_system_mozmtpdatabase_h__
diff --git a/dom/system/gonk/MozMtpServer.cpp b/dom/system/gonk/MozMtpServer.cpp
deleted file mode 100644
index c26b6368b..000000000
--- a/dom/system/gonk/MozMtpServer.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MozMtpServer.h"
-#include "MozMtpDatabase.h"
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-#include <private/android_filesystem_config.h>
-
-#include "base/message_loop.h"
-#include "DeviceStorage.h"
-#include "mozilla/LazyIdleThread.h"
-#include "mozilla/Scoped.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticPtr.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsISupportsImpl.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-
-#include "Volume.h"
-
-#define DEFAULT_THREAD_TIMEOUT_MS 30000
-
-using namespace android;
-using namespace mozilla;
-BEGIN_MTP_NAMESPACE
-
-static const char* kMtpWatcherUpdate = "mtp-watcher-update";
-
-class MtpWatcherUpdateRunnable final : public Runnable
-{
-public:
- MtpWatcherUpdateRunnable(MozMtpDatabase* aMozMtpDatabase,
- RefCountedMtpServer* aMtpServer,
- DeviceStorageFile* aFile,
- const nsACString& aEventType)
- : mMozMtpDatabase(aMozMtpDatabase),
- mMtpServer(aMtpServer),
- mFile(aFile),
- mEventType(aEventType)
- {}
-
- NS_IMETHOD Run() override
- {
- // Runs on the MtpWatcherUpdate->mIOThread
- MOZ_ASSERT(!NS_IsMainThread());
-
- mMozMtpDatabase->MtpWatcherUpdate(mMtpServer, mFile, mEventType);
- return NS_OK;
- }
-
-private:
- RefPtr<MozMtpDatabase> mMozMtpDatabase;
- RefPtr<RefCountedMtpServer> mMtpServer;
- RefPtr<DeviceStorageFile> mFile;
- nsCString mEventType;
-};
-
-// The MtpWatcherUpdate class listens for mtp-watcher-update events
-// and tells the MtpServer about changes made in device storage.
-class MtpWatcherUpdate final : public nsIObserver
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
-
- MtpWatcherUpdate(MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer)
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- mIOThread = new LazyIdleThread(
- DEFAULT_THREAD_TIMEOUT_MS,
- NS_LITERAL_CSTRING("MtpWatcherUpdate"));
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- obs->AddObserver(this, kMtpWatcherUpdate, false);
- }
-
- NS_IMETHOD
- Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- if (strcmp(aTopic, kMtpWatcherUpdate)) {
- // We're only interested in mtp-watcher-update events
- return NS_OK;
- }
-
- NS_ConvertUTF16toUTF8 eventType(aData);
- if (!eventType.EqualsLiteral("modified") && !eventType.EqualsLiteral("deleted")) {
- // Bug 1074604: Needn't handle "created" event, once file operation
- // finished, it would trigger "modified" event.
- return NS_OK;
- }
-
- DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
- file->Dump(kMtpWatcherUpdate);
- MTP_LOG("%s: file %s %s", kMtpWatcherUpdate,
- NS_LossyConvertUTF16toASCII(file->mPath).get(),
- eventType.get());
-
- RefPtr<MozMtpDatabase> mozMtpDatabase = mMozMtpServer->GetMozMtpDatabase();
- RefPtr<RefCountedMtpServer> mtpServer = mMozMtpServer->GetMtpServer();
-
- // We're not supposed to perform I/O on the main thread, so punt the
- // notification (which will write to /dev/mtp_usb) to an I/O Thread.
-
- RefPtr<MtpWatcherUpdateRunnable> r =
- new MtpWatcherUpdateRunnable(mozMtpDatabase, mtpServer, file, eventType);
- mIOThread->Dispatch(r, NS_DISPATCH_NORMAL);
-
- return NS_OK;
- }
-
-protected:
- ~MtpWatcherUpdate()
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- obs->RemoveObserver(this, kMtpWatcherUpdate);
- }
-
-private:
- RefPtr<MozMtpServer> mMozMtpServer;
- nsCOMPtr<nsIThread> mIOThread;
-};
-NS_IMPL_ISUPPORTS(MtpWatcherUpdate, nsIObserver)
-static StaticRefPtr<MtpWatcherUpdate> sMtpWatcherUpdate;
-
-class AllocMtpWatcherUpdateRunnable final : public Runnable
-{
-public:
- AllocMtpWatcherUpdateRunnable(MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer)
- {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- sMtpWatcherUpdate = new MtpWatcherUpdate(mMozMtpServer);
- return NS_OK;
- }
-private:
- RefPtr<MozMtpServer> mMozMtpServer;
-};
-
-class FreeMtpWatcherUpdateRunnable final : public Runnable
-{
-public:
- FreeMtpWatcherUpdateRunnable(MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer)
- {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- sMtpWatcherUpdate = nullptr;
- return NS_OK;
- }
-private:
- RefPtr<MozMtpServer> mMozMtpServer;
-};
-
-class MtpServerRunnable : public Runnable
-{
-public:
- MtpServerRunnable(int aMtpUsbFd, MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer),
- mMtpUsbFd(aMtpUsbFd)
- {
- }
-
- nsresult Run()
- {
- RefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
-
- DebugOnly<nsresult> rv =
- NS_DispatchToMainThread(new AllocMtpWatcherUpdateRunnable(mMozMtpServer));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-
- MTP_LOG("MozMtpServer started");
- server->run();
- MTP_LOG("MozMtpServer finished");
-
- // server->run will have closed the file descriptor.
- mMtpUsbFd.forget();
-
- rv = NS_DispatchToMainThread(new FreeMtpWatcherUpdateRunnable(mMozMtpServer));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-
- return NS_OK;
- }
-
-private:
- RefPtr<MozMtpServer> mMozMtpServer;
- ScopedClose mMtpUsbFd; // We want to hold this open while the server runs
-};
-
-already_AddRefed<RefCountedMtpServer>
-MozMtpServer::GetMtpServer()
-{
- RefPtr<RefCountedMtpServer> server = mMtpServer;
- return server.forget();
-}
-
-already_AddRefed<MozMtpDatabase>
-MozMtpServer::GetMozMtpDatabase()
-{
- RefPtr<MozMtpDatabase> db = mMozMtpDatabase;
- return db.forget();
-}
-
-bool
-MozMtpServer::Init()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- const char *mtpUsbFilename = "/dev/mtp_usb";
- mMtpUsbFd = open(mtpUsbFilename, O_RDWR);
- if (mMtpUsbFd.get() < 0) {
- MTP_ERR("open of '%s' failed((%s))", mtpUsbFilename, strerror(errno));
- return false;
- }
- MTP_LOG("Opened '%s' fd %d", mtpUsbFilename, mMtpUsbFd.get());
-
- mMozMtpDatabase = new MozMtpDatabase();
- mMtpServer = new RefCountedMtpServer(mMtpUsbFd.get(), // fd
- mMozMtpDatabase.get(), // MtpDatabase
- false, // ptp?
- AID_MEDIA_RW, // file group
- 0664, // file permissions
- 0775); // dir permissions
- return true;
-}
-
-void
-MozMtpServer::Run()
-{
- nsresult rv = NS_NewNamedThread("MtpServer", getter_AddRefs(mServerThread));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
- MOZ_ASSERT(mServerThread);
- mServerThread->Dispatch(new MtpServerRunnable(mMtpUsbFd.forget(), this), NS_DISPATCH_NORMAL);
-}
-
-END_MTP_NAMESPACE
diff --git a/dom/system/gonk/MozMtpServer.h b/dom/system/gonk/MozMtpServer.h
deleted file mode 100644
index 4989c25ef..000000000
--- a/dom/system/gonk/MozMtpServer.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozmtpserver_h__
-#define mozilla_system_mozmtpserver_h__
-
-#include "MozMtpCommon.h"
-#include "MozMtpDatabase.h"
-
-#include "mozilla/FileUtils.h"
-
-#include "nsCOMPtr.h"
-#include "nsIThread.h"
-
-BEGIN_MTP_NAMESPACE
-using namespace android;
-
-class RefCountedMtpServer : public MtpServer
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMtpServer)
-
- RefCountedMtpServer(int aFd, MtpDatabase* aDatabase, bool aPtp,
- int aFileGroup, int aFilePerm, int aDirectoryPerm)
- : MtpServer(aFd, aDatabase, aPtp, aFileGroup, aFilePerm, aDirectoryPerm)
- {
- }
-
-protected:
- virtual ~RefCountedMtpServer() {}
-};
-
-class MozMtpServer
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpServer)
-
- bool Init();
- void Run();
-
- already_AddRefed<RefCountedMtpServer> GetMtpServer();
- already_AddRefed<MozMtpDatabase> GetMozMtpDatabase();
-
-protected:
- virtual ~MozMtpServer() {}
-
-private:
- RefPtr<RefCountedMtpServer> mMtpServer;
- RefPtr<MozMtpDatabase> mMozMtpDatabase;
- nsCOMPtr<nsIThread> mServerThread;
- ScopedClose mMtpUsbFd;
-};
-
-END_MTP_NAMESPACE
-
-#endif // mozilla_system_mozmtpserver_h__
-
-
diff --git a/dom/system/gonk/MozMtpStorage.cpp b/dom/system/gonk/MozMtpStorage.cpp
deleted file mode 100644
index 9c358a132..000000000
--- a/dom/system/gonk/MozMtpStorage.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MozMtpStorage.h"
-#include "MozMtpDatabase.h"
-#include "MozMtpServer.h"
-
-#include "base/message_loop.h"
-#include "nsXULAppAPI.h"
-
-BEGIN_MTP_NAMESPACE
-using namespace android;
-
-MozMtpStorage::MozMtpStorage(Volume* aVolume, MozMtpServer* aMozMtpServer)
- : mMozMtpServer(aMozMtpServer),
- mVolume(aVolume)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // The MtpStorageID has the physical volume in the top 16 bits, and the
- // logical volumein the lower 16 bits. We treat each volume as a separate
- // phsyical storage;
- mStorageID = mVolume->Id() << 16 | 1;
-
- MTP_LOG("Storage constructed for Volume %s mStorageID 0x%08x",
- aVolume->NameStr(), mStorageID);
-
- Volume::RegisterVolumeObserver(this, "MozMtpStorage");
-
- // Get things in sync
- Notify(mVolume);
-}
-
-MozMtpStorage::~MozMtpStorage()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- MTP_LOG("Storage destructed for Volume %s mStorageID 0x%08x",
- mVolume->NameStr(), mStorageID);
-
- Volume::UnregisterVolumeObserver(this, "MozMtpStorage");
- if (mMtpStorage) {
- StorageUnavailable();
- }
-}
-
-// virtual
-void
-MozMtpStorage::Notify(Volume* const& aVolume)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (aVolume != mVolume) {
- // Not our volume
- return;
- }
- Volume::STATE volState = aVolume->State();
-
- MTP_LOG("Volume %s mStorageID 0x%08x state changed to %s SharingEnabled: %d",
- aVolume->NameStr(), mStorageID, aVolume->StateStr(),
- aVolume->IsSharingEnabled());
-
- // vol->IsSharingEnabled really only applies to UMS volumes. We assume that
- // that as long as MTP is enabled, then all volumes will be shared. The UI
- // currently doesn't give us anything more granular than on/off.
-
- if (mMtpStorage) {
- if (volState != nsIVolume::STATE_MOUNTED) {
- // The volume is no longer accessible. We need to remove this storage
- // from the MTP server
- StorageUnavailable();
- }
- } else {
- if (volState == nsIVolume::STATE_MOUNTED) {
- // The volume is accessible. Tell the MTP server.
- StorageAvailable();
- }
- }
-}
-
-void
-MozMtpStorage::StorageAvailable()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- nsCString mountPoint = mVolume->MountPoint();
-
- MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MozMtpDatabase",
- mVolume->NameStr(), mStorageID, mountPoint.get());
-
- RefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
- db->AddStorage(mStorageID, mountPoint.get(), mVolume->NameStr());
-
- MOZ_ASSERT(!mMtpStorage);
-
- //TODO: Figure out what to do about maxFileSize.
-
- mMtpStorage.reset(new MtpStorage(mStorageID, // id
- mountPoint.get(), // filePath
- mVolume->NameStr(), // description
- 1024uLL * 1024uLL, // reserveSpace
- mVolume->IsHotSwappable(), // removable
- 2uLL * 1024uLL * 1024uLL * 1024uLL)); // maxFileSize
- RefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
-
- MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MtpServer",
- mVolume->NameStr(), mStorageID, mountPoint.get());
- server->addStorage(mMtpStorage.get());
-}
-
-void
-MozMtpStorage::StorageUnavailable()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(mMtpStorage);
-
- MTP_LOG("Removing mStorageID 0x%08x from MtpServer", mStorageID);
-
- RefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
- server->removeStorage(mMtpStorage.get());
-
- MTP_LOG("Removing mStorageID 0x%08x from MozMtpDatabse", mStorageID);
-
- RefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
- db->RemoveStorage(mStorageID);
-
- mMtpStorage = nullptr;
-}
-
-END_MTP_NAMESPACE
-
-
diff --git a/dom/system/gonk/MozMtpStorage.h b/dom/system/gonk/MozMtpStorage.h
deleted file mode 100644
index 18d1e04ac..000000000
--- a/dom/system/gonk/MozMtpStorage.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozmtpstorage_h__
-#define mozilla_system_mozmtpstorage_h__
-
-#include "MozMtpCommon.h"
-
-#include "mozilla/UniquePtr.h"
-
-#include "Volume.h"
-
-BEGIN_MTP_NAMESPACE
-using namespace android;
-
-class MozMtpServer;
-
-class MozMtpStorage : public Volume::EventObserver
-{
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpStorage)
-
- MozMtpStorage(Volume* aVolume, MozMtpServer* aMozMtpServer);
-
- typedef nsTArray<RefPtr<MozMtpStorage> > Array;
-
-private:
- virtual ~MozMtpStorage();
- virtual void Notify(Volume* const& aEvent);
-
- void StorageAvailable();
- void StorageUnavailable();
-
- RefPtr<MozMtpServer> mMozMtpServer;
- UniquePtr<MtpStorage> mMtpStorage;
- RefPtr<Volume> mVolume;
- MtpStorageID mStorageID;
-};
-
-END_MTP_NAMESPACE
-
-#endif // mozilla_system_mozmtpstorage_h__
-
-
diff --git a/dom/system/gonk/NetIdManager.cpp b/dom/system/gonk/NetIdManager.cpp
deleted file mode 100644
index 510ec8b22..000000000
--- a/dom/system/gonk/NetIdManager.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "NetIdManager.h"
-
-NetIdManager::NetIdManager()
- : mNextNetId(MIN_NET_ID)
-{
-}
-
-int NetIdManager::getNextNetId()
-{
- // Modified from
- // http://androidxref.com/5.0.0_r2/xref/frameworks/base/services/
- // core/java/com/android/server/ConnectivityService.java#764
-
- int netId = mNextNetId;
- if (++mNextNetId > MAX_NET_ID) {
- mNextNetId = MIN_NET_ID;
- }
-
- return netId;
-}
-
-void NetIdManager::acquire(const nsString& aInterfaceName,
- NetIdInfo* aNetIdInfo)
-{
- // Lookup or create one.
- if (!mInterfaceToNetIdHash.Get(aInterfaceName, aNetIdInfo)) {
- aNetIdInfo->mNetId = getNextNetId();
- aNetIdInfo->mRefCnt = 1;
- } else {
- aNetIdInfo->mRefCnt++;
- }
-
- // Update hash and return.
- mInterfaceToNetIdHash.Put(aInterfaceName, *aNetIdInfo);
-
- return;
-}
-
-bool NetIdManager::lookup(const nsString& aInterfaceName,
- NetIdInfo* aNetIdInfo)
-{
- return mInterfaceToNetIdHash.Get(aInterfaceName, aNetIdInfo);
-}
-
-bool NetIdManager::release(const nsString& aInterfaceName,
- NetIdInfo* aNetIdInfo)
-{
- if (!mInterfaceToNetIdHash.Get(aInterfaceName, aNetIdInfo)) {
- return false; // No such key.
- }
-
- aNetIdInfo->mRefCnt--;
-
- // Update the hash if still be referenced.
- if (aNetIdInfo->mRefCnt > 0) {
- mInterfaceToNetIdHash.Put(aInterfaceName, *aNetIdInfo);
- return true;
- }
-
- // No longer be referenced. Remove the entry.
- mInterfaceToNetIdHash.Remove(aInterfaceName);
-
- return true;
-} \ No newline at end of file
diff --git a/dom/system/gonk/NetIdManager.h b/dom/system/gonk/NetIdManager.h
deleted file mode 100644
index e35d0ecd2..000000000
--- a/dom/system/gonk/NetIdManager.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef NetIdManager_h
-#define NetIdManager_h
-
-#include "nsString.h"
-#include "nsDataHashtable.h"
-
-// NetId is a logical network identifier defined by netd.
-// A network is typically a physical one (i.e. PhysicalNetwork.cpp)
-// for netd but it could be a virtual network as well.
-// We currently use physical network only and use one-to-one
-// network-interface mapping.
-
-class NetIdManager {
-public:
- // keep in sync with system/netd/NetworkController.cpp
- enum {
- MIN_NET_ID = 100,
- MAX_NET_ID = 65535,
- };
-
- // We need to count the number of references since different
- // application like data and mms may use the same interface.
- struct NetIdInfo {
- int mNetId;
- int mRefCnt;
- };
-
-public:
- NetIdManager();
-
- bool lookup(const nsString& aInterfaceName, NetIdInfo* aNetIdInfo);
- void acquire(const nsString& aInterfaceName, NetIdInfo* aNetIdInfo);
- bool release(const nsString& aInterfaceName, NetIdInfo* aNetIdInfo);
-
-private:
- int getNextNetId();
- int mNextNetId;
- nsDataHashtable<nsStringHashKey, NetIdInfo> mInterfaceToNetIdHash;
-};
-
-#endif \ No newline at end of file
diff --git a/dom/system/gonk/NetworkInterfaceListService.js b/dom/system/gonk/NetworkInterfaceListService.js
deleted file mode 100644
index 62fe046aa..000000000
--- a/dom/system/gonk/NetworkInterfaceListService.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const NETWORKLISTSERVICE_CONTRACTID =
- "@mozilla.org/network/interface-list-service;1";
-const NETWORKLISTSERVICE_CID =
- Components.ID("{3780be6e-7012-4e53-ade6-15212fb88a0d}");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsISyncMessageSender");
-
-function NetworkInterfaceListService () {
-}
-
-NetworkInterfaceListService.prototype = {
- classID: NETWORKLISTSERVICE_CID,
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterfaceListService]),
-
- getDataInterfaceList: function(aConditions) {
- return new NetworkInterfaceList(
- cpmm.sendSyncMessage(
- 'NetworkInterfaceList:ListInterface',
- {
- excludeSupl: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_SUPL_INTERFACES) != 0,
- excludeMms: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_MMS_INTERFACES) != 0,
- excludeIms: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_IMS_INTERFACES) != 0,
- excludeDun: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_DUN_INTERFACES) != 0,
- excludeFota: (aConditions &
- Ci.nsINetworkInterfaceListService.
- LIST_NOT_INCLUDE_FOTA_INTERFACES) != 0
- }
- )[0]);
- }
-};
-
-function FakeNetworkInfo(aAttributes) {
- this.state = aAttributes.state;
- this.type = aAttributes.type;
- this.name = aAttributes.name;
- this.ips = aAttributes.ips;
- this.prefixLengths = aAttributes.prefixLengths;
- this.gateways = aAttributes.gateways;
- this.dnses = aAttributes.dnses;
-}
-FakeNetworkInfo.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]),
-
- getAddresses: function (ips, prefixLengths) {
- ips.value = this.ips.slice();
- prefixLengths.value = this.prefixLengths.slice();
-
- return this.ips.length;
- },
-
- getGateways: function (count) {
- if (count) {
- count.value = this.gateways.length;
- }
- return this.gateways.slice();
- },
-
- getDnses: function (count) {
- if (count) {
- count.value = this.dnses.length;
- }
- return this.dnses.slice();
- }
-};
-
-function NetworkInterfaceList (aInterfaceLiterals) {
- this._interfaces = [];
- for (let entry of aInterfaceLiterals) {
- this._interfaces.push(new FakeNetworkInfo(entry));
- }
-}
-
-NetworkInterfaceList.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterfaceList]),
-
- getNumberOfInterface: function() {
- return this._interfaces.length;
- },
-
- getInterfaceInfo: function(index) {
- if (!this._interfaces) {
- return null;
- }
- return this._interfaces[index];
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkInterfaceListService]);
-
diff --git a/dom/system/gonk/NetworkInterfaceListService.manifest b/dom/system/gonk/NetworkInterfaceListService.manifest
deleted file mode 100644
index a827e778f..000000000
--- a/dom/system/gonk/NetworkInterfaceListService.manifest
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2012 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# NetworkInterfaceListService.js
-component {3780be6e-7012-4e53-ade6-15212fb88a0d} NetworkInterfaceListService.js
-contract @mozilla.org/network/interface-list-service;1 {3780be6e-7012-4e53-ade6-15212fb88a0d}
diff --git a/dom/system/gonk/NetworkManager.js b/dom/system/gonk/NetworkManager.js
deleted file mode 100644
index 9d7a5683e..000000000
--- a/dom/system/gonk/NetworkManager.js
+++ /dev/null
@@ -1,1219 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-const NETWORKMANAGER_CONTRACTID = "@mozilla.org/network/manager;1";
-const NETWORKMANAGER_CID =
- Components.ID("{1ba9346b-53b5-4660-9dc6-58f0b258d0a6}");
-
-const DEFAULT_PREFERRED_NETWORK_TYPE = Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET;
-
-XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
- return Cc["@mozilla.org/parentprocessmessagemanager;1"]
- .getService(Ci.nsIMessageBroadcaster);
-});
-
-XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
- "@mozilla.org/network/dns-service;1",
- "nsIDNSService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gTetheringService",
- "@mozilla.org/tethering/service;1",
- "nsITetheringService");
-
-const TOPIC_INTERFACE_REGISTERED = "network-interface-registered";
-const TOPIC_INTERFACE_UNREGISTERED = "network-interface-unregistered";
-const TOPIC_ACTIVE_CHANGED = "network-active-changed";
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
-const PREF_MANAGE_OFFLINE_STATUS = "network.gonk.manage-offline-status";
-const PREF_NETWORK_DEBUG_ENABLED = "network.debugging.enabled";
-
-const IPV4_ADDRESS_ANY = "0.0.0.0";
-const IPV6_ADDRESS_ANY = "::0";
-
-const IPV4_MAX_PREFIX_LENGTH = 32;
-const IPV6_MAX_PREFIX_LENGTH = 128;
-
-// Connection Type for Network Information API
-const CONNECTION_TYPE_CELLULAR = 0;
-const CONNECTION_TYPE_BLUETOOTH = 1;
-const CONNECTION_TYPE_ETHERNET = 2;
-const CONNECTION_TYPE_WIFI = 3;
-const CONNECTION_TYPE_OTHER = 4;
-const CONNECTION_TYPE_NONE = 5;
-
-const MANUAL_PROXY_CONFIGURATION = 1;
-
-var debug;
-function updateDebug() {
- let debugPref = false; // set default value here.
- try {
- debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
- } catch (e) {}
-
- if (debugPref) {
- debug = function(s) {
- dump("-*- NetworkManager: " + s + "\n");
- };
- } else {
- debug = function(s) {};
- }
-}
-updateDebug();
-
-function defineLazyRegExp(obj, name, pattern) {
- obj.__defineGetter__(name, function() {
- delete obj[name];
- return obj[name] = new RegExp(pattern);
- });
-}
-
-function ExtraNetworkInfo(aNetwork) {
- let ips = {};
- let prefixLengths = {};
- aNetwork.info.getAddresses(ips, prefixLengths);
-
- this.state = aNetwork.info.state;
- this.type = aNetwork.info.type;
- this.name = aNetwork.info.name;
- this.ips = ips.value;
- this.prefixLengths = prefixLengths.value;
- this.gateways = aNetwork.info.getGateways();
- this.dnses = aNetwork.info.getDnses();
- this.httpProxyHost = aNetwork.httpProxyHost;
- this.httpProxyPort = aNetwork.httpProxyPort;
- this.mtu = aNetwork.mtu;
-}
-ExtraNetworkInfo.prototype = {
- getAddresses: function(aIps, aPrefixLengths) {
- aIps.value = this.ips.slice();
- aPrefixLengths.value = this.prefixLengths.slice();
-
- return this.ips.length;
- },
-
- getGateways: function(aCount) {
- if (aCount) {
- aCount.value = this.gateways.length;
- }
-
- return this.gateways.slice();
- },
-
- getDnses: function(aCount) {
- if (aCount) {
- aCount.value = this.dnses.length;
- }
-
- return this.dnses.slice();
- }
-};
-
-function NetworkInterfaceLinks()
-{
- this.resetLinks();
-}
-NetworkInterfaceLinks.prototype = {
- linkRoutes: null,
- gateways: null,
- interfaceName: null,
- extraRoutes: null,
-
- setLinks: function(linkRoutes, gateways, interfaceName) {
- this.linkRoutes = linkRoutes;
- this.gateways = gateways;
- this.interfaceName = interfaceName;
- },
-
- resetLinks: function() {
- this.linkRoutes = [];
- this.gateways = [];
- this.interfaceName = "";
- this.extraRoutes = [];
- },
-
- compareGateways: function(gateways) {
- if (this.gateways.length != gateways.length) {
- return false;
- }
-
- for (let i = 0; i < this.gateways.length; i++) {
- if (this.gateways[i] != gateways[i]) {
- return false;
- }
- }
-
- return true;
- }
-};
-
-/**
- * This component watches for network interfaces changing state and then
- * adjusts routes etc. accordingly.
- */
-function NetworkManager() {
- this.networkInterfaces = {};
- this.networkInterfaceLinks = {};
-
- try {
- this._manageOfflineStatus =
- Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
- } catch(ex) {
- // Ignore.
- }
- Services.prefs.addObserver(PREF_MANAGE_OFFLINE_STATUS, this, false);
- Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
-
- this.setAndConfigureActive();
-
- ppmm.addMessageListener('NetworkInterfaceList:ListInterface', this);
-
- // Used in resolveHostname().
- defineLazyRegExp(this, "REGEXP_IPV4", "^\\d{1,3}(?:\\.\\d{1,3}){3}$");
- defineLazyRegExp(this, "REGEXP_IPV6", "^[\\da-fA-F]{4}(?::[\\da-fA-F]{4}){7}$");
-}
-NetworkManager.prototype = {
- classID: NETWORKMANAGER_CID,
- classInfo: XPCOMUtils.generateCI({classID: NETWORKMANAGER_CID,
- contractID: NETWORKMANAGER_CONTRACTID,
- classDescription: "Network Manager",
- interfaces: [Ci.nsINetworkManager]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkManager,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver,
- Ci.nsISettingsServiceCallback]),
-
- // nsIObserver
-
- observe: function(subject, topic, data) {
- switch (topic) {
- case TOPIC_PREF_CHANGED:
- if (data === PREF_NETWORK_DEBUG_ENABLED) {
- updateDebug();
- } else if (data === PREF_MANAGE_OFFLINE_STATUS) {
- this._manageOfflineStatus =
- Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
- debug(PREF_MANAGE_OFFLINE_STATUS + " has changed to " + this._manageOfflineStatus);
- }
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- Services.prefs.removeObserver(PREF_MANAGE_OFFLINE_STATUS, this);
- Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
- break;
- }
- },
-
- receiveMessage: function(aMsg) {
- switch (aMsg.name) {
- case "NetworkInterfaceList:ListInterface": {
- let excludeMms = aMsg.json.excludeMms;
- let excludeSupl = aMsg.json.excludeSupl;
- let excludeIms = aMsg.json.excludeIms;
- let excludeDun = aMsg.json.excludeDun;
- let excludeFota = aMsg.json.excludeFota;
- let interfaces = [];
-
- for (let key in this.networkInterfaces) {
- let network = this.networkInterfaces[key];
- let i = network.info;
- if ((i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS && excludeMms) ||
- (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL && excludeSupl) ||
- (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS && excludeIms) ||
- (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN && excludeDun) ||
- (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA && excludeFota)) {
- continue;
- }
-
- let ips = {};
- let prefixLengths = {};
- i.getAddresses(ips, prefixLengths);
-
- interfaces.push({
- state: i.state,
- type: i.type,
- name: i.name,
- ips: ips.value,
- prefixLengths: prefixLengths.value,
- gateways: i.getGateways(),
- dnses: i.getDnses()
- });
- }
- return interfaces;
- }
- }
- },
-
- getNetworkId: function(aNetworkInfo) {
- let id = "device";
- try {
- if (aNetworkInfo instanceof Ci.nsIRilNetworkInfo) {
- let rilInfo = aNetworkInfo.QueryInterface(Ci.nsIRilNetworkInfo);
- id = "ril" + rilInfo.serviceId;
- }
- } catch (e) {}
-
- return id + "-" + aNetworkInfo.type;
- },
-
- // nsINetworkManager
-
- registerNetworkInterface: function(network) {
- if (!(network instanceof Ci.nsINetworkInterface)) {
- throw Components.Exception("Argument must be nsINetworkInterface.",
- Cr.NS_ERROR_INVALID_ARG);
- }
- let networkId = this.getNetworkId(network.info);
- if (networkId in this.networkInterfaces) {
- throw Components.Exception("Network with that type already registered!",
- Cr.NS_ERROR_INVALID_ARG);
- }
- this.networkInterfaces[networkId] = network;
- this.networkInterfaceLinks[networkId] = new NetworkInterfaceLinks();
-
- Services.obs.notifyObservers(network.info, TOPIC_INTERFACE_REGISTERED, null);
- debug("Network '" + networkId + "' registered.");
- },
-
- _addSubnetRoutes: function(network) {
- let ips = {};
- let prefixLengths = {};
- let length = network.getAddresses(ips, prefixLengths);
- let promises = [];
-
- for (let i = 0; i < length; i++) {
- debug('Adding subnet routes: ' + ips.value[i] + '/' + prefixLengths.value[i]);
- promises.push(
- gNetworkService.modifyRoute(Ci.nsINetworkService.MODIFY_ROUTE_ADD,
- network.name, ips.value[i], prefixLengths.value[i])
- .catch(aError => {
- debug("_addSubnetRoutes error: " + aError);
- }));
- }
-
- return Promise.all(promises);
- },
-
- updateNetworkInterface: function(network) {
- if (!(network instanceof Ci.nsINetworkInterface)) {
- throw Components.Exception("Argument must be nsINetworkInterface.",
- Cr.NS_ERROR_INVALID_ARG);
- }
- let networkId = this.getNetworkId(network.info);
- if (!(networkId in this.networkInterfaces)) {
- throw Components.Exception("No network with that type registered.",
- Cr.NS_ERROR_INVALID_ARG);
- }
- debug("Network " + network.info.type + "/" + network.info.name +
- " changed state to " + network.info.state);
-
- // Keep a copy of network in case it is modified while we are updating.
- let extNetworkInfo = new ExtraNetworkInfo(network);
-
- // Note that since Lollipop we need to allocate and initialize
- // something through netd, so we add createNetwork/destroyNetwork
- // to deal with that explicitly.
-
- switch (extNetworkInfo.state) {
- case Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED:
-
- this._createNetwork(extNetworkInfo.name)
- // Remove pre-created default route and let setAndConfigureActive()
- // to set default route only on preferred network
- .then(() => this._removeDefaultRoute(extNetworkInfo))
- // Set DNS server as early as possible to prevent from
- // premature domain name lookup.
- .then(() => this._setDNS(extNetworkInfo))
- .then(() => {
- // Add host route for data calls
- if (!this.isNetworkTypeMobile(extNetworkInfo.type)) {
- return;
- }
-
- let currentInterfaceLinks = this.networkInterfaceLinks[networkId];
- let newLinkRoutes = extNetworkInfo.getDnses().concat(
- extNetworkInfo.httpProxyHost);
- // If gateways have changed, remove all old routes first.
- return this._handleGateways(networkId, extNetworkInfo.getGateways())
- .then(() => this._updateRoutes(currentInterfaceLinks.linkRoutes,
- newLinkRoutes,
- extNetworkInfo.getGateways(),
- extNetworkInfo.name))
- .then(() => currentInterfaceLinks.setLinks(newLinkRoutes,
- extNetworkInfo.getGateways(),
- extNetworkInfo.name));
- })
- .then(() => {
- if (extNetworkInfo.type !=
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) {
- return;
- }
- // Dun type is a special case where we add the default route to a
- // secondary table.
- return this.setSecondaryDefaultRoute(extNetworkInfo);
- })
- .then(() => this._addSubnetRoutes(extNetworkInfo))
- .then(() => {
- if (extNetworkInfo.mtu <= 0) {
- return;
- }
-
- return this._setMtu(extNetworkInfo);
- })
- .then(() => this.setAndConfigureActive())
- .then(() => {
- // Update data connection when Wifi connected/disconnected
- if (extNetworkInfo.type ==
- Ci.nsINetworkInfo.NETWORK_TYPE_WIFI && this.mRil) {
- for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
- this.mRil.getRadioInterface(i).updateRILNetworkInterface();
- }
- }
-
- // Probing the public network accessibility after routing table is ready
- CaptivePortalDetectionHelper
- .notify(CaptivePortalDetectionHelper.EVENT_CONNECT,
- this.activeNetworkInfo);
- })
- .then(() => {
- // Notify outer modules like MmsService to start the transaction after
- // the configuration of the network interface is done.
- Services.obs.notifyObservers(network.info,
- TOPIC_CONNECTION_STATE_CHANGED,
- this.convertConnectionType(network.info));
- })
- .catch(aError => {
- debug("updateNetworkInterface error: " + aError);
- });
- break;
- case Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED:
- Promise.resolve()
- .then(() => {
- if (!this.isNetworkTypeMobile(extNetworkInfo.type)) {
- return;
- }
- // Remove host route for data calls
- return this._cleanupAllHostRoutes(networkId);
- })
- .then(() => {
- if (extNetworkInfo.type !=
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) {
- return;
- }
- // Remove secondary default route for dun.
- return this.removeSecondaryDefaultRoute(extNetworkInfo);
- })
- .then(() => {
- if (extNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI ||
- extNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_ETHERNET) {
- // Remove routing table in /proc/net/route
- return this._resetRoutingTable(extNetworkInfo.name);
- }
- if (extNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) {
- return this._removeDefaultRoute(extNetworkInfo)
- }
- })
- .then(() => {
- // Clear http proxy on active network.
- if (this.activeNetworkInfo &&
- extNetworkInfo.type == this.activeNetworkInfo.type) {
- this.clearNetworkProxy();
- }
-
- // Abort ongoing captive portal detection on the wifi interface
- CaptivePortalDetectionHelper
- .notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, extNetworkInfo);
- })
- .then(() => this.setAndConfigureActive())
- .then(() => {
- // Update data connection when Wifi connected/disconnected
- if (extNetworkInfo.type ==
- Ci.nsINetworkInfo.NETWORK_TYPE_WIFI && this.mRil) {
- for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
- this.mRil.getRadioInterface(i).updateRILNetworkInterface();
- }
- }
- })
- .then(() => this._destroyNetwork(extNetworkInfo.name))
- .then(() => {
- // Notify outer modules like MmsService to start the transaction after
- // the configuration of the network interface is done.
- Services.obs.notifyObservers(network.info,
- TOPIC_CONNECTION_STATE_CHANGED,
- this.convertConnectionType(network.info));
- })
- .catch(aError => {
- debug("updateNetworkInterface error: " + aError);
- });
- break;
- }
- },
-
- unregisterNetworkInterface: function(network) {
- if (!(network instanceof Ci.nsINetworkInterface)) {
- throw Components.Exception("Argument must be nsINetworkInterface.",
- Cr.NS_ERROR_INVALID_ARG);
- }
- let networkId = this.getNetworkId(network.info);
- if (!(networkId in this.networkInterfaces)) {
- throw Components.Exception("No network with that type registered.",
- Cr.NS_ERROR_INVALID_ARG);
- }
-
- // This is for in case a network gets unregistered without being
- // DISCONNECTED.
- if (this.isNetworkTypeMobile(network.info.type)) {
- this._cleanupAllHostRoutes(networkId);
- }
-
- delete this.networkInterfaces[networkId];
-
- Services.obs.notifyObservers(network.info, TOPIC_INTERFACE_UNREGISTERED, null);
- debug("Network '" + networkId + "' unregistered.");
- },
-
- _manageOfflineStatus: true,
-
- networkInterfaces: null,
-
- networkInterfaceLinks: null,
-
- _networkTypePriorityList: [Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET,
- Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
- Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE],
- get networkTypePriorityList() {
- return this._networkTypePriorityList;
- },
- set networkTypePriorityList(val) {
- if (val.length != this._networkTypePriorityList.length) {
- throw "Priority list length should equal to " +
- this._networkTypePriorityList.length;
- }
-
- // Check if types in new priority list are valid and also make sure there
- // are no duplicate types.
- let list = [Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET,
- Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
- Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE];
- while (list.length) {
- let type = list.shift();
- if (val.indexOf(type) == -1) {
- throw "There is missing network type";
- }
- }
-
- this._networkTypePriorityList = val;
- },
-
- getPriority: function(type) {
- if (this._networkTypePriorityList.indexOf(type) == -1) {
- // 0 indicates the lowest priority.
- return 0;
- }
-
- return this._networkTypePriorityList.length -
- this._networkTypePriorityList.indexOf(type);
- },
-
- get allNetworkInfo() {
- let allNetworkInfo = {};
-
- for (let networkId in this.networkInterfaces) {
- if (this.networkInterfaces.hasOwnProperty(networkId)) {
- allNetworkInfo[networkId] = this.networkInterfaces[networkId].info;
- }
- }
-
- return allNetworkInfo;
- },
-
- _preferredNetworkType: DEFAULT_PREFERRED_NETWORK_TYPE,
- get preferredNetworkType() {
- return this._preferredNetworkType;
- },
- set preferredNetworkType(val) {
- if ([Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
- Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
- Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET].indexOf(val) == -1) {
- throw "Invalid network type";
- }
- this._preferredNetworkType = val;
- },
-
- _activeNetwork: null,
-
- get activeNetworkInfo() {
- return this._activeNetwork && this._activeNetwork.info;
- },
-
- _overriddenActive: null,
-
- overrideActive: function(network) {
- if ([Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
- Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
- Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET].indexOf(val) == -1) {
- throw "Invalid network type";
- }
-
- this._overriddenActive = network;
- this.setAndConfigureActive();
- },
-
- _updateRoutes: function(oldLinks, newLinks, gateways, interfaceName) {
- // Returns items that are in base but not in target.
- function getDifference(base, target) {
- return base.filter(function(i) { return target.indexOf(i) < 0; });
- }
-
- let addedLinks = getDifference(newLinks, oldLinks);
- let removedLinks = getDifference(oldLinks, newLinks);
-
- if (addedLinks.length === 0 && removedLinks.length === 0) {
- return Promise.resolve();
- }
-
- return this._setHostRoutes(false, removedLinks, interfaceName, gateways)
- .then(this._setHostRoutes(true, addedLinks, interfaceName, gateways));
- },
-
- _setHostRoutes: function(doAdd, ipAddresses, networkName, gateways) {
- let getMaxPrefixLength = (aIp) => {
- return aIp.match(this.REGEXP_IPV4) ? IPV4_MAX_PREFIX_LENGTH : IPV6_MAX_PREFIX_LENGTH;
- }
-
- let promises = [];
-
- ipAddresses.forEach((aIpAddress) => {
- let gateway = this.selectGateway(gateways, aIpAddress);
- if (gateway) {
- promises.push((doAdd)
- ? gNetworkService.modifyRoute(Ci.nsINetworkService.MODIFY_ROUTE_ADD,
- networkName, aIpAddress,
- getMaxPrefixLength(aIpAddress), gateway)
- : gNetworkService.modifyRoute(Ci.nsINetworkService.MODIFY_ROUTE_REMOVE,
- networkName, aIpAddress,
- getMaxPrefixLength(aIpAddress), gateway));
- }
- });
-
- return Promise.all(promises);
- },
-
- isValidatedNetwork: function(aNetworkInfo) {
- let isValid = false;
- try {
- isValid = (this.getNetworkId(aNetworkInfo) in this.networkInterfaces);
- } catch (e) {
- debug("Invalid network interface: " + e);
- }
-
- return isValid;
- },
-
- addHostRoute: function(aNetworkInfo, aHost) {
- if (!this.isValidatedNetwork(aNetworkInfo)) {
- return Promise.reject("Invalid network info.");
- }
-
- return this.resolveHostname(aNetworkInfo, aHost)
- .then((ipAddresses) => {
- let promises = [];
- let networkId = this.getNetworkId(aNetworkInfo);
-
- ipAddresses.forEach((aIpAddress) => {
- let promise =
- this._setHostRoutes(true, [aIpAddress], aNetworkInfo.name, aNetworkInfo.getGateways())
- .then(() => this.networkInterfaceLinks[networkId].extraRoutes.push(aIpAddress));
-
- promises.push(promise);
- });
-
- return Promise.all(promises);
- });
- },
-
- removeHostRoute: function(aNetworkInfo, aHost) {
- if (!this.isValidatedNetwork(aNetworkInfo)) {
- return Promise.reject("Invalid network info.");
- }
-
- return this.resolveHostname(aNetworkInfo, aHost)
- .then((ipAddresses) => {
- let promises = [];
- let networkId = this.getNetworkId(aNetworkInfo);
-
- ipAddresses.forEach((aIpAddress) => {
- let found = this.networkInterfaceLinks[networkId].extraRoutes.indexOf(aIpAddress);
- if (found < 0) {
- return; // continue
- }
-
- let promise =
- this._setHostRoutes(false, [aIpAddress], aNetworkInfo.name, aNetworkInfo.getGateways())
- .then(() => {
- this.networkInterfaceLinks[networkId].extraRoutes.splice(found, 1);
- }, () => {
- // We should remove it even if the operation failed.
- this.networkInterfaceLinks[networkId].extraRoutes.splice(found, 1);
- });
- promises.push(promise);
- });
-
- return Promise.all(promises);
- });
- },
-
- isNetworkTypeSecondaryMobile: function(type) {
- return (type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS ||
- type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL ||
- type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS ||
- type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN ||
- type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA);
- },
-
- isNetworkTypeMobile: function(type) {
- return (type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE ||
- this.isNetworkTypeSecondaryMobile(type));
- },
-
- _handleGateways: function(networkId, gateways) {
- let currentNetworkLinks = this.networkInterfaceLinks[networkId];
- if (currentNetworkLinks.gateways.length == 0 ||
- currentNetworkLinks.compareGateways(gateways)) {
- return Promise.resolve();
- }
-
- let currentExtraRoutes = currentNetworkLinks.extraRoutes;
- return this._cleanupAllHostRoutes(networkId)
- .then(() => {
- // If gateways have changed, re-add extra host routes with new gateways.
- if (currentExtraRoutes.length > 0) {
- this._setHostRoutes(true,
- currentExtraRoutes,
- currentNetworkLinks.interfaceName,
- gateways)
- .then(() => {
- currentNetworkLinks.extraRoutes = currentExtraRoutes;
- });
- }
- });
- },
-
- _cleanupAllHostRoutes: function(networkId) {
- let currentNetworkLinks = this.networkInterfaceLinks[networkId];
- let hostRoutes = currentNetworkLinks.linkRoutes.concat(
- currentNetworkLinks.extraRoutes);
-
- if (hostRoutes.length === 0) {
- return Promise.resolve();
- }
-
- return this._setHostRoutes(false,
- hostRoutes,
- currentNetworkLinks.interfaceName,
- currentNetworkLinks.gateways)
- .catch((aError) => {
- debug("Error (" + aError + ") on _cleanupAllHostRoutes, keep proceeding.");
- })
- .then(() => currentNetworkLinks.resetLinks());
- },
-
- selectGateway: function(gateways, host) {
- for (let i = 0; i < gateways.length; i++) {
- let gateway = gateways[i];
- if (gateway.match(this.REGEXP_IPV4) && host.match(this.REGEXP_IPV4) ||
- gateway.indexOf(":") != -1 && host.indexOf(":") != -1) {
- return gateway;
- }
- }
- return null;
- },
-
- _setSecondaryRoute: function(aDoAdd, aInterfaceName, aRoute) {
- return new Promise((aResolve, aReject) => {
- if (aDoAdd) {
- gNetworkService.addSecondaryRoute(aInterfaceName, aRoute,
- (aSuccess) => {
- if (!aSuccess) {
- aReject("addSecondaryRoute failed");
- return;
- }
- aResolve();
- });
- } else {
- gNetworkService.removeSecondaryRoute(aInterfaceName, aRoute,
- (aSuccess) => {
- if (!aSuccess) {
- debug("removeSecondaryRoute failed")
- }
- // Always resolve.
- aResolve();
- });
- }
- });
- },
-
- setSecondaryDefaultRoute: function(network) {
- let gateways = network.getGateways();
- let promises = [];
-
- for (let i = 0; i < gateways.length; i++) {
- let isIPv6 = (gateways[i].indexOf(":") != -1) ? true : false;
- // First, we need to add a host route to the gateway in the secondary
- // routing table to make the gateway reachable. Host route takes the max
- // prefix and gateway address 'any'.
- let hostRoute = {
- ip: gateways[i],
- prefix: isIPv6 ? IPV6_MAX_PREFIX_LENGTH : IPV4_MAX_PREFIX_LENGTH,
- gateway: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY
- };
- // Now we can add the default route through gateway. Default route takes the
- // min prefix and destination ip 'any'.
- let defaultRoute = {
- ip: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY,
- prefix: 0,
- gateway: gateways[i]
- };
-
- let promise = this._setSecondaryRoute(true, network.name, hostRoute)
- .then(() => this._setSecondaryRoute(true, network.name, defaultRoute));
-
- promises.push(promise);
- }
-
- return Promise.all(promises);
- },
-
- removeSecondaryDefaultRoute: function(network) {
- let gateways = network.getGateways();
- let promises = [];
-
- for (let i = 0; i < gateways.length; i++) {
- let isIPv6 = (gateways[i].indexOf(":") != -1) ? true : false;
- // Remove both default route and host route.
- let defaultRoute = {
- ip: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY,
- prefix: 0,
- gateway: gateways[i]
- };
- let hostRoute = {
- ip: gateways[i],
- prefix: isIPv6 ? IPV6_MAX_PREFIX_LENGTH : IPV4_MAX_PREFIX_LENGTH,
- gateway: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY
- };
-
- let promise = this._setSecondaryRoute(false, network.name, defaultRoute)
- .then(() => this._setSecondaryRoute(false, network.name, hostRoute));
-
- promises.push(promise);
- }
-
- return Promise.all(promises);
- },
-
- /**
- * Determine the active interface and configure it.
- */
- setAndConfigureActive: function() {
- debug("Evaluating whether active network needs to be changed.");
- let oldActive = this._activeNetwork;
-
- if (this._overriddenActive) {
- debug("We have an override for the active network: " +
- this._overriddenActive.info.name);
- // The override was just set, so reconfigure the network.
- if (this._activeNetwork != this._overriddenActive) {
- this._activeNetwork = this._overriddenActive;
- this._setDefaultRouteAndProxy(this._activeNetwork, oldActive);
- Services.obs.notifyObservers(this.activeNetworkInfo,
- TOPIC_ACTIVE_CHANGED, null);
- }
- return;
- }
-
- // The active network is already our preferred type.
- if (this.activeNetworkInfo &&
- this.activeNetworkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED &&
- this.activeNetworkInfo.type == this._preferredNetworkType) {
- debug("Active network is already our preferred type.");
- return this._setDefaultRouteAndProxy(this._activeNetwork, oldActive);
- }
-
- // Find a suitable network interface to activate.
- this._activeNetwork = null;
- let anyConnected = false;
-
- for (let key in this.networkInterfaces) {
- let network = this.networkInterfaces[key];
- if (network.info.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- continue;
- }
- anyConnected = true;
-
- // Set active only for default connections.
- if (network.info.type != Ci.nsINetworkInfo.NETWORK_TYPE_WIFI &&
- network.info.type != Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE &&
- network.info.type != Ci.nsINetworkInfo.NETWORK_TYPE_ETHERNET) {
- continue;
- }
-
- if (network.info.type == this.preferredNetworkType) {
- this._activeNetwork = network;
- debug("Found our preferred type of network: " + network.info.name);
- break;
- }
-
- // Initialize the active network with the first connected network.
- if (!this._activeNetwork) {
- this._activeNetwork = network;
- continue;
- }
-
- // Compare the prioriy between two network types. If found incoming
- // network with higher priority, replace the active network.
- if (this.getPriority(this._activeNetwork.type) < this.getPriority(network.type)) {
- this._activeNetwork = network;
- }
- }
-
- return Promise.resolve()
- .then(() => {
- if (!this._activeNetwork) {
- return Promise.resolve();
- }
-
- return this._setDefaultRouteAndProxy(this._activeNetwork, oldActive);
- })
- .then(() => {
- if (this._activeNetwork != oldActive) {
- Services.obs.notifyObservers(this.activeNetworkInfo,
- TOPIC_ACTIVE_CHANGED, null);
- }
-
- if (this._manageOfflineStatus) {
- Services.io.offline = !anyConnected &&
- (gTetheringService.state ===
- Ci.nsITetheringService.TETHERING_STATE_INACTIVE);
- }
- });
- },
-
- resolveHostname: function(aNetworkInfo, aHostname) {
- // Sanity check for null, undefined and empty string... etc.
- if (!aHostname) {
- return Promise.reject(new Error("hostname is empty: " + aHostname));
- }
-
- if (aHostname.match(this.REGEXP_IPV4) ||
- aHostname.match(this.REGEXP_IPV6)) {
- return Promise.resolve([aHostname]);
- }
-
- // Wrap gDNSService.asyncResolveExtended to a promise, which
- // resolves with an array of ip addresses or rejects with
- // the reason otherwise.
- let hostResolveWrapper = aNetId => {
- return new Promise((aResolve, aReject) => {
- // Callback for gDNSService.asyncResolveExtended.
- let onLookupComplete = (aRequest, aRecord, aStatus) => {
- if (!Components.isSuccessCode(aStatus)) {
- aReject(new Error("Failed to resolve '" + aHostname +
- "', with status: " + aStatus));
- return;
- }
-
- let retval = [];
- while (aRecord.hasMore()) {
- retval.push(aRecord.getNextAddrAsString());
- }
-
- if (!retval.length) {
- aReject(new Error("No valid address after DNS lookup!"));
- return;
- }
-
- debug("hostname is resolved: " + aHostname);
- debug("Addresses: " + JSON.stringify(retval));
-
- aResolve(retval);
- };
-
- debug('Calling gDNSService.asyncResolveExtended: ' + aNetId + ', ' + aHostname);
- gDNSService.asyncResolveExtended(aHostname,
- 0,
- aNetId,
- onLookupComplete,
- Services.tm.mainThread);
- });
- };
-
- // TODO: |getNetId| will be implemented as a sync call in nsINetworkManager
- // once Bug 1141903 is landed.
- return gNetworkService.getNetId(aNetworkInfo.name)
- .then(aNetId => hostResolveWrapper(aNetId));
- },
-
- convertConnectionType: function(aNetworkInfo) {
- // If there is internal interface change (e.g., MOBILE_MMS, MOBILE_SUPL),
- // the function will return null so that it won't trigger type change event
- // in NetworkInformation API.
- if (aNetworkInfo.type != Ci.nsINetworkInterface.NETWORK_TYPE_WIFI &&
- aNetworkInfo.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE &&
- aNetworkInfo.type != Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET) {
- return null;
- }
-
- if (aNetworkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED) {
- return CONNECTION_TYPE_NONE;
- }
-
- switch (aNetworkInfo.type) {
- case Ci.nsINetworkInfo.NETWORK_TYPE_WIFI:
- return CONNECTION_TYPE_WIFI;
- case Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE:
- return CONNECTION_TYPE_CELLULAR;
- case Ci.nsINetworkInterface.NETWORK_TYPE_ETHERNET:
- return CONNECTION_TYPE_ETHERNET;
- }
- },
-
- _setDNS: function(aNetworkInfo) {
- return new Promise((aResolve, aReject) => {
- let dnses = aNetworkInfo.getDnses();
- let gateways = aNetworkInfo.getGateways();
- gNetworkService.setDNS(aNetworkInfo.name, dnses.length, dnses,
- gateways.length, gateways, (aError) => {
- if (aError) {
- aReject("setDNS failed");
- return;
- }
- aResolve();
- });
- });
- },
-
- _setMtu: function(aNetworkInfo) {
- return new Promise((aResolve, aReject) => {
- gNetworkService.setMtu(aNetworkInfo.name, aNetworkInfo.mtu, (aSuccess) => {
- if (!aSuccess) {
- debug("setMtu failed");
- }
- // Always resolve.
- aResolve();
- });
- });
- },
-
- _createNetwork: function(aInterfaceName) {
- return new Promise((aResolve, aReject) => {
- gNetworkService.createNetwork(aInterfaceName, (aSuccess) => {
- if (!aSuccess) {
- aReject("createNetwork failed");
- return;
- }
- aResolve();
- });
- });
- },
-
- _destroyNetwork: function(aInterfaceName) {
- return new Promise((aResolve, aReject) => {
- gNetworkService.destroyNetwork(aInterfaceName, (aSuccess) => {
- if (!aSuccess) {
- debug("destroyNetwork failed")
- }
- // Always resolve.
- aResolve();
- });
- });
- },
-
- _resetRoutingTable: function(aInterfaceName) {
- return new Promise((aResolve, aReject) => {
- gNetworkService.resetRoutingTable(aInterfaceName, (aSuccess) => {
- if (!aSuccess) {
- debug("resetRoutingTable failed");
- }
- // Always resolve.
- aResolve();
- });
- });
- },
-
- _removeDefaultRoute: function(aNetworkInfo) {
- return new Promise((aResolve, aReject) => {
- let gateways = aNetworkInfo.getGateways();
- gNetworkService.removeDefaultRoute(aNetworkInfo.name, gateways.length,
- gateways, (aSuccess) => {
- if (!aSuccess) {
- debug("removeDefaultRoute failed");
- }
- // Always resolve.
- aResolve();
- });
- });
- },
-
- _setDefaultRouteAndProxy: function(aNetwork, aOldNetwork) {
- if (aOldNetwork) {
- return this._removeDefaultRoute(aOldNetwork.info)
- .then(() => this._setDefaultRouteAndProxy(aNetwork, null));
- }
-
- return new Promise((aResolve, aReject) => {
- let networkInfo = aNetwork.info;
- let gateways = networkInfo.getGateways();
-
- gNetworkService.setDefaultRoute(networkInfo.name, gateways.length, gateways,
- (aSuccess) => {
- if (!aSuccess) {
- gNetworkService.destroyNetwork(networkInfo.name, function() {
- aReject("setDefaultRoute failed");
- });
- return;
- }
- this.setNetworkProxy(aNetwork);
- aResolve();
- });
- });
- },
-
- setNetworkProxy: function(aNetwork) {
- try {
- if (!aNetwork.httpProxyHost || aNetwork.httpProxyHost === "") {
- // Sets direct connection to internet.
- this.clearNetworkProxy();
-
- debug("No proxy support for " + aNetwork.info.name + " network interface.");
- return;
- }
-
- debug("Going to set proxy settings for " + aNetwork.info.name + " network interface.");
- // Sets manual proxy configuration.
- Services.prefs.setIntPref("network.proxy.type", MANUAL_PROXY_CONFIGURATION);
-
- // Do not use this proxy server for all protocols.
- Services.prefs.setBoolPref("network.proxy.share_proxy_settings", false);
- Services.prefs.setCharPref("network.proxy.http", aNetwork.httpProxyHost);
- Services.prefs.setCharPref("network.proxy.ssl", aNetwork.httpProxyHost);
- let port = aNetwork.httpProxyPort === 0 ? 8080 : aNetwork.httpProxyPort;
- Services.prefs.setIntPref("network.proxy.http_port", port);
- Services.prefs.setIntPref("network.proxy.ssl_port", port);
- } catch(ex) {
- debug("Exception " + ex + ". Unable to set proxy setting for " +
- aNetwork.info.name + " network interface.");
- }
- },
-
- clearNetworkProxy: function() {
- debug("Going to clear all network proxy.");
-
- Services.prefs.clearUserPref("network.proxy.type");
- Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
- Services.prefs.clearUserPref("network.proxy.http");
- Services.prefs.clearUserPref("network.proxy.http_port");
- Services.prefs.clearUserPref("network.proxy.ssl");
- Services.prefs.clearUserPref("network.proxy.ssl_port");
- },
-};
-
-var CaptivePortalDetectionHelper = (function() {
-
- const EVENT_CONNECT = "Connect";
- const EVENT_DISCONNECT = "Disconnect";
- let _ongoingInterface = null;
- let _available = ("nsICaptivePortalDetector" in Ci);
- let getService = function() {
- return Cc['@mozilla.org/toolkit/captive-detector;1']
- .getService(Ci.nsICaptivePortalDetector);
- };
-
- let _performDetection = function(interfaceName, callback) {
- let capService = getService();
- let capCallback = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
- prepare: function() {
- capService.finishPreparation(interfaceName);
- },
- complete: function(success) {
- _ongoingInterface = null;
- callback(success);
- }
- };
-
- // Abort any unfinished captive portal detection.
- if (_ongoingInterface != null) {
- capService.abort(_ongoingInterface);
- _ongoingInterface = null;
- }
- try {
- capService.checkCaptivePortal(interfaceName, capCallback);
- _ongoingInterface = interfaceName;
- } catch (e) {
- debug('Fail to detect captive portal due to: ' + e.message);
- }
- };
-
- let _abort = function(interfaceName) {
- if (_ongoingInterface !== interfaceName) {
- return;
- }
-
- let capService = getService();
- capService.abort(_ongoingInterface);
- _ongoingInterface = null;
- };
-
- return {
- EVENT_CONNECT: EVENT_CONNECT,
- EVENT_DISCONNECT: EVENT_DISCONNECT,
- notify: function(eventType, network) {
- switch (eventType) {
- case EVENT_CONNECT:
- // perform captive portal detection on wifi interface
- if (_available && network &&
- network.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
- _performDetection(network.name, function() {
- // TODO: bug 837600
- // We can disconnect wifi in here if user abort the login procedure.
- });
- }
-
- break;
- case EVENT_DISCONNECT:
- if (_available &&
- network.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
- _abort(network.name);
- }
- break;
- }
- }
- };
-}());
-
-XPCOMUtils.defineLazyGetter(NetworkManager.prototype, "mRil", function() {
- try {
- return Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
- } catch (e) {}
-
- return null;
-});
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
diff --git a/dom/system/gonk/NetworkManager.manifest b/dom/system/gonk/NetworkManager.manifest
deleted file mode 100644
index 995fa6559..000000000
--- a/dom/system/gonk/NetworkManager.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-# NetworkManager.js
-component {1ba9346b-53b5-4660-9dc6-58f0b258d0a6} NetworkManager.js
-contract @mozilla.org/network/manager;1 {1ba9346b-53b5-4660-9dc6-58f0b258d0a6}
diff --git a/dom/system/gonk/NetworkService.js b/dom/system/gonk/NetworkService.js
deleted file mode 100644
index 7147f40c7..000000000
--- a/dom/system/gonk/NetworkService.js
+++ /dev/null
@@ -1,862 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-const NETWORKSERVICE_CONTRACTID = "@mozilla.org/network/service;1";
-const NETWORKSERVICE_CID = Components.ID("{48c13741-aec9-4a86-8962-432011708261}");
-
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const PREF_NETWORK_DEBUG_ENABLED = "network.debugging.enabled";
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkWorker",
- "@mozilla.org/network/worker;1",
- "nsINetworkWorker");
-
-// 1xx - Requested action is proceeding
-const NETD_COMMAND_PROCEEDING = 100;
-// 2xx - Requested action has been successfully completed
-const NETD_COMMAND_OKAY = 200;
-// 4xx - The command is accepted but the requested action didn't
-// take place.
-const NETD_COMMAND_FAIL = 400;
-// 5xx - The command syntax or parameters error
-const NETD_COMMAND_ERROR = 500;
-// 6xx - Unsolicited broadcasts
-const NETD_COMMAND_UNSOLICITED = 600;
-
-const WIFI_CTRL_INTERFACE = "wl0.1";
-
-var debug;
-function updateDebug() {
- let debugPref = false; // set default value here.
- try {
- debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
- } catch (e) {}
-
- if (debugPref) {
- debug = function(s) {
- dump("-*- NetworkService: " + s + "\n");
- };
- } else {
- debug = function(s) {};
- }
-}
-updateDebug();
-
-function netdResponseType(aCode) {
- return Math.floor(aCode / 100) * 100;
-}
-
-function isError(aCode) {
- let type = netdResponseType(aCode);
- return (type !== NETD_COMMAND_PROCEEDING && type !== NETD_COMMAND_OKAY);
-}
-
-function Task(aId, aParams, aSetupFunction) {
- this.id = aId;
- this.params = aParams;
- this.setupFunction = aSetupFunction;
-}
-
-function NetworkWorkerRequestQueue(aNetworkService) {
- this.networkService = aNetworkService;
- this.tasks = [];
-}
-NetworkWorkerRequestQueue.prototype = {
- runQueue: function() {
- if (this.tasks.length === 0) {
- return;
- }
-
- let task = this.tasks[0];
- debug("run task id: " + task.id);
-
- if (typeof task.setupFunction === 'function') {
- // If setupFunction returns false, skip sending to Network Worker but call
- // handleWorkerMessage() directly with task id, as if the response was
- // returned from Network Worker.
- if (!task.setupFunction()) {
- this.networkService.handleWorkerMessage({id: task.id});
- return;
- }
- }
-
- gNetworkWorker.postMessage(task.params);
- },
-
- enqueue: function(aId, aParams, aSetupFunction) {
- debug("enqueue id: " + aId);
- this.tasks.push(new Task(aId, aParams, aSetupFunction));
-
- if (this.tasks.length === 1) {
- this.runQueue();
- }
- },
-
- dequeue: function(aId) {
- debug("dequeue id: " + aId);
-
- if (!this.tasks.length || this.tasks[0].id != aId) {
- debug("Id " + aId + " is not on top of the queue");
- return;
- }
-
- this.tasks.shift();
- if (this.tasks.length > 0) {
- // Run queue on the next tick.
- Services.tm.currentThread.dispatch(() => {
- this.runQueue();
- }, Ci.nsIThread.DISPATCH_NORMAL);
- }
- }
-};
-
-
-/**
- * This component watches for network interfaces changing state and then
- * adjusts routes etc. accordingly.
- */
-function NetworkService() {
- debug("Starting NetworkService.");
-
- let self = this;
-
- if (gNetworkWorker) {
- let networkListener = {
- onEvent: function(aEvent) {
- self.handleWorkerMessage(aEvent);
- }
- };
- gNetworkWorker.start(networkListener);
- }
- // Callbacks to invoke when a reply arrives from the net_worker.
- this.controlCallbacks = Object.create(null);
-
- this.addedRoutes = new Map();
- this.netWorkerRequestQueue = new NetworkWorkerRequestQueue(this);
- this.shutdown = false;
-
- Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
-}
-
-NetworkService.prototype = {
- classID: NETWORKSERVICE_CID,
- classInfo: XPCOMUtils.generateCI({classID: NETWORKSERVICE_CID,
- contractID: NETWORKSERVICE_CONTRACTID,
- classDescription: "Network Service",
- interfaces: [Ci.nsINetworkService]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkService,
- Ci.nsIObserver]),
-
- addedRoutes: null,
-
- shutdown: false,
-
- // nsIObserver
-
- observe: function(aSubject, aTopic, aData) {
- switch (aTopic) {
- case TOPIC_PREF_CHANGED:
- if (aData === PREF_NETWORK_DEBUG_ENABLED) {
- updateDebug();
- }
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- debug("NetworkService shutdown");
- this.shutdown = true;
- if (gNetworkWorker) {
- gNetworkWorker.shutdown();
- gNetworkWorker = null;
- }
-
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
- break;
- }
- },
-
- // Helpers
-
- idgen: 0,
- controlMessage: function(aParams, aCallback, aSetupFunction) {
- if (this.shutdown) {
- return;
- }
-
- let id = this.idgen++;
- aParams.id = id;
- if (aCallback) {
- this.controlCallbacks[id] = aCallback;
- }
-
- // For now, we use aSetupFunction to determine if this command needs to be
- // queued or not.
- if (aSetupFunction) {
- this.netWorkerRequestQueue.enqueue(id, aParams, aSetupFunction);
- return;
- }
-
- if (gNetworkWorker) {
- gNetworkWorker.postMessage(aParams);
- }
- },
-
- handleWorkerMessage: function(aResponse) {
- debug("NetworkManager received message from worker: " + JSON.stringify(aResponse));
- let id = aResponse.id;
- if (aResponse.broadcast === true) {
- Services.obs.notifyObservers(null, aResponse.topic, aResponse.reason);
- return;
- }
- let callback = this.controlCallbacks[id];
- if (callback) {
- callback.call(this, aResponse);
- delete this.controlCallbacks[id];
- }
-
- this.netWorkerRequestQueue.dequeue(id);
- },
-
- // nsINetworkService
-
- getNetworkInterfaceStats: function(aInterfaceName, aCallback) {
- debug("getNetworkInterfaceStats for " + aInterfaceName);
-
- let file = new FileUtils.File("/proc/net/dev");
- if (!file) {
- aCallback.networkStatsAvailable(false, 0, 0, Date.now());
- return;
- }
-
- NetUtil.asyncFetch({
- uri: NetUtil.newURI(file),
- loadUsingSystemPrincipal: true
- }, function(inputStream, status) {
- let rxBytes = 0,
- txBytes = 0,
- now = Date.now();
-
- if (Components.isSuccessCode(status)) {
- // Find record for corresponding interface.
- let statExpr = /(\S+): +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+/;
- let data =
- NetUtil.readInputStreamToString(inputStream, inputStream.available())
- .split("\n");
- for (let i = 2; i < data.length; i++) {
- let parseResult = statExpr.exec(data[i]);
- if (parseResult && parseResult[1] === aInterfaceName) {
- rxBytes = parseInt(parseResult[2], 10);
- txBytes = parseInt(parseResult[3], 10);
- break;
- }
- }
- }
-
- // netd always return success even interface doesn't exist.
- aCallback.networkStatsAvailable(true, rxBytes, txBytes, now);
- });
- },
-
- setNetworkTetheringAlarm(aEnable, aInterface) {
- // Method called when enabling disabling tethering, it checks if there is
- // some alarm active and move from interfaceAlarm to globalAlarm because
- // interfaceAlarm doens't work in tethering scenario due to forwarding.
- debug("setNetworkTetheringAlarm for tethering" + aEnable);
-
- let filename = aEnable ? "/proc/net/xt_quota/" + aInterface + "Alert" :
- "/proc/net/xt_quota/globalAlert";
-
- let file = new FileUtils.File(filename);
- if (!file) {
- return;
- }
-
- NetUtil.asyncFetch({
- uri: NetUtil.newURI(file),
- loadUsingSystemPrincipal: true
- }, (inputStream, status) => {
- if (Components.isSuccessCode(status)) {
- let data = NetUtil.readInputStreamToString(inputStream, inputStream.available())
- .split("\n");
- if (data) {
- let threshold = parseInt(data[0], 10);
-
- this._setNetworkTetheringAlarm(aEnable, aInterface, threshold);
- }
- }
- });
- },
-
- _setNetworkTetheringAlarm(aEnable, aInterface, aThreshold, aCallback) {
- debug("_setNetworkTetheringAlarm for tethering" + aEnable);
-
- let cmd = aEnable ? "setTetheringAlarm" : "removeTetheringAlarm";
-
- let params = {
- cmd: cmd,
- ifname: aInterface,
- threshold: aThreshold,
- };
-
- this.controlMessage(params, function(aData) {
- let code = aData.resultCode;
- let reason = aData.resultReason;
- let enableString = aEnable ? "Enable" : "Disable";
- debug(enableString + " tethering Alarm result: Code " + code + " reason " + reason);
- if (aCallback) {
- aCallback.networkUsageAlarmResult(null);
- }
- });
- },
-
- setNetworkInterfaceAlarm: function(aInterfaceName, aThreshold, aCallback) {
- if (!aInterfaceName) {
- aCallback.networkUsageAlarmResult(-1);
- return;
- }
-
- let self = this;
- this._disableNetworkInterfaceAlarm(aInterfaceName, function(aResult) {
- if (aThreshold < 0) {
- if (!isError(aResult.resultCode)) {
- aCallback.networkUsageAlarmResult(null);
- return;
- }
- aCallback.networkUsageAlarmResult(aResult.reason);
- return
- }
-
- // Check if tethering is enabled
- let params = {
- cmd: "getTetheringStatus"
- };
-
- self.controlMessage(params, function(aResult) {
- if (isError(aResult.resultCode)) {
- aCallback.networkUsageAlarmResult(aResult.reason);
- return;
- }
-
- if (aResult.resultReason.indexOf('started') == -1) {
- // Tethering disabled, set interfaceAlarm
- self._setNetworkInterfaceAlarm(aInterfaceName, aThreshold, aCallback);
- return;
- }
-
- // Tethering enabled, set globalAlarm
- self._setNetworkTetheringAlarm(true, aInterfaceName, aThreshold, aCallback);
- });
- });
- },
-
- _setNetworkInterfaceAlarm: function(aInterfaceName, aThreshold, aCallback) {
- debug("setNetworkInterfaceAlarm for " + aInterfaceName + " at " + aThreshold + "bytes");
-
- let params = {
- cmd: "setNetworkInterfaceAlarm",
- ifname: aInterfaceName,
- threshold: aThreshold
- };
-
- params.report = true;
-
- this.controlMessage(params, function(aResult) {
- if (!isError(aResult.resultCode)) {
- aCallback.networkUsageAlarmResult(null);
- return;
- }
-
- this._enableNetworkInterfaceAlarm(aInterfaceName, aThreshold, aCallback);
- });
- },
-
- _enableNetworkInterfaceAlarm: function(aInterfaceName, aThreshold, aCallback) {
- debug("enableNetworkInterfaceAlarm for " + aInterfaceName + " at " + aThreshold + "bytes");
-
- let params = {
- cmd: "enableNetworkInterfaceAlarm",
- ifname: aInterfaceName,
- threshold: aThreshold
- };
-
- params.report = true;
-
- this.controlMessage(params, function(aResult) {
- if (!isError(aResult.resultCode)) {
- aCallback.networkUsageAlarmResult(null);
- return;
- }
- aCallback.networkUsageAlarmResult(aResult.reason);
- });
- },
-
- _disableNetworkInterfaceAlarm: function(aInterfaceName, aCallback) {
- debug("disableNetworkInterfaceAlarm for " + aInterfaceName);
-
- let params = {
- cmd: "disableNetworkInterfaceAlarm",
- ifname: aInterfaceName,
- };
-
- params.report = true;
-
- this.controlMessage(params, function(aResult) {
- aCallback(aResult);
- });
- },
-
- setWifiOperationMode: function(aInterfaceName, aMode, aCallback) {
- debug("setWifiOperationMode on " + aInterfaceName + " to " + aMode);
-
- let params = {
- cmd: "setWifiOperationMode",
- ifname: aInterfaceName,
- mode: aMode
- };
-
- params.report = true;
-
- this.controlMessage(params, function(aResult) {
- if (isError(aResult.resultCode)) {
- aCallback.wifiOperationModeResult("netd command error");
- } else {
- aCallback.wifiOperationModeResult(null);
- }
- });
- },
-
- resetRoutingTable: function(aInterfaceName, aCallback) {
- let options = {
- cmd: "removeNetworkRoute",
- ifname: aInterfaceName
- };
-
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- setDNS: function(aInterfaceName, aDnsesCount, aDnses, aGatewaysCount,
- aGateways, aCallback) {
- debug("Going to set DNS to " + aInterfaceName);
- let options = {
- cmd: "setDNS",
- ifname: aInterfaceName,
- domain: "mozilla." + aInterfaceName + ".domain",
- dnses: aDnses,
- gateways: aGateways
- };
- this.controlMessage(options, function(aResult) {
- aCallback.setDnsResult(aResult.success ? null : aResult.reason);
- });
- },
-
- setDefaultRoute: function(aInterfaceName, aCount, aGateways, aCallback) {
- debug("Going to change default route to " + aInterfaceName);
- let options = {
- cmd: "setDefaultRoute",
- ifname: aInterfaceName,
- gateways: aGateways
- };
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- removeDefaultRoute: function(aInterfaceName, aCount, aGateways, aCallback) {
- debug("Remove default route for " + aInterfaceName);
- let options = {
- cmd: "removeDefaultRoute",
- ifname: aInterfaceName,
- gateways: aGateways
- };
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- _routeToString: function(aInterfaceName, aHost, aPrefixLength, aGateway) {
- return aHost + "-" + aPrefixLength + "-" + aGateway + "-" + aInterfaceName;
- },
-
- modifyRoute: function(aAction, aInterfaceName, aHost, aPrefixLength, aGateway) {
- let command;
-
- switch (aAction) {
- case Ci.nsINetworkService.MODIFY_ROUTE_ADD:
- command = 'addHostRoute';
- break;
- case Ci.nsINetworkService.MODIFY_ROUTE_REMOVE:
- command = 'removeHostRoute';
- break;
- default:
- debug('Unknown action: ' + aAction);
- return Promise.reject();
- }
-
- let route = this._routeToString(aInterfaceName, aHost, aPrefixLength, aGateway);
- let setupFunc = () => {
- let count = this.addedRoutes.get(route);
- debug(command + ": " + route + " -> " + count);
-
- // Return false if there is no need to send the command to network worker.
- if ((aAction == Ci.nsINetworkService.MODIFY_ROUTE_ADD && count) ||
- (aAction == Ci.nsINetworkService.MODIFY_ROUTE_REMOVE &&
- (!count || count > 1))) {
- return false;
- }
-
- return true;
- };
-
- debug(command + " " + aHost + " on " + aInterfaceName);
- let options = {
- cmd: command,
- ifname: aInterfaceName,
- gateway: aGateway,
- prefixLength: aPrefixLength,
- ip: aHost
- };
-
- return new Promise((aResolve, aReject) => {
- this.controlMessage(options, (aData) => {
- let count = this.addedRoutes.get(route);
-
- // Remove route from addedRoutes on success or failure.
- if (aAction == Ci.nsINetworkService.MODIFY_ROUTE_REMOVE) {
- if (count > 1) {
- this.addedRoutes.set(route, count - 1);
- } else {
- this.addedRoutes.delete(route);
- }
- }
-
- if (aData.error) {
- aReject(aData.reason);
- return;
- }
-
- if (aAction == Ci.nsINetworkService.MODIFY_ROUTE_ADD) {
- this.addedRoutes.set(route, count ? count + 1 : 1);
- }
-
- aResolve();
- }, setupFunc);
- });
- },
-
- addSecondaryRoute: function(aInterfaceName, aRoute, aCallback) {
- debug("Going to add route to secondary table on " + aInterfaceName);
- let options = {
- cmd: "addSecondaryRoute",
- ifname: aInterfaceName,
- ip: aRoute.ip,
- prefix: aRoute.prefix,
- gateway: aRoute.gateway
- };
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- removeSecondaryRoute: function(aInterfaceName, aRoute, aCallback) {
- debug("Going to remove route from secondary table on " + aInterfaceName);
- let options = {
- cmd: "removeSecondaryRoute",
- ifname: aInterfaceName,
- ip: aRoute.ip,
- prefix: aRoute.prefix,
- gateway: aRoute.gateway
- };
- this.controlMessage(options, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- // Enable/Disable DHCP server.
- setDhcpServer: function(aEnabled, aConfig, aCallback) {
- if (null === aConfig) {
- aConfig = {};
- }
-
- aConfig.cmd = "setDhcpServer";
- aConfig.enabled = aEnabled;
-
- this.controlMessage(aConfig, function(aResponse) {
- if (!aResponse.success) {
- aCallback.dhcpServerResult('Set DHCP server error');
- return;
- }
- aCallback.dhcpServerResult(null);
- });
- },
-
- // Enable/disable WiFi tethering by sending commands to netd.
- setWifiTethering: function(aEnable, aConfig, aCallback) {
- // config should've already contained:
- // .ifname
- // .internalIfname
- // .externalIfname
- aConfig.wifictrlinterfacename = WIFI_CTRL_INTERFACE;
- aConfig.cmd = "setWifiTethering";
-
- // The callback function in controlMessage may not be fired immediately.
- this.controlMessage(aConfig, (aData) => {
- let code = aData.resultCode;
- let reason = aData.resultReason;
- let enable = aData.enable;
- let enableString = aEnable ? "Enable" : "Disable";
-
- debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
-
- this.setNetworkTetheringAlarm(aEnable, aConfig.externalIfname);
-
- if (isError(code)) {
- aCallback.wifiTetheringEnabledChange("netd command error");
- } else {
- aCallback.wifiTetheringEnabledChange(null);
- }
- });
- },
-
- // Enable/disable USB tethering by sending commands to netd.
- setUSBTethering: function(aEnable, aConfig, aCallback) {
- aConfig.cmd = "setUSBTethering";
- // The callback function in controlMessage may not be fired immediately.
- this.controlMessage(aConfig, (aData) => {
- let code = aData.resultCode;
- let reason = aData.resultReason;
- let enable = aData.enable;
- let enableString = aEnable ? "Enable" : "Disable";
-
- debug(enableString + " USB tethering result: Code " + code + " reason " + reason);
-
- this.setNetworkTetheringAlarm(aEnable, aConfig.externalIfname);
-
- if (isError(code)) {
- aCallback.usbTetheringEnabledChange("netd command error");
- } else {
- aCallback.usbTetheringEnabledChange(null);
- }
- });
- },
-
- // Switch usb function by modifying property of persist.sys.usb.config.
- enableUsbRndis: function(aEnable, aCallback) {
- debug("enableUsbRndis: " + aEnable);
-
- let params = {
- cmd: "enableUsbRndis",
- enable: aEnable
- };
- // Ask net work to report the result when this value is set to true.
- if (aCallback) {
- params.report = true;
- } else {
- params.report = false;
- }
-
- // The callback function in controlMessage may not be fired immediately.
- //this._usbTetheringAction = TETHERING_STATE_ONGOING;
- this.controlMessage(params, function(aData) {
- aCallback.enableUsbRndisResult(aData.result, aData.enable);
- });
- },
-
- updateUpStream: function(aPrevious, aCurrent, aCallback) {
- let params = {
- cmd: "updateUpStream",
- preInternalIfname: aPrevious.internalIfname,
- preExternalIfname: aPrevious.externalIfname,
- curInternalIfname: aCurrent.internalIfname,
- curExternalIfname: aCurrent.externalIfname
- };
-
- this.controlMessage(params, function(aData) {
- let code = aData.resultCode;
- let reason = aData.resultReason;
- debug("updateUpStream result: Code " + code + " reason " + reason);
- aCallback.updateUpStreamResult(!isError(code), aData.curExternalIfname);
- });
- },
-
- getInterfaces: function(callback) {
- let params = {
- cmd: "getInterfaces",
- isAsync: true
- };
-
- this.controlMessage(params, function(data) {
- debug("getInterfaces result: " + JSON.stringify(data));
- let success = !isError(data.resultCode);
- callback.getInterfacesResult(success, data.interfaceList);
- });
- },
-
- getInterfaceConfig: function(ifname, callback) {
- let params = {
- cmd: "getInterfaceConfig",
- ifname: ifname,
- isAsync: true
- };
-
- this.controlMessage(params, function(data) {
- debug("getInterfaceConfig result: " + JSON.stringify(data));
- let success = !isError(data.resultCode);
- let result = { ip: data.ipAddr,
- prefix: data.prefixLength,
- link: data.flag,
- mac: data.macAddr };
- callback.getInterfaceConfigResult(success, result);
- });
- },
-
- setInterfaceConfig: function(config, callback) {
- config.cmd = "setInterfaceConfig";
- config.isAsync = true;
-
- this.controlMessage(config, function(data) {
- debug("setInterfaceConfig result: " + JSON.stringify(data));
- let success = !isError(data.resultCode);
- callback.setInterfaceConfigResult(success);
- });
- },
-
- configureInterface: function(aConfig, aCallback) {
- let params = {
- cmd: "configureInterface",
- ifname: aConfig.ifname,
- ipaddr: aConfig.ipaddr,
- mask: aConfig.mask,
- gateway_long: aConfig.gateway,
- dns1_long: aConfig.dns1,
- dns2_long: aConfig.dns2,
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- dhcpRequest: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "dhcpRequest",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.dhcpRequestResult(!aResult.error, aResult.error ? null : aResult);
- });
- },
-
- stopDhcp: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "stopDhcp",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- enableInterface: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "enableInterface",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- disableInterface: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "disableInterface",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- resetConnections: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "resetConnections",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- createNetwork: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "createNetwork",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- destroyNetwork: function(aInterfaceName, aCallback) {
- let params = {
- cmd: "destroyNetwork",
- ifname: aInterfaceName
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- },
-
- getNetId: function(aInterfaceName) {
- let params = {
- cmd: "getNetId",
- ifname: aInterfaceName
- };
-
- return new Promise((aResolve, aReject) => {
- this.controlMessage(params, result => {
- if (result.error) {
- aReject(result.reason);
- return;
- }
- aResolve(result.netId);
- });
- });
- },
-
- setMtu: function (aInterfaceName, aMtu, aCallback) {
- debug("Set MTU on " + aInterfaceName + ": " + aMtu);
-
- let params = {
- cmd: "setMtu",
- ifname: aInterfaceName,
- mtu: aMtu
- };
-
- this.controlMessage(params, function(aResult) {
- aCallback.nativeCommandResult(!aResult.error);
- });
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkService]);
diff --git a/dom/system/gonk/NetworkService.manifest b/dom/system/gonk/NetworkService.manifest
deleted file mode 100644
index caf8f2554..000000000
--- a/dom/system/gonk/NetworkService.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-# NetworkService.js
-component {48c13741-aec9-4a86-8962-432011708261} NetworkService.js
-contract @mozilla.org/network/service;1 {48c13741-aec9-4a86-8962-432011708261}
diff --git a/dom/system/gonk/NetworkUtils.cpp b/dom/system/gonk/NetworkUtils.cpp
deleted file mode 100644
index d661368b8..000000000
--- a/dom/system/gonk/NetworkUtils.cpp
+++ /dev/null
@@ -1,2973 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "NetworkUtils.h"
-
-#include "mozilla/Sprintf.h"
-#include "SystemProperty.h"
-
-#include <android/log.h>
-#include <limits>
-#include "mozilla/dom/network/NetUtils.h"
-#include "mozilla/fallible.h"
-#include "base/task.h"
-
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h> // struct addrinfo
-#include <sys/socket.h> // getaddrinfo(), freeaddrinfo()
-#include <netdb.h>
-#include <arpa/inet.h> // inet_ntop()
-
-#define _DEBUG 0
-
-#define WARN(args...) __android_log_print(ANDROID_LOG_WARN, "NetworkUtils", ## args)
-#define ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "NetworkUtils", ## args)
-
-#if _DEBUG
-#define NU_DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "NetworkUtils" , ## args)
-#else
-#define NU_DBG(args...)
-#endif
-
-using namespace mozilla::dom;
-using namespace mozilla::ipc;
-using mozilla::system::Property;
-
-static const char* PERSIST_SYS_USB_CONFIG_PROPERTY = "persist.sys.usb.config";
-static const char* SYS_USB_CONFIG_PROPERTY = "sys.usb.config";
-static const char* SYS_USB_STATE_PROPERTY = "sys.usb.state";
-
-static const char* USB_FUNCTION_RNDIS = "rndis";
-static const char* USB_FUNCTION_ADB = "adb";
-
-// Use this command to continue the function chain.
-static const char* DUMMY_COMMAND = "tether status";
-
-// IPV6 Tethering is not supported in AOSP, use the property to
-// identify vendor specific support in IPV6. We can remove this flag
-// once upstream Android support IPV6 in tethering.
-static const char* IPV6_TETHERING = "ro.tethering.ipv6";
-
-// Retry 20 times (2 seconds) for usb state transition.
-static const uint32_t USB_FUNCTION_RETRY_TIMES = 20;
-// Check "sys.usb.state" every 100ms.
-static const uint32_t USB_FUNCTION_RETRY_INTERVAL = 100;
-
-// 1xx - Requested action is proceeding
-static const uint32_t NETD_COMMAND_PROCEEDING = 100;
-// 2xx - Requested action has been successfully completed
-static const uint32_t NETD_COMMAND_OKAY = 200;
-// 4xx - The command is accepted but the requested action didn't
-// take place.
-static const uint32_t NETD_COMMAND_FAIL = 400;
-// 5xx - The command syntax or parameters error
-static const uint32_t NETD_COMMAND_ERROR = 500;
-// 6xx - Unsolicited broadcasts
-static const uint32_t NETD_COMMAND_UNSOLICITED = 600;
-
-// Broadcast messages
-static const uint32_t NETD_COMMAND_INTERFACE_CHANGE = 600;
-static const uint32_t NETD_COMMAND_BANDWIDTH_CONTROLLER = 601;
-
-static const char* INTERFACE_DELIMIT = ",";
-static const char* USB_CONFIG_DELIMIT = ",";
-static const char* NETD_MESSAGE_DELIMIT = " ";
-
-static const uint32_t BUF_SIZE = 1024;
-
-static const int32_t SUCCESS = 0;
-
-static uint32_t SDK_VERSION;
-static uint32_t SUPPORT_IPV6_TETHERING;
-
-struct IFProperties {
- char gateway[Property::VALUE_MAX_LENGTH];
- char dns1[Property::VALUE_MAX_LENGTH];
- char dns2[Property::VALUE_MAX_LENGTH];
-};
-
-struct CurrentCommand {
- CommandChain* chain;
- CommandCallback callback;
- char command[MAX_COMMAND_SIZE];
-};
-
-typedef Tuple3<NetdCommand*, CommandChain*, CommandCallback> QueueData;
-
-#define GET_CURRENT_NETD_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a)
-#define GET_CURRENT_CHAIN (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].b)
-#define GET_CURRENT_CALLBACK (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].c)
-#define GET_CURRENT_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a->mData)
-
-// A macro for native function call return value check.
-// For native function call, non-zero return value means failure.
-#define RETURN_IF_FAILED(rv) do { \
- if (SUCCESS != rv) { \
- return rv; \
- } \
-} while (0);
-
-#define WARN_IF_FAILED(rv) do { \
- if (SUCCESS != rv) { \
- WARN("Error (%d) occurred in %s (%s:%d)", rv, __PRETTY_FUNCTION__, __FILE__, __LINE__); \
- } \
-} while (0);
-
-static NetworkUtils* gNetworkUtils;
-static nsTArray<QueueData> gCommandQueue;
-static CurrentCommand gCurrentCommand;
-static bool gPending = false;
-static nsTArray<nsCString> gReason;
-static NetworkParams *gWifiTetheringParms = 0;
-
-static nsTArray<CommandChain*> gCommandChainQueue;
-
-const CommandFunc NetworkUtils::sWifiEnableChain[] = {
- NetworkUtils::clearWifiTetherParms,
- NetworkUtils::wifiFirmwareReload,
- NetworkUtils::startAccessPointDriver,
- NetworkUtils::setAccessPoint,
- NetworkUtils::startSoftAP,
- NetworkUtils::setConfig,
- NetworkUtils::tetherInterface,
- NetworkUtils::addInterfaceToLocalNetwork,
- NetworkUtils::addRouteToLocalNetwork,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::tetheringStatus,
- NetworkUtils::startTethering,
- NetworkUtils::setDnsForwarders,
- NetworkUtils::enableNat,
- NetworkUtils::wifiTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sWifiDisableChain[] = {
- NetworkUtils::clearWifiTetherParms,
- NetworkUtils::stopSoftAP,
- NetworkUtils::stopAccessPointDriver,
- NetworkUtils::wifiFirmwareReload,
- NetworkUtils::untetherInterface,
- NetworkUtils::removeInterfaceFromLocalNetwork,
- NetworkUtils::preTetherInterfaceList,
- NetworkUtils::postTetherInterfaceList,
- NetworkUtils::disableNat,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::stopTethering,
- NetworkUtils::wifiTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sWifiFailChain[] = {
- NetworkUtils::clearWifiTetherParms,
- NetworkUtils::stopSoftAP,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::stopTethering
-};
-
-const CommandFunc NetworkUtils::sWifiRetryChain[] = {
- NetworkUtils::clearWifiTetherParms,
- NetworkUtils::stopSoftAP,
- NetworkUtils::stopTethering,
-
- // sWifiEnableChain:
- NetworkUtils::wifiFirmwareReload,
- NetworkUtils::startAccessPointDriver,
- NetworkUtils::setAccessPoint,
- NetworkUtils::startSoftAP,
- NetworkUtils::setConfig,
- NetworkUtils::tetherInterface,
- NetworkUtils::addInterfaceToLocalNetwork,
- NetworkUtils::addRouteToLocalNetwork,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::tetheringStatus,
- NetworkUtils::startTethering,
- NetworkUtils::setDnsForwarders,
- NetworkUtils::enableNat,
- NetworkUtils::wifiTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sWifiOperationModeChain[] = {
- NetworkUtils::wifiFirmwareReload,
- NetworkUtils::wifiOperationModeSuccess
-};
-
-const CommandFunc NetworkUtils::sUSBEnableChain[] = {
- NetworkUtils::setConfig,
- NetworkUtils::enableNat,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::tetherInterface,
- NetworkUtils::addInterfaceToLocalNetwork,
- NetworkUtils::addRouteToLocalNetwork,
- NetworkUtils::tetheringStatus,
- NetworkUtils::startTethering,
- NetworkUtils::setDnsForwarders,
- NetworkUtils::addUpstreamInterface,
- NetworkUtils::usbTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sUSBDisableChain[] = {
- NetworkUtils::untetherInterface,
- NetworkUtils::removeInterfaceFromLocalNetwork,
- NetworkUtils::preTetherInterfaceList,
- NetworkUtils::postTetherInterfaceList,
- NetworkUtils::removeUpstreamInterface,
- NetworkUtils::disableNat,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::stopTethering,
- NetworkUtils::usbTetheringSuccess
-};
-
-const CommandFunc NetworkUtils::sUSBFailChain[] = {
- NetworkUtils::stopSoftAP,
- NetworkUtils::setIpForwardingEnabled,
- NetworkUtils::stopTethering
-};
-
-const CommandFunc NetworkUtils::sUpdateUpStreamChain[] = {
- NetworkUtils::cleanUpStream,
- NetworkUtils::removeUpstreamInterface,
- NetworkUtils::createUpStream,
- NetworkUtils::addUpstreamInterface,
- NetworkUtils::updateUpStreamSuccess
-};
-
-const CommandFunc NetworkUtils::sStartDhcpServerChain[] = {
- NetworkUtils::setConfig,
- NetworkUtils::startTethering,
- NetworkUtils::setDhcpServerSuccess
-};
-
-const CommandFunc NetworkUtils::sStopDhcpServerChain[] = {
- NetworkUtils::stopTethering,
- NetworkUtils::setDhcpServerSuccess
-};
-
-const CommandFunc NetworkUtils::sNetworkInterfaceEnableAlarmChain[] = {
- NetworkUtils::enableAlarm,
- NetworkUtils::setQuota,
- NetworkUtils::setAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sNetworkInterfaceDisableAlarmChain[] = {
- NetworkUtils::removeQuota,
- NetworkUtils::disableAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sNetworkInterfaceSetAlarmChain[] = {
- NetworkUtils::setAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sGetInterfacesChain[] = {
- NetworkUtils::getInterfaceList,
- NetworkUtils::getInterfacesSuccess
-};
-
-const CommandFunc NetworkUtils::sGetInterfaceConfigChain[] = {
- NetworkUtils::getConfig,
- NetworkUtils::getInterfaceConfigSuccess
-};
-
-const CommandFunc NetworkUtils::sSetInterfaceConfigChain[] = {
- NetworkUtils::setConfig,
- NetworkUtils::setInterfaceConfigSuccess
-};
-
-const CommandFunc NetworkUtils::sTetheringInterfaceSetAlarmChain[] = {
- NetworkUtils::setGlobalAlarm,
- NetworkUtils::removeAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sTetheringInterfaceRemoveAlarmChain[] = {
- NetworkUtils::removeGlobalAlarm,
- NetworkUtils::setAlarm,
- NetworkUtils::networkInterfaceAlarmSuccess
-};
-
-const CommandFunc NetworkUtils::sTetheringGetStatusChain[] = {
- NetworkUtils::tetheringStatus,
- NetworkUtils::defaultAsyncSuccessHandler
-};
-
-/**
- * Helper function to get the mask from given prefix length.
- */
-static uint32_t makeMask(const uint32_t prefixLength)
-{
- uint32_t mask = 0;
- for (uint32_t i = 0; i < prefixLength; ++i) {
- mask |= (0x80000000 >> i);
- }
- return ntohl(mask);
-}
-
-/**
- * Helper function to get the network part of an ip from prefix.
- * param ip must be in network byte order.
- */
-static char* getNetworkAddr(const uint32_t ip, const uint32_t prefix)
-{
- uint32_t mask = 0, subnet = 0;
-
- mask = ~mask << (32 - prefix);
- mask = htonl(mask);
- subnet = ip & mask;
-
- struct in_addr addr;
- addr.s_addr = subnet;
-
- return inet_ntoa(addr);
-}
-
-/**
- * Helper function to split string by seperator, store split result as an nsTArray.
- */
-static void split(char* str, const char* sep, nsTArray<nsCString>& result)
-{
- char *s = strtok(str, sep);
- while (s != nullptr) {
- result.AppendElement(s);
- s = strtok(nullptr, sep);
- }
-}
-
-static void split(char* str, const char* sep, nsTArray<nsString>& result)
-{
- char *s = strtok(str, sep);
- while (s != nullptr) {
- result.AppendElement(NS_ConvertUTF8toUTF16(s));
- s = strtok(nullptr, sep);
- }
-}
-
-/**
- * Helper function that implement join function.
- */
-static void join(nsTArray<nsCString>& array,
- const char* sep,
- const uint32_t maxlen,
- char* result)
-{
-#define CHECK_LENGTH(len, add, max) len += add; \
- if (len > max - 1) \
- return; \
-
- uint32_t len = 0;
- uint32_t seplen = strlen(sep);
-
- if (array.Length() > 0) {
- CHECK_LENGTH(len, strlen(array[0].get()), maxlen)
- strcpy(result, array[0].get());
-
- for (uint32_t i = 1; i < array.Length(); i++) {
- CHECK_LENGTH(len, seplen, maxlen)
- strcat(result, sep);
-
- CHECK_LENGTH(len, strlen(array[i].get()), maxlen)
- strcat(result, array[i].get());
- }
- }
-
-#undef CHECK_LEN
-}
-
-static void convertUTF8toUTF16(nsTArray<nsCString>& narrow,
- nsTArray<nsString>& wide,
- uint32_t length)
-{
- for (uint32_t i = 0; i < length; i++) {
- wide.AppendElement(NS_ConvertUTF8toUTF16(narrow[i].get()));
- }
-}
-
-/**
- * Helper function to get network interface properties from the system property table.
- */
-static void getIFProperties(const char* ifname, IFProperties& prop)
-{
- char key[Property::KEY_MAX_LENGTH];
- snprintf(key, Property::KEY_MAX_LENGTH - 1, "net.%s.gw", ifname);
- Property::Get(key, prop.gateway, "");
- snprintf(key, Property::KEY_MAX_LENGTH - 1, "net.%s.dns1", ifname);
- Property::Get(key, prop.dns1, "");
- snprintf(key, Property::KEY_MAX_LENGTH - 1, "net.%s.dns2", ifname);
- Property::Get(key, prop.dns2, "");
-}
-
-static int getIpType(const char *aIp) {
- struct addrinfo hint, *ip_info = NULL;
-
- memset(&hint, 0, sizeof(hint));
- hint.ai_family = AF_UNSPEC;
- hint.ai_flags = AI_NUMERICHOST;
-
- if (getaddrinfo(aIp, NULL, &hint, &ip_info)) {
- return AF_UNSPEC;
- }
-
- int type = ip_info->ai_family;
- freeaddrinfo(ip_info);
-
- return type;
-}
-
-static void postMessage(NetworkResultOptions& aResult)
-{
- MOZ_ASSERT(gNetworkUtils);
- MOZ_ASSERT(gNetworkUtils->getMessageCallback());
-
- if (*(gNetworkUtils->getMessageCallback()))
- (*(gNetworkUtils->getMessageCallback()))(aResult);
-}
-
-static void postMessage(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- MOZ_ASSERT(gNetworkUtils);
- MOZ_ASSERT(gNetworkUtils->getMessageCallback());
-
- aResult.mId = aOptions.mId;
-
- if (*(gNetworkUtils->getMessageCallback()))
- (*(gNetworkUtils->getMessageCallback()))(aResult);
-}
-
-void NetworkUtils::runNextQueuedCommandChain()
-{
- if (gCommandChainQueue.IsEmpty()) {
- NU_DBG("No command chain left in the queue. Done!");
- return;
- }
- NU_DBG("Process the queued command chain.");
- CommandChain* nextChain = gCommandChainQueue[0];
- NetworkResultOptions newResult;
- next(nextChain, false, newResult);
-}
-
-void NetworkUtils::next(CommandChain* aChain, bool aError, NetworkResultOptions& aResult)
-{
- if (aError) {
- ErrorCallback onError = aChain->getErrorCallback();
- if(onError) {
- aResult.mError = true;
- (*onError)(aChain->getParams(), aResult);
- }
- delete aChain;
- gCommandChainQueue.RemoveElementAt(0);
- runNextQueuedCommandChain();
- return;
- }
- CommandFunc f = aChain->getNextCommand();
- if (!f) {
- delete aChain;
- gCommandChainQueue.RemoveElementAt(0);
- runNextQueuedCommandChain();
- return;
- }
-
- (*f)(aChain, next, aResult);
-}
-
-CommandResult::CommandResult(int32_t aResultCode)
- : mIsPending(false)
-{
- // This is usually not a netd command. We treat the return code
- // typical linux convention, which uses 0 to indicate success.
- mResult.mError = (aResultCode == SUCCESS ? false : true);
- mResult.mResultCode = aResultCode;
- if (aResultCode != SUCCESS) {
- // The returned value is sometimes negative, make sure we pass a positive
- // error number to strerror.
- enum { STRERROR_R_BUF_SIZE = 1024, };
- char strerrorBuf[STRERROR_R_BUF_SIZE];
- strerror_r(abs(aResultCode), strerrorBuf, STRERROR_R_BUF_SIZE);
- mResult.mReason = NS_ConvertUTF8toUTF16(strerrorBuf);
- }
-}
-
-CommandResult::CommandResult(const mozilla::dom::NetworkResultOptions& aResult)
- : mResult(aResult)
- , mIsPending(false)
-{
-}
-
-CommandResult::CommandResult(const Pending&)
- : mIsPending(true)
-{
-}
-
-bool CommandResult::isPending() const
-{
- return mIsPending;
-}
-
-/**
- * Send command to netd.
- */
-void NetworkUtils::nextNetdCommand()
-{
- if (gCommandQueue.IsEmpty() || gPending) {
- return;
- }
-
- gCurrentCommand.chain = GET_CURRENT_CHAIN;
- gCurrentCommand.callback = GET_CURRENT_CALLBACK;
- snprintf(gCurrentCommand.command, MAX_COMMAND_SIZE - 1, "%s", GET_CURRENT_COMMAND);
-
- NU_DBG("Sending \'%s\' command to netd.", gCurrentCommand.command);
- SendNetdCommand(GET_CURRENT_NETD_COMMAND);
-
- gCommandQueue.RemoveElementAt(0);
- gPending = true;
-}
-
-/**
- * Composite NetdCommand sent to netd
- *
- * @param aCommand Command sent to netd to execute.
- * @param aChain Store command chain data, ex. command parameter.
- * @param aCallback Callback function to be executed when the result of
- * this command is returned from netd.
- */
-void NetworkUtils::doCommand(const char* aCommand, CommandChain* aChain, CommandCallback aCallback)
-{
- NU_DBG("Preparing to send \'%s\' command...", aCommand);
-
- NetdCommand* netdCommand = new NetdCommand();
-
- // Android JB version adds sequence number to netd command.
- if (SDK_VERSION >= 16) {
- snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "0 %s", aCommand);
- } else {
- snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "%s", aCommand);
- }
- netdCommand->mSize = strlen((char*)netdCommand->mData) + 1;
-
- gCommandQueue.AppendElement(QueueData(netdCommand, aChain, aCallback));
-
- nextNetdCommand();
-}
-
-/*
- * Netd command function
- */
-#define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aChain->getParams().prop).get()
-#define GET_FIELD(prop) aChain->getParams().prop
-
-void NetworkUtils::wifiFirmwareReload(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap fwreload %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::startAccessPointDriver(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version >= 16.
- if (SDK_VERSION >= 16) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap start %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::stopAccessPointDriver(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version >= 16.
- if (SDK_VERSION >= 16) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap stop %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-/**
- * Command format for sdk version < 16
- * Arguments:
- * argv[2] - wlan interface
- * argv[3] - SSID
- * argv[4] - Security
- * argv[5] - Key
- * argv[6] - Channel
- * argv[7] - Preamble
- * argv[8] - Max SCB
- *
- * Command format for sdk version >= 16
- * Arguments:
- * argv[2] - wlan interface
- * argv[3] - SSID
- * argv[4] - Security
- * argv[5] - Key
- *
- * Command format for sdk version >= 18
- * Arguments:
- * argv[2] - wlan interface
- * argv[3] - SSID
- * argv[4] - Broadcast/Hidden
- * argv[5] - Channel
- * argv[6] - Security
- * argv[7] - Key
- */
-void NetworkUtils::setAccessPoint(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- nsCString ssid(GET_CHAR(mSsid));
- nsCString key(GET_CHAR(mKey));
-
- escapeQuote(ssid);
- escapeQuote(key);
-
- if (SDK_VERSION >= 19) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s \"%s\" broadcast 6 %s \"%s\"",
- GET_CHAR(mIfname),
- ssid.get(),
- GET_CHAR(mSecurity),
- key.get());
- } else if (SDK_VERSION >= 16) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s \"%s\" %s \"%s\"",
- GET_CHAR(mIfname),
- ssid.get(),
- GET_CHAR(mSecurity),
- key.get());
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s %s \"%s\" %s \"%s\" 6 0 8",
- GET_CHAR(mIfname),
- GET_CHAR(mWifictrlinterfacename),
- ssid.get(),
- GET_CHAR(mSecurity),
- key.get());
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::cleanUpStream(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0", GET_CHAR(mPreInternalIfname), GET_CHAR(mPreExternalIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::createUpStream(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0", GET_CHAR(mCurInternalIfname), GET_CHAR(mCurExternalIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::startSoftAP(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "softap startap";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::stopSoftAP(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "softap stopap";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::clearWifiTetherParms(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- delete gWifiTetheringParms;
- gWifiTetheringParms = 0;
- next(aChain, false, aResult);
-}
-
-void NetworkUtils::enableAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "bandwidth enable";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::disableAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "bandwidth disable";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setQuota(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setiquota %s % " PRId64, GET_CHAR(mIfname), INT64_MAX);
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeQuota(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth removeiquota %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setinterfacealert %s %lld",
- GET_CHAR(mIfname), GET_FIELD(mThreshold));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth removeinterfacealert %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setGlobalAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setglobalalert %lld", GET_FIELD(mThreshold));
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeGlobalAlarm(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth removeglobalalert");
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::tetherInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface add %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addInterfaceToLocalNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version < 20.
- if (SDK_VERSION < 20) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network interface add local %s",
- GET_CHAR(mInternalIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addRouteToLocalNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version < 20.
- if (SDK_VERSION < 20) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- uint32_t prefix = atoi(GET_CHAR(mPrefix));
- uint32_t ip = inet_addr(GET_CHAR(mIp));
- char* networkAddr = getNetworkAddr(ip, prefix);
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "network route add local %s %s/%s",
- GET_CHAR(mInternalIfname), networkAddr, GET_CHAR(mPrefix));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::preTetherInterfaceList(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- if (SDK_VERSION >= 16) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list");
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list 0");
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::postTetherInterfaceList(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Send the dummy command to continue the function chain.
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
-
- char buf[BUF_SIZE];
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
-
- size_t length = reason.Length() + 1 < BUF_SIZE ? reason.Length() + 1 : BUF_SIZE;
- memcpy(buf, reason.get(), length);
- split(buf, INTERFACE_DELIMIT, GET_FIELD(mInterfaceList));
-
- doCommand(command, aChain, aCallback);
-}
-
-bool isCommandChainIPv6(CommandChain* aChain, const char *externalInterface) {
- // Check by gateway address
- if (getIpType(GET_CHAR(mGateway)) == AF_INET6) {
- return true;
- }
-
- uint32_t length = GET_FIELD(mGateways).Length();
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoGateway(GET_FIELD(mGateways)[i]);
- if(getIpType(autoGateway.get()) == AF_INET6) {
- return true;
- }
- }
-
- // Check by external inteface address
- FILE *file = fopen("/proc/net/if_inet6", "r");
- if (!file) {
- return false;
- }
-
- bool isIPv6 = false;
- char interface[32];
- while(fscanf(file, "%*s %*s %*s %*s %*s %32s", interface)) {
- if (strcmp(interface, externalInterface) == 0) {
- isIPv6 = true;
- break;
- }
- }
-
- fclose(file);
- return isIPv6;
-}
-
-void NetworkUtils::addUpstreamInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- nsCString interface(GET_CHAR(mExternalIfname));
- if (!interface.get()[0]) {
- interface = GET_CHAR(mCurExternalIfname);
- }
-
- if (SUPPORT_IPV6_TETHERING == 0 || !isCommandChainIPv6(aChain, interface.get())) {
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface add_upstream %s",
- interface.get());
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeUpstreamInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- nsCString interface(GET_CHAR(mExternalIfname));
- if (!interface.get()[0]) {
- interface = GET_CHAR(mPreExternalIfname);
- }
-
- if (SUPPORT_IPV6_TETHERING == 0 || !isCommandChainIPv6(aChain, interface.get())) {
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface remove_upstream %s",
- interface.get());
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setIpForwardingEnabled(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- if (GET_FIELD(mEnable)) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd enable");
- } else {
- // Don't disable ip forwarding because others interface still need it.
- // Send the dummy command to continue the function chain.
- if (GET_FIELD(mInterfaceList).Length() > 1) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd disable");
- }
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::tetheringStatus(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- const char* command= "tether status";
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::stopTethering(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- // Don't stop tethering because others interface still need it.
- // Send the dummy to continue the function chain.
- if (GET_FIELD(mInterfaceList).Length() > 1) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether stop");
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::startTethering(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- // We don't need to start tethering again.
- // Send the dummy command to continue the function chain.
- if (aResult.mResultReason.Find("started") != kNotFound) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
- } else {
- // If usbStartIp/usbEndIp is not valid, don't append them since
- // the trailing white spaces will be parsed to extra empty args
- // See: http://androidxref.com/4.3_r2.1/xref/system/core/libsysutils/src/FrameworkListener.cpp#78
- if (!GET_FIELD(mUsbStartIp).IsEmpty() && !GET_FIELD(mUsbEndIp).IsEmpty()) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s %s %s",
- GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp),
- GET_CHAR(mUsbStartIp), GET_CHAR(mUsbEndIp));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s",
- GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp));
- }
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::untetherInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface remove %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeInterfaceFromLocalNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // Skip the command for sdk version < 20.
- if (SDK_VERSION < 20) {
- aResult.mResultCode = 0;
- aResult.mResultReason = NS_ConvertUTF8toUTF16("");
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network interface remove local %s",
- GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setDnsForwarders(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- if (SDK_VERSION >= 20) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether dns set %d %s %s",
- GET_FIELD(mNetId), GET_CHAR(mDns1), GET_CHAR(mDns2));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "tether dns set %s %s",
- GET_CHAR(mDns1), GET_CHAR(mDns2));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::enableNat(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- if (!GET_FIELD(mIp).IsEmpty() && !GET_FIELD(mPrefix).IsEmpty()) {
- uint32_t prefix = atoi(GET_CHAR(mPrefix));
- uint32_t ip = inet_addr(GET_CHAR(mIp));
- char* networkAddr = getNetworkAddr(ip, prefix);
-
- // address/prefix will only take effect when secondary routing table exists.
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 1 %s/%s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname), networkAddr,
- GET_CHAR(mPrefix));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::disableNat(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
-
- if (!GET_FIELD(mIp).IsEmpty() && !GET_FIELD(mPrefix).IsEmpty()) {
- uint32_t prefix = atoi(GET_CHAR(mPrefix));
- uint32_t ip = inet_addr(GET_CHAR(mIp));
- char* networkAddr = getNetworkAddr(ip, prefix);
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 1 %s/%s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname), networkAddr,
- GET_CHAR(mPrefix));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setDefaultInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "resolver setdefaultif %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeDefaultRoute(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- if (GET_FIELD(mLoopIndex) >= GET_FIELD(mGateways).Length()) {
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- nsTArray<nsString>& gateways = GET_FIELD(mGateways);
- NS_ConvertUTF16toUTF8 autoGateway(gateways[GET_FIELD(mLoopIndex)]);
-
- int type = getIpType(autoGateway.get());
- snprintf(command, MAX_COMMAND_SIZE - 1, "network route remove %d %s %s/0 %s",
- GET_FIELD(mNetId), GET_CHAR(mIfname),
- type == AF_INET6 ? "::" : "0.0.0.0", autoGateway.get());
-
- struct MyCallback {
- static void callback(CommandCallback::CallbackType aOriginalCallback,
- CommandChain* aChain,
- bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- NU_DBG("removeDefaultRoute's reason: %s", reason.get());
- if (aError && !reason.EqualsASCII("removeRoute() failed (No such process)")) {
- return aOriginalCallback(aChain, aError, aResult);
- }
-
- GET_FIELD(mLoopIndex)++;
- return removeDefaultRoute(aChain, aOriginalCallback, aResult);
- }
- };
-
- CommandCallback wrappedCallback(MyCallback::callback, aCallback);
- doCommand(command, aChain, wrappedCallback);
-}
-
-void NetworkUtils::setInterfaceDns(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- int written;
-
- if (SDK_VERSION >= 20) {
- written = SprintfLiteral(command, "resolver setnetdns %d %s",
- GET_FIELD(mNetId), GET_CHAR(mDomain));
- } else {
- written = SprintfLiteral(command, "resolver setifdns %s %s",
- GET_CHAR(mIfname), GET_CHAR(mDomain));
- }
-
- nsTArray<nsString>& dnses = GET_FIELD(mDnses);
- uint32_t length = dnses.Length();
-
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoDns(dnses[i]);
-
- int ret = snprintf(command + written, sizeof(command) - written, " %s", autoDns.get());
- if (ret <= 1) {
- command[written] = '\0';
- continue;
- }
-
- if (((size_t)ret + written) >= sizeof(command)) {
- command[written] = '\0';
- break;
- }
-
- written += ret;
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::getInterfaceList(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface list");
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::getConfig(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface getcfg %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setConfig(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- if (SDK_VERSION >= 16) {
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s %s",
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mLink));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s [%s]",
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mLink));
- }
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::clearAddrForInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface clearaddrs %s", GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::createNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network create %d", GET_FIELD(mNetId));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::destroyNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network destroy %d", GET_FIELD(mNetId));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addInterfaceToNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network interface add %d %s",
- GET_FIELD(mNetId), GET_CHAR(mIfname));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addRouteToInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- struct MyCallback {
- static void callback(CommandCallback::CallbackType aOriginalCallback,
- CommandChain* aChain,
- bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- NU_DBG("addRouteToInterface's reason: %s", reason.get());
- if (aError && reason.EqualsASCII("addRoute() failed (File exists)")) {
- NU_DBG("Ignore \"File exists\" error when adding host route.");
- return aOriginalCallback(aChain, false, aResult);
- }
- aOriginalCallback(aChain, aError, aResult);
- }
- };
-
- CommandCallback wrappedCallback(MyCallback::callback, aCallback);
- modifyRouteOnInterface(aChain, wrappedCallback, aResult, true);
-}
-
-void NetworkUtils::removeRouteFromInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- modifyRouteOnInterface(aChain, aCallback, aResult, false);
-}
-
-void NetworkUtils::modifyRouteOnInterface(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult,
- bool aDoAdd)
-{
- char command[MAX_COMMAND_SIZE];
-
- // AOSP adds host route to its interface table but it doesn't work for
- // B2G because we cannot set fwmark per application. So, we add
- // all host routes to legacy_system table except scope link route.
-
- nsCString ipOrSubnetIp = NS_ConvertUTF16toUTF8(GET_FIELD(mIp));
- nsCString gatewayOrEmpty;
- const char* legacyOrEmpty = "legacy 0 "; // Add to legacy by default.
- if (GET_FIELD(mGateway).IsEmpty()) {
- ipOrSubnetIp = getSubnetIp(ipOrSubnetIp, GET_FIELD(mPrefixLength));
- legacyOrEmpty = ""; // Add to interface table for scope link route.
- } else {
- gatewayOrEmpty = nsCString(" ") + NS_ConvertUTF16toUTF8(GET_FIELD(mGateway));
- }
-
- const char* action = aDoAdd ? "add" : "remove";
-
- snprintf(command, MAX_COMMAND_SIZE - 1, "network route %s%s %d %s %s/%d%s",
- legacyOrEmpty, action,
- GET_FIELD(mNetId), GET_CHAR(mIfname), ipOrSubnetIp.get(),
- GET_FIELD(mPrefixLength), gatewayOrEmpty.get());
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addDefaultRouteToNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- if (GET_FIELD(mLoopIndex) >= GET_FIELD(mGateways).Length()) {
- aCallback(aChain, false, aResult);
- return;
- }
-
- char command[MAX_COMMAND_SIZE];
- nsTArray<nsString>& gateways = GET_FIELD(mGateways);
- NS_ConvertUTF16toUTF8 autoGateway(gateways[GET_FIELD(mLoopIndex)]);
-
- int type = getIpType(autoGateway.get());
- snprintf(command, MAX_COMMAND_SIZE - 1, "network route add %d %s %s/0 %s",
- GET_FIELD(mNetId), GET_CHAR(mIfname),
- type == AF_INET6 ? "::" : "0.0.0.0", autoGateway.get());
-
- struct MyCallback {
- static void callback(CommandCallback::CallbackType aOriginalCallback,
- CommandChain* aChain,
- bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- NU_DBG("addDefaultRouteToNetwork's reason: %s", reason.get());
- if (aError && !reason.EqualsASCII("addRoute() failed (File exists)")) {
- return aOriginalCallback(aChain, aError, aResult);
- }
-
- GET_FIELD(mLoopIndex)++;
- return addDefaultRouteToNetwork(aChain, aOriginalCallback, aResult);
- }
- };
-
- CommandCallback wrappedCallback(MyCallback::callback, aCallback);
- doCommand(command, aChain, wrappedCallback);
-}
-
-void NetworkUtils::setDefaultNetwork(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "network default set %d", GET_FIELD(mNetId));
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::addRouteToSecondaryTable(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult) {
-
- char command[MAX_COMMAND_SIZE];
-
- if (SDK_VERSION >= 20) {
- snprintf(command, MAX_COMMAND_SIZE - 1,
- "network route add %d %s %s/%s %s",
- GET_FIELD(mNetId),
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mGateway));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1,
- "interface route add %s secondary %s %s %s",
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mGateway));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::removeRouteFromSecondaryTable(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult) {
- char command[MAX_COMMAND_SIZE];
-
- if (SDK_VERSION >= 20) {
- snprintf(command, MAX_COMMAND_SIZE - 1,
- "network route remove %d %s %s/%s %s",
- GET_FIELD(mNetId),
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mGateway));
- } else {
- snprintf(command, MAX_COMMAND_SIZE - 1,
- "interface route remove %s secondary %s %s %s",
- GET_CHAR(mIfname),
- GET_CHAR(mIp),
- GET_CHAR(mPrefix),
- GET_CHAR(mGateway));
- }
-
- doCommand(command, aChain, aCallback);
-}
-
-void NetworkUtils::setIpv6Enabled(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult,
- bool aEnabled)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface ipv6 %s %s",
- GET_CHAR(mIfname), aEnabled ? "enable" : "disable");
-
- struct MyCallback {
- static void callback(CommandCallback::CallbackType aOriginalCallback,
- CommandChain* aChain,
- bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- aOriginalCallback(aChain, false, aResult);
- }
- };
-
- CommandCallback wrappedCallback(MyCallback::callback, aCallback);
- doCommand(command, aChain, wrappedCallback);
-}
-
-void NetworkUtils::enableIpv6(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- setIpv6Enabled(aChain, aCallback, aResult, true);
-}
-
-void NetworkUtils::disableIpv6(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- setIpv6Enabled(aChain, aCallback, aResult, false);
-}
-
-void NetworkUtils::setMtu(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char command[MAX_COMMAND_SIZE];
- snprintf(command, MAX_COMMAND_SIZE - 1, "interface setmtu %s %ld",
- GET_CHAR(mIfname), GET_FIELD(mMtu));
-
- doCommand(command, aChain, aCallback);
-}
-
-#undef GET_CHAR
-#undef GET_FIELD
-
-/*
- * Netd command success/fail function
- */
-#define ASSIGN_FIELD(prop) aResult.prop = aChain->getParams().prop;
-#define ASSIGN_FIELD_VALUE(prop, value) aResult.prop = value;
-
-template<size_t N>
-void NetworkUtils::runChain(const NetworkParams& aParams,
- const CommandFunc (&aCmds)[N],
- ErrorCallback aError)
-{
- CommandChain* chain = new CommandChain(aParams, aCmds, N, aError);
- gCommandChainQueue.AppendElement(chain);
-
- if (gCommandChainQueue.Length() > 1) {
- NU_DBG("%d command chains are queued. Wait!", gCommandChainQueue.Length());
- return;
- }
-
- NetworkResultOptions result;
- NetworkUtils::next(gCommandChainQueue[0], false, result);
-}
-
-// Called to clean up the command chain and process the queued command chain if any.
-void NetworkUtils::finalizeSuccess(CommandChain* aChain,
- NetworkResultOptions& aResult)
-{
- next(aChain, false, aResult);
-}
-
-void NetworkUtils::wifiTetheringFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- // Notify the main thread.
- postMessage(aOptions, aResult);
-
- // If one of the stages fails, we try roll back to ensure
- // we don't leave the network systems in limbo.
- ASSIGN_FIELD_VALUE(mEnable, false)
- runChain(aOptions, sWifiFailChain, nullptr);
-}
-
-void NetworkUtils::wifiTetheringSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- ASSIGN_FIELD(mEnable)
-
- if (aChain->getParams().mEnable) {
- MOZ_ASSERT(!gWifiTetheringParms);
- gWifiTetheringParms = new NetworkParams(aChain->getParams());
- }
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::usbTetheringFail(NetworkParams& aOptions,
- NetworkResultOptions& aResult)
-{
- // Notify the main thread.
- postMessage(aOptions, aResult);
- // Try to roll back to ensure
- // we don't leave the network systems in limbo.
- // This parameter is used to disable ipforwarding.
- {
- aOptions.mEnable = false;
- runChain(aOptions, sUSBFailChain, nullptr);
- }
-
- // Disable usb rndis function.
- {
- NetworkParams options;
- options.mEnable = false;
- options.mReport = false;
- gNetworkUtils->enableUsbRndis(options);
- }
-}
-
-void NetworkUtils::usbTetheringSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- ASSIGN_FIELD(mEnable)
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::networkInterfaceAlarmFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::networkInterfaceAlarmSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- // TODO : error is not used , and it is conflict with boolean type error.
- // params.error = parseFloat(params.resultReason);
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::updateUpStreamFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::updateUpStreamSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- ASSIGN_FIELD(mCurExternalIfname)
- ASSIGN_FIELD(mCurInternalIfname)
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::setDhcpServerFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- aResult.mSuccess = false;
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::setDhcpServerSuccess(CommandChain* aChain, CommandCallback aCallback, NetworkResultOptions& aResult)
-{
- aResult.mSuccess = true;
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::wifiOperationModeFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::wifiOperationModeSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::setDnsFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::defaultAsyncSuccessHandler(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- NU_DBG("defaultAsyncSuccessHandler");
- aResult.mRet = true;
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::defaultAsyncFailureHandler(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- aResult.mRet = false;
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::getInterfacesFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::getInterfacesSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char buf[BUF_SIZE];
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- memcpy(buf, reason.get(), strlen(reason.get()));
-
- nsTArray<nsCString> result;
- split(buf, INTERFACE_DELIMIT, result);
-
- nsTArray<nsString> interfaceList;
- uint32_t length = result.Length();
- convertUTF8toUTF16(result, interfaceList, length);
-
- aResult.mInterfaceList.Construct();
- for (uint32_t i = 0; i < length; i++) {
- aResult.mInterfaceList.Value().AppendElement(interfaceList[i], fallible_t());
- }
-
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::getInterfaceConfigFail(NetworkParams& aOptions,
- NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::getInterfaceConfigSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- char buf[BUF_SIZE];
- NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
- memcpy(buf, reason.get(), strlen(reason.get()));
-
- nsTArray<nsCString> result;
- split(buf, NETD_MESSAGE_DELIMIT, result);
-
- ASSIGN_FIELD_VALUE(mMacAddr, NS_ConvertUTF8toUTF16(result[0]))
- ASSIGN_FIELD_VALUE(mIpAddr, NS_ConvertUTF8toUTF16(result[1]))
- ASSIGN_FIELD_VALUE(mPrefixLength, atol(result[2].get()))
-
- if (result[3].Find("up")) {
- ASSIGN_FIELD_VALUE(mFlag, NS_ConvertUTF8toUTF16("up"))
- } else {
- ASSIGN_FIELD_VALUE(mFlag, NS_ConvertUTF8toUTF16("down"))
- }
-
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-void NetworkUtils::setInterfaceConfigFail(NetworkParams& aOptions,
- NetworkResultOptions& aResult)
-{
- postMessage(aOptions, aResult);
-}
-
-void NetworkUtils::setInterfaceConfigSuccess(CommandChain* aChain,
- CommandCallback aCallback,
- NetworkResultOptions& aResult)
-{
- postMessage(aChain->getParams(), aResult);
- finalizeSuccess(aChain, aResult);
-}
-
-#undef ASSIGN_FIELD
-#undef ASSIGN_FIELD_VALUE
-
-NetworkUtils::NetworkUtils(MessageCallback aCallback)
- : mMessageCallback(aCallback)
-{
- mNetUtils = new NetUtils();
-
- char value[Property::VALUE_MAX_LENGTH];
- Property::Get("ro.build.version.sdk", value, nullptr);
- SDK_VERSION = atoi(value);
-
- Property::Get(IPV6_TETHERING, value, "0");
- SUPPORT_IPV6_TETHERING = atoi(value);
-
- gNetworkUtils = this;
-}
-
-NetworkUtils::~NetworkUtils()
-{
-}
-
-#define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aOptions.prop).get()
-#define GET_FIELD(prop) aOptions.prop
-
-// Hoist this type definition to global to avoid template
-// instantiation error on gcc 4.4 used by ICS emulator.
-typedef CommandResult (NetworkUtils::*CommandHandler)(NetworkParams&);
-struct CommandHandlerEntry
-{
- const char* mCommandName;
- CommandHandler mCommandHandler;
-};
-
-void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
-{
- const static CommandHandlerEntry
- COMMAND_HANDLER_TABLE[] = {
-
- // For command 'testCommand', BUILD_ENTRY(testCommand) will generate
- // {"testCommand", NetworkUtils::testCommand}
- #define BUILD_ENTRY(c) {#c, &NetworkUtils::c}
-
- BUILD_ENTRY(removeNetworkRoute),
- BUILD_ENTRY(setDNS),
- BUILD_ENTRY(setDefaultRoute),
- BUILD_ENTRY(removeDefaultRoute),
- BUILD_ENTRY(addHostRoute),
- BUILD_ENTRY(removeHostRoute),
- BUILD_ENTRY(addSecondaryRoute),
- BUILD_ENTRY(removeSecondaryRoute),
- BUILD_ENTRY(setNetworkInterfaceAlarm),
- BUILD_ENTRY(enableNetworkInterfaceAlarm),
- BUILD_ENTRY(disableNetworkInterfaceAlarm),
- BUILD_ENTRY(setTetheringAlarm),
- BUILD_ENTRY(removeTetheringAlarm),
- BUILD_ENTRY(getTetheringStatus),
- BUILD_ENTRY(setWifiOperationMode),
- BUILD_ENTRY(setDhcpServer),
- BUILD_ENTRY(setWifiTethering),
- BUILD_ENTRY(setUSBTethering),
- BUILD_ENTRY(enableUsbRndis),
- BUILD_ENTRY(updateUpStream),
- BUILD_ENTRY(configureInterface),
- BUILD_ENTRY(dhcpRequest),
- BUILD_ENTRY(stopDhcp),
- BUILD_ENTRY(enableInterface),
- BUILD_ENTRY(disableInterface),
- BUILD_ENTRY(resetConnections),
- BUILD_ENTRY(createNetwork),
- BUILD_ENTRY(destroyNetwork),
- BUILD_ENTRY(getNetId),
- BUILD_ENTRY(getInterfaces),
- BUILD_ENTRY(getInterfaceConfig),
- BUILD_ENTRY(setInterfaceConfig),
- BUILD_ENTRY(setMtu),
-
- #undef BUILD_ENTRY
- };
-
- // Loop until we find the command name which matches aOptions.mCmd.
- CommandHandler handler = nullptr;
- for (size_t i = 0; i < mozilla::ArrayLength(COMMAND_HANDLER_TABLE); i++) {
- if (aOptions.mCmd.EqualsASCII(COMMAND_HANDLER_TABLE[i].mCommandName)) {
- handler = COMMAND_HANDLER_TABLE[i].mCommandHandler;
- break;
- }
- }
-
- if (!handler) {
- // Command not found in COMMAND_HANDLER_TABLE.
- WARN("unknown message: %s", NS_ConvertUTF16toUTF8(aOptions.mCmd).get());
- return;
- }
-
- // The handler would return one of the following 3 values
- // to be wrapped to CommandResult:
- //
- // 1) |int32_t| for mostly synchronous native function calls.
- // 2) |NetworkResultOptions| to populate additional results. (e.g. dhcpRequest)
- // 3) |CommandResult::Pending| to indicate the result is not
- // obtained yet.
- //
- // If the handler returns "Pending", the handler should take the
- // responsibility for posting result to main thread.
- CommandResult commandResult = (this->*handler)(aOptions);
- if (!commandResult.isPending()) {
- postMessage(aOptions, commandResult.mResult);
- }
-}
-
-/**
- * Handle received data from netd.
- */
-void NetworkUtils::onNetdMessage(NetdCommand* aCommand)
-{
- char* data = (char*)aCommand->mData;
-
- // get code & reason.
- char* result = strtok(data, NETD_MESSAGE_DELIMIT);
-
- if (!result) {
- nextNetdCommand();
- return;
- }
- uint32_t code = atoi(result);
-
- if (!isBroadcastMessage(code) && SDK_VERSION >= 16) {
- strtok(nullptr, NETD_MESSAGE_DELIMIT);
- }
-
- char* reason = strtok(nullptr, "\0");
-
- if (isBroadcastMessage(code)) {
- NU_DBG("Receiving broadcast message from netd.");
- NU_DBG(" ==> Code: %d Reason: %s", code, reason);
- sendBroadcastMessage(code, reason);
-
- if (code == NETD_COMMAND_INTERFACE_CHANGE) {
- if (gWifiTetheringParms) {
- char linkdownReason[MAX_COMMAND_SIZE];
- snprintf(linkdownReason, MAX_COMMAND_SIZE - 1,
- "Iface linkstate %s down",
- NS_ConvertUTF16toUTF8(gWifiTetheringParms->mIfname).get());
-
- if (!strcmp(reason, linkdownReason)) {
- NU_DBG("Wifi link down, restarting tethering.");
- runChain(*gWifiTetheringParms, sWifiRetryChain, wifiTetheringFail);
- }
- }
- }
-
- nextNetdCommand();
- return;
- }
-
- // Set pending to false before we handle next command.
- NU_DBG("Receiving \"%s\" command response from netd.", gCurrentCommand.command);
- NU_DBG(" ==> Code: %d Reason: %s", code, reason);
-
- gReason.AppendElement(nsCString(reason));
-
- // 1xx response code regards as command is proceeding, we need to wait for
- // final response code such as 2xx, 4xx and 5xx before sending next command.
- if (isProceeding(code)) {
- return;
- }
-
- if (isComplete(code)) {
- gPending = false;
- }
-
- {
- char buf[BUF_SIZE];
- join(gReason, INTERFACE_DELIMIT, BUF_SIZE, buf);
-
- NetworkResultOptions result;
- result.mResultCode = code;
- result.mResultReason = NS_ConvertUTF8toUTF16(buf);
- (gCurrentCommand.callback)(gCurrentCommand.chain, isError(code), result);
- gReason.Clear();
- }
-
- // Handling pending commands if any.
- if (isComplete(code)) {
- nextNetdCommand();
- }
-}
-
-/**
- * Start/Stop DHCP server.
- */
-CommandResult NetworkUtils::setDhcpServer(NetworkParams& aOptions)
-{
- if (aOptions.mEnabled) {
- aOptions.mWifiStartIp = aOptions.mStartIp;
- aOptions.mWifiEndIp = aOptions.mEndIp;
- aOptions.mIp = aOptions.mServerIp;
- aOptions.mPrefix = aOptions.mMaskLength;
- aOptions.mLink = NS_ConvertUTF8toUTF16("up");
-
- runChain(aOptions, sStartDhcpServerChain, setDhcpServerFail);
- } else {
- runChain(aOptions, sStopDhcpServerChain, setDhcpServerFail);
- }
- return CommandResult::Pending();
-}
-
-/**
- * Set DNS servers for given network interface.
- */
-CommandResult NetworkUtils::setDNS(NetworkParams& aOptions)
-{
- uint32_t length = aOptions.mDnses.Length();
-
- if (length > 0) {
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoDns(aOptions.mDnses[i]);
-
- char dns_prop_key[Property::VALUE_MAX_LENGTH];
- SprintfLiteral(dns_prop_key, "net.dns%d", i+1);
- Property::Set(dns_prop_key, autoDns.get());
- }
- } else {
- // Set dnses from system properties.
- IFProperties interfaceProperties;
- getIFProperties(GET_CHAR(mIfname), interfaceProperties);
-
- Property::Set("net.dns1", interfaceProperties.dns1);
- Property::Set("net.dns2", interfaceProperties.dns2);
- }
-
- // Bump the DNS change property.
- char dnschange[Property::VALUE_MAX_LENGTH];
- Property::Get("net.dnschange", dnschange, "0");
-
- char num[Property::VALUE_MAX_LENGTH];
- snprintf(num, Property::VALUE_MAX_LENGTH - 1, "%d", atoi(dnschange) + 1);
- Property::Set("net.dnschange", num);
-
- // DNS needs to be set through netd since JellyBean (4.3).
- if (SDK_VERSION >= 20) {
- // Lollipop.
- static CommandFunc COMMAND_CHAIN[] = {
- setInterfaceDns,
- addDefaultRouteToNetwork,
- defaultAsyncSuccessHandler
- };
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mIfname, &netIdInfo)) {
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, setDnsFail);
- return CommandResult::Pending();
- }
- if (SDK_VERSION >= 18) {
- // JB, KK.
- static CommandFunc COMMAND_CHAIN[] = {
- #if ANDROID_VERSION == 18
- // Since we don't use per-interface DNS lookup feature on JB,
- // we need to set the default DNS interface whenever setting the
- // DNS name server.
- setDefaultInterface,
- #endif
- setInterfaceDns,
- defaultAsyncSuccessHandler
- };
- runChain(aOptions, COMMAND_CHAIN, setDnsFail);
- return CommandResult::Pending();
- }
-
- return SUCCESS;
-}
-
-CommandResult NetworkUtils::configureInterface(NetworkParams& aOptions)
-{
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- return mNetUtils->do_ifc_configure(
- autoIfname.get(),
- aOptions.mIpaddr,
- aOptions.mMask,
- aOptions.mGateway_long,
- aOptions.mDns1_long,
- aOptions.mDns2_long
- );
-}
-
-CommandResult NetworkUtils::stopDhcp(NetworkParams& aOptions)
-{
- return mNetUtils->do_dhcp_stop(GET_CHAR(mIfname));
-}
-
-CommandResult NetworkUtils::dhcpRequest(NetworkParams& aOptions) {
- mozilla::dom::NetworkResultOptions result;
-
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- char ipaddr[Property::VALUE_MAX_LENGTH];
- char gateway[Property::VALUE_MAX_LENGTH];
- uint32_t prefixLength;
- char dns1[Property::VALUE_MAX_LENGTH];
- char dns2[Property::VALUE_MAX_LENGTH];
- char server[Property::VALUE_MAX_LENGTH];
- uint32_t lease;
- char vendorinfo[Property::VALUE_MAX_LENGTH];
- int32_t ret = mNetUtils->do_dhcp_do_request(autoIfname.get(),
- ipaddr,
- gateway,
- &prefixLength,
- dns1,
- dns2,
- server,
- &lease,
- vendorinfo);
-
- RETURN_IF_FAILED(ret);
-
- result.mIpaddr_str = NS_ConvertUTF8toUTF16(ipaddr);
- result.mGateway_str = NS_ConvertUTF8toUTF16(gateway);
- result.mDns1_str = NS_ConvertUTF8toUTF16(dns1);
- result.mDns2_str = NS_ConvertUTF8toUTF16(dns2);
- result.mServer_str = NS_ConvertUTF8toUTF16(server);
- result.mVendor_str = NS_ConvertUTF8toUTF16(vendorinfo);
- result.mLease = lease;
- result.mPrefixLength = prefixLength;
- result.mMask = makeMask(prefixLength);
-
- uint32_t inet4; // only support IPv4 for now.
-
-#define INET_PTON(var, field) \
- PR_BEGIN_MACRO \
- inet_pton(AF_INET, var, &inet4); \
- result.field = inet4; \
- PR_END_MACRO
-
- INET_PTON(ipaddr, mIpaddr);
- INET_PTON(gateway, mGateway);
-
- if (dns1[0] != '\0') {
- INET_PTON(dns1, mDns1);
- }
-
- if (dns2[0] != '\0') {
- INET_PTON(dns2, mDns2);
- }
-
- INET_PTON(server, mServer);
-
- char inet_str[64];
- if (inet_ntop(AF_INET, &result.mMask, inet_str, sizeof(inet_str))) {
- result.mMask_str = NS_ConvertUTF8toUTF16(inet_str);
- }
-
- return result;
-}
-
-CommandResult NetworkUtils::enableInterface(NetworkParams& aOptions) {
- return mNetUtils->do_ifc_enable(
- NS_ConvertUTF16toUTF8(aOptions.mIfname).get());
-}
-
-CommandResult NetworkUtils::disableInterface(NetworkParams& aOptions) {
- return mNetUtils->do_ifc_disable(
- NS_ConvertUTF16toUTF8(aOptions.mIfname).get());
-}
-
-CommandResult NetworkUtils::resetConnections(NetworkParams& aOptions) {
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- return mNetUtils->do_ifc_reset_connections(
- NS_ConvertUTF16toUTF8(aOptions.mIfname).get(),
- RESET_ALL_ADDRESSES);
-}
-
-/**
- * Set default route and DNS servers for given network interface.
- */
-CommandResult NetworkUtils::setDefaultRoute(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return setDefaultRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- addDefaultRouteToNetwork,
- setDefaultNetwork,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No such interface");
- return -1;
- }
-
- aOptions.mNetId = netIdInfo.mNetId;
- aOptions.mLoopIndex = 0;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * Set default route and DNS servers for given network interface by obsoleted libnetutils.
- */
-CommandResult NetworkUtils::setDefaultRouteLegacy(NetworkParams& aOptions)
-{
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
-
- uint32_t length = aOptions.mGateways.Length();
- if (length > 0) {
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[i]);
-
- int type = getIpType(autoGateway.get());
- if (type != AF_INET && type != AF_INET6) {
- continue;
- }
-
- if (type == AF_INET6) {
- RETURN_IF_FAILED(mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, autoGateway.get()));
- } else { /* type == AF_INET */
- RETURN_IF_FAILED(mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(autoGateway.get())));
- }
- }
- } else {
- // Set default froute from system properties.
- char key[Property::KEY_MAX_LENGTH];
- char gateway[Property::KEY_MAX_LENGTH];
-
- snprintf(key, sizeof key - 1, "net.%s.gw", autoIfname.get());
- Property::Get(key, gateway, "");
-
- int type = getIpType(gateway);
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- if (type == AF_INET6) {
- RETURN_IF_FAILED(mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, gateway));
- } else { /* type == AF_INET */
- RETURN_IF_FAILED(mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(gateway)));
- }
- }
-
- // Set the default DNS interface.
- if (SDK_VERSION >= 18) {
- // For JB, KK only.
- static CommandFunc COMMAND_CHAIN[] = {
- setDefaultInterface,
- defaultAsyncSuccessHandler
- };
- runChain(aOptions, COMMAND_CHAIN, setDnsFail);
- return CommandResult::Pending();
- }
-
- return SUCCESS;
-}
-
-/**
- * Remove default route for given network interface.
- */
-CommandResult NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
-{
- NU_DBG("Calling NetworkUtils::removeDefaultRoute");
-
- if (SDK_VERSION < 20) {
- return removeDefaultRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- removeDefaultRoute,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mIfname));
- return -1;
- }
-
- NU_DBG("Obtained netid %d for interface %s", netIdInfo.mNetId, GET_CHAR(mIfname));
-
- aOptions.mNetId = netIdInfo.mNetId;
- aOptions.mLoopIndex = 0;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * Remove default route for given network interface by obsoleted libnetutils.
- */
-CommandResult NetworkUtils::removeDefaultRouteLegacy(NetworkParams& aOptions)
-{
- // Legacy libnetutils calls before Lollipop.
- uint32_t length = aOptions.mGateways.Length();
- for (uint32_t i = 0; i < length; i++) {
- NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[i]);
-
- int type = getIpType(autoGateway.get());
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- WARN_IF_FAILED(mNetUtils->do_ifc_remove_route(GET_CHAR(mIfname),
- type == AF_INET ? "0.0.0.0" : "::",
- 0, autoGateway.get()));
- }
-
- return SUCCESS;
-}
-
-/**
- * Add host route for given network interface.
- */
-CommandResult NetworkUtils::addHostRoute(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return addHostRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- addRouteToInterface,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mIfname));
- return -1;
- }
-
- NU_DBG("Obtained netid %d for interface %s", netIdInfo.mNetId, GET_CHAR(mIfname));
-
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * Add host route for given network interface.
- */
-CommandResult NetworkUtils::addHostRouteLegacy(NetworkParams& aOptions)
-{
- if (aOptions.mGateway.IsEmpty()) {
- ERROR("addHostRouteLegacy does not support empty gateway.");
- return EINVAL;
- }
-
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- NS_ConvertUTF16toUTF8 autoHostname(aOptions.mIp);
- NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateway);
- int type, prefix;
-
- type = getIpType(autoHostname.get());
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- if (type != getIpType(autoGateway.get())) {
- return EINVAL;
- }
-
- prefix = type == AF_INET ? 32 : 128;
- return mNetUtils->do_ifc_add_route(autoIfname.get(), autoHostname.get(),
- prefix, autoGateway.get());
-}
-
-/**
- * Remove host route for given network interface.
- */
-CommandResult NetworkUtils::removeHostRoute(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return removeHostRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- removeRouteFromInterface,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mIfname));
- return -1;
- }
-
- NU_DBG("Obtained netid %d for interface %s", netIdInfo.mNetId, GET_CHAR(mIfname));
-
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * Remove host route for given network interface.
- */
-CommandResult NetworkUtils::removeHostRouteLegacy(NetworkParams& aOptions)
-{
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- NS_ConvertUTF16toUTF8 autoHostname(aOptions.mIp);
- NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateway);
- int type, prefix;
-
- type = getIpType(autoHostname.get());
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- if (type != getIpType(autoGateway.get())) {
- return EINVAL;
- }
-
- prefix = type == AF_INET ? 32 : 128;
- return mNetUtils->do_ifc_remove_route(autoIfname.get(), autoHostname.get(),
- prefix, autoGateway.get());
-}
-
-CommandResult NetworkUtils::removeNetworkRoute(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return removeNetworkRouteLegacy(aOptions);
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- clearAddrForInterface,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("interface %s is not present in any network", GET_CHAR(mIfname));
- return -1;
- }
-
- NU_DBG("Obtained netid %d for interface %s", netIdInfo.mNetId, GET_CHAR(mIfname));
-
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-nsCString NetworkUtils::getSubnetIp(const nsCString& aIp, int aPrefixLength)
-{
- int type = getIpType(aIp.get());
-
- if (AF_INET6 == type) {
- struct in6_addr in6;
- if (inet_pton(AF_INET6, aIp.get(), &in6) != 1) {
- return nsCString();
- }
-
- uint32_t p, i, p1, mask;
- p = aPrefixLength;
- i = 0;
- while (i < 4) {
- p1 = p > 32 ? 32 : p;
- p -= p1;
- mask = p1 ? ~0x0 << (32 - p1) : 0;
- in6.s6_addr32[i++] &= htonl(mask);
- }
-
- char subnetStr[INET6_ADDRSTRLEN];
- if (!inet_ntop(AF_INET6, &in6, subnetStr, sizeof subnetStr)) {
- return nsCString();
- }
-
- return nsCString(subnetStr);
- }
-
- if (AF_INET == type) {
- uint32_t ip = inet_addr(aIp.get());
- uint32_t netmask = makeMask(aPrefixLength);
- uint32_t subnet = ip & netmask;
- struct in_addr addr;
- addr.s_addr = subnet;
- return nsCString(inet_ntoa(addr));
- }
-
- return nsCString();
-}
-
-CommandResult NetworkUtils::removeNetworkRouteLegacy(NetworkParams& aOptions)
-{
- NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
- NS_ConvertUTF16toUTF8 autoIp(aOptions.mIp);
-
- int type = getIpType(autoIp.get());
- if (type != AF_INET && type != AF_INET6) {
- return EAFNOSUPPORT;
- }
-
- uint32_t prefixLength = GET_FIELD(mPrefixLength);
-
- if (type == AF_INET6) {
- // Calculate subnet.
- struct in6_addr in6;
- if (inet_pton(AF_INET6, autoIp.get(), &in6) != 1) {
- return EINVAL;
- }
-
- uint32_t p, i, p1, mask;
- p = prefixLength;
- i = 0;
- while (i < 4) {
- p1 = p > 32 ? 32 : p;
- p -= p1;
- mask = p1 ? ~0x0 << (32 - p1) : 0;
- in6.s6_addr32[i++] &= htonl(mask);
- }
-
- char subnetStr[INET6_ADDRSTRLEN];
- if (!inet_ntop(AF_INET6, &in6, subnetStr, sizeof subnetStr)) {
- return EINVAL;
- }
-
- // Remove default route.
- WARN_IF_FAILED(mNetUtils->do_ifc_remove_route(autoIfname.get(), "::", 0, NULL));
-
- // Remove subnet route.
- RETURN_IF_FAILED(mNetUtils->do_ifc_remove_route(autoIfname.get(), subnetStr, prefixLength, NULL));
- return SUCCESS;
- }
-
- /* type == AF_INET */
- uint32_t ip = inet_addr(autoIp.get());
- uint32_t netmask = makeMask(prefixLength);
- uint32_t subnet = ip & netmask;
- const char* gateway = "0.0.0.0";
- struct in_addr addr;
- addr.s_addr = subnet;
- const char* dst = inet_ntoa(addr);
-
- RETURN_IF_FAILED(mNetUtils->do_ifc_remove_default_route(autoIfname.get()));
- RETURN_IF_FAILED(mNetUtils->do_ifc_remove_route(autoIfname.get(), dst, prefixLength, gateway));
- return SUCCESS;
-}
-
-CommandResult NetworkUtils::addSecondaryRoute(NetworkParams& aOptions)
-{
- static CommandFunc COMMAND_CHAIN[] = {
- addRouteToSecondaryTable,
- defaultAsyncSuccessHandler
- };
-
- if (SDK_VERSION >= 20) {
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mIfname, &netIdInfo)) {
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- }
-
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::removeSecondaryRoute(NetworkParams& aOptions)
-{
- static CommandFunc COMMAND_CHAIN[] = {
- removeRouteFromSecondaryTable,
- defaultAsyncSuccessHandler
- };
-
- if (SDK_VERSION >= 20) {
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mIfname, &netIdInfo)) {
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- }
-
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::setNetworkInterfaceAlarm(NetworkParams& aOptions)
-{
- NU_DBG("setNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
- runChain(aOptions, sNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::enableNetworkInterfaceAlarm(NetworkParams& aOptions)
-{
- NU_DBG("enableNetworkInterfaceAlarm: %s", GET_CHAR(mIfname));
- runChain(aOptions, sNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::disableNetworkInterfaceAlarm(NetworkParams& aOptions)
-{
- NU_DBG("disableNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
- runChain(aOptions, sNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::setTetheringAlarm(NetworkParams& aOptions)
-{
- NU_DBG("setTetheringAlarm");
- runChain(aOptions, sTetheringInterfaceSetAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::removeTetheringAlarm(NetworkParams& aOptions)
-{
- NU_DBG("removeTetheringAlarm");
- runChain(aOptions, sTetheringInterfaceRemoveAlarmChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::getTetheringStatus(NetworkParams& aOptions)
-{
- NU_DBG("getTetheringStatus");
- runChain(aOptions, sTetheringGetStatusChain, networkInterfaceAlarmFail);
- return CommandResult::Pending();
-}
-
-/**
- * handling main thread's reload Wifi firmware request
- */
-CommandResult NetworkUtils::setWifiOperationMode(NetworkParams& aOptions)
-{
- NU_DBG("setWifiOperationMode: %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
- runChain(aOptions, sWifiOperationModeChain, wifiOperationModeFail);
- return CommandResult::Pending();
-}
-
-/**
- * handling main thread's enable/disable WiFi Tethering request
- */
-CommandResult NetworkUtils::setWifiTethering(NetworkParams& aOptions)
-{
- bool enable = aOptions.mEnable;
- IFProperties interfaceProperties;
- getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
-
- if (strcmp(interfaceProperties.dns1, "")) {
- int type = getIpType(interfaceProperties.dns1);
- if (type != AF_INET6) {
- aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
- }
- }
- if (strcmp(interfaceProperties.dns2, "")) {
- int type = getIpType(interfaceProperties.dns2);
- if (type != AF_INET6) {
- aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
- }
- }
- dumpParams(aOptions, "WIFI");
-
- if (SDK_VERSION >= 20) {
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mExternalIfname, &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mExternalIfname));
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- }
-
- if (enable) {
- NU_DBG("Starting Wifi Tethering on %s <-> %s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- runChain(aOptions, sWifiEnableChain, wifiTetheringFail);
- } else {
- NU_DBG("Stopping Wifi Tethering on %s <-> %s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- runChain(aOptions, sWifiDisableChain, wifiTetheringFail);
- }
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::setUSBTethering(NetworkParams& aOptions)
-{
- bool enable = aOptions.mEnable;
- IFProperties interfaceProperties;
- getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
-
- if (strcmp(interfaceProperties.dns1, "")) {
- int type = getIpType(interfaceProperties.dns1);
- if (type != AF_INET6) {
- aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
- }
- }
- if (strcmp(interfaceProperties.dns2, "")) {
- int type = getIpType(interfaceProperties.dns2);
- if (type != AF_INET6) {
- aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
- }
- }
- dumpParams(aOptions, "USB");
-
- if (SDK_VERSION >= 20) {
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.lookup(aOptions.mExternalIfname, &netIdInfo)) {
- ERROR("No such interface: %s", GET_CHAR(mExternalIfname));
- return -1;
- }
- aOptions.mNetId = netIdInfo.mNetId;
- }
-
- if (enable) {
- NU_DBG("Starting USB Tethering on %s <-> %s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- runChain(aOptions, sUSBEnableChain, usbTetheringFail);
- } else {
- NU_DBG("Stopping USB Tethering on %s <-> %s",
- GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
- runChain(aOptions, sUSBDisableChain, usbTetheringFail);
- }
- return CommandResult::Pending();
-}
-
-void NetworkUtils::escapeQuote(nsCString& aString)
-{
- aString.ReplaceSubstring("\\", "\\\\");
- aString.ReplaceSubstring("\"", "\\\"");
-}
-
-CommandResult NetworkUtils::checkUsbRndisState(NetworkParams& aOptions)
-{
- static uint32_t retry = 0;
-
- char currentState[Property::VALUE_MAX_LENGTH];
- Property::Get(SYS_USB_STATE_PROPERTY, currentState, nullptr);
-
- nsTArray<nsCString> stateFuncs;
- split(currentState, USB_CONFIG_DELIMIT, stateFuncs);
- bool rndisPresent = stateFuncs.Contains(nsCString(USB_FUNCTION_RNDIS));
-
- if (aOptions.mEnable == rndisPresent) {
- NetworkResultOptions result;
- result.mEnable = aOptions.mEnable;
- result.mResult = true;
- retry = 0;
- return result;
- }
- if (retry < USB_FUNCTION_RETRY_TIMES) {
- retry++;
- usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
- return checkUsbRndisState(aOptions);
- }
-
- NetworkResultOptions result;
- result.mResult = false;
- retry = 0;
- return result;
-}
-
-/**
- * Modify usb function's property to turn on USB RNDIS function
- */
-CommandResult NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
-{
- bool report = aOptions.mReport;
-
- // For some reason, rndis doesn't play well with diag,modem,nmea.
- // So when turning rndis on, we set sys.usb.config to either "rndis"
- // or "rndis,adb". When turning rndis off, we go back to
- // persist.sys.usb.config.
- //
- // On the otoro/unagi, persist.sys.usb.config should be one of:
- //
- // diag,modem,nmea,mass_storage
- // diag,modem,nmea,mass_storage,adb
- //
- // When rndis is enabled, sys.usb.config should be one of:
- //
- // rdnis
- // rndis,adb
- //
- // and when rndis is disabled, it should revert to persist.sys.usb.config
-
- char currentConfig[Property::VALUE_MAX_LENGTH];
- Property::Get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
-
- nsTArray<nsCString> configFuncs;
- split(currentConfig, USB_CONFIG_DELIMIT, configFuncs);
-
- char persistConfig[Property::VALUE_MAX_LENGTH];
- Property::Get(PERSIST_SYS_USB_CONFIG_PROPERTY, persistConfig, nullptr);
-
- nsTArray<nsCString> persistFuncs;
- split(persistConfig, USB_CONFIG_DELIMIT, persistFuncs);
-
- if (aOptions.mEnable) {
- configFuncs.Clear();
- configFuncs.AppendElement(nsCString(USB_FUNCTION_RNDIS));
- if (persistFuncs.Contains(nsCString(USB_FUNCTION_ADB))) {
- configFuncs.AppendElement(nsCString(USB_FUNCTION_ADB));
- }
- } else {
- // We're turning rndis off, revert back to the persist setting.
- // adb will already be correct there, so we don't need to do any
- // further adjustments.
- configFuncs = persistFuncs;
- }
-
- char newConfig[Property::VALUE_MAX_LENGTH] = "";
- Property::Get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
- join(configFuncs, USB_CONFIG_DELIMIT, Property::VALUE_MAX_LENGTH, newConfig);
- if (strcmp(currentConfig, newConfig)) {
- Property::Set(SYS_USB_CONFIG_PROPERTY, newConfig);
- }
-
- // Trigger the timer to check usb state and report the result to NetworkManager.
- if (report) {
- usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
- return checkUsbRndisState(aOptions);
- }
- return SUCCESS;
-}
-
-/**
- * handling upstream interface change event.
- */
-CommandResult NetworkUtils::updateUpStream(NetworkParams& aOptions)
-{
- runChain(aOptions, sUpdateUpStreamChain, updateUpStreamFail);
- return CommandResult::Pending();
-}
-
-/**
- * handling upstream interface change event.
- */
-CommandResult NetworkUtils::createNetwork(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return SUCCESS;
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- createNetwork,
- enableIpv6,
- addInterfaceToNetwork,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- mNetIdManager.acquire(GET_FIELD(mIfname), &netIdInfo);
- if (netIdInfo.mRefCnt > 1) {
- // Already created. Just return.
- NU_DBG("Interface %s (%d) has been created.", GET_CHAR(mIfname),
- netIdInfo.mNetId);
- return SUCCESS;
- }
-
- NU_DBG("Request netd to create a network with netid %d", netIdInfo.mNetId);
- // Newly created netid. Ask netd to create network.
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
-
- return CommandResult::Pending();
-}
-
-/**
- * handling upstream interface change event.
- */
-CommandResult NetworkUtils::destroyNetwork(NetworkParams& aOptions)
-{
- if (SDK_VERSION < 20) {
- return SUCCESS;
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- disableIpv6,
- destroyNetwork,
- defaultAsyncSuccessHandler,
- };
-
- NetIdManager::NetIdInfo netIdInfo;
- if (!mNetIdManager.release(GET_FIELD(mIfname), &netIdInfo)) {
- ERROR("No existing netid for %s", GET_CHAR(mIfname));
- return -1;
- }
-
- if (netIdInfo.mRefCnt > 0) {
- // Still be referenced. Just return.
- NU_DBG("Someone is still using this interface.");
- return SUCCESS;
- }
-
- NU_DBG("Interface %s (%d) is no longer used. Tell netd to destroy.",
- GET_CHAR(mIfname), netIdInfo.mNetId);
-
- aOptions.mNetId = netIdInfo.mNetId;
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
- return CommandResult::Pending();
-}
-
-/**
- * Query the netId associated with the given network interface name.
- */
-CommandResult NetworkUtils::getNetId(NetworkParams& aOptions)
-{
- NetworkResultOptions result;
-
- if (SDK_VERSION < 20) {
- // For pre-Lollipop, use the interface name as the fallback.
- result.mNetId = GET_FIELD(mIfname);
- return result;
- }
-
- NetIdManager::NetIdInfo netIdInfo;
- if (-1 == mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
- return ESRCH;
- }
- result.mNetId.AppendInt(netIdInfo.mNetId, 10);
- return result;
-}
-
-/**
- * Get existing network interfaces.
- */
-CommandResult NetworkUtils::getInterfaces(NetworkParams& aOptions)
-{
- runChain(aOptions, sGetInterfacesChain, getInterfacesFail);
- return CommandResult::Pending();
-}
-
-/**
- * Get network config of a specified interface.
- */
-CommandResult NetworkUtils::getInterfaceConfig(NetworkParams& aOptions)
-{
- runChain(aOptions, sGetInterfaceConfigChain, getInterfaceConfigFail);
- return CommandResult::Pending();
-}
-
-/**
- * Set network config for a specified interface.
- */
-CommandResult NetworkUtils::setInterfaceConfig(NetworkParams& aOptions)
-{
- runChain(aOptions, sSetInterfaceConfigChain, setInterfaceConfigFail);
- return CommandResult::Pending();
-}
-
-CommandResult NetworkUtils::setMtu(NetworkParams& aOptions)
-{
- // Setting/getting mtu is supported since Kitkat.
- if (SDK_VERSION < 19) {
- ERROR("setMtu is not supported in current SDK_VERSION.");
- return -1;
- }
-
- static CommandFunc COMMAND_CHAIN[] = {
- setMtu,
- defaultAsyncSuccessHandler,
- };
-
- runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
- return CommandResult::Pending();
-}
-
-void NetworkUtils::sendBroadcastMessage(uint32_t code, char* reason)
-{
- NetworkResultOptions result;
- switch(code) {
- case NETD_COMMAND_INTERFACE_CHANGE:
- result.mTopic = NS_ConvertUTF8toUTF16("netd-interface-change");
- break;
- case NETD_COMMAND_BANDWIDTH_CONTROLLER:
- result.mTopic = NS_ConvertUTF8toUTF16("netd-bandwidth-control");
- break;
- default:
- return;
- }
-
- result.mBroadcast = true;
- result.mReason = NS_ConvertUTF8toUTF16(reason);
- postMessage(result);
-}
-
-inline uint32_t NetworkUtils::netdResponseType(uint32_t code)
-{
- return (code / 100) * 100;
-}
-
-inline bool NetworkUtils::isBroadcastMessage(uint32_t code)
-{
- uint32_t type = netdResponseType(code);
- return type == NETD_COMMAND_UNSOLICITED;
-}
-
-inline bool NetworkUtils::isError(uint32_t code)
-{
- uint32_t type = netdResponseType(code);
- return type != NETD_COMMAND_PROCEEDING && type != NETD_COMMAND_OKAY;
-}
-
-inline bool NetworkUtils::isComplete(uint32_t code)
-{
- uint32_t type = netdResponseType(code);
- return type != NETD_COMMAND_PROCEEDING;
-}
-
-inline bool NetworkUtils::isProceeding(uint32_t code)
-{
- uint32_t type = netdResponseType(code);
- return type == NETD_COMMAND_PROCEEDING;
-}
-
-void NetworkUtils::dumpParams(NetworkParams& aOptions, const char* aType)
-{
-#ifdef _DEBUG
- NU_DBG("Dump params:");
- NU_DBG(" ifname: %s", GET_CHAR(mIfname));
- NU_DBG(" ip: %s", GET_CHAR(mIp));
- NU_DBG(" link: %s", GET_CHAR(mLink));
- NU_DBG(" prefix: %s", GET_CHAR(mPrefix));
- NU_DBG(" wifiStartIp: %s", GET_CHAR(mWifiStartIp));
- NU_DBG(" wifiEndIp: %s", GET_CHAR(mWifiEndIp));
- NU_DBG(" usbStartIp: %s", GET_CHAR(mUsbStartIp));
- NU_DBG(" usbEndIp: %s", GET_CHAR(mUsbEndIp));
- NU_DBG(" dnsserver1: %s", GET_CHAR(mDns1));
- NU_DBG(" dnsserver2: %s", GET_CHAR(mDns2));
- NU_DBG(" internalIfname: %s", GET_CHAR(mInternalIfname));
- NU_DBG(" externalIfname: %s", GET_CHAR(mExternalIfname));
- if (!strcmp(aType, "WIFI")) {
- NU_DBG(" wifictrlinterfacename: %s", GET_CHAR(mWifictrlinterfacename));
- NU_DBG(" ssid: %s", GET_CHAR(mSsid));
- NU_DBG(" security: %s", GET_CHAR(mSecurity));
- NU_DBG(" key: %s", GET_CHAR(mKey));
- }
-#endif
-}
-
-#undef GET_CHAR
-#undef GET_FIELD
diff --git a/dom/system/gonk/NetworkUtils.h b/dom/system/gonk/NetworkUtils.h
deleted file mode 100644
index d1af35f09..000000000
--- a/dom/system/gonk/NetworkUtils.h
+++ /dev/null
@@ -1,498 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef NetworkUtils_h
-#define NetworkUtils_h
-
-#include "nsAutoPtr.h"
-#include "nsString.h"
-#include "mozilla/dom/NetworkOptionsBinding.h"
-#include "mozilla/dom/network/NetUtils.h"
-#include "mozilla/ipc/Netd.h"
-#include "nsTArray.h"
-#include "NetIdManager.h"
-
-class NetworkParams;
-class CommandChain;
-
-class CommandCallback {
-public:
- typedef void (*CallbackType)(CommandChain*, bool,
- mozilla::dom::NetworkResultOptions& aResult);
-
- typedef void (*CallbackWrapperType)(CallbackType aOriginalCallback,
- CommandChain*, bool,
- mozilla::dom::NetworkResultOptions& aResult);
-
- CommandCallback()
- : mCallback(nullptr)
- , mCallbackWrapper(nullptr)
- {
- }
-
- CommandCallback(CallbackType aCallback)
- : mCallback(aCallback)
- , mCallbackWrapper(nullptr)
- {
- }
-
- CommandCallback(CallbackWrapperType aCallbackWrapper,
- CommandCallback aOriginalCallback)
- : mCallback(aOriginalCallback.mCallback)
- , mCallbackWrapper(aCallbackWrapper)
- {
- }
-
- void operator()(CommandChain* aChain, bool aError,
- mozilla::dom::NetworkResultOptions& aResult)
- {
- if (mCallbackWrapper) {
- return mCallbackWrapper(mCallback, aChain, aError, aResult);
- }
- if (mCallback) {
- return mCallback(aChain, aError, aResult);
- }
- }
-
-private:
- CallbackType mCallback;
- CallbackWrapperType mCallbackWrapper;
-};
-
-typedef void (*CommandFunc)(CommandChain*, CommandCallback,
- mozilla::dom::NetworkResultOptions& aResult);
-typedef void (*MessageCallback)(mozilla::dom::NetworkResultOptions& aResult);
-typedef void (*ErrorCallback)(NetworkParams& aOptions,
- mozilla::dom::NetworkResultOptions& aResult);
-
-class NetworkParams
-{
-public:
- NetworkParams() {
- }
-
- NetworkParams(const mozilla::dom::NetworkCommandOptions& aOther) {
-
-#define COPY_SEQUENCE_FIELD(prop, type) \
- if (aOther.prop.WasPassed()) { \
- mozilla::dom::Sequence<type > const & currentValue = aOther.prop.InternalValue(); \
- uint32_t length = currentValue.Length(); \
- for (uint32_t idx = 0; idx < length; idx++) { \
- prop.AppendElement(currentValue[idx]); \
- } \
- }
-
-#define COPY_OPT_STRING_FIELD(prop, defaultValue) \
- if (aOther.prop.WasPassed()) { \
- if (aOther.prop.Value().EqualsLiteral("null")) { \
- prop = defaultValue; \
- } else { \
- prop = aOther.prop.Value(); \
- } \
- } else { \
- prop = defaultValue; \
- }
-
-#define COPY_OPT_FIELD(prop, defaultValue) \
- if (aOther.prop.WasPassed()) { \
- prop = aOther.prop.Value(); \
- } else { \
- prop = defaultValue; \
- }
-
-#define COPY_FIELD(prop) prop = aOther.prop;
-
- COPY_FIELD(mId)
- COPY_FIELD(mCmd)
- COPY_OPT_STRING_FIELD(mDomain, EmptyString())
- COPY_OPT_STRING_FIELD(mGateway, EmptyString())
- COPY_SEQUENCE_FIELD(mGateways, nsString)
- COPY_OPT_STRING_FIELD(mIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mIp, EmptyString())
- COPY_OPT_FIELD(mPrefixLength, 0)
- COPY_OPT_STRING_FIELD(mMode, EmptyString())
- COPY_OPT_FIELD(mReport, false)
- COPY_OPT_FIELD(mEnabled, false)
- COPY_OPT_STRING_FIELD(mWifictrlinterfacename, EmptyString())
- COPY_OPT_STRING_FIELD(mInternalIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mExternalIfname, EmptyString())
- COPY_OPT_FIELD(mEnable, false)
- COPY_OPT_STRING_FIELD(mSsid, EmptyString())
- COPY_OPT_STRING_FIELD(mSecurity, EmptyString())
- COPY_OPT_STRING_FIELD(mKey, EmptyString())
- COPY_OPT_STRING_FIELD(mPrefix, EmptyString())
- COPY_OPT_STRING_FIELD(mLink, EmptyString())
- COPY_SEQUENCE_FIELD(mInterfaceList, nsString)
- COPY_OPT_STRING_FIELD(mWifiStartIp, EmptyString())
- COPY_OPT_STRING_FIELD(mWifiEndIp, EmptyString())
- COPY_OPT_STRING_FIELD(mUsbStartIp, EmptyString())
- COPY_OPT_STRING_FIELD(mUsbEndIp, EmptyString())
- COPY_OPT_STRING_FIELD(mDns1, EmptyString())
- COPY_OPT_STRING_FIELD(mDns2, EmptyString())
- COPY_SEQUENCE_FIELD(mDnses, nsString)
- COPY_OPT_STRING_FIELD(mStartIp, EmptyString())
- COPY_OPT_STRING_FIELD(mEndIp, EmptyString())
- COPY_OPT_STRING_FIELD(mServerIp, EmptyString())
- COPY_OPT_STRING_FIELD(mMaskLength, EmptyString())
- COPY_OPT_STRING_FIELD(mPreInternalIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mPreExternalIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mCurInternalIfname, EmptyString())
- COPY_OPT_STRING_FIELD(mCurExternalIfname, EmptyString())
- COPY_OPT_FIELD(mThreshold, -1)
- COPY_OPT_FIELD(mIpaddr, 0)
- COPY_OPT_FIELD(mMask, 0)
- COPY_OPT_FIELD(mGateway_long, 0)
- COPY_OPT_FIELD(mDns1_long, 0)
- COPY_OPT_FIELD(mDns2_long, 0)
- COPY_OPT_FIELD(mMtu, 0)
-
- mLoopIndex = 0;
-
-#undef COPY_SEQUENCE_FIELD
-#undef COPY_OPT_STRING_FIELD
-#undef COPY_OPT_FIELD
-#undef COPY_FIELD
- }
-
- // Followings attributes are 1-to-1 mapping to NetworkCommandOptions.
- int32_t mId;
- nsString mCmd;
- nsString mDomain;
- nsString mGateway;
- nsTArray<nsString> mGateways;
- nsString mIfname;
- nsString mIp;
- uint32_t mPrefixLength;
- nsString mMode;
- bool mReport;
- bool mEnabled;
- nsString mWifictrlinterfacename;
- nsString mInternalIfname;
- nsString mExternalIfname;
- bool mEnable;
- nsString mSsid;
- nsString mSecurity;
- nsString mKey;
- nsString mPrefix;
- nsString mLink;
- nsTArray<nsString> mInterfaceList;
- nsString mWifiStartIp;
- nsString mWifiEndIp;
- nsString mUsbStartIp;
- nsString mUsbEndIp;
- nsString mDns1;
- nsString mDns2;
- nsTArray<nsString> mDnses;
- nsString mStartIp;
- nsString mEndIp;
- nsString mServerIp;
- nsString mMaskLength;
- nsString mPreInternalIfname;
- nsString mPreExternalIfname;
- nsString mCurInternalIfname;
- nsString mCurExternalIfname;
- long long mThreshold;
- long mIpaddr;
- long mMask;
- long mGateway_long;
- long mDns1_long;
- long mDns2_long;
- long mMtu;
-
- // Auxiliary information required to carry accros command chain.
- int mNetId; // A locally defined id per interface.
- uint32_t mLoopIndex; // Loop index for adding/removing multiple gateways.
-};
-
-// CommandChain store the necessary information to execute command one by one.
-// Including :
-// 1. Command parameters.
-// 2. Command list.
-// 3. Error callback function.
-// 4. Index of current execution command.
-class CommandChain final
-{
-public:
- CommandChain(const NetworkParams& aParams,
- const CommandFunc aCmds[],
- uint32_t aLength,
- ErrorCallback aError)
- : mIndex(-1)
- , mParams(aParams)
- , mCommands(aCmds)
- , mLength(aLength)
- , mError(aError) {
- }
-
- NetworkParams&
- getParams()
- {
- return mParams;
- };
-
- CommandFunc
- getNextCommand()
- {
- mIndex++;
- return mIndex < mLength ? mCommands[mIndex] : nullptr;
- };
-
- ErrorCallback
- getErrorCallback() const
- {
- return mError;
- };
-
-private:
- uint32_t mIndex;
- NetworkParams mParams;
- const CommandFunc* mCommands;
- uint32_t mLength;
- ErrorCallback mError;
-};
-
-// A helper class to easily construct a resolved
-// or a pending result for command execution.
-class CommandResult
-{
-public:
- struct Pending {};
-
-public:
- CommandResult(int32_t aResultCode);
- CommandResult(const mozilla::dom::NetworkResultOptions& aResult);
- CommandResult(const Pending&);
- bool isPending() const;
-
- mozilla::dom::NetworkResultOptions mResult;
-
-private:
- bool mIsPending;
-};
-
-class NetworkUtils final
-{
-public:
- NetworkUtils(MessageCallback aCallback);
- ~NetworkUtils();
-
- void ExecuteCommand(NetworkParams aOptions);
- void onNetdMessage(mozilla::ipc::NetdCommand* aCommand);
-
- MessageCallback getMessageCallback() { return mMessageCallback; }
-
-private:
- /**
- * Commands supported by NetworkUtils.
- */
- CommandResult configureInterface(NetworkParams& aOptions);
- CommandResult dhcpRequest(NetworkParams& aOptions);
- CommandResult stopDhcp(NetworkParams& aOptions);
- CommandResult enableInterface(NetworkParams& aOptions);
- CommandResult disableInterface(NetworkParams& aOptions);
- CommandResult resetConnections(NetworkParams& aOptions);
- CommandResult setDefaultRoute(NetworkParams& aOptions);
- CommandResult addHostRoute(NetworkParams& aOptions);
- CommandResult removeDefaultRoute(NetworkParams& aOptions);
- CommandResult removeHostRoute(NetworkParams& aOptions);
- CommandResult removeNetworkRoute(NetworkParams& aOptions);
- CommandResult setDNS(NetworkParams& aOptions);
- CommandResult addSecondaryRoute(NetworkParams& aOptions);
- CommandResult removeSecondaryRoute(NetworkParams& aOptions);
- CommandResult setNetworkInterfaceAlarm(NetworkParams& aOptions);
- CommandResult enableNetworkInterfaceAlarm(NetworkParams& aOptions);
- CommandResult disableNetworkInterfaceAlarm(NetworkParams& aOptions);
- CommandResult setTetheringAlarm(NetworkParams& aOptions);
- CommandResult removeTetheringAlarm(NetworkParams& aOptions);
- CommandResult getTetheringStatus(NetworkParams& aOptions);
- CommandResult setWifiOperationMode(NetworkParams& aOptions);
- CommandResult setDhcpServer(NetworkParams& aOptions);
- CommandResult setWifiTethering(NetworkParams& aOptions);
- CommandResult setUSBTethering(NetworkParams& aOptions);
- CommandResult enableUsbRndis(NetworkParams& aOptions);
- CommandResult updateUpStream(NetworkParams& aOptions);
- CommandResult createNetwork(NetworkParams& aOptions);
- CommandResult destroyNetwork(NetworkParams& aOptions);
- CommandResult getNetId(NetworkParams& aOptions);
- CommandResult setMtu(NetworkParams& aOptions);
- CommandResult getInterfaces(NetworkParams& aOptions);
- CommandResult getInterfaceConfig(NetworkParams& aOptions);
- CommandResult setInterfaceConfig(NetworkParams& aOptions);
-
- CommandResult addHostRouteLegacy(NetworkParams& aOptions);
- CommandResult removeHostRouteLegacy(NetworkParams& aOptions);
- CommandResult setDefaultRouteLegacy(NetworkParams& aOptions);
- CommandResult removeDefaultRouteLegacy(NetworkParams& aOptions);
- CommandResult removeNetworkRouteLegacy(NetworkParams& aOptions);
-
-
- /**
- * function pointer array holds all netd commands should be executed
- * in sequence to accomplish a given command by other module.
- */
- static const CommandFunc sWifiEnableChain[];
- static const CommandFunc sWifiDisableChain[];
- static const CommandFunc sWifiFailChain[];
- static const CommandFunc sWifiRetryChain[];
- static const CommandFunc sWifiOperationModeChain[];
- static const CommandFunc sUSBEnableChain[];
- static const CommandFunc sUSBDisableChain[];
- static const CommandFunc sUSBFailChain[];
- static const CommandFunc sUpdateUpStreamChain[];
- static const CommandFunc sStartDhcpServerChain[];
- static const CommandFunc sStopDhcpServerChain[];
- static const CommandFunc sNetworkInterfaceEnableAlarmChain[];
- static const CommandFunc sNetworkInterfaceDisableAlarmChain[];
- static const CommandFunc sNetworkInterfaceSetAlarmChain[];
- static const CommandFunc sTetheringInterfaceSetAlarmChain[];
- static const CommandFunc sTetheringInterfaceRemoveAlarmChain[];
- static const CommandFunc sTetheringGetStatusChain[];
- static const CommandFunc sGetInterfacesChain[];
- static const CommandFunc sGetInterfaceConfigChain[];
- static const CommandFunc sSetInterfaceConfigChain[];
-
- /**
- * Individual netd command stored in command chain.
- */
-#define PARAMS CommandChain* aChain, CommandCallback aCallback, \
- mozilla::dom::NetworkResultOptions& aResult
- static void wifiFirmwareReload(PARAMS);
- static void startAccessPointDriver(PARAMS);
- static void stopAccessPointDriver(PARAMS);
- static void setAccessPoint(PARAMS);
- static void cleanUpStream(PARAMS);
- static void createUpStream(PARAMS);
- static void startSoftAP(PARAMS);
- static void stopSoftAP(PARAMS);
- static void clearWifiTetherParms(PARAMS);
- static void enableAlarm(PARAMS);
- static void disableAlarm(PARAMS);
- static void setQuota(PARAMS);
- static void removeQuota(PARAMS);
- static void setAlarm(PARAMS);
- static void removeAlarm(PARAMS);
- static void setGlobalAlarm(PARAMS);
- static void removeGlobalAlarm(PARAMS);
- static void tetherInterface(PARAMS);
- static void addInterfaceToLocalNetwork(PARAMS);
- static void addRouteToLocalNetwork(PARAMS);
- static void preTetherInterfaceList(PARAMS);
- static void postTetherInterfaceList(PARAMS);
- static void addUpstreamInterface(PARAMS);
- static void removeUpstreamInterface(PARAMS);
- static void setIpForwardingEnabled(PARAMS);
- static void tetheringStatus(PARAMS);
- static void stopTethering(PARAMS);
- static void startTethering(PARAMS);
- static void untetherInterface(PARAMS);
- static void removeInterfaceFromLocalNetwork(PARAMS);
- static void setDnsForwarders(PARAMS);
- static void enableNat(PARAMS);
- static void disableNat(PARAMS);
- static void setDefaultInterface(PARAMS);
- static void setInterfaceDns(PARAMS);
- static void getInterfaceList(PARAMS);
- static void getConfig(PARAMS);
- static void setConfig(PARAMS);
- static void wifiTetheringSuccess(PARAMS);
- static void usbTetheringSuccess(PARAMS);
- static void networkInterfaceAlarmSuccess(PARAMS);
- static void updateUpStreamSuccess(PARAMS);
- static void setDhcpServerSuccess(PARAMS);
- static void wifiOperationModeSuccess(PARAMS);
- static void clearAddrForInterface(PARAMS);
- static void createNetwork(PARAMS);
- static void destroyNetwork(PARAMS);
- static void addInterfaceToNetwork(PARAMS);
- static void addDefaultRouteToNetwork(PARAMS);
- static void setDefaultNetwork(PARAMS);
- static void removeDefaultRoute(PARAMS);
- static void removeNetworkRouteSuccess(PARAMS);
- static void removeNetworkRoute(PARAMS);
- static void addRouteToInterface(PARAMS);
- static void removeRouteFromInterface(PARAMS);
- static void modifyRouteOnInterface(PARAMS, bool aDoAdd);
- static void enableIpv6(PARAMS);
- static void disableIpv6(PARAMS);
- static void setMtu(PARAMS);
- static void setIpv6Enabled(PARAMS, bool aEnabled);
- static void addRouteToSecondaryTable(PARAMS);
- static void removeRouteFromSecondaryTable(PARAMS);
- static void defaultAsyncSuccessHandler(PARAMS);
- static void getInterfacesSuccess(PARAMS);
- static void getInterfaceConfigSuccess(PARAMS);
- static void setInterfaceConfigSuccess(PARAMS);
-
-#undef PARAMS
-
- /**
- * Error callback function executed when a command is fail.
- */
-#define PARAMS NetworkParams& aOptions, \
- mozilla::dom::NetworkResultOptions& aResult
- static void wifiTetheringFail(PARAMS);
- static void wifiOperationModeFail(PARAMS);
- static void usbTetheringFail(PARAMS);
- static void updateUpStreamFail(PARAMS);
- static void setDhcpServerFail(PARAMS);
- static void networkInterfaceAlarmFail(PARAMS);
- static void setDnsFail(PARAMS);
- static void defaultAsyncFailureHandler(PARAMS);
- static void getInterfacesFail(PARAMS);
- static void getInterfaceConfigFail(PARAMS);
- static void setInterfaceConfigFail(PARAMS);
-
-#undef PARAMS
-
- /**
- * Command chain processing functions.
- */
- static void next(CommandChain* aChain, bool aError,
- mozilla::dom::NetworkResultOptions& aResult);
- static void nextNetdCommand();
- static void doCommand(const char* aCommand, CommandChain* aChain, CommandCallback aCallback);
-
- /**
- * Notify broadcast message to main thread.
- */
- void sendBroadcastMessage(uint32_t code, char* reason);
-
- /**
- * Utility functions.
- */
- CommandResult checkUsbRndisState(NetworkParams& aOptions);
- void dumpParams(NetworkParams& aOptions, const char* aType);
-
- static void escapeQuote(nsCString& aString);
- inline uint32_t netdResponseType(uint32_t code);
- inline bool isBroadcastMessage(uint32_t code);
- inline bool isError(uint32_t code);
- inline bool isComplete(uint32_t code);
- inline bool isProceeding(uint32_t code);
- void Shutdown();
- static void runNextQueuedCommandChain();
- static void finalizeSuccess(CommandChain* aChain,
- mozilla::dom::NetworkResultOptions& aResult);
-
- template<size_t N>
- static void runChain(const NetworkParams& aParams,
- const CommandFunc (&aCmds)[N],
- ErrorCallback aError);
-
- static nsCString getSubnetIp(const nsCString& aIp, int aPrefixLength);
-
- /**
- * Callback function to send netd result to main thread.
- */
- MessageCallback mMessageCallback;
-
- /*
- * Utility class to access libnetutils.
- */
- nsAutoPtr<NetUtils> mNetUtils;
-
- NetIdManager mNetIdManager;
-};
-
-#endif
diff --git a/dom/system/gonk/NetworkWorker.cpp b/dom/system/gonk/NetworkWorker.cpp
deleted file mode 100644
index caf07f375..000000000
--- a/dom/system/gonk/NetworkWorker.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "NetworkWorker.h"
-#include "NetworkUtils.h"
-#include <nsThreadUtils.h>
-#include "mozilla/ModuleUtils.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/ToJSValue.h"
-#include "nsAutoPtr.h"
-#include "nsXULAppAPI.h"
-
-#define NS_NETWORKWORKER_CID \
- { 0x6df093e1, 0x8127, 0x4fa7, {0x90, 0x13, 0xa3, 0xaa, 0xa7, 0x79, 0xbb, 0xdd} }
-
-using namespace mozilla;
-using namespace mozilla::dom;
-using namespace mozilla::ipc;
-
-namespace mozilla {
-
-nsCOMPtr<nsIThread> gWorkerThread;
-
-// The singleton network worker, to be used on the main thread.
-StaticRefPtr<NetworkWorker> gNetworkWorker;
-
-// The singleton networkutils class, that can be used on any thread.
-static nsAutoPtr<NetworkUtils> gNetworkUtils;
-
-// Runnable used dispatch command result on the main thread.
-class NetworkResultDispatcher : public Runnable
-{
-public:
- NetworkResultDispatcher(const NetworkResultOptions& aResult)
- : mResult(aResult)
- {
- MOZ_ASSERT(!NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- if (gNetworkWorker) {
- gNetworkWorker->DispatchNetworkResult(mResult);
- }
- return NS_OK;
- }
-private:
- NetworkResultOptions mResult;
-};
-
-// Runnable used dispatch netd command on the worker thread.
-class NetworkCommandDispatcher : public Runnable
-{
-public:
- NetworkCommandDispatcher(const NetworkParams& aParams)
- : mParams(aParams)
- {
- MOZ_ASSERT(NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- if (gNetworkUtils) {
- gNetworkUtils->ExecuteCommand(mParams);
- }
- return NS_OK;
- }
-private:
- NetworkParams mParams;
-};
-
-// Runnable used dispatch netd result on the worker thread.
-class NetdEventRunnable : public Runnable
-{
-public:
- NetdEventRunnable(NetdCommand* aCommand)
- : mCommand(aCommand)
- {
- MOZ_ASSERT(!NS_IsMainThread());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- if (gNetworkUtils) {
- gNetworkUtils->onNetdMessage(mCommand);
- }
- return NS_OK;
- }
-
-private:
- nsAutoPtr<NetdCommand> mCommand;
-};
-
-class NetdMessageConsumer : public NetdConsumer
-{
-public:
- NetdMessageConsumer()
- {
- MOZ_ASSERT(NS_IsMainThread());
- }
-
- void MessageReceived(NetdCommand* aCommand)
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCOMPtr<nsIRunnable> runnable = new NetdEventRunnable(aCommand);
- if (gWorkerThread) {
- gWorkerThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
- }
- }
-};
-
-NS_IMPL_ISUPPORTS(NetworkWorker, nsINetworkWorker)
-
-NetworkWorker::NetworkWorker()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!gNetworkWorker);
-}
-
-NetworkWorker::~NetworkWorker()
-{
- MOZ_ASSERT(!gNetworkWorker);
- MOZ_ASSERT(!mListener);
-}
-
-already_AddRefed<NetworkWorker>
-NetworkWorker::FactoryCreate()
-{
- if (!XRE_IsParentProcess()) {
- return nullptr;
- }
-
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!gNetworkWorker) {
- gNetworkWorker = new NetworkWorker();
- ClearOnShutdown(&gNetworkWorker);
-
- gNetworkUtils = new NetworkUtils(NetworkWorker::NotifyResult);
- ClearOnShutdown(&gNetworkUtils);
- }
-
- RefPtr<NetworkWorker> worker = gNetworkWorker.get();
- return worker.forget();
-}
-
-NS_IMETHODIMP
-NetworkWorker::Start(nsINetworkEventListener* aListener)
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(aListener);
-
- if (mListener) {
- return NS_OK;
- }
-
- nsresult rv;
-
- rv = NS_NewNamedThread("NetworkWorker", getter_AddRefs(gWorkerThread));
- if (NS_FAILED(rv)) {
- NS_WARNING("Can't create network control thread");
- return NS_ERROR_FAILURE;
- }
-
- StartNetd(new NetdMessageConsumer());
- mListener = aListener;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-NetworkWorker::Shutdown()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!mListener) {
- return NS_OK;
- }
-
- StopNetd();
-
- gWorkerThread->Shutdown();
- gWorkerThread = nullptr;
-
- mListener = nullptr;
- return NS_OK;
-}
-
-// Receive command from main thread (NetworkService.js).
-NS_IMETHODIMP
-NetworkWorker::PostMessage(JS::Handle<JS::Value> aOptions, JSContext* aCx)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- NetworkCommandOptions options;
- if (!options.Init(aCx, aOptions)) {
- NS_WARNING("Bad dictionary passed to NetworkWorker::SendCommand");
- return NS_ERROR_FAILURE;
- }
-
- // Dispatch the command to the control thread.
- NetworkParams NetworkParams(options);
- nsCOMPtr<nsIRunnable> runnable = new NetworkCommandDispatcher(NetworkParams);
- if (gWorkerThread) {
- gWorkerThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
- }
- return NS_OK;
-}
-
-void
-NetworkWorker::DispatchNetworkResult(const NetworkResultOptions& aOptions)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mozilla::AutoSafeJSContext cx;
- JS::RootedValue val(cx);
-
- if (!ToJSValue(cx, aOptions, &val)) {
- return;
- }
-
- // Call the listener with a JS value.
- if (mListener) {
- mListener->OnEvent(val);
- }
-}
-
-// Callback function from network worker thread to update result on main thread.
-void
-NetworkWorker::NotifyResult(NetworkResultOptions& aResult)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCOMPtr<nsIRunnable> runnable = new NetworkResultDispatcher(aResult);
- NS_DispatchToMainThread(runnable);
-}
-
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(NetworkWorker,
- NetworkWorker::FactoryCreate)
-
-NS_DEFINE_NAMED_CID(NS_NETWORKWORKER_CID);
-
-static const mozilla::Module::CIDEntry kNetworkWorkerCIDs[] = {
- { &kNS_NETWORKWORKER_CID, false, nullptr, NetworkWorkerConstructor },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kNetworkWorkerContracts[] = {
- { "@mozilla.org/network/worker;1", &kNS_NETWORKWORKER_CID },
- { nullptr }
-};
-
-static const mozilla::Module kNetworkWorkerModule = {
- mozilla::Module::kVersion,
- kNetworkWorkerCIDs,
- kNetworkWorkerContracts,
- nullptr
-};
-
-} // namespace mozilla
-
-NSMODULE_DEFN(NetworkWorkerModule) = &kNetworkWorkerModule;
diff --git a/dom/system/gonk/NetworkWorker.h b/dom/system/gonk/NetworkWorker.h
deleted file mode 100644
index f5c0a8fdd..000000000
--- a/dom/system/gonk/NetworkWorker.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef NetworkWorker_h
-#define NetworkWorker_h
-
-#include "mozilla/dom/NetworkOptionsBinding.h"
-#include "mozilla/ipc/Netd.h"
-#include "nsINetworkWorker.h"
-#include "nsCOMPtr.h"
-#include "nsThread.h"
-
-namespace mozilla {
-
-class NetworkWorker final : public nsINetworkWorker
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSINETWORKWORKER
-
- static already_AddRefed<NetworkWorker> FactoryCreate();
-
- void DispatchNetworkResult(const mozilla::dom::NetworkResultOptions& aOptions);
-
-private:
- NetworkWorker();
- ~NetworkWorker();
-
- static void NotifyResult(mozilla::dom::NetworkResultOptions& aResult);
-
- nsCOMPtr<nsINetworkEventListener> mListener;
-};
-
-} // namespace mozilla
-
-#endif // NetworkWorker_h
diff --git a/dom/system/gonk/OpenFileFinder.cpp b/dom/system/gonk/OpenFileFinder.cpp
deleted file mode 100644
index 388e813e1..000000000
--- a/dom/system/gonk/OpenFileFinder.cpp
+++ /dev/null
@@ -1,251 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "OpenFileFinder.h"
-
-#include "mozilla/FileUtils.h"
-#include "nsPrintfCString.h"
-
-#include <sys/stat.h>
-#include <errno.h>
-
-#undef USE_DEBUG
-#define USE_DEBUG 0
-
-#undef LOG
-#undef LOGW
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "OpenFileFinder", ## args)
-#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "OpenFileFinder", ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "OpenFileFinder", ## args)
-
-#undef DBG
-#if USE_DEBUG
-#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "OpenFileFinder" , ## args)
-#else
-#define DBG(args...)
-#endif
-
-namespace mozilla {
-namespace system {
-
-OpenFileFinder::OpenFileFinder(const nsACString& aPath,
- bool aCheckIsB2gOrDescendant /* = true */)
- : mPath(aPath),
- mProcDir(nullptr),
- mFdDir(nullptr),
- mPid(0),
- mCheckIsB2gOrDescendant(aCheckIsB2gOrDescendant)
-{
- // We assume that we're running in the parent process
- mMyPid = getpid();
-}
-
-OpenFileFinder::~OpenFileFinder()
-{
- Close();
-}
-
-bool
-OpenFileFinder::First(OpenFileFinder::Info* aInfo)
-{
- Close();
-
- mProcDir = opendir("/proc");
- if (!mProcDir) {
- return false;
- }
- mState = NEXT_PID;
- return Next(aInfo);
-}
-
-bool
-OpenFileFinder::Next(OpenFileFinder::Info* aInfo)
-{
- // NOTE: This function calls readdir and readlink, neither of which should
- // block since we're using the proc filesystem, which is a purely
- // kernel in-memory filesystem and doesn't depend on external driver
- // behaviour.
- while (mState != DONE) {
- switch (mState) {
- case NEXT_PID: {
- struct dirent *pidEntry;
- pidEntry = readdir(mProcDir);
- if (!pidEntry) {
- mState = DONE;
- break;
- }
- char *endPtr;
- mPid = strtol(pidEntry->d_name, &endPtr, 10);
- if (mPid == 0 || *endPtr != '\0') {
- // Not a +ve number - ignore
- continue;
- }
- // We've found a /proc/PID directory. Scan open file descriptors.
- if (mFdDir) {
- closedir(mFdDir);
- }
- nsPrintfCString fdDirPath("/proc/%d/fd", mPid);
- mFdDir = opendir(fdDirPath.get());
- if (!mFdDir) {
- continue;
- }
- mState = CHECK_FDS;
- }
- // Fall through
- case CHECK_FDS: {
- struct dirent *fdEntry;
- while((fdEntry = readdir(mFdDir))) {
- if (!strcmp(fdEntry->d_name, ".") ||
- !strcmp(fdEntry->d_name, "..")) {
- continue;
- }
- nsPrintfCString fdSymLink("/proc/%d/fd/%s", mPid, fdEntry->d_name);
- nsCString resolvedPath;
- if (ReadSymLink(fdSymLink, resolvedPath) && PathMatches(resolvedPath)) {
- // We found an open file contained within the directory tree passed
- // into the constructor.
- FillInfo(aInfo, resolvedPath);
- // If sCheckIsB2gOrDescendant is set false, the caller cares about
- // all processes which have open files. If sCheckIsB2gOrDescendant
- // is set false, we only care about the b2g proccess or its descendants.
- if (!mCheckIsB2gOrDescendant || aInfo->mIsB2gOrDescendant) {
- return true;
- }
- LOG("Ignore process(%d), not a b2g process or its descendant.",
- aInfo->mPid);
- }
- }
- // We've checked all of the files for this pid, move onto the next one.
- mState = NEXT_PID;
- continue;
- }
- case DONE:
- default:
- mState = DONE; // covers the default case
- break;
- }
- }
- return false;
-}
-
-void
-OpenFileFinder::Close()
-{
- if (mFdDir) {
- closedir(mFdDir);
- }
- if (mProcDir) {
- closedir(mProcDir);
- }
-}
-
-void
-OpenFileFinder::FillInfo(OpenFileFinder::Info* aInfo, const nsACString& aPath)
-{
- aInfo->mFileName = aPath;
- aInfo->mPid = mPid;
- nsPrintfCString exePath("/proc/%d/exe", mPid);
- ReadSymLink(exePath, aInfo->mExe);
- aInfo->mComm.Truncate();
- aInfo->mAppName.Truncate();
- nsPrintfCString statPath("/proc/%d/stat", mPid);
- nsCString statString;
- statString.SetLength(200);
- char *stat = statString.BeginWriting();
- if (!stat) {
- return;
- }
- ReadSysFile(statPath.get(), stat, statString.Length());
- // The stat line includes the comm field, surrounded by parenthesis.
- // However, the contents of the comm field itself is arbitrary and
- // and can include ')', so we search for the rightmost ) as being
- // the end of the comm field.
- char *closeParen = strrchr(stat, ')');
- if (!closeParen) {
- return;
- }
- char *openParen = strchr(stat, '(');
- if (!openParen) {
- return;
- }
- if (openParen >= closeParen) {
- return;
- }
- nsDependentCSubstring comm(&openParen[1], closeParen - openParen - 1);
- aInfo->mComm = comm;
- // There is a single character field after the comm and then
- // the parent pid (the field we're interested in).
- // ) X ppid
- // 01234
- int ppid = atoi(&closeParen[4]);
-
- if (mPid == mMyPid) {
- // This is chrome process
- aInfo->mIsB2gOrDescendant = true;
- DBG("Chrome process has open file(s)");
- return;
- }
- // For the rest (non-chrome process), we recursively check the ppid to know
- // it is a descendant of b2g or not. See bug 931456.
- while (ppid != mMyPid && ppid != 1) {
- DBG("Process(%d) is not forked from b2g(%d) or Init(1), keep looking",
- ppid, mMyPid);
- nsPrintfCString ppStatPath("/proc/%d/stat", ppid);
- ReadSysFile(ppStatPath.get(), stat, statString.Length());
- closeParen = strrchr(stat, ')');
- if (!closeParen) {
- return;
- }
- ppid = atoi(&closeParen[4]);
- }
- if (ppid == 1) {
- // This is a not a b2g process.
- DBG("Non-b2g process has open file(s)");
- aInfo->mIsB2gOrDescendant = false;
- return;
- }
- if (ppid == mMyPid) {
- // This is a descendant of b2g.
- DBG("Child process of chrome process has open file(s)");
- aInfo->mIsB2gOrDescendant = true;
- }
-
- // This looks like a content process. The comm field will be the
- // app name.
- aInfo->mAppName = aInfo->mComm;
-}
-
-bool
-OpenFileFinder::ReadSymLink(const nsACString& aSymLink, nsACString& aOutPath)
-{
- aOutPath.Truncate();
- const char *symLink = aSymLink.BeginReading();
-
- // Verify that we actually have a symlink.
- struct stat st;
- if (lstat(symLink, &st)) {
- return false;
- }
- if ((st.st_mode & S_IFMT) != S_IFLNK) {
- return false;
- }
-
- // Contrary to the documentation st.st_size doesn't seem to be a reliable
- // indication of the length when reading from /proc, so we use a fixed
- // size buffer instead.
-
- char resolvedSymLink[PATH_MAX];
- ssize_t pathLength = readlink(symLink, resolvedSymLink,
- sizeof(resolvedSymLink) - 1);
- if (pathLength <= 0) {
- return false;
- }
- resolvedSymLink[pathLength] = '\0';
- aOutPath.Assign(resolvedSymLink);
- return true;
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/OpenFileFinder.h b/dom/system/gonk/OpenFileFinder.h
deleted file mode 100644
index 24517965a..000000000
--- a/dom/system/gonk/OpenFileFinder.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_openfilefinder_h__
-#define mozilla_system_openfilefinder_h__
-
-#include "nsString.h"
-
-#include <dirent.h>
-
-namespace mozilla {
-namespace system {
-
-class OpenFileFinder
-{
-public:
- enum State
- {
- NEXT_PID,
- CHECK_FDS,
- DONE
- };
- class Info
- {
- public:
- nsCString mFileName; // name of the the open file
- nsCString mAppName; // App which has the file open (if it's a b2g app)
- pid_t mPid; // pid of the process which has the file open
- nsCString mComm; // comm associated with pid
- nsCString mExe; // executable name associated with pid
- bool mIsB2gOrDescendant; // this is b2g/its descendant or not
- };
-
- OpenFileFinder(const nsACString& aPath, bool aCheckIsB2gOrDescendant = true);
- ~OpenFileFinder();
-
- bool First(Info* aInfo); // Return the first open file
- bool Next(Info* aInfo); // Return the next open file
- void Close();
-
-private:
-
- void FillInfo(Info *aInfo, const nsACString& aPath);
- bool ReadSymLink(const nsACString& aSymLink, nsACString& aOutPath);
- bool PathMatches(const nsACString& aPath)
- {
- return Substring(aPath, 0, mPath.Length()).Equals(mPath);
- }
-
- State mState; // Keeps track of what we're doing.
- nsCString mPath; // Only report files contained within this directory tree
- DIR* mProcDir; // Used for scanning /proc
- DIR* mFdDir; // Used for scanning /proc/PID/fd
- int mPid; // PID currently being processed
- pid_t mMyPid; // PID of parent process, we assume we're running on it.
- bool mCheckIsB2gOrDescendant; // Do we care about non-b2g process?
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_nsvolume_h__
diff --git a/dom/system/gonk/RILSystemMessenger.jsm b/dom/system/gonk/RILSystemMessenger.jsm
deleted file mode 100644
index 81373458c..000000000
--- a/dom/system/gonk/RILSystemMessenger.jsm
+++ /dev/null
@@ -1,338 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "RIL", function () {
- let obj = {};
- Cu.import("resource://gre/modules/ril_consts.js", obj);
- return obj;
-});
-
-/**
- * RILSystemMessenger
- */
-this.RILSystemMessenger = function() {};
-RILSystemMessenger.prototype = {
-
- /**
- * Hook of Broadcast function
- *
- * @param aType
- * The type of the message to be sent.
- * @param aMessage
- * The message object to be broadcasted.
- */
- broadcastMessage: function(aType, aMessage) {
- // Function stub to be replaced by the owner of this messenger.
- },
-
- /**
- * Hook of the function to create MozStkCommand message.
- * @param aStkProactiveCmd
- * nsIStkProactiveCmd instance.
- *
- * @return a JS object which complies the dictionary of MozStkCommand defined
- * in MozStkCommandEvent.webidl
- */
- createCommandMessage: function(aStkProactiveCmd) {
- // Function stub to be replaced by the owner of this messenger.
- },
-
- /**
- * Wrapper to send "telephony-new-call" system message.
- */
- notifyNewCall: function() {
- this.broadcastMessage("telephony-new-call", {});
- },
-
- /**
- * Wrapper to send "telephony-call-ended" system message.
- */
- notifyCallEnded: function(aServiceId, aNumber, aCdmaWaitingNumber, aEmergency,
- aDuration, aOutgoing, aHangUpLocal) {
- let data = {
- serviceId: aServiceId,
- number: aNumber,
- emergency: aEmergency,
- duration: aDuration,
- direction: aOutgoing ? "outgoing" : "incoming",
- hangUpLocal: aHangUpLocal
- };
-
- if (aCdmaWaitingNumber != null) {
- data.secondNumber = aCdmaWaitingNumber;
- }
-
- this.broadcastMessage("telephony-call-ended", data);
- },
-
- _convertSmsMessageClass: function(aMessageClass) {
- return RIL.GECKO_SMS_MESSAGE_CLASSES[aMessageClass] || null;
- },
-
- _convertSmsDelivery: function(aDelivery) {
- return ["received", "sending", "sent", "error"][aDelivery] || null;
- },
-
- _convertSmsDeliveryStatus: function(aDeliveryStatus) {
- return [
- RIL.GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE,
- RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
- RIL.GECKO_SMS_DELIVERY_STATUS_PENDING,
- RIL.GECKO_SMS_DELIVERY_STATUS_ERROR
- ][aDeliveryStatus] || null;
- },
-
- /**
- * Wrapper to send 'sms-received', 'sms-delivery-success', 'sms-sent',
- * 'sms-failed', 'sms-delivery-error' system message.
- */
- notifySms: function(aNotificationType, aId, aThreadId, aIccId, aDelivery,
- aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
- aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead) {
- let msgType = [
- "sms-received",
- "sms-sent",
- "sms-delivery-success",
- "sms-failed",
- "sms-delivery-error"
- ][aNotificationType];
-
- if (!msgType) {
- throw new Error("Invalid Notification Type: " + aNotificationType);
- }
-
- this.broadcastMessage(msgType, {
- iccId: aIccId,
- type: "sms",
- id: aId,
- threadId: aThreadId,
- delivery: this._convertSmsDelivery(aDelivery),
- deliveryStatus: this._convertSmsDeliveryStatus(aDeliveryStatus),
- sender: aSender,
- receiver: aReceiver,
- body: aBody,
- messageClass: this._convertSmsMessageClass(aMessageClass),
- timestamp: aTimestamp,
- sentTimestamp: aSentTimestamp,
- deliveryTimestamp: aDeliveryTimestamp,
- read: aRead
- });
- },
-
- _convertCbGsmGeographicalScope: function(aGeographicalScope) {
- return RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[aGeographicalScope] || null;
- },
-
- _convertCbMessageClass: function(aMessageClass) {
- return RIL.GECKO_SMS_MESSAGE_CLASSES[aMessageClass] || null;
- },
-
- _convertCbEtwsWarningType: function(aWarningType) {
- return RIL.CB_ETWS_WARNING_TYPE_NAMES[aWarningType] || null;
- },
-
- /**
- * Wrapper to send 'cellbroadcast-received' system message.
- */
- notifyCbMessageReceived: function(aServiceId, aGsmGeographicalScope, aMessageCode,
- aMessageId, aLanguage, aBody, aMessageClass,
- aTimestamp, aCdmaServiceCategory, aHasEtwsInfo,
- aEtwsWarningType, aEtwsEmergencyUserAlert, aEtwsPopup) {
- // Align the same layout to MozCellBroadcastMessage
- let data = {
- serviceId: aServiceId,
- gsmGeographicalScope: this._convertCbGsmGeographicalScope(aGsmGeographicalScope),
- messageCode: aMessageCode,
- messageId: aMessageId,
- language: aLanguage,
- body: aBody,
- messageClass: this._convertCbMessageClass(aMessageClass),
- timestamp: aTimestamp,
- cdmaServiceCategory: null,
- etws: null
- };
-
- if (aHasEtwsInfo) {
- data.etws = {
- warningType: this._convertCbEtwsWarningType(aEtwsWarningType),
- emergencyUserAlert: aEtwsEmergencyUserAlert,
- popup: aEtwsPopup
- };
- }
-
- if (aCdmaServiceCategory !=
- Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID) {
- data.cdmaServiceCategory = aCdmaServiceCategory;
- }
-
- this.broadcastMessage("cellbroadcast-received", data);
- },
-
- /**
- * Wrapper to send 'ussd-received' system message.
- */
- notifyUssdReceived: function(aServiceId, aMessage, aSessionEnded) {
- this.broadcastMessage("ussd-received", {
- serviceId: aServiceId,
- message: aMessage,
- sessionEnded: aSessionEnded
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Display Info.
- */
- notifyCdmaInfoRecDisplay: function(aServiceId, aDisplay) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- display: aDisplay
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Called Party
- * Number Info.
- */
- notifyCdmaInfoRecCalledPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- calledNumber: {
- type: aType,
- plan: aPlan,
- number: aNumber,
- pi: aPi,
- si: aSi
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Calling Party
- * Number Info.
- */
- notifyCdmaInfoRecCallingPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- callingNumber: {
- type: aType,
- plan: aPlan,
- number: aNumber,
- pi: aPi,
- si: aSi
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Connected Party
- * Number Info.
- */
- notifyCdmaInfoRecConnectedPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- connectedNumber: {
- type: aType,
- plan: aPlan,
- number: aNumber,
- pi: aPi,
- si: aSi
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Signal Info.
- */
- notifyCdmaInfoRecSignal: function(aServiceId, aType, aAlertPitch, aSignal) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- signal: {
- type: aType,
- alertPitch: aAlertPitch,
- signal: aSignal
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Redirecting
- * Number Info.
- */
- notifyCdmaInfoRecRedirectingNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi, aReason) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- redirect: {
- type: aType,
- plan: aPlan,
- number: aNumber,
- pi: aPi,
- si: aSi,
- reason: aReason
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Line Control Info.
- */
- notifyCdmaInfoRecLineControl: function(aServiceId, aPolarityIncluded,
- aToggle, aReverse, aPowerDenial) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- lineControl: {
- polarityIncluded: aPolarityIncluded,
- toggle: aToggle,
- reverse: aReverse,
- powerDenial: aPowerDenial
- }
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with CLIR Info.
- */
- notifyCdmaInfoRecClir: function(aServiceId, aCause) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- clirCause: aCause
- });
- },
-
- /**
- * Wrapper to send 'cdma-info-rec-received' system message with Audio Control Info.
- */
- notifyCdmaInfoRecAudioControl: function(aServiceId, aUpLink, aDownLink) {
- this.broadcastMessage("cdma-info-rec-received", {
- clientId: aServiceId,
- audioControl: {
- upLink: aUpLink,
- downLink: aDownLink
- }
- });
- },
-
- /**
- * Wrapper to send 'icc-stkcommand' system message with Audio Control Info.
- */
- notifyStkProactiveCommand: function(aIccId, aCommand) {
- this.broadcastMessage("icc-stkcommand", {
- iccId: aIccId,
- command: this.createCommandMessage(aCommand)
- });
- }
-};
-
-this.EXPORTED_SYMBOLS = [
- 'RILSystemMessenger'
-];
diff --git a/dom/system/gonk/RILSystemMessengerHelper.js b/dom/system/gonk/RILSystemMessengerHelper.js
deleted file mode 100644
index 6ef263b66..000000000
--- a/dom/system/gonk/RILSystemMessengerHelper.js
+++ /dev/null
@@ -1,169 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-var RSM = {};
-Cu.import("resource://gre/modules/RILSystemMessenger.jsm", RSM);
-
-const RILSYSTEMMESSENGERHELPER_CONTRACTID =
- "@mozilla.org/ril/system-messenger-helper;1";
-const RILSYSTEMMESSENGERHELPER_CID =
- Components.ID("{19d9a4ea-580d-11e4-8f6c-37ababfaaea9}");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
- "@mozilla.org/system-message-internal;1",
- "nsISystemMessagesInternal");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory",
- "@mozilla.org/icc/stkcmdfactory;1",
- "nsIStkCmdFactory");
-
-var DEBUG = false;
-function debug(s) {
- dump("-@- RILSystemMessenger: " + s + "\n");
-};
-
-// Read debug setting from pref.
-try {
- let debugPref = Services.prefs.getBoolPref("ril.debugging.enabled");
- DEBUG = DEBUG || debugPref;
-} catch (e) {}
-
-/**
- * RILSystemMessengerHelper
- */
-function RILSystemMessengerHelper() {
- this.messenger = new RSM.RILSystemMessenger();
- this.messenger.broadcastMessage = (aType, aMessage) => {
- if (DEBUG) {
- debug("broadcastMessage: aType: " + aType +
- ", aMessage: "+ JSON.stringify(aMessage));
- }
-
- gSystemMessenger.broadcastMessage(aType, aMessage);
- };
-
- this.messenger.createCommandMessage = (aStkProactiveCmd) => {
- return gStkCmdFactory.createCommandMessage(aStkProactiveCmd);
- };
-}
-RILSystemMessengerHelper.prototype = {
-
- classID: RILSYSTEMMESSENGERHELPER_CID,
- QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyMessenger,
- Ci.nsISmsMessenger,
- Ci.nsICellbroadcastMessenger,
- Ci.nsIMobileConnectionMessenger,
- Ci.nsIIccMessenger]),
-
- /**
- * RILSystemMessenger instance.
- */
- messenger: null,
-
- /**
- * nsITelephonyMessenger API
- */
- notifyNewCall: function() {
- this.messenger.notifyNewCall();
- },
-
- notifyCallEnded: function(aServiceId, aNumber, aCdmaWaitingNumber, aEmergency,
- aDuration, aOutgoing, aHangUpLocal) {
- this.messenger.notifyCallEnded(aServiceId, aNumber, aCdmaWaitingNumber, aEmergency,
- aDuration, aOutgoing, aHangUpLocal);
- },
-
- notifyUssdReceived: function(aServiceId, aMessage, aSessionEnded) {
- this.messenger.notifyUssdReceived(aServiceId, aMessage, aSessionEnded);
- },
-
- /**
- * nsISmsMessenger API
- */
- notifySms: function(aNotificationType, aId, aThreadId, aIccId, aDelivery,
- aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
- aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead) {
- this.messenger.notifySms(aNotificationType, aId, aThreadId, aIccId, aDelivery,
- aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
- aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead);
- },
-
- /**
- * nsICellbroadcastMessenger API
- */
- notifyCbMessageReceived: function(aServiceId, aGsmGeographicalScope, aMessageCode,
- aMessageId, aLanguage, aBody, aMessageClass,
- aTimestamp, aCdmaServiceCategory, aHasEtwsInfo,
- aEtwsWarningType, aEtwsEmergencyUserAlert, aEtwsPopup) {
- this.messenger.notifyCbMessageReceived(aServiceId, aGsmGeographicalScope, aMessageCode,
- aMessageId, aLanguage, aBody, aMessageClass,
- aTimestamp, aCdmaServiceCategory, aHasEtwsInfo,
- aEtwsWarningType, aEtwsEmergencyUserAlert, aEtwsPopup);
- },
-
- /**
- * nsIMobileConnectionMessenger API
- */
- notifyCdmaInfoRecDisplay: function(aServiceId, aDisplay) {
- this.messenger.notifyCdmaInfoRecDisplay(aServiceId, aDisplay);
- },
-
- notifyCdmaInfoRecCalledPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.messenger.notifyCdmaInfoRecCalledPartyNumber(aServiceId, aType, aPlan,
- aNumber, aPi, aSi);
- },
-
- notifyCdmaInfoRecCallingPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.messenger.notifyCdmaInfoRecCallingPartyNumber(aServiceId, aType, aPlan,
- aNumber, aPi, aSi);
- },
-
- notifyCdmaInfoRecConnectedPartyNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi) {
- this.messenger.notifyCdmaInfoRecConnectedPartyNumber(aServiceId, aType, aPlan,
- aNumber, aPi, aSi);
- },
-
- notifyCdmaInfoRecSignal: function(aServiceId, aType, aAlertPitch, aSignal) {
- this.messenger.notifyCdmaInfoRecSignal(aServiceId, aType, aAlertPitch, aSignal);
- },
-
- notifyCdmaInfoRecRedirectingNumber: function(aServiceId, aType, aPlan,
- aNumber, aPi, aSi, aReason) {
- this.messenger.notifyCdmaInfoRecRedirectingNumber(aServiceId, aType, aPlan,
- aNumber, aPi, aSi, aReason);
- },
-
- notifyCdmaInfoRecLineControl: function(aServiceId, aPolarityIncluded,
- aToggle, aReverse, aPowerDenial) {
- this.messenger.notifyCdmaInfoRecLineControl(aServiceId, aPolarityIncluded,
- aToggle, aReverse, aPowerDenial);
- },
-
- notifyCdmaInfoRecClir: function(aServiceId, aCause) {
- this.messenger.notifyCdmaInfoRecClir(aServiceId, aCause);
- },
-
- notifyCdmaInfoRecAudioControl: function(aServiceId, aUpLink, aDownLink) {
- this.messenger.notifyCdmaInfoRecAudioControl(aServiceId, aUpLink, aDownLink);
- },
-
- /**
- * nsIIccMessenger API
- */
- notifyStkProactiveCommand: function(aIccId, aCommand) {
- this.messenger.notifyStkProactiveCommand(aIccId, aCommand);
- }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RILSystemMessengerHelper]);
diff --git a/dom/system/gonk/RILSystemMessengerHelper.manifest b/dom/system/gonk/RILSystemMessengerHelper.manifest
deleted file mode 100644
index 7d1943702..000000000
--- a/dom/system/gonk/RILSystemMessengerHelper.manifest
+++ /dev/null
@@ -1,6 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-component {19d9a4ea-580d-11e4-8f6c-37ababfaaea9} RILSystemMessengerHelper.js
-contract @mozilla.org/ril/system-messenger-helper;1 {19d9a4ea-580d-11e4-8f6c-37ababfaaea9} \ No newline at end of file
diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js
deleted file mode 100644
index f5885db5d..000000000
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ /dev/null
@@ -1,1324 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Sntp.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "RIL", function () {
- let obj = {};
- Cu.import("resource://gre/modules/ril_consts.js", obj);
- return obj;
-});
-
-// Ril quirk to always turn the radio off for the client without SIM card
-// except hw default client.
-var RILQUIRKS_RADIO_OFF_WO_CARD =
- libcutils.property_get("ro.moz.ril.radio_off_wo_card", "false") == "true";
-
-const RADIOINTERFACELAYER_CID =
- Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
-const RADIOINTERFACE_CID =
- Components.ID("{6a7c91f0-a2b3-4193-8562-8969296c0b54}");
-
-const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
-const kNetworkConnStateChangedTopic = "network-connection-state-changed";
-const kMozSettingsChangedObserverTopic = "mozsettings-changed";
-const kSysMsgListenerReadyObserverTopic = "system-message-listener-ready";
-const kSysClockChangeObserverTopic = "system-clock-change";
-const kScreenStateChangedTopic = "screen-state-changed";
-
-const kSettingsClockAutoUpdateEnabled = "time.clock.automatic-update.enabled";
-const kSettingsClockAutoUpdateAvailable = "time.clock.automatic-update.available";
-const kSettingsTimezoneAutoUpdateEnabled = "time.timezone.automatic-update.enabled";
-const kSettingsTimezoneAutoUpdateAvailable = "time.timezone.automatic-update.available";
-
-const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
-
-const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
-const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
-
-const RADIO_POWER_OFF_TIMEOUT = 30000;
-const HW_DEFAULT_CLIENT_ID = 0;
-
-const NETWORK_TYPE_WIFI = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
-const NETWORK_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
-
-// set to true in ril_consts.js to see debug messages
-var DEBUG = RIL.DEBUG_RIL;
-
-function updateDebugFlag() {
- // Read debug setting from pref
- let debugPref;
- try {
- debugPref = Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
- } catch (e) {
- debugPref = false;
- }
- DEBUG = RIL.DEBUG_RIL || debugPref;
-}
-updateDebugFlag();
-
-function debug(s) {
- dump("-*- RadioInterfaceLayer: " + s + "\n");
-}
-
-XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
- "@mozilla.org/icc/gonkiccservice;1",
- "nsIGonkIccService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileMessageService",
- "@mozilla.org/mobilemessage/mobilemessageservice;1",
- "nsIMobileMessageService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
- "@mozilla.org/sms/gonksmsservice;1",
- "nsIGonkSmsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageBroadcaster");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gTimeService",
- "@mozilla.org/time/timeservice;1",
- "nsITimeService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSystemWorkerManager",
- "@mozilla.org/telephony/system-worker-manager;1",
- "nsISystemWorkerManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gTelephonyService",
- "@mozilla.org/telephony/telephonyservice;1",
- "nsIGonkTelephonyService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
- "@mozilla.org/mobileconnection/mobileconnectionservice;1",
- "nsIGonkMobileConnectionService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gCellBroadcastService",
- "@mozilla.org/cellbroadcast/cellbroadcastservice;1",
- "nsIGonkCellBroadcastService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gDataCallManager",
- "@mozilla.org/datacall/manager;1",
- "nsIDataCallManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gDataCallInterfaceService",
- "@mozilla.org/datacall/interfaceservice;1",
- "nsIGonkDataCallInterfaceService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory",
- "@mozilla.org/icc/stkcmdfactory;1",
- "nsIStkCmdFactory");
-
-XPCOMUtils.defineLazyGetter(this, "gRadioEnabledController", function() {
- let _ril = null;
- let _pendingMessages = []; // For queueing "setRadioEnabled" message.
- let _isProcessingPending = false;
- let _timer = null;
- let _request = null;
- let _deactivatingDeferred = {};
- let _initializedCardState = {};
- let _allCardStateInitialized = !RILQUIRKS_RADIO_OFF_WO_CARD;
-
- return {
- init: function(ril) {
- _ril = ril;
- },
-
- receiveCardState: function(clientId) {
- if (_allCardStateInitialized) {
- return;
- }
-
- if (DEBUG) debug("RadioControl: receive cardState from " + clientId);
- _initializedCardState[clientId] = true;
- if (Object.keys(_initializedCardState).length == _ril.numRadioInterfaces) {
- _allCardStateInitialized = true;
- this._startProcessingPending();
- }
- },
-
- setRadioEnabled: function(clientId, data, callback) {
- if (DEBUG) debug("setRadioEnabled: " + clientId + ": " + JSON.stringify(data));
- let message = {
- clientId: clientId,
- data: data,
- callback: callback
- };
- _pendingMessages.push(message);
- this._startProcessingPending();
- },
-
- notifyRadioStateChanged: function(clientId, radioState) {
- gMobileConnectionService.notifyRadioStateChanged(clientId, radioState);
- },
-
- _startProcessingPending: function() {
- if (!_isProcessingPending) {
- if (DEBUG) debug("RadioControl: start dequeue");
- _isProcessingPending = true;
- this._processNextMessage();
- }
- },
-
- _processNextMessage: function() {
- if (_pendingMessages.length === 0 || !_allCardStateInitialized) {
- if (DEBUG) debug("RadioControl: stop dequeue");
- _isProcessingPending = false;
- return;
- }
-
- let msg = _pendingMessages.shift();
- this._handleMessage(msg);
- },
-
- _getNumCards: function() {
- let numCards = 0;
- for (let i = 0, N = _ril.numRadioInterfaces; i < N; ++i) {
- if (_ril.getRadioInterface(i).isCardPresent()) {
- numCards++;
- }
- }
- return numCards;
- },
-
- _isRadioAbleToEnableAtClient: function(clientId, numCards) {
- if (!RILQUIRKS_RADIO_OFF_WO_CARD) {
- return true;
- }
-
- // We could only turn on the radio for clientId if
- // 1. a SIM card is presented or
- // 2. it is the default clientId and there is no any SIM card at any client.
-
- if (_ril.getRadioInterface(clientId).isCardPresent()) {
- return true;
- }
-
- numCards = numCards == null ? this._getNumCards() : numCards;
- if (clientId === HW_DEFAULT_CLIENT_ID && numCards === 0) {
- return true;
- }
-
- return false;
- },
-
- _handleMessage: function(message) {
- if (DEBUG) debug("RadioControl: handleMessage: " + JSON.stringify(message));
- let clientId = message.clientId || 0;
- let connection =
- gMobileConnectionService.getItemByServiceId(clientId);
- let radioState = connection && connection.radioState;
-
- if (message.data.enabled) {
- if (this._isRadioAbleToEnableAtClient(clientId)) {
- this._setRadioEnabledInternal(message);
- } else {
- // Not really do it but respond success.
- message.callback(message.data);
- }
-
- this._processNextMessage();
- } else {
- _request = this._setRadioEnabledInternal.bind(this, message);
-
- // In 2G network, modem takes 35+ seconds to process deactivate data
- // call request if device has active voice call (please see bug 964974
- // for more details). Therefore we should hangup all active voice calls
- // first. And considering some DSDS architecture, toggling one radio may
- // toggle both, so we send hangUpAll to all clients.
- let hangUpCallback = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyCallback]),
- notifySuccess: function() {},
- notifyError: function() {}
- };
-
- gTelephonyService.enumerateCalls({
- QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
- enumerateCallState: function(aInfo) {
- gTelephonyService.hangUpCall(aInfo.clientId, aInfo.callIndex,
- hangUpCallback);
- },
- enumerateCallStateComplete: function() {}
- });
-
- // In some DSDS architecture with only one modem, toggling one radio may
- // toggle both. Therefore, for safely turning off, we should first
- // explicitly deactivate all data calls from all clients.
- this._deactivateDataCalls().then(() => {
- if (DEBUG) debug("RadioControl: deactivation done");
- this._executeRequest();
- });
-
- this._createTimer();
- }
- },
-
- _setRadioEnabledInternal: function(message) {
- let clientId = message.clientId || 0;
- let enabled = message.data.enabled || false;
- let radioInterface = _ril.getRadioInterface(clientId);
-
- radioInterface.workerMessenger.send("setRadioEnabled", message.data,
- (function(response) {
- if (response.errorMsg) {
- // If request fails, set current radio state to unknown, since we will
- // handle it in |mobileConnectionService|.
- this.notifyRadioStateChanged(clientId,
- Ci.nsIMobileConnection.MOBILE_RADIO_STATE_UNKNOWN);
- }
- return message.callback(response);
- }).bind(this));
- },
-
- _deactivateDataCalls: function() {
- if (DEBUG) debug("RadioControl: deactivating data calls...");
- _deactivatingDeferred = {};
-
- let promise = Promise.resolve();
- for (let i = 0, N = _ril.numRadioInterfaces; i < N; ++i) {
- promise = promise.then(this._deactivateDataCallsForClient(i));
- }
-
- return promise;
- },
-
- _deactivateDataCallsForClient: function(clientId) {
- return function() {
- let deferred = _deactivatingDeferred[clientId] = Promise.defer();
- let dataCallHandler = gDataCallManager.getDataCallHandler(clientId);
-
- dataCallHandler.deactivateDataCalls(function() {
- deferred.resolve();
- });
-
- return deferred.promise;
- };
- },
-
- _createTimer: function() {
- if (!_timer) {
- _timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- }
- _timer.initWithCallback(this._executeRequest.bind(this),
- RADIO_POWER_OFF_TIMEOUT,
- Ci.nsITimer.TYPE_ONE_SHOT);
- },
-
- _cancelTimer: function() {
- if (_timer) {
- _timer.cancel();
- }
- },
-
- _executeRequest: function() {
- if (typeof _request === "function") {
- if (DEBUG) debug("RadioControl: executeRequest");
- this._cancelTimer();
- _request();
- _request = null;
- }
- this._processNextMessage();
- },
- };
-});
-
-// Initialize shared preference "ril.numRadioInterfaces" according to system
-// property.
-try {
- Services.prefs.setIntPref(kPrefRilNumRadioInterfaces, (function() {
- // When Gonk property "ro.moz.ril.numclients" is not set, return 1; if
- // explicitly set to any number larger-equal than 0, return num; else, return
- // 1 for compatibility.
- try {
- let numString = libcutils.property_get("ro.moz.ril.numclients", "1");
- let num = parseInt(numString, 10);
- if (num >= 0) {
- return num;
- }
- } catch (e) {}
-
- return 1;
- })());
-} catch (e) {}
-
-function DataCall(aAttributes) {
- for (let key in aAttributes) {
- if (key === "pdpType") {
- // Convert pdp type into constant int value.
- this[key] = RIL.RIL_DATACALL_PDP_TYPES.indexOf(aAttributes[key]);
- continue;
- }
-
- this[key] = aAttributes[key];
- }
-}
-DataCall.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCall]),
-
- failCause: Ci.nsIDataCallInterface.DATACALL_FAIL_NONE,
- suggestedRetryTime: -1,
- cid: -1,
- active: -1,
- pdpType: -1,
- ifname: null,
- addreses: null,
- dnses: null,
- gateways: null,
- pcscf: null,
- mtu: -1
-};
-
-function RadioInterfaceLayer() {
- let workerMessenger = new WorkerMessenger();
- workerMessenger.init();
- this.setWorkerDebugFlag = workerMessenger.setDebugFlag.bind(workerMessenger);
-
- let numIfaces = this.numRadioInterfaces;
- if (DEBUG) debug(numIfaces + " interfaces");
- this.radioInterfaces = [];
- for (let clientId = 0; clientId < numIfaces; clientId++) {
- this.radioInterfaces.push(new RadioInterface(clientId, workerMessenger));
- }
-
- Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
- Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
-
- gRadioEnabledController.init(this);
-}
-RadioInterfaceLayer.prototype = {
-
- classID: RADIOINTERFACELAYER_CID,
- classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
- classDescription: "RadioInterfaceLayer",
- interfaces: [Ci.nsIRadioInterfaceLayer]}),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioInterfaceLayer,
- Ci.nsIObserver]),
-
- /**
- * nsIObserver interface methods.
- */
-
- observe: function(subject, topic, data) {
- switch (topic) {
- case NS_XPCOM_SHUTDOWN_OBSERVER_ID:
- for (let radioInterface of this.radioInterfaces) {
- radioInterface.shutdown();
- }
- this.radioInterfaces = null;
- Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
- break;
-
- case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
- if (data === kPrefRilDebuggingEnabled) {
- updateDebugFlag();
- this.setWorkerDebugFlag(DEBUG);
- }
- break;
- }
- },
-
- /**
- * nsIRadioInterfaceLayer interface methods.
- */
-
- getRadioInterface: function(clientId) {
- return this.radioInterfaces[clientId];
- },
-
- setMicrophoneMuted: function(muted) {
- for (let clientId = 0; clientId < this.numRadioInterfaces; clientId++) {
- let radioInterface = this.radioInterfaces[clientId];
- radioInterface.workerMessenger.send("setMute", { muted: muted });
- }
- }
-};
-
-XPCOMUtils.defineLazyGetter(RadioInterfaceLayer.prototype,
- "numRadioInterfaces", function() {
- try {
- return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces);
- } catch(e) {}
-
- return 1;
-});
-
-function WorkerMessenger() {
- // Initial owning attributes.
- this.radioInterfaces = [];
- this.tokenCallbackMap = {};
-
- this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
- this.worker.onerror = this.onerror.bind(this);
- this.worker.onmessage = this.onmessage.bind(this);
-}
-WorkerMessenger.prototype = {
- radioInterfaces: null,
- worker: null,
-
- // This gets incremented each time we send out a message.
- token: 1,
-
- // Maps tokens we send out with messages to the message callback.
- tokenCallbackMap: null,
-
- init: function() {
- let options = {
- debug: DEBUG,
- quirks: {
- callstateExtraUint32:
- libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true",
- requestUseDialEmergencyCall:
- libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true",
- simAppStateExtraFields:
- libcutils.property_get("ro.moz.ril.simstate_extra_field", "false") === "true",
- extraUint2ndCall:
- libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") === "true",
- haveQueryIccLockRetryCount:
- libcutils.property_get("ro.moz.ril.query_icc_count", "false") === "true",
- sendStkProfileDownload:
- libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") === "true",
- smscAddressFormat:
- libcutils.property_get("ro.moz.ril.smsc_address_format", "text"),
- dataRegistrationOnDemand:
- libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") === "true",
- subscriptionControl:
- libcutils.property_get("ro.moz.ril.subscription_control", "false") === "true",
- signalExtraInt:
- libcutils.property_get("ro.moz.ril.signal_extra_int", "false") === "true",
- availableNetworkExtraStr:
- libcutils.property_get("ro.moz.ril.avlbl_nw_extra_str", "false") === "true",
- }
- };
-
- this.send(null, "setInitialOptions", options);
- },
-
- setDebugFlag: function(aDebug) {
- let options = { debug: aDebug };
- this.send(null, "setDebugFlag", options);
- },
-
- debug: function(aClientId, aMessage) {
- // We use the same debug subject with RadioInterface's here.
- dump("-*- RadioInterface[" + aClientId + "]: " + aMessage + "\n");
- },
-
- onerror: function(event) {
- if (DEBUG) {
- this.debug("X", "Got an error: " + event.filename + ":" +
- event.lineno + ": " + event.message + "\n");
- }
- event.preventDefault();
- },
-
- /**
- * Process the incoming message from the RIL worker.
- */
- onmessage: function(event) {
- let message = event.data;
- let clientId = message.rilMessageClientId;
- if (clientId === null) {
- return;
- }
-
- if (DEBUG) {
- this.debug(clientId, "Received message from worker: " + JSON.stringify(message));
- }
-
- let token = message.rilMessageToken;
- if (token == null) {
- // That's an unsolicited message. Pass to RadioInterface directly.
- let radioInterface = this.radioInterfaces[clientId];
- radioInterface.handleUnsolicitedWorkerMessage(message);
- return;
- }
-
- let callback = this.tokenCallbackMap[message.rilMessageToken];
- if (!callback) {
- if (DEBUG) this.debug(clientId, "Ignore orphan token: " + message.rilMessageToken);
- return;
- }
-
- let keep = false;
- try {
- keep = callback(message);
- } catch(e) {
- if (DEBUG) this.debug(clientId, "callback throws an exception: " + e);
- }
-
- if (!keep) {
- delete this.tokenCallbackMap[message.rilMessageToken];
- }
- },
-
- registerClient: function(aClientId, aRadioInterface) {
- if (DEBUG) this.debug(aClientId, "Starting RIL Worker");
-
- // Keep a reference so that we can dispatch unsolicited messages to it.
- this.radioInterfaces[aClientId] = aRadioInterface;
-
- this.send(null, "registerClient", { clientId: aClientId });
- gSystemWorkerManager.registerRilWorker(aClientId, this.worker);
- },
-
- /**
- * Send arbitrary message to worker.
- *
- * @param rilMessageType
- * A text message type.
- * @param message [optional]
- * An optional message object to send.
- * @param callback [optional]
- * An optional callback function which is called when worker replies
- * with an message containing a "rilMessageToken" attribute of the
- * same value we passed. This callback function accepts only one
- * parameter -- the reply from worker. It also returns a boolean
- * value true to keep current token-callback mapping and wait for
- * another worker reply, or false to remove the mapping.
- */
- send: function(clientId, rilMessageType, message, callback) {
- message = message || {};
-
- message.rilMessageClientId = clientId;
- message.rilMessageToken = this.token;
- this.token++;
-
- if (callback) {
- // Only create the map if callback is provided. For sending a request
- // and intentionally leaving the callback undefined, that reply will
- // be dropped in |this.onmessage| because of that orphan token.
- //
- // For sending a request that never replied at all, we're fine with this
- // because no callback shall be passed and we leave nothing to be cleaned
- // up later.
- this.tokenCallbackMap[message.rilMessageToken] = callback;
- }
-
- message.rilMessageType = rilMessageType;
- this.worker.postMessage(message);
- }
-};
-
-function RadioInterface(aClientId, aWorkerMessenger) {
- this.clientId = aClientId;
- this.workerMessenger = {
- send: aWorkerMessenger.send.bind(aWorkerMessenger, aClientId)
- };
- aWorkerMessenger.registerClient(aClientId, this);
-
- this.operatorInfo = {};
-
- let lock = gSettingsService.createLock();
-
- // Read the "time.clock.automatic-update.enabled" setting to see if
- // we need to adjust the system clock time by NITZ or SNTP.
- lock.get(kSettingsClockAutoUpdateEnabled, this);
-
- // Read the "time.timezone.automatic-update.enabled" setting to see if
- // we need to adjust the system timezone by NITZ.
- lock.get(kSettingsTimezoneAutoUpdateEnabled, this);
-
- // Set "time.clock.automatic-update.available" to false when starting up.
- this.setClockAutoUpdateAvailable(false);
-
- // Set "time.timezone.automatic-update.available" to false when starting up.
- this.setTimezoneAutoUpdateAvailable(false);
-
- Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
- Services.obs.addObserver(this, kSysClockChangeObserverTopic, false);
- Services.obs.addObserver(this, kScreenStateChangedTopic, false);
-
- Services.obs.addObserver(this, kNetworkConnStateChangedTopic, false);
-
- this._sntp = new Sntp(this.setClockBySntp.bind(this),
- Services.prefs.getIntPref("network.sntp.maxRetryCount"),
- Services.prefs.getIntPref("network.sntp.refreshPeriod"),
- Services.prefs.getIntPref("network.sntp.timeout"),
- Services.prefs.getCharPref("network.sntp.pools").split(";"),
- Services.prefs.getIntPref("network.sntp.port"));
-}
-
-RadioInterface.prototype = {
-
- classID: RADIOINTERFACE_CID,
- classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACE_CID,
- classDescription: "RadioInterface",
- interfaces: [Ci.nsIRadioInterface]}),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioInterface,
- Ci.nsIObserver,
- Ci.nsISettingsServiceCallback]),
-
- // A private wrapped WorkerMessenger instance.
- workerMessenger: null,
-
- debug: function(s) {
- dump("-*- RadioInterface[" + this.clientId + "]: " + s + "\n");
- },
-
- shutdown: function() {
- Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic);
- Services.obs.removeObserver(this, kSysClockChangeObserverTopic);
- Services.obs.removeObserver(this, kScreenStateChangedTopic);
- Services.obs.removeObserver(this, kNetworkConnStateChangedTopic);
- },
-
- isCardPresent: function() {
- let icc = gIccService.getIccByServiceId(this.clientId);
- let cardState = icc ? icc.cardState : Ci.nsIIcc.CARD_STATE_UNKNOWN;
- return cardState !== Ci.nsIIcc.CARD_STATE_UNDETECTED &&
- cardState !== Ci.nsIIcc.CARD_STATE_UNKNOWN;
- },
-
- handleUnsolicitedWorkerMessage: function(message) {
- switch (message.rilMessageType) {
- case "callRing":
- gTelephonyService.notifyCallRing();
- break;
- case "currentCalls":
- gTelephonyService.notifyCurrentCalls(this.clientId, message.calls);
- break;
- case "cdmaCallWaiting":
- gTelephonyService.notifyCdmaCallWaiting(this.clientId,
- message.waitingCall);
- break;
- case "suppSvcNotification":
- gTelephonyService.notifySupplementaryService(this.clientId,
- message.number,
- message.notification);
- break;
- case "ussdreceived":
- gTelephonyService.notifyUssdReceived(this.clientId, message.message,
- message.sessionEnded);
- break;
- case "datacalllistchanged":
- let dataCalls = message.datacalls.map(dataCall => new DataCall(dataCall));
- gDataCallInterfaceService.notifyDataCallListChanged(this.clientId,
- dataCalls.length,
- dataCalls);
- break;
- case "emergencyCbModeChange":
- gMobileConnectionService.notifyEmergencyCallbackModeChanged(this.clientId,
- message.active,
- message.timeoutMs);
- break;
- case "networkinfochanged":
- gMobileConnectionService.notifyNetworkInfoChanged(this.clientId,
- message);
- break;
- case "networkselectionmodechange":
- gMobileConnectionService.notifyNetworkSelectModeChanged(this.clientId,
- message.mode);
- break;
- case "voiceregistrationstatechange":
- gMobileConnectionService.notifyVoiceInfoChanged(this.clientId, message);
- break;
- case "dataregistrationstatechange":
- gMobileConnectionService.notifyDataInfoChanged(this.clientId, message);
- break;
- case "signalstrengthchange":
- gMobileConnectionService.notifySignalStrengthChanged(this.clientId,
- message);
- break;
- case "operatorchange":
- gMobileConnectionService.notifyOperatorChanged(this.clientId, message);
- break;
- case "otastatuschange":
- gMobileConnectionService.notifyOtaStatusChanged(this.clientId, message.status);
- break;
- case "deviceidentitieschange":
- gMobileConnectionService.notifyDeviceIdentitiesChanged(this.clientId,
- message.deviceIdentities.imei,
- message.deviceIdentities.imeisv,
- message.deviceIdentities.esn,
- message.deviceIdentities.meid);
- break;
- case "radiostatechange":
- // gRadioEnabledController should know the radio state for each client,
- // so notify gRadioEnabledController here.
- gRadioEnabledController.notifyRadioStateChanged(this.clientId,
- message.radioState);
- break;
- case "cardstatechange":
- gIccService.notifyCardStateChanged(this.clientId,
- message.cardState);
- gRadioEnabledController.receiveCardState(this.clientId);
- break;
- case "sms-received":
- this.handleSmsReceived(message);
- break;
- case "cellbroadcast-received":
- this.handleCellbroadcastMessageReceived(message);
- break;
- case "nitzTime":
- this.handleNitzTime(message);
- break;
- case "iccinfochange":
- gIccService.notifyIccInfoChanged(this.clientId,
- message.iccid ? message : null);
- break;
- case "iccimsi":
- gIccService.notifyImsiChanged(this.clientId, message.imsi);
- break;
- case "iccmbdn":
- this.handleIccMbdn(message);
- break;
- case "iccmwis":
- this.handleIccMwis(message.mwi);
- break;
- case "stkcommand":
- gIccService.notifyStkCommand(this.clientId,
- gStkCmdFactory.createCommand(message));
- break;
- case "stksessionend":
- gIccService.notifyStkSessionEnd(this.clientId);
- break;
- case "cdma-info-rec-received":
- this.handleCdmaInformationRecords(message.records);
- break;
- default:
- throw new Error("Don't know about this message type: " +
- message.rilMessageType);
- }
- },
-
- setDataRegistration: function(attach) {
- let deferred = Promise.defer();
- this.workerMessenger.send("setDataRegistration",
- {attach: attach},
- (function(response) {
- // Always resolve to proceed with the following steps.
- deferred.resolve(response.errorMsg ? response.errorMsg : null);
- }).bind(this));
-
- return deferred.promise;
- },
-
- /**
- * TODO: Bug 911713 - B2G NetworkManager: Move policy control logic to
- * NetworkManager
- */
- updateRILNetworkInterface: function() {
- let connHandler = gDataCallManager.getDataCallHandler(this.clientId);
- connHandler.updateRILNetworkInterface();
- },
-
- /**
- * handle received SMS.
- */
- handleSmsReceived: function(aMessage) {
- let header = aMessage.header;
- // Concatenation Info:
- // - segmentRef: a modulo 256 counter indicating the reference number for a
- // particular concatenated short message. '0' is a valid number.
- // - The concatenation info will not be available in |header| if
- // segmentSeq or segmentMaxSeq is 0.
- // See 3GPP TS 23.040, 9.2.3.24.1 Concatenated Short Messages.
- let segmentRef = (header && header.segmentRef !== undefined)
- ? header.segmentRef : 1;
- let segmentSeq = header && header.segmentSeq || 1;
- let segmentMaxSeq = header && header.segmentMaxSeq || 1;
- // Application Ports:
- // The port number ranges from 0 to 49151.
- // see 3GPP TS 23.040, 9.2.3.24.3/4 Application Port Addressing.
- let originatorPort = (header && header.originatorPort !== undefined)
- ? header.originatorPort
- : Ci.nsIGonkSmsService.SMS_APPLICATION_PORT_INVALID;
- let destinationPort = (header && header.destinationPort !== undefined)
- ? header.destinationPort
- : Ci.nsIGonkSmsService.SMS_APPLICATION_PORT_INVALID;
- // MWI info:
- let mwiPresent = (aMessage.mwi)? true : false;
- let mwiDiscard = (mwiPresent)? aMessage.mwi.discard: false;
- let mwiMsgCount = (mwiPresent)? aMessage.mwi.msgCount: 0;
- let mwiActive = (mwiPresent)? aMessage.mwi.active: false;
- // CDMA related attributes:
- let cdmaMessageType = aMessage.messageType || 0;
- let cdmaTeleservice = aMessage.teleservice || 0;
- let cdmaServiceCategory = aMessage.serviceCategory || 0;
-
- gSmsService
- .notifyMessageReceived(this.clientId,
- aMessage.SMSC || null,
- aMessage.sentTimestamp,
- aMessage.sender,
- aMessage.pid,
- aMessage.encoding,
- RIL.GECKO_SMS_MESSAGE_CLASSES
- .indexOf(aMessage.messageClass),
- aMessage.language || null,
- segmentRef,
- segmentSeq,
- segmentMaxSeq,
- originatorPort,
- destinationPort,
- mwiPresent,
- mwiDiscard,
- mwiMsgCount,
- mwiActive,
- cdmaMessageType,
- cdmaTeleservice,
- cdmaServiceCategory,
- aMessage.body || null,
- aMessage.data || [],
- (aMessage.data) ? aMessage.data.length : 0);
- },
-
- /**
- * Set the setting value of "time.clock.automatic-update.available".
- */
- setClockAutoUpdateAvailable: function(value) {
- gSettingsService.createLock().set(kSettingsClockAutoUpdateAvailable, value, null);
- },
-
- /**
- * Set the setting value of "time.timezone.automatic-update.available".
- */
- setTimezoneAutoUpdateAvailable: function(value) {
- gSettingsService.createLock().set(kSettingsTimezoneAutoUpdateAvailable, value, null);
- },
-
- /**
- * Set the system clock by NITZ.
- */
- setClockByNitz: function(message) {
- // To set the system clock time. Note that there could be a time diff
- // between when the NITZ was received and when the time is actually set.
- gTimeService.set(
- message.networkTimeInMS + (Date.now() - message.receiveTimeInMS));
- },
-
- /**
- * Set the system time zone by NITZ.
- */
- setTimezoneByNitz: function(message) {
- // To set the sytem timezone. Note that we need to convert the time zone
- // value to a UTC repesentation string in the format of "UTC(+/-)hh:mm".
- // Ex, time zone -480 is "UTC+08:00"; time zone 630 is "UTC-10:30".
- //
- // We can unapply the DST correction if we want the raw time zone offset:
- // message.networkTimeZoneInMinutes -= message.networkDSTInMinutes;
- if (message.networkTimeZoneInMinutes != (new Date()).getTimezoneOffset()) {
- let absTimeZoneInMinutes = Math.abs(message.networkTimeZoneInMinutes);
- let timeZoneStr = "UTC";
- timeZoneStr += (message.networkTimeZoneInMinutes > 0 ? "-" : "+");
- timeZoneStr += ("0" + Math.floor(absTimeZoneInMinutes / 60)).slice(-2);
- timeZoneStr += ":";
- timeZoneStr += ("0" + absTimeZoneInMinutes % 60).slice(-2);
- gSettingsService.createLock().set("time.timezone", timeZoneStr, null);
- }
- },
-
- /**
- * Handle the NITZ message.
- */
- handleNitzTime: function(message) {
- // Got the NITZ info received from the ril_worker.
- this.setClockAutoUpdateAvailable(true);
- this.setTimezoneAutoUpdateAvailable(true);
-
- // Cache the latest NITZ message whenever receiving it.
- this._lastNitzMessage = message;
-
- // Set the received NITZ clock if the setting is enabled.
- if (this._clockAutoUpdateEnabled) {
- this.setClockByNitz(message);
- }
- // Set the received NITZ timezone if the setting is enabled.
- if (this._timezoneAutoUpdateEnabled) {
- this.setTimezoneByNitz(message);
- }
- },
-
- /**
- * Set the system clock by SNTP.
- */
- setClockBySntp: function(offset) {
- // Got the SNTP info.
- this.setClockAutoUpdateAvailable(true);
- if (!this._clockAutoUpdateEnabled) {
- return;
- }
- if (this._lastNitzMessage) {
- if (DEBUG) debug("SNTP: NITZ available, discard SNTP");
- return;
- }
- gTimeService.set(Date.now() + offset);
- },
-
- handleIccMbdn: function(message) {
- let service = Cc["@mozilla.org/voicemail/voicemailservice;1"]
- .getService(Ci.nsIGonkVoicemailService);
- service.notifyInfoChanged(this.clientId, message.number, message.alphaId);
- },
-
- handleIccMwis: function(mwi) {
- let service = Cc["@mozilla.org/voicemail/voicemailservice;1"]
- .getService(Ci.nsIGonkVoicemailService);
- // Note: returnNumber and returnMessage is not available from UICC.
- service.notifyStatusChanged(this.clientId, mwi.active, mwi.msgCount,
- null, null);
- },
-
- _convertCbGsmGeographicalScope: function(aGeographicalScope) {
- return (aGeographicalScope != null)
- ? aGeographicalScope
- : Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_INVALID;
- },
-
- _convertCbMessageClass: function(aMessageClass) {
- let index = RIL.GECKO_SMS_MESSAGE_CLASSES.indexOf(aMessageClass);
- return (index != -1)
- ? index
- : Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_NORMAL;
- },
-
- _convertCbEtwsWarningType: function(aWarningType) {
- return (aWarningType != null)
- ? aWarningType
- : Ci.nsICellBroadcastService.GSM_ETWS_WARNING_INVALID;
- },
-
- handleCellbroadcastMessageReceived: function(aMessage) {
- let etwsInfo = aMessage.etws;
- let hasEtwsInfo = etwsInfo != null;
- let serviceCategory = (aMessage.serviceCategory)
- ? aMessage.serviceCategory
- : Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID;
-
- gCellBroadcastService
- .notifyMessageReceived(this.clientId,
- this._convertCbGsmGeographicalScope(aMessage.geographicalScope),
- aMessage.messageCode,
- aMessage.messageId,
- aMessage.language,
- aMessage.fullBody,
- this._convertCbMessageClass(aMessage.messageClass),
- Date.now(),
- serviceCategory,
- hasEtwsInfo,
- (hasEtwsInfo)
- ? this._convertCbEtwsWarningType(etwsInfo.warningType)
- : Ci.nsICellBroadcastService.GSM_ETWS_WARNING_INVALID,
- hasEtwsInfo ? etwsInfo.emergencyUserAlert : false,
- hasEtwsInfo ? etwsInfo.popup : false);
- },
-
- handleCdmaInformationRecords: function(aRecords) {
- if (DEBUG) this.debug("cdma-info-rec-received: " + JSON.stringify(aRecords));
-
- let clientId = this.clientId;
-
- aRecords.forEach(function(aRecord) {
- if (aRecord.display) {
- gMobileConnectionService
- .notifyCdmaInfoRecDisplay(clientId, aRecord.display);
- return;
- }
-
- if (aRecord.calledNumber) {
- gMobileConnectionService
- .notifyCdmaInfoRecCalledPartyNumber(clientId,
- aRecord.calledNumber.type,
- aRecord.calledNumber.plan,
- aRecord.calledNumber.number,
- aRecord.calledNumber.pi,
- aRecord.calledNumber.si);
- return;
- }
-
- if (aRecord.callingNumber) {
- gMobileConnectionService
- .notifyCdmaInfoRecCallingPartyNumber(clientId,
- aRecord.callingNumber.type,
- aRecord.callingNumber.plan,
- aRecord.callingNumber.number,
- aRecord.callingNumber.pi,
- aRecord.callingNumber.si);
- return;
- }
-
- if (aRecord.connectedNumber) {
- gMobileConnectionService
- .notifyCdmaInfoRecConnectedPartyNumber(clientId,
- aRecord.connectedNumber.type,
- aRecord.connectedNumber.plan,
- aRecord.connectedNumber.number,
- aRecord.connectedNumber.pi,
- aRecord.connectedNumber.si);
- return;
- }
-
- if (aRecord.signal) {
- gMobileConnectionService
- .notifyCdmaInfoRecSignal(clientId,
- aRecord.signal.type,
- aRecord.signal.alertPitch,
- aRecord.signal.signal);
- return;
- }
-
- if (aRecord.redirect) {
- gMobileConnectionService
- .notifyCdmaInfoRecRedirectingNumber(clientId,
- aRecord.redirect.type,
- aRecord.redirect.plan,
- aRecord.redirect.number,
- aRecord.redirect.pi,
- aRecord.redirect.si,
- aRecord.redirect.reason);
- return;
- }
-
- if (aRecord.lineControl) {
- gMobileConnectionService
- .notifyCdmaInfoRecLineControl(clientId,
- aRecord.lineControl.polarityIncluded,
- aRecord.lineControl.toggle,
- aRecord.lineControl.reverse,
- aRecord.lineControl.powerDenial);
- return;
- }
-
- if (aRecord.clirCause) {
- gMobileConnectionService
- .notifyCdmaInfoRecClir(clientId,
- aRecord.clirCause);
- return;
- }
-
- if (aRecord.audioControl) {
- gMobileConnectionService
- .notifyCdmaInfoRecAudioControl(clientId,
- aRecord.audioControl.upLink,
- aRecord.audioControl.downLink);
- return;
- }
- });
- },
-
- // nsIObserver
-
- observe: function(subject, topic, data) {
- switch (topic) {
- case kMozSettingsChangedObserverTopic:
- if ("wrappedJSObject" in subject) {
- subject = subject.wrappedJSObject;
- }
- this.handleSettingsChange(subject.key, subject.value, subject.isInternalChange);
- break;
- case kSysClockChangeObserverTopic:
- let offset = parseInt(data, 10);
- if (this._lastNitzMessage) {
- this._lastNitzMessage.receiveTimeInMS += offset;
- }
- this._sntp.updateOffset(offset);
- break;
- case kNetworkConnStateChangedTopic:
- let networkInfo = subject.QueryInterface(Ci.nsINetworkInfo);
- if (networkInfo.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- return;
- }
-
- // SNTP can only update when we have mobile or Wifi connections.
- if (networkInfo.type != NETWORK_TYPE_WIFI &&
- networkInfo.type != NETWORK_TYPE_MOBILE) {
- return;
- }
-
- // If the network comes from RIL, make sure the RIL service is matched.
- if (subject instanceof Ci.nsIRilNetworkInfo) {
- networkInfo = subject.QueryInterface(Ci.nsIRilNetworkInfo);
- if (networkInfo.serviceId != this.clientId) {
- return;
- }
- }
-
- // SNTP won't update unless the SNTP is already expired.
- if (this._sntp.isExpired()) {
- this._sntp.request();
- }
- break;
- case kScreenStateChangedTopic:
- this.workerMessenger.send("setScreenState", { on: (data === "on") });
- break;
- }
- },
-
- // Flag to determine whether to update system clock automatically. It
- // corresponds to the "time.clock.automatic-update.enabled" setting.
- _clockAutoUpdateEnabled: null,
-
- // Flag to determine whether to update system timezone automatically. It
- // corresponds to the "time.clock.automatic-update.enabled" setting.
- _timezoneAutoUpdateEnabled: null,
-
- // Remember the last NITZ message so that we can set the time based on
- // the network immediately when users enable network-based time.
- _lastNitzMessage: null,
-
- // Object that handles SNTP.
- _sntp: null,
-
- // Cell Broadcast settings values.
- _cellBroadcastSearchList: null,
-
- handleSettingsChange: function(aName, aResult, aIsInternalSetting) {
- // Don't allow any content processes to modify the setting
- // "time.clock.automatic-update.available" except for the chrome process.
- if (aName === kSettingsClockAutoUpdateAvailable &&
- !aIsInternalSetting) {
- let isClockAutoUpdateAvailable = this._lastNitzMessage !== null ||
- this._sntp.isAvailable();
- if (aResult !== isClockAutoUpdateAvailable) {
- if (DEBUG) {
- debug("Content processes cannot modify 'time.clock.automatic-update.available'. Restore!");
- }
- // Restore the setting to the current value.
- this.setClockAutoUpdateAvailable(isClockAutoUpdateAvailable);
- }
- }
-
- // Don't allow any content processes to modify the setting
- // "time.timezone.automatic-update.available" except for the chrome
- // process.
- if (aName === kSettingsTimezoneAutoUpdateAvailable &&
- !aIsInternalSetting) {
- let isTimezoneAutoUpdateAvailable = this._lastNitzMessage !== null;
- if (aResult !== isTimezoneAutoUpdateAvailable) {
- if (DEBUG) {
- this.debug("Content processes cannot modify 'time.timezone.automatic-update.available'. Restore!");
- }
- // Restore the setting to the current value.
- this.setTimezoneAutoUpdateAvailable(isTimezoneAutoUpdateAvailable);
- }
- }
-
- this.handle(aName, aResult);
- },
-
- // nsISettingsServiceCallback
- handle: function(aName, aResult) {
- switch(aName) {
- case kSettingsClockAutoUpdateEnabled:
- this._clockAutoUpdateEnabled = aResult;
- if (!this._clockAutoUpdateEnabled) {
- break;
- }
-
- // Set the latest cached NITZ time if it's available.
- if (this._lastNitzMessage) {
- this.setClockByNitz(this._lastNitzMessage);
- } else if (gNetworkManager.activeNetworkInfo &&
- gNetworkManager.activeNetworkInfo.state ==
- Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- // Set the latest cached SNTP time if it's available.
- if (!this._sntp.isExpired()) {
- this.setClockBySntp(this._sntp.getOffset());
- } else {
- // Or refresh the SNTP.
- this._sntp.request();
- }
- } else {
- // Set a sane minimum time.
- let buildTime = libcutils.property_get("ro.build.date.utc", "0") * 1000;
- let file = FileUtils.File("/system/b2g/b2g");
- if (file.lastModifiedTime > buildTime) {
- buildTime = file.lastModifiedTime;
- }
- if (buildTime > Date.now()) {
- gTimeService.set(buildTime);
- }
- }
- break;
- case kSettingsTimezoneAutoUpdateEnabled:
- this._timezoneAutoUpdateEnabled = aResult;
-
- if (this._timezoneAutoUpdateEnabled) {
- // Apply the latest cached NITZ for timezone if it's available.
- if (this._timezoneAutoUpdateEnabled && this._lastNitzMessage) {
- this.setTimezoneByNitz(this._lastNitzMessage);
- }
- }
- break;
- }
- },
-
- handleError: function(aErrorMessage) {
- if (DEBUG) {
- this.debug("There was an error while reading RIL settings.");
- }
- },
-
- // nsIRadioInterface
-
- // TODO: Bug 928861 - B2G NetworkManager: Provide a more generic function
- // for connecting
- setupDataCallByType: function(networkType) {
- let connHandler = gDataCallManager.getDataCallHandler(this.clientId);
- connHandler.setupDataCallByType(networkType);
- },
-
- // TODO: Bug 928861 - B2G NetworkManager: Provide a more generic function
- // for connecting
- deactivateDataCallByType: function(networkType) {
- let connHandler = gDataCallManager.getDataCallHandler(this.clientId);
- connHandler.deactivateDataCallByType(networkType);
- },
-
- // TODO: Bug 904514 - [meta] NetworkManager enhancement
- getDataCallStateByType: function(networkType) {
- let connHandler = gDataCallManager.getDataCallHandler(this.clientId);
- return connHandler.getDataCallStateByType(networkType);
- },
-
- sendWorkerMessage: function(rilMessageType, message, callback) {
- // Special handler for setRadioEnabled.
- if (rilMessageType === "setRadioEnabled") {
- // Forward it to gRadioEnabledController.
- gRadioEnabledController.setRadioEnabled(this.clientId, message,
- callback.handleResponse);
- return;
- }
-
- if (callback) {
- this.workerMessenger.send(rilMessageType, message, function(response) {
- return callback.handleResponse(response);
- });
- } else {
- this.workerMessenger.send(rilMessageType, message);
- }
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RadioInterfaceLayer]);
diff --git a/dom/system/gonk/RadioInterfaceLayer.manifest b/dom/system/gonk/RadioInterfaceLayer.manifest
deleted file mode 100644
index 3c7c3b808..000000000
--- a/dom/system/gonk/RadioInterfaceLayer.manifest
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2012 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# RadioInterfaceLayer.js
-component {2d831c8d-6017-435b-a80c-e5d422810cea} RadioInterfaceLayer.js
-contract @mozilla.org/ril;1 {2d831c8d-6017-435b-a80c-e5d422810cea}
-category profile-after-change RadioInterfaceLayer @mozilla.org/ril;1
diff --git a/dom/system/gonk/SystemProperty.cpp b/dom/system/gonk/SystemProperty.cpp
deleted file mode 100644
index 1f874ce90..000000000
--- a/dom/system/gonk/SystemProperty.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SystemProperty.h"
-
-#include <dlfcn.h>
-#include <string.h>
-
-#include "nsDebug.h"
-#include "prinit.h"
-
-namespace mozilla {
-namespace system {
-
-namespace {
-
-typedef int (*PropertyGet)(const char*, char*, const char*);
-typedef int (*PropertySet)(const char*, const char*);
-
-static void *sLibcUtils;
-static PRCallOnceType sInitLibcUtils;
-
-static int
-FakePropertyGet(const char* key, char* value, const char* default_value)
-{
- if(!default_value) {
- value[0] = '\0';
- return 0;
- }
-
- int len = strlen(default_value);
- if (len >= Property::VALUE_MAX_LENGTH) {
- len = Property::VALUE_MAX_LENGTH - 1;
- }
- memcpy(value, default_value, len);
- value[len] = '\0';
-
- return len;
-}
-
-static int
-FakePropertySet(const char* key, const char* value)
-{
- return 0;
-}
-
-static PRStatus
-InitLibcUtils()
-{
- sLibcUtils = dlopen("/system/lib/libcutils.so", RTLD_LAZY);
- // We will fallback to the fake getter/setter when sLibcUtils is not valid.
- return PR_SUCCESS;
-}
-
-static void*
-GetLibcUtils()
-{
- PR_CallOnce(&sInitLibcUtils, InitLibcUtils);
- return sLibcUtils;
-}
-
-} // anonymous namespace
-
-/*static*/ int
-Property::Get(const char* key, char* value, const char* default_value)
-{
- void *libcutils = GetLibcUtils();
- if (libcutils) {
- PropertyGet getter = (PropertyGet) dlsym(libcutils, "property_get");
- if (getter) {
- return getter(key, value, default_value);
- }
- NS_WARNING("Failed to get property_get() from libcutils!");
- }
- NS_WARNING("Fallback to the FakePropertyGet()");
- return FakePropertyGet(key, value, default_value);
-}
-
-/*static*/ int
-Property::Set(const char* key, const char* value)
-{
- void *libcutils = GetLibcUtils();
- if (libcutils) {
- PropertySet setter = (PropertySet) dlsym(libcutils, "property_set");
- if (setter) {
- return setter(key, value);
- }
- NS_WARNING("Failed to get property_set() from libcutils!");
- }
- NS_WARNING("Fallback to the FakePropertySet()");
- return FakePropertySet(key, value);
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/SystemProperty.h b/dom/system/gonk/SystemProperty.h
deleted file mode 100644
index 2b5ceae8b..000000000
--- a/dom/system/gonk/SystemProperty.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_Property_h
-#define mozilla_system_Property_h
-
-namespace mozilla {
-namespace system {
-
-/**
-* Abstraction of property_get/property_get in libcutils from AOSP.
-*/
-class Property
-{
-public:
- // Constants defined in system_properties.h from AOSP.
- enum {
- KEY_MAX_LENGTH = 32,
- VALUE_MAX_LENGTH = 92
- };
-
- static int
- Get(const char* key, char* value, const char* default_value);
-
- static int
- Set(const char* key, const char* value);
-
-private:
- Property() {}
- virtual ~Property() {}
-};
-
-} // namespace system
-} // namespace mozilla
-
- #endif // mozilla_system_Property_h
diff --git a/dom/system/gonk/SystemWorkerManager.cpp b/dom/system/gonk/SystemWorkerManager.cpp
deleted file mode 100644
index ee3fc8de3..000000000
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SystemWorkerManager.h"
-
-#include "nsINetworkService.h"
-#include "nsIWifi.h"
-#include "nsIWorkerHolder.h"
-#include "nsIXPConnect.h"
-
-#include "jsfriendapi.h"
-#include "mozilla/dom/workers/Workers.h"
-#include "AutoMounter.h"
-#include "TimeZoneSettingObserver.h"
-#include "AudioManager.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/ipc/KeyStore.h"
-#include "nsIObserverService.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "WifiWorker.h"
-#include "mozilla/Services.h"
-
-USING_WORKERS_NAMESPACE
-
-using namespace mozilla::dom::gonk;
-using namespace mozilla::ipc;
-using namespace mozilla::system;
-
-namespace {
-
-NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID);
-
-// Doesn't carry a reference, we're owned by services.
-SystemWorkerManager *gInstance = nullptr;
-
-} // namespace
-
-SystemWorkerManager::SystemWorkerManager()
- : mShutdown(false)
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
- NS_ASSERTION(!gInstance, "There should only be one instance!");
-}
-
-SystemWorkerManager::~SystemWorkerManager()
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
- NS_ASSERTION(!gInstance || gInstance == this,
- "There should only be one instance!");
- gInstance = nullptr;
-}
-
-nsresult
-SystemWorkerManager::Init()
-{
- if (!XRE_IsParentProcess()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread");
- NS_ASSERTION(!mShutdown, "Already shutdown!");
-
- nsresult rv = InitWifi();
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to initialize WiFi Networking!");
- return rv;
- }
-
- InitKeyStore();
-
- InitAutoMounter();
- InitializeTimeZoneSettingObserver();
- nsCOMPtr<nsIAudioManager> audioManager =
- do_GetService(NS_AUDIOMANAGER_CONTRACTID);
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (!obs) {
- NS_WARNING("Failed to get observer service!");
- return NS_ERROR_FAILURE;
- }
-
- rv = obs->AddObserver(this, WORKERS_SHUTDOWN_TOPIC, false);
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to initialize worker shutdown event!");
- return rv;
- }
-
- return NS_OK;
-}
-
-void
-SystemWorkerManager::Shutdown()
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
- mShutdown = true;
-
- ShutdownAutoMounter();
-
- nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker));
- if (wifi) {
- wifi->Shutdown();
- wifi = nullptr;
- }
- mWifiWorker = nullptr;
-
- if (mKeyStore) {
- mKeyStore->Shutdown();
- mKeyStore = nullptr;
- }
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (obs) {
- obs->RemoveObserver(this, WORKERS_SHUTDOWN_TOPIC);
- }
-}
-
-// static
-already_AddRefed<SystemWorkerManager>
-SystemWorkerManager::FactoryCreate()
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
- RefPtr<SystemWorkerManager> instance(gInstance);
-
- if (!instance) {
- instance = new SystemWorkerManager();
- if (NS_FAILED(instance->Init())) {
- instance->Shutdown();
- return nullptr;
- }
-
- gInstance = instance;
- }
-
- return instance.forget();
-}
-
-// static
-nsIInterfaceRequestor*
-SystemWorkerManager::GetInterfaceRequestor()
-{
- return gInstance;
-}
-
-NS_IMETHODIMP
-SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult)
-{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
- if (aIID.Equals(NS_GET_IID(nsIWifi))) {
- return CallQueryInterface(mWifiWorker,
- reinterpret_cast<nsIWifi**>(aResult));
- }
-
- NS_WARNING("Got nothing for the requested IID!");
- return NS_ERROR_NO_INTERFACE;
-}
-
-nsresult
-SystemWorkerManager::RegisterRilWorker(unsigned int aClientId,
- JS::Handle<JS::Value> aWorker,
- JSContext *aCx)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-nsresult
-SystemWorkerManager::InitWifi()
-{
- nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kWifiWorkerCID);
- NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
-
- mWifiWorker = worker;
- return NS_OK;
-}
-
-nsresult
-SystemWorkerManager::InitKeyStore()
-{
- mKeyStore = new KeyStore();
- return NS_OK;
-}
-
-NS_IMPL_ISUPPORTS(SystemWorkerManager,
- nsIObserver,
- nsIInterfaceRequestor,
- nsISystemWorkerManager)
-
-NS_IMETHODIMP
-SystemWorkerManager::Observe(nsISupports *aSubject, const char *aTopic,
- const char16_t *aData)
-{
- if (!strcmp(aTopic, WORKERS_SHUTDOWN_TOPIC)) {
- Shutdown();
- }
-
- return NS_OK;
-}
diff --git a/dom/system/gonk/SystemWorkerManager.h b/dom/system/gonk/SystemWorkerManager.h
deleted file mode 100644
index 625cda261..000000000
--- a/dom/system/gonk/SystemWorkerManager.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 mozilla_dom_system_b2g_systemworkermanager_h__
-#define mozilla_dom_system_b2g_systemworkermanager_h__
-
-#include "nsIInterfaceRequestor.h"
-#include "nsISystemWorkerManager.h"
-#include "nsIObserver.h"
-#include "nsCOMPtr.h"
-#include "nsXULAppAPI.h" // For XRE_GetProcessType
-
-class nsIWorkerHolder;
-
-namespace mozilla {
-
-namespace ipc {
- class KeyStore;
-}
-
-namespace dom {
-namespace gonk {
-
-class SystemWorkerManager final : public nsIObserver,
- public nsIInterfaceRequestor,
- public nsISystemWorkerManager
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- NS_DECL_NSIINTERFACEREQUESTOR
- NS_DECL_NSISYSTEMWORKERMANAGER
-
- nsresult Init();
- void Shutdown();
-
- static already_AddRefed<SystemWorkerManager>
- FactoryCreate();
-
- static nsIInterfaceRequestor*
- GetInterfaceRequestor();
-
-private:
- SystemWorkerManager();
- ~SystemWorkerManager();
-
- nsresult InitWifi();
- nsresult InitKeyStore();
-
- nsCOMPtr<nsIWorkerHolder> mWifiWorker;
-
- RefPtr<mozilla::ipc::KeyStore> mKeyStore;
-
- bool mShutdown;
-};
-
-}
-}
-}
-
-#endif // mozilla_dom_system_b2g_systemworkermanager_h__
diff --git a/dom/system/gonk/TetheringService.js b/dom/system/gonk/TetheringService.js
deleted file mode 100644
index c5c478180..000000000
--- a/dom/system/gonk/TetheringService.js
+++ /dev/null
@@ -1,891 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-const TETHERINGSERVICE_CONTRACTID = "@mozilla.org/tethering/service;1";
-const TETHERINGSERVICE_CID =
- Components.ID("{527a4121-ee5a-4651-be9c-f46f59cf7c01}");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
- "@mozilla.org/network/manager;1",
- "nsINetworkManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
- "@mozilla.org/network/service;1",
- "nsINetworkService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
- "@mozilla.org/mobileconnection/mobileconnectionservice;1",
- "nsIMobileConnectionService");
-
-XPCOMUtils.defineLazyGetter(this, "gRil", function() {
- try {
- return Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
- } catch (e) {}
-
- return null;
-});
-
-const TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed";
-const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
-const TOPIC_PREF_CHANGED = "nsPref:changed";
-const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
-const PREF_MANAGE_OFFLINE_STATUS = "network.gonk.manage-offline-status";
-const PREF_NETWORK_DEBUG_ENABLED = "network.debugging.enabled";
-
-const POSSIBLE_USB_INTERFACE_NAME = "rndis0,usb0";
-const DEFAULT_USB_INTERFACE_NAME = "rndis0";
-const DEFAULT_3G_INTERFACE_NAME = "rmnet0";
-const DEFAULT_WIFI_INTERFACE_NAME = "wlan0";
-
-// The kernel's proc entry for network lists.
-const KERNEL_NETWORK_ENTRY = "/sys/class/net";
-
-const TETHERING_TYPE_WIFI = "WiFi";
-const TETHERING_TYPE_USB = "USB";
-
-const WIFI_FIRMWARE_AP = "AP";
-const WIFI_FIRMWARE_STATION = "STA";
-const WIFI_SECURITY_TYPE_NONE = "open";
-const WIFI_SECURITY_TYPE_WPA_PSK = "wpa-psk";
-const WIFI_SECURITY_TYPE_WPA2_PSK = "wpa2-psk";
-const WIFI_CTRL_INTERFACE = "wl0.1";
-
-const NETWORK_INTERFACE_UP = "up";
-const NETWORK_INTERFACE_DOWN = "down";
-
-const TETHERING_STATE_ONGOING = "ongoing";
-const TETHERING_STATE_IDLE = "idle";
-const TETHERING_STATE_ACTIVE = "active";
-
-// Settings DB path for USB tethering.
-const SETTINGS_USB_ENABLED = "tethering.usb.enabled";
-const SETTINGS_USB_IP = "tethering.usb.ip";
-const SETTINGS_USB_PREFIX = "tethering.usb.prefix";
-const SETTINGS_USB_DHCPSERVER_STARTIP = "tethering.usb.dhcpserver.startip";
-const SETTINGS_USB_DHCPSERVER_ENDIP = "tethering.usb.dhcpserver.endip";
-const SETTINGS_USB_DNS1 = "tethering.usb.dns1";
-const SETTINGS_USB_DNS2 = "tethering.usb.dns2";
-
-// Settings DB path for WIFI tethering.
-const SETTINGS_WIFI_DHCPSERVER_STARTIP = "tethering.wifi.dhcpserver.startip";
-const SETTINGS_WIFI_DHCPSERVER_ENDIP = "tethering.wifi.dhcpserver.endip";
-
-// Settings DB patch for dun required setting.
-const SETTINGS_DUN_REQUIRED = "tethering.dun.required";
-
-// Default value for USB tethering.
-const DEFAULT_USB_IP = "192.168.0.1";
-const DEFAULT_USB_PREFIX = "24";
-const DEFAULT_USB_DHCPSERVER_STARTIP = "192.168.0.10";
-const DEFAULT_USB_DHCPSERVER_ENDIP = "192.168.0.30";
-
-const DEFAULT_DNS1 = "8.8.8.8";
-const DEFAULT_DNS2 = "8.8.4.4";
-
-const DEFAULT_WIFI_DHCPSERVER_STARTIP = "192.168.1.10";
-const DEFAULT_WIFI_DHCPSERVER_ENDIP = "192.168.1.30";
-
-const SETTINGS_DATA_DEFAULT_SERVICE_ID = "ril.data.defaultServiceId";
-const MOBILE_DUN_CONNECT_TIMEOUT = 30000;
-const MOBILE_DUN_RETRY_INTERVAL = 5000;
-const MOBILE_DUN_MAX_RETRIES = 5;
-
-var debug;
-function updateDebug() {
- let debugPref = false; // set default value here.
- try {
- debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
- } catch (e) {}
-
- if (debugPref) {
- debug = function(s) {
- dump("-*- TetheringService: " + s + "\n");
- };
- } else {
- debug = function(s) {};
- }
-}
-updateDebug();
-
-function TetheringService() {
- Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
- Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false);
- Services.obs.addObserver(this, TOPIC_CONNECTION_STATE_CHANGED, false);
- Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
- Services.prefs.addObserver(PREF_MANAGE_OFFLINE_STATUS, this, false);
-
- try {
- this._manageOfflineStatus =
- Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
- } catch(ex) {
- // Ignore.
- }
-
- this._dataDefaultServiceId = 0;
-
- // Possible usb tethering interfaces for different gonk platform.
- this.possibleInterface = POSSIBLE_USB_INTERFACE_NAME.split(",");
-
- // Default values for internal and external interfaces.
- this._tetheringInterface = {};
- this._tetheringInterface[TETHERING_TYPE_USB] = {
- externalInterface: DEFAULT_3G_INTERFACE_NAME,
- internalInterface: DEFAULT_USB_INTERFACE_NAME
- };
- this._tetheringInterface[TETHERING_TYPE_WIFI] = {
- externalInterface: DEFAULT_3G_INTERFACE_NAME,
- internalInterface: DEFAULT_WIFI_INTERFACE_NAME
- };
-
- this.tetheringSettings = {};
- this.initTetheringSettings();
-
- let settingsLock = gSettingsService.createLock();
- // Read the default service id for data call.
- settingsLock.get(SETTINGS_DATA_DEFAULT_SERVICE_ID, this);
-
- // Read usb tethering data from settings DB.
- settingsLock.get(SETTINGS_USB_IP, this);
- settingsLock.get(SETTINGS_USB_PREFIX, this);
- settingsLock.get(SETTINGS_USB_DHCPSERVER_STARTIP, this);
- settingsLock.get(SETTINGS_USB_DHCPSERVER_ENDIP, this);
- settingsLock.get(SETTINGS_USB_DNS1, this);
- settingsLock.get(SETTINGS_USB_DNS2, this);
- settingsLock.get(SETTINGS_USB_ENABLED, this);
-
- // Read wifi tethering data from settings DB.
- settingsLock.get(SETTINGS_WIFI_DHCPSERVER_STARTIP, this);
- settingsLock.get(SETTINGS_WIFI_DHCPSERVER_ENDIP, this);
-
- this._usbTetheringSettingsToRead = [SETTINGS_USB_IP,
- SETTINGS_USB_PREFIX,
- SETTINGS_USB_DHCPSERVER_STARTIP,
- SETTINGS_USB_DHCPSERVER_ENDIP,
- SETTINGS_USB_DNS1,
- SETTINGS_USB_DNS2,
- SETTINGS_USB_ENABLED,
- SETTINGS_WIFI_DHCPSERVER_STARTIP,
- SETTINGS_WIFI_DHCPSERVER_ENDIP];
-
- this.wantConnectionEvent = null;
-
- this.dunConnectTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- this.dunRetryTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- this._pendingTetheringRequests = [];
-}
-TetheringService.prototype = {
- classID: TETHERINGSERVICE_CID,
- classInfo: XPCOMUtils.generateCI({classID: TETHERINGSERVICE_CID,
- contractID: TETHERINGSERVICE_CONTRACTID,
- classDescription: "Tethering Service",
- interfaces: [Ci.nsITetheringService]}),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsITetheringService,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver,
- Ci.nsISettingsServiceCallback]),
-
- // Flag to record the default client id for data call.
- _dataDefaultServiceId: null,
-
- // Number of usb tehering requests to be processed.
- _usbTetheringRequestCount: 0,
-
- // Usb tethering state.
- _usbTetheringAction: TETHERING_STATE_IDLE,
-
- // Tethering settings.
- tetheringSettings: null,
-
- // Tethering settings need to be read from settings DB.
- _usbTetheringSettingsToRead: null,
-
- // Previous usb tethering enabled state.
- _oldUsbTetheringEnabledState: null,
-
- // External and internal interface name.
- _tetheringInterface: null,
-
- // Dun connection timer.
- dunConnectTimer: null,
-
- // Dun connection retry times.
- dunRetryTimes: 0,
-
- // Dun retry timer.
- dunRetryTimer: null,
-
- // Pending tethering request to handle after dun is connected.
- _pendingTetheringRequests: null,
-
- // Flag to indicate wether wifi tethering is being processed.
- _wifiTetheringRequestOngoing: false,
-
- // Arguments for pending wifi tethering request.
- _pendingWifiTetheringRequestArgs: null,
-
- // The state of tethering.
- state: Ci.nsITetheringService.TETHERING_STATE_INACTIVE,
-
- // Flag to check if we can modify the Services.io.offline.
- _manageOfflineStatus: true,
-
- // nsIObserver
-
- observe: function(aSubject, aTopic, aData) {
- let network;
-
- switch(aTopic) {
- case TOPIC_PREF_CHANGED:
- if (aData === PREF_NETWORK_DEBUG_ENABLED) {
- updateDebug();
- }
- break;
- case TOPIC_MOZSETTINGS_CHANGED:
- if ("wrappedJSObject" in aSubject) {
- aSubject = aSubject.wrappedJSObject;
- }
- this.handle(aSubject.key, aSubject.value);
- break;
- case TOPIC_CONNECTION_STATE_CHANGED:
- network = aSubject.QueryInterface(Ci.nsINetworkInfo);
- debug("Network " + network.type + "/" + network.name +
- " changed state to " + network.state);
- this.onConnectionChanged(network);
- break;
- case TOPIC_XPCOM_SHUTDOWN:
- Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
- Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED);
- Services.obs.removeObserver(this, TOPIC_CONNECTION_STATE_CHANGED);
- Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
- Services.prefs.removeObserver(PREF_MANAGE_OFFLINE_STATUS, this);
-
- this.dunConnectTimer.cancel();
- this.dunRetryTimer.cancel();
- break;
- case PREF_MANAGE_OFFLINE_STATUS:
- try {
- this._manageOfflineStatus =
- Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
- } catch(ex) {
- // Ignore.
- }
- break;
- }
- },
-
- // nsISettingsServiceCallback
-
- handle: function(aName, aResult) {
- switch(aName) {
- case SETTINGS_DATA_DEFAULT_SERVICE_ID:
- this._dataDefaultServiceId = aResult || 0;
- debug("'_dataDefaultServiceId' is now " + this._dataDefaultServiceId);
- break;
- case SETTINGS_USB_ENABLED:
- this._oldUsbTetheringEnabledState = this.tetheringSettings[SETTINGS_USB_ENABLED];
- case SETTINGS_USB_IP:
- case SETTINGS_USB_PREFIX:
- case SETTINGS_USB_DHCPSERVER_STARTIP:
- case SETTINGS_USB_DHCPSERVER_ENDIP:
- case SETTINGS_USB_DNS1:
- case SETTINGS_USB_DNS2:
- case SETTINGS_WIFI_DHCPSERVER_STARTIP:
- case SETTINGS_WIFI_DHCPSERVER_ENDIP:
- if (aResult !== null) {
- this.tetheringSettings[aName] = aResult;
- }
- debug("'" + aName + "'" + " is now " + this.tetheringSettings[aName]);
- let index = this._usbTetheringSettingsToRead.indexOf(aName);
-
- if (index != -1) {
- this._usbTetheringSettingsToRead.splice(index, 1);
- }
-
- if (this._usbTetheringSettingsToRead.length) {
- debug("We haven't read completely the usb Tethering data from settings db.");
- break;
- }
-
- if (this._oldUsbTetheringEnabledState === this.tetheringSettings[SETTINGS_USB_ENABLED]) {
- debug("No changes for SETTINGS_USB_ENABLED flag. Nothing to do.");
- this.handlePendingWifiTetheringRequest();
- break;
- }
-
- this._usbTetheringRequestCount++;
- if (this._usbTetheringRequestCount === 1) {
- if (this._wifiTetheringRequestOngoing) {
- debug('USB tethering request is blocked by ongoing wifi tethering request.');
- } else {
- this.handleLastUsbTetheringRequest();
- }
- }
- break;
- };
- },
-
- handleError: function(aErrorMessage) {
- debug("There was an error while reading Tethering settings.");
- this.tetheringSettings = {};
- this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
- },
-
- initTetheringSettings: function() {
- this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
- this.tetheringSettings[SETTINGS_USB_IP] = DEFAULT_USB_IP;
- this.tetheringSettings[SETTINGS_USB_PREFIX] = DEFAULT_USB_PREFIX;
- this.tetheringSettings[SETTINGS_USB_DHCPSERVER_STARTIP] = DEFAULT_USB_DHCPSERVER_STARTIP;
- this.tetheringSettings[SETTINGS_USB_DHCPSERVER_ENDIP] = DEFAULT_USB_DHCPSERVER_ENDIP;
- this.tetheringSettings[SETTINGS_USB_DNS1] = DEFAULT_DNS1;
- this.tetheringSettings[SETTINGS_USB_DNS2] = DEFAULT_DNS2;
-
- this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP] = DEFAULT_WIFI_DHCPSERVER_STARTIP;
- this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP] = DEFAULT_WIFI_DHCPSERVER_ENDIP;
-
- this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
- libcutils.property_get("ro.tethering.dun_required") === "1";
- },
-
- getNetworkInfo: function(aType, aServiceId) {
- for (let networkId in gNetworkManager.allNetworkInfo) {
- let networkInfo = gNetworkManager.allNetworkInfo[networkId];
- if (networkInfo.type == aType) {
- try {
- if (networkInfo instanceof Ci.nsIRilNetworkInfo) {
- let rilNetwork = networkInfo.QueryInterface(Ci.nsIRilNetworkInfo);
- if (rilNetwork.serviceId != aServiceId) {
- continue;
- }
- }
- } catch (e) {}
- return networkInfo;
- }
- }
- return null;
- },
-
- handleLastUsbTetheringRequest: function() {
- debug('handleLastUsbTetheringRequest... ' + this._usbTetheringRequestCount);
-
- if (this._usbTetheringRequestCount === 0) {
- if (this.wantConnectionEvent) {
- if (this.tetheringSettings[SETTINGS_USB_ENABLED]) {
- this.wantConnectionEvent.call(this);
- }
- this.wantConnectionEvent = null;
- }
- this.handlePendingWifiTetheringRequest();
- return;
- }
-
- // Cancel the accumlated count to 1 since we only care about the
- // last state.
- this._usbTetheringRequestCount = 1;
- this.handleUSBTetheringToggle(this.tetheringSettings[SETTINGS_USB_ENABLED]);
- this.wantConnectionEvent = null;
- },
-
- handlePendingWifiTetheringRequest: function() {
- if (this._pendingWifiTetheringRequestArgs) {
- this.setWifiTethering.apply(this, this._pendingWifiTetheringRequestArgs);
- this._pendingWifiTetheringRequestArgs = null;
- }
- },
-
- /**
- * Callback when dun connection fails to connect within timeout.
- */
- onDunConnectTimerTimeout: function() {
- while (this._pendingTetheringRequests.length > 0) {
- debug("onDunConnectTimerTimeout: callback without network info.");
- let callback = this._pendingTetheringRequests.shift();
- if (typeof callback === 'function') {
- callback();
- }
- }
- },
-
- setupDunConnection: function() {
- this.dunRetryTimer.cancel();
- let connection =
- gMobileConnectionService.getItemByServiceId(this._dataDefaultServiceId);
- let data = connection && connection.data;
- if (data && data.state === "registered") {
- let ril = gRil.getRadioInterface(this._dataDefaultServiceId);
-
- this.dunRetryTimes = 0;
- ril.setupDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN);
- this.dunConnectTimer.cancel();
- this.dunConnectTimer.
- initWithCallback(this.onDunConnectTimerTimeout.bind(this),
- MOBILE_DUN_CONNECT_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
- return;
- }
-
- if (this.dunRetryTimes++ >= this.MOBILE_DUN_MAX_RETRIES) {
- debug("setupDunConnection: max retries reached.");
- this.dunRetryTimes = 0;
- // same as dun connect timeout.
- this.onDunConnectTimerTimeout();
- return;
- }
-
- debug("Data not ready, retry dun after " + MOBILE_DUN_RETRY_INTERVAL + " ms.");
- this.dunRetryTimer.
- initWithCallback(this.setupDunConnection.bind(this),
- MOBILE_DUN_RETRY_INTERVAL, Ci.nsITimer.TYPE_ONE_SHOT);
- },
-
- _dunActiveUsers: 0,
- handleDunConnection: function(aEnable, aCallback) {
- debug("handleDunConnection: " + aEnable);
- let dun = this.getNetworkInfo(
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN, this._dataDefaultServiceId);
-
- if (!aEnable) {
- this._dunActiveUsers--;
- if (this._dunActiveUsers > 0) {
- debug("Dun still needed by others, do not disconnect.")
- return;
- }
-
- this.dunRetryTimes = 0;
- this.dunRetryTimer.cancel();
- this.dunConnectTimer.cancel();
- this._pendingTetheringRequests = [];
-
- if (dun && (dun.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) {
- gRil.getRadioInterface(this._dataDefaultServiceId)
- .deactivateDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN);
- }
- return;
- }
-
- this._dunActiveUsers++;
- if (!dun || (dun.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) {
- debug("DUN data call inactive, setup dun data call!")
- this._pendingTetheringRequests.push(aCallback);
- this.dunRetryTimes = 0;
- this.setupDunConnection();
-
- return;
- }
-
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = dun.name;
- aCallback(dun);
- },
-
- handleUSBTetheringToggle: function(aEnable) {
- debug("handleUSBTetheringToggle: " + aEnable);
- if (aEnable &&
- (this._usbTetheringAction === TETHERING_STATE_ONGOING ||
- this._usbTetheringAction === TETHERING_STATE_ACTIVE)) {
- debug("Usb tethering already connecting/connected.");
- this._usbTetheringRequestCount = 0;
- this.handlePendingWifiTetheringRequest();
- return;
- }
-
- if (!aEnable &&
- this._usbTetheringAction === TETHERING_STATE_IDLE) {
- debug("Usb tethering already disconnected.");
- this._usbTetheringRequestCount = 0;
- this.handlePendingWifiTetheringRequest();
- return;
- }
-
- if (!aEnable) {
- this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
- gNetworkService.enableUsbRndis(false, this.enableUsbRndisResult.bind(this));
- return;
- }
-
- this.tetheringSettings[SETTINGS_USB_ENABLED] = true;
- this._usbTetheringAction = TETHERING_STATE_ONGOING;
-
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(true, (aNetworkInfo) => {
- if (!aNetworkInfo){
- this.usbTetheringResultReport(aEnable, "Dun connection failed");
- return;
- }
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface =
- aNetworkInfo.name;
- gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this));
- });
- return;
- }
-
- if (gNetworkManager.activeNetworkInfo) {
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface =
- gNetworkManager.activeNetworkInfo.name;
- } else {
- let mobile = this.getNetworkInfo(
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId);
- if (mobile && mobile.name) {
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = mobile.name;
- }
- }
- gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this));
- },
-
- getUSBTetheringParameters: function(aEnable, aTetheringInterface) {
- let interfaceIp = this.tetheringSettings[SETTINGS_USB_IP];
- let prefix = this.tetheringSettings[SETTINGS_USB_PREFIX];
- let wifiDhcpStartIp = this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP];
- let wifiDhcpEndIp = this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP];
- let usbDhcpStartIp = this.tetheringSettings[SETTINGS_USB_DHCPSERVER_STARTIP];
- let usbDhcpEndIp = this.tetheringSettings[SETTINGS_USB_DHCPSERVER_ENDIP];
- let dns1 = this.tetheringSettings[SETTINGS_USB_DNS1];
- let dns2 = this.tetheringSettings[SETTINGS_USB_DNS2];
- let internalInterface = aTetheringInterface.internalInterface;
- let externalInterface = aTetheringInterface.externalInterface;
-
- // Using the default values here until application support these settings.
- if (interfaceIp == "" || prefix == "" ||
- wifiDhcpStartIp == "" || wifiDhcpEndIp == "" ||
- usbDhcpStartIp == "" || usbDhcpEndIp == "") {
- debug("Invalid subnet information.");
- return null;
- }
-
- return {
- ifname: internalInterface,
- ip: interfaceIp,
- prefix: prefix,
- wifiStartIp: wifiDhcpStartIp,
- wifiEndIp: wifiDhcpEndIp,
- usbStartIp: usbDhcpStartIp,
- usbEndIp: usbDhcpEndIp,
- dns1: dns1,
- dns2: dns2,
- internalIfname: internalInterface,
- externalIfname: externalInterface,
- enable: aEnable,
- link: aEnable ? NETWORK_INTERFACE_UP : NETWORK_INTERFACE_DOWN
- };
- },
-
- notifyError: function(aResetSettings, aCallback, aMsg) {
- if (aResetSettings) {
- let settingsLock = gSettingsService.createLock();
- // Disable wifi tethering with a useful error message for the user.
- settingsLock.set("tethering.wifi.enabled", false, null, aMsg);
- }
-
- debug("setWifiTethering: " + (aMsg ? aMsg : "success"));
-
- if (aCallback) {
- // Callback asynchronously to avoid netsted toggling.
- Services.tm.currentThread.dispatch(() => {
- aCallback.wifiTetheringEnabledChange(aMsg);
- }, Ci.nsIThread.DISPATCH_NORMAL);
- }
- },
-
- enableWifiTethering: function(aEnable, aConfig, aCallback) {
- // Fill in config's required fields.
- aConfig.ifname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
- aConfig.internalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
- aConfig.externalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface;
-
- this._wifiTetheringRequestOngoing = true;
- gNetworkService.setWifiTethering(aEnable, aConfig, (aError) => {
- // Change the tethering state to WIFI if there is no error.
- if (aEnable && !aError) {
- this.state = Ci.nsITetheringService.TETHERING_STATE_WIFI;
- } else {
- // If wifi thethering is disable, or any error happens,
- // then consider the following statements.
-
- // Check whether the state is USB now or not. If no then just change
- // it to INACTIVE, if yes then just keep it.
- // It means that don't let the disable or error of WIFI affect
- // the original active state.
- if (this.state != Ci.nsITetheringService.TETHERING_STATE_USB) {
- this.state = Ci.nsITetheringService.TETHERING_STATE_INACTIVE;
- }
-
- // Disconnect dun on error or when wifi tethering is disabled.
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(false);
- }
- }
-
- if (this._manageOfflineStatus) {
- Services.io.offline = !this.isAnyConnected() &&
- (this.state ===
- Ci.nsITetheringService.TETHERING_STATE_INACTIVE);
- }
-
- let resetSettings = aError;
- debug('gNetworkService.setWifiTethering finished');
- this.notifyError(resetSettings, aCallback, aError);
- this._wifiTetheringRequestOngoing = false;
- if (this._usbTetheringRequestCount > 0) {
- debug('Perform pending USB tethering requests.');
- this.handleLastUsbTetheringRequest();
- }
- });
- },
-
- // Enable/disable WiFi tethering by sending commands to netd.
- setWifiTethering: function(aEnable, aInterfaceName, aConfig, aCallback) {
- debug("setWifiTethering: " + aEnable);
- if (!aInterfaceName) {
- this.notifyError(true, aCallback, "invalid network interface name");
- return;
- }
-
- if (!aConfig) {
- this.notifyError(true, aCallback, "invalid configuration");
- return;
- }
-
- if (this._usbTetheringRequestCount > 0) {
- // If there's still pending usb tethering request, save
- // the request params and redo |setWifiTethering| on
- // usb tethering task complete.
- debug('USB tethering request is being processed. Queue this wifi tethering request.');
- this._pendingWifiTetheringRequestArgs = Array.prototype.slice.call(arguments);
- debug('Pending args: ' + JSON.stringify(this._pendingWifiTetheringRequestArgs));
- return;
- }
-
- // Re-check again, test cases set this property later.
- this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
- libcutils.property_get("ro.tethering.dun_required") === "1";
-
- if (!aEnable) {
- this.enableWifiTethering(false, aConfig, aCallback);
- return;
- }
-
- this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface =
- aInterfaceName;
-
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(true, (aNetworkInfo) => {
- if (!aNetworkInfo) {
- this.notifyError(true, aCallback, "Dun connection failed");
- return;
- }
- this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface =
- aNetworkInfo.name;
- this.enableWifiTethering(true, aConfig, aCallback);
- });
- return;
- }
-
- let mobile = this.getNetworkInfo(
- Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId);
- // Update the real interface name
- if (mobile && mobile.name) {
- this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name;
- }
-
- this.enableWifiTethering(true, aConfig, aCallback);
- },
-
- // Enable/disable USB tethering by sending commands to netd.
- setUSBTethering: function(aEnable, aTetheringInterface, aCallback) {
- let params = this.getUSBTetheringParameters(aEnable, aTetheringInterface);
-
- if (params === null) {
- gNetworkService.enableUsbRndis(false, function() {
- this.usbTetheringResultReport(aEnable, "Invalid parameters");
- });
- return;
- }
-
- gNetworkService.setUSBTethering(aEnable, params, aCallback);
- },
-
- getUsbInterface: function() {
- // Find the rndis interface.
- for (let i = 0; i < this.possibleInterface.length; i++) {
- try {
- let file = new FileUtils.File(KERNEL_NETWORK_ENTRY + "/" +
- this.possibleInterface[i]);
- if (file.exists()) {
- return this.possibleInterface[i];
- }
- } catch (e) {
- debug("Not " + this.possibleInterface[i] + " interface.");
- }
- }
- debug("Can't find rndis interface in possible lists.");
- return DEFAULT_USB_INTERFACE_NAME;
- },
-
- enableUsbRndisResult: function(aSuccess, aEnable) {
- if (aSuccess) {
- // If enable is false, don't find usb interface cause it is already down,
- // just use the internal interface in settings.
- if (aEnable) {
- this._tetheringInterface[TETHERING_TYPE_USB].internalInterface =
- this.getUsbInterface();
- }
- this.setUSBTethering(aEnable,
- this._tetheringInterface[TETHERING_TYPE_USB],
- this.usbTetheringResultReport.bind(this, aEnable));
- } else {
- this.usbTetheringResultReport(aEnable, "enableUsbRndisResult failure");
- throw new Error("failed to set USB Function to adb");
- }
- },
-
- usbTetheringResultReport: function(aEnable, aError) {
- this._usbTetheringRequestCount--;
-
- let settingsLock = gSettingsService.createLock();
-
- debug('usbTetheringResultReport callback. enable: ' + aEnable +
- ', error: ' + aError);
-
- // Disable tethering settings when fail to enable it.
- if (aError) {
- this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
- settingsLock.set("tethering.usb.enabled", false, null);
- // Skip others request when we found an error.
- this._usbTetheringRequestCount = 0;
- this._usbTetheringAction = TETHERING_STATE_IDLE;
- // If the thethering state is WIFI now, then just keep it,
- // if not, just change the state to INACTIVE.
- // It means that don't let the error of USB affect the original active state.
- if (this.state != Ci.nsITetheringService.TETHERING_STATE_WIFI) {
- this.state = Ci.nsITetheringService.TETHERING_STATE_INACTIVE;
- }
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(false);
- }
- } else {
- if (aEnable) {
- this._usbTetheringAction = TETHERING_STATE_ACTIVE;
- this.state = Ci.nsITetheringService.TETHERING_STATE_USB;
- } else {
- this._usbTetheringAction = TETHERING_STATE_IDLE;
- // If the state is now WIFI, don't let the disable of USB affect it.
- if (this.state != Ci.nsITetheringService.TETHERING_STATE_WIFI) {
- this.state = Ci.nsITetheringService.TETHERING_STATE_INACTIVE;
- }
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
- this.handleDunConnection(false);
- }
- }
-
- if (this._manageOfflineStatus) {
- Services.io.offline = !this.isAnyConnected() &&
- (this.state ===
- Ci.nsITetheringService.TETHERING_STATE_INACTIVE);
- }
-
- this.handleLastUsbTetheringRequest();
- }
- },
-
- onConnectionChangedReport: function(aSuccess, aExternalIfname) {
- debug("onConnectionChangedReport result: success " + aSuccess);
-
- if (aSuccess) {
- // Update the external interface.
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface =
- aExternalIfname;
- debug("Change the interface name to " + aExternalIfname);
- }
- },
-
- onConnectionChanged: function(aNetworkInfo) {
- if (aNetworkInfo.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- debug("We are only interested in CONNECTED event");
- return;
- }
-
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
- aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) {
- this.dunConnectTimer.cancel();
- debug("DUN data call connected, process callbacks.");
- while (this._pendingTetheringRequests.length > 0) {
- let callback = this._pendingTetheringRequests.shift();
- if (typeof callback === 'function') {
- callback(aNetworkInfo);
- }
- }
- return;
- }
-
- if (!this.tetheringSettings[SETTINGS_USB_ENABLED]) {
- debug("Usb tethering settings is not enabled");
- return;
- }
-
- if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
- aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN &&
- this._tetheringInterface[TETHERING_TYPE_USB].externalInterface ===
- aNetworkInfo.name) {
- debug("Dun required and dun interface is the same");
- return;
- }
-
- if (this._tetheringInterface[TETHERING_TYPE_USB].externalInterface ===
- gNetworkManager.activeNetworkInfo.name) {
- debug("The active interface is the same");
- return;
- }
-
- let previous = {
- internalIfname: this._tetheringInterface[TETHERING_TYPE_USB].internalInterface,
- externalIfname: this._tetheringInterface[TETHERING_TYPE_USB].externalInterface
- };
-
- let current = {
- internalIfname: this._tetheringInterface[TETHERING_TYPE_USB].internalInterface,
- externalIfname: aNetworkInfo.name
- };
-
- let callback = (() => {
- // Update external network interface.
- debug("Update upstream interface to " + aNetworkInfo.name);
- gNetworkService.updateUpStream(previous, current,
- this.onConnectionChangedReport.bind(this));
- });
-
- if (this._usbTetheringAction === TETHERING_STATE_ONGOING) {
- debug("Postpone the event and handle it when state is idle.");
- this.wantConnectionEvent = callback;
- return;
- }
- this.wantConnectionEvent = null;
-
- callback.call(this);
- },
-
- isAnyConnected: function() {
- let allNetworkInfo = gNetworkManager.allNetworkInfo;
- for (let networkId in allNetworkInfo) {
- if (allNetworkInfo.hasOwnProperty(networkId) &&
- allNetworkInfo[networkId].state === Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- return true;
- }
- }
- return false;
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TetheringService]);
diff --git a/dom/system/gonk/TetheringService.manifest b/dom/system/gonk/TetheringService.manifest
deleted file mode 100644
index b8f18dec1..000000000
--- a/dom/system/gonk/TetheringService.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-# TetheringService.js
-component {527a4121-ee5a-4651-be9c-f46f59cf7c01} TetheringService.js
-contract @mozilla.org/tethering/service;1 {527a4121-ee5a-4651-be9c-f46f59cf7c01}
-category profile-after-change TetheringService @mozilla.org/tethering/service;1
diff --git a/dom/system/gonk/TimeZoneSettingObserver.cpp b/dom/system/gonk/TimeZoneSettingObserver.cpp
deleted file mode 100644
index 512f79908..000000000
--- a/dom/system/gonk/TimeZoneSettingObserver.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "base/message_loop.h"
-#include "jsapi.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/Hal.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticPtr.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsISettingsService.h"
-#include "nsJSUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-#include "TimeZoneSettingObserver.h"
-#include "xpcpublic.h"
-#include "nsContentUtils.h"
-#include "nsPrintfCString.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/SettingChangeNotificationBinding.h"
-
-#undef LOG
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Time Zone Setting" , ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "Time Zone Setting" , ## args)
-
-#define TIME_TIMEZONE "time.timezone"
-#define MOZSETTINGS_CHANGED "mozsettings-changed"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-namespace {
-
-class TimeZoneSettingObserver : public nsIObserver
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- TimeZoneSettingObserver();
- static nsresult SetTimeZone(const JS::Value &aValue, JSContext *aContext);
-
-protected:
- virtual ~TimeZoneSettingObserver();
-};
-
-class TimeZoneSettingCb final : public nsISettingsServiceCallback
-{
-public:
- NS_DECL_ISUPPORTS
-
- TimeZoneSettingCb() {}
-
- NS_IMETHOD Handle(const nsAString &aName, JS::Handle<JS::Value> aResult) {
-
- JSContext *cx = nsContentUtils::GetCurrentJSContext();
- NS_ENSURE_TRUE(cx, NS_OK);
-
- // If we don't have time.timezone value in the settings, we need
- // to initialize the settings based on the current system timezone
- // to make settings consistent with system. This usually happens
- // at the very first boot. After that, settings must have a value.
- if (aResult.isNull()) {
- // Get the current system time zone offset. Note that we need to
- // convert the value to a UTC representation in the format of
- // "UTC{+,-}hh:mm", so that the Gaia end can know how to interpret.
- // E.g., -480 is "UTC+08:00"; 630 is "UTC-10:30".
- int32_t timeZoneOffset = hal::GetTimezoneOffset();
- nsPrintfCString curTimeZone("UTC%+03d:%02d",
- -timeZoneOffset / 60,
- abs(timeZoneOffset) % 60);
-
- // Convert it to a JS string.
- NS_ConvertUTF8toUTF16 utf16Str(curTimeZone);
-
- JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx,
- utf16Str.get(),
- utf16Str.Length()));
- if (!jsStr) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- // Set the settings based on the current system timezone.
- nsCOMPtr<nsISettingsServiceLock> lock;
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- if (!settingsService) {
- ERR("Failed to get settingsLock service!");
- return NS_OK;
- }
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- JS::Rooted<JS::Value> value(cx, JS::StringValue(jsStr));
- lock->Set(TIME_TIMEZONE, value, nullptr, nullptr);
- return NS_OK;
- }
-
- // Set the system timezone based on the current settings.
- if (aResult.isString()) {
- return TimeZoneSettingObserver::SetTimeZone(aResult, cx);
- }
-
- return NS_OK;
- }
-
- NS_IMETHOD HandleError(const nsAString &aName) {
- ERR("TimeZoneSettingCb::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
- return NS_OK;
- }
-
-protected:
- ~TimeZoneSettingCb() {}
-};
-
-NS_IMPL_ISUPPORTS(TimeZoneSettingCb, nsISettingsServiceCallback)
-
-TimeZoneSettingObserver::TimeZoneSettingObserver()
-{
- // Setup an observer to watch changes to the setting.
- nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
- if (!observerService) {
- ERR("GetObserverService failed");
- return;
- }
- nsresult rv;
- rv = observerService->AddObserver(this, MOZSETTINGS_CHANGED, false);
- if (NS_FAILED(rv)) {
- ERR("AddObserver failed");
- return;
- }
-
- // Read the 'time.timezone' setting in order to start with a known
- // value at boot time. The handle() will be called after reading.
- nsCOMPtr<nsISettingsServiceLock> lock;
- nsCOMPtr<nsISettingsService> settingsService =
- do_GetService("@mozilla.org/settingsService;1");
- if (!settingsService) {
- ERR("Failed to get settingsLock service!");
- return;
- }
- settingsService->CreateLock(nullptr, getter_AddRefs(lock));
- nsCOMPtr<nsISettingsServiceCallback> callback = new TimeZoneSettingCb();
- lock->Get(TIME_TIMEZONE, callback);
-}
-
-nsresult TimeZoneSettingObserver::SetTimeZone(const JS::Value &aValue, JSContext *aContext)
-{
- // Convert the JS value to a nsCString type.
- // The value should be a JS string like "America/Chicago" or "UTC-05:00".
- nsAutoJSString valueStr;
- if (!valueStr.init(aContext, aValue.toString())) {
- ERR("Failed to convert JS value to nsCString");
- return NS_ERROR_FAILURE;
- }
- NS_ConvertUTF16toUTF8 newTimezone(valueStr);
-
- // Hal expects opposite sign from general notations,
- // so we need to flip it.
- if (newTimezone.Find(NS_LITERAL_CSTRING("UTC+")) == 0) {
- if (!newTimezone.SetCharAt('-', 3)) {
- return NS_ERROR_FAILURE;
- }
- } else if (newTimezone.Find(NS_LITERAL_CSTRING("UTC-")) == 0) {
- if (!newTimezone.SetCharAt('+', 3)) {
- return NS_ERROR_FAILURE;
- }
- }
-
- // Set the timezone only when the system timezone is not identical.
- nsCString curTimezone = hal::GetTimezone();
- if (!curTimezone.Equals(newTimezone)) {
- hal::SetTimezone(newTimezone);
- }
-
- return NS_OK;
-}
-
-TimeZoneSettingObserver::~TimeZoneSettingObserver()
-{
- nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
- if (observerService) {
- observerService->RemoveObserver(this, MOZSETTINGS_CHANGED);
- }
-}
-
-NS_IMPL_ISUPPORTS(TimeZoneSettingObserver, nsIObserver)
-
-NS_IMETHODIMP
-TimeZoneSettingObserver::Observe(nsISupports *aSubject,
- const char *aTopic,
- const char16_t *aData)
-{
- if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
- return NS_OK;
- }
-
- // Note that this function gets called for any and all settings changes,
- // so we need to carefully check if we have the one we're interested in.
- //
- // The string that we're interested in will be a JSON string that looks like:
- // {"key":"time.timezone","value":"America/Chicago"} or
- // {"key":"time.timezone","value":"UTC-05:00"}
-
- AutoSafeJSContext cx;
- RootedDictionary<SettingChangeNotification> setting(cx);
- if (!WrappedJSToDictionary(cx, aSubject, setting)) {
- return NS_OK;
- }
- if (!setting.mKey.EqualsASCII(TIME_TIMEZONE)) {
- return NS_OK;
- }
- if (!setting.mValue.isString()) {
- return NS_OK;
- }
-
- // Set the system timezone.
- return SetTimeZone(setting.mValue, cx);
-}
-
-} // namespace
-
-static mozilla::StaticRefPtr<TimeZoneSettingObserver> sTimeZoneSettingObserver;
-namespace mozilla {
-namespace system {
-void
-InitializeTimeZoneSettingObserver()
-{
- sTimeZoneSettingObserver = new TimeZoneSettingObserver();
- ClearOnShutdown(&sTimeZoneSettingObserver);
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/TimeZoneSettingObserver.h b/dom/system/gonk/TimeZoneSettingObserver.h
deleted file mode 100644
index 08b7cebb3..000000000
--- a/dom/system/gonk/TimeZoneSettingObserver.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_timesetting_h__
-#define mozilla_system_timesetting_h__
-
-namespace mozilla {
-namespace system {
-
-// Initialize TimeZoneSettingObserver which observes the time zone change
-// event from settings service. When receiving the event, it modifies the
-// system time zone.
-void InitializeTimeZoneSettingObserver();
-
-} // namespace system
-} // namespace mozilla
-
-#endif // mozilla_system_timesetting_h__
-
diff --git a/dom/system/gonk/Volume.cpp b/dom/system/gonk/Volume.cpp
deleted file mode 100644
index f90c7b693..000000000
--- a/dom/system/gonk/Volume.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "Volume.h"
-#include "VolumeCommand.h"
-#include "VolumeManager.h"
-#include "VolumeManagerLog.h"
-#include "nsIVolume.h"
-#include "nsXULAppAPI.h"
-
-#include <vold/ResponseCode.h>
-
-namespace mozilla {
-namespace system {
-
-#if DEBUG_VOLUME_OBSERVER
-void
-VolumeObserverList::Broadcast(Volume* const& aVolume)
-{
- uint32_t size = mObservers.Length();
- for (uint32_t i = 0; i < size; ++i) {
- LOG("VolumeObserverList::Broadcast to [%u] %p volume '%s'",
- i, mObservers[i], aVolume->NameStr());
- mObservers[i]->Notify(aVolume);
- }
-}
-#endif
-
-VolumeObserverList Volume::sEventObserverList;
-
-// We have a feature where volumes can be locked when mounted. This
-// is used to prevent a volume from being shared with the PC while
-// it is actively being used (say for storing an update image)
-//
-// We use WakeLocks (a poor choice of name, but it does what we want)
-// from the PowerManagerService to determine when we're locked.
-// In particular we'll create a wakelock called volume-NAME-GENERATION
-// (where NAME is the volume name, and GENERATION is its generation
-// number), and if this wakelock is locked, then we'll prevent a volume
-// from being shared.
-//
-// Implementation Details:
-//
-// Since the AutoMounter can only control when something gets mounted
-// and not when it gets unmounted (for example: a user pulls the SDCard)
-// and because Volume and nsVolume data structures are maintained on
-// separate threads, we have the potential for some race conditions.
-// We eliminate the race conditions by introducing the concept of a
-// generation number. Every time a volume transitions to the Mounted
-// state, it gets assigned a new generation number. Whenever the state
-// of a Volume changes, we send the updated state and current generation
-// number to the main thread where it gets updated in the nsVolume.
-//
-// Since WakeLocks can only be queried from the main-thread, the
-// nsVolumeService looks for WakeLock status changes, and forwards
-// the results to the IOThread.
-//
-// If the Volume (IOThread) receives a volume update where the generation
-// number mismatches, then the update is simply ignored.
-//
-// When a Volume (IOThread) initially becomes mounted, we assume it to
-// be locked until we get our first update from nsVolume (MainThread).
-static int32_t sMountGeneration = 0;
-
-static uint32_t sNextId = 1;
-
-// We don't get media inserted/removed events at startup. So we
-// assume it's present, and we'll be told that it's missing.
-Volume::Volume(const nsCSubstring& aName)
- : mMediaPresent(true),
- mState(nsIVolume::STATE_INIT),
- mName(aName),
- mMountGeneration(-1),
- mMountLocked(true), // Needs to agree with nsVolume::nsVolume
- mSharingEnabled(false),
- mFormatRequested(false),
- mMountRequested(false),
- mUnmountRequested(false),
- mCanBeShared(true),
- mIsSharing(false),
- mIsFormatting(false),
- mIsUnmounting(false),
- mIsRemovable(false),
- mIsHotSwappable(false),
- mId(sNextId++)
-{
- DBG("Volume %s: created", NameStr());
-}
-
-void
-Volume::Dump(const char* aLabel) const
-{
- LOG("%s: Volume: %s (%d) is %s and %s @ %s gen %d locked %d",
- aLabel,
- NameStr(),
- Id(),
- StateStr(),
- MediaPresent() ? "inserted" : "missing",
- MountPoint().get(),
- MountGeneration(),
- (int)IsMountLocked());
- LOG("%s: Sharing %s Mounting %s Formating %s Unmounting %s",
- aLabel,
- CanBeShared() ? (IsSharingEnabled() ? (IsSharing() ? "en-y" : "en-n")
- : "dis")
- : "x",
- IsMountRequested() ? "req" : "n",
- IsFormatRequested() ? (IsFormatting() ? "req-y" : "req-n")
- : (IsFormatting() ? "y" : "n"),
- IsUnmountRequested() ? (IsUnmounting() ? "req-y" : "req-n")
- : (IsUnmounting() ? "y" : "n"));
-}
-
-void
-Volume::ResolveAndSetMountPoint(const nsCSubstring& aMountPoint)
-{
- nsCString mountPoint(aMountPoint);
- char realPathBuf[PATH_MAX];
-
- // Call realpath so that we wind up with a path which is compatible with
- // functions like nsVolumeService::GetVolumeByPath.
-
- if (realpath(mountPoint.get(), realPathBuf) < 0) {
- // The path we were handed doesn't exist. Warn about it, but use it
- // anyways assuming that the user knows what they're doing.
-
- ERR("ResolveAndSetMountPoint: realpath on '%s' failed: %d",
- mountPoint.get(), errno);
- mMountPoint = mountPoint;
- } else {
- mMountPoint = realPathBuf;
- }
- DBG("Volume %s: Setting mountpoint to '%s'", NameStr(), mMountPoint.get());
-}
-
-void Volume::SetFakeVolume(const nsACString& aMountPoint)
-{
- this->mMountLocked = false;
- this->mCanBeShared = false;
- ResolveAndSetMountPoint(aMountPoint);
- SetState(nsIVolume::STATE_MOUNTED);
-}
-
-void
-Volume::SetIsSharing(bool aIsSharing)
-{
- if (aIsSharing == mIsSharing) {
- return;
- }
- mIsSharing = aIsSharing;
- LOG("Volume %s: IsSharing set to %d state %s",
- NameStr(), (int)mIsSharing, StateStr(mState));
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetIsFormatting(bool aIsFormatting)
-{
- if (aIsFormatting == mIsFormatting) {
- return;
- }
- mIsFormatting = aIsFormatting;
- LOG("Volume %s: IsFormatting set to %d state %s",
- NameStr(), (int)mIsFormatting, StateStr(mState));
- if (mIsFormatting) {
- sEventObserverList.Broadcast(this);
- }
-}
-
-void
-Volume::SetIsUnmounting(bool aIsUnmounting)
-{
- if (aIsUnmounting == mIsUnmounting) {
- return;
- }
- mIsUnmounting = aIsUnmounting;
- LOG("Volume %s: IsUnmounting set to %d state %s",
- NameStr(), (int)mIsUnmounting, StateStr(mState));
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetIsRemovable(bool aIsRemovable)
-{
- if (aIsRemovable == mIsRemovable) {
- return;
- }
- mIsRemovable = aIsRemovable;
- if (!mIsRemovable) {
- mIsHotSwappable = false;
- }
- LOG("Volume %s: IsRemovable set to %d state %s",
- NameStr(), (int)mIsRemovable, StateStr(mState));
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetIsHotSwappable(bool aIsHotSwappable)
-{
- if (aIsHotSwappable == mIsHotSwappable) {
- return;
- }
- mIsHotSwappable = aIsHotSwappable;
- if (mIsHotSwappable) {
- mIsRemovable = true;
- }
- LOG("Volume %s: IsHotSwappable set to %d state %s",
- NameStr(), (int)mIsHotSwappable, StateStr(mState));
- sEventObserverList.Broadcast(this);
-}
-
-bool
-Volume::BoolConfigValue(const nsCString& aConfigValue, bool& aBoolValue)
-{
- if (aConfigValue.EqualsLiteral("1") ||
- aConfigValue.LowerCaseEqualsLiteral("true")) {
- aBoolValue = true;
- return true;
- }
- if (aConfigValue.EqualsLiteral("0") ||
- aConfigValue.LowerCaseEqualsLiteral("false")) {
- aBoolValue = false;
- return true;
- }
- return false;
-}
-
-void
-Volume::SetConfig(const nsCString& aConfigName, const nsCString& aConfigValue)
-{
- if (aConfigName.LowerCaseEqualsLiteral("removable")) {
- bool value = false;
- if (BoolConfigValue(aConfigValue, value)) {
- SetIsRemovable(value);
- } else {
- ERR("Volume %s: invalid value '%s' for configuration '%s'",
- NameStr(), aConfigValue.get(), aConfigName.get());
- }
- return;
- }
- if (aConfigName.LowerCaseEqualsLiteral("hotswappable")) {
- bool value = false;
- if (BoolConfigValue(aConfigValue, value)) {
- SetIsHotSwappable(value);
- } else {
- ERR("Volume %s: invalid value '%s' for configuration '%s'",
- NameStr(), aConfigValue.get(), aConfigName.get());
- }
- return;
- }
- ERR("Volume %s: invalid config '%s'", NameStr(), aConfigName.get());
-}
-
-void
-Volume::SetMediaPresent(bool aMediaPresent)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // mMediaPresent is slightly redunant to the state, however
- // when media is removed (while Idle), we get the following:
- // 631 Volume sdcard /mnt/sdcard disk removed (179:0)
- // 605 Volume sdcard /mnt/sdcard state changed from 1 (Idle-Unmounted) to 0 (No-Media)
- //
- // And on media insertion, we get:
- // 630 Volume sdcard /mnt/sdcard disk inserted (179:0)
- // 605 Volume sdcard /mnt/sdcard state changed from 0 (No-Media) to 2 (Pending)
- // 605 Volume sdcard /mnt/sdcard state changed from 2 (Pending) to 1 (Idle-Unmounted)
- //
- // On media removal while the media is mounted:
- // 632 Volume sdcard /mnt/sdcard bad removal (179:1)
- // 605 Volume sdcard /mnt/sdcard state changed from 4 (Mounted) to 5 (Unmounting)
- // 605 Volume sdcard /mnt/sdcard state changed from 5 (Unmounting) to 1 (Idle-Unmounted)
- // 631 Volume sdcard /mnt/sdcard disk removed (179:0)
- // 605 Volume sdcard /mnt/sdcard state changed from 1 (Idle-Unmounted) to 0 (No-Media)
- //
- // When sharing with a PC, it goes Mounted -> Idle -> Shared
- // When unsharing with a PC, it goes Shared -> Idle -> Mounted
- //
- // The AutoMounter needs to know whether the media is present or not when
- // processing the Idle state.
-
- if (mMediaPresent == aMediaPresent) {
- return;
- }
-
- LOG("Volume: %s media %s", NameStr(), aMediaPresent ? "inserted" : "removed");
- mMediaPresent = aMediaPresent;
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetSharingEnabled(bool aSharingEnabled)
-{
- mSharingEnabled = aSharingEnabled;
-
- LOG("SetSharingMode for volume %s to %d canBeShared = %d",
- NameStr(), (int)mSharingEnabled, (int)mCanBeShared);
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetFormatRequested(bool aFormatRequested)
-{
- mFormatRequested = aFormatRequested;
-
- LOG("SetFormatRequested for volume %s to %d CanBeFormatted = %d",
- NameStr(), (int)mFormatRequested, (int)CanBeFormatted());
-}
-
-void
-Volume::SetMountRequested(bool aMountRequested)
-{
- mMountRequested = aMountRequested;
-
- LOG("SetMountRequested for volume %s to %d CanBeMounted = %d",
- NameStr(), (int)mMountRequested, (int)CanBeMounted());
-}
-
-void
-Volume::SetUnmountRequested(bool aUnmountRequested)
-{
- mUnmountRequested = aUnmountRequested;
-
- LOG("SetUnmountRequested for volume %s to %d CanBeMounted = %d",
- NameStr(), (int)mUnmountRequested, (int)CanBeMounted());
-}
-
-void
-Volume::SetState(Volume::STATE aNewState)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (aNewState == mState) {
- return;
- }
- if (aNewState == nsIVolume::STATE_MOUNTED) {
- mMountGeneration = ++sMountGeneration;
- LOG("Volume %s (%u): changing state from %s to %s @ '%s' (%d observers) "
- "mountGeneration = %d, locked = %d",
- NameStr(), mId, StateStr(mState),
- StateStr(aNewState), mMountPoint.get(), sEventObserverList.Length(),
- mMountGeneration, (int)mMountLocked);
- } else {
- LOG("Volume %s (%u): changing state from %s to %s (%d observers)",
- NameStr(), mId, StateStr(mState),
- StateStr(aNewState), sEventObserverList.Length());
- }
-
- switch (aNewState) {
- case nsIVolume::STATE_NOMEDIA:
- // Cover the startup case where we don't get insertion/removal events
- mMediaPresent = false;
- mIsSharing = false;
- mUnmountRequested = false;
- mMountRequested = false;
- mIsUnmounting = false;
- break;
-
- case nsIVolume::STATE_MOUNTED:
- case nsIVolume::STATE_MOUNT_FAIL:
- mMountRequested = false;
- mIsFormatting = false;
- mIsSharing = false;
- mIsUnmounting = false;
- break;
-
- case nsIVolume::STATE_FORMATTING:
- mFormatRequested = false;
- mIsFormatting = true;
- mIsSharing = false;
- mIsUnmounting = false;
- break;
-
- case nsIVolume::STATE_SHARED:
- case nsIVolume::STATE_SHAREDMNT:
- // Covers startup cases. Normally, mIsSharing would be set to true
- // when we issue the command to initiate the sharing process, but
- // it's conceivable that a volume could already be in a shared state
- // when b2g starts.
- mIsSharing = true;
- mIsUnmounting = false;
- mIsFormatting = false;
- break;
-
- case nsIVolume::STATE_UNMOUNTING:
- mIsUnmounting = true;
- mIsFormatting = false;
- mIsSharing = false;
- break;
-
- case nsIVolume::STATE_IDLE: // Fall through
- case nsIVolume::STATE_CHECKMNT: // Fall through
- default:
- break;
- }
- mState = aNewState;
- sEventObserverList.Broadcast(this);
-}
-
-void
-Volume::SetMountPoint(const nsCSubstring& aMountPoint)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (mMountPoint.Equals(aMountPoint)) {
- return;
- }
- ResolveAndSetMountPoint(aMountPoint);
-}
-
-void
-Volume::StartMount(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "mount", "", aCallback));
-}
-
-void
-Volume::StartUnmount(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "unmount", "force", aCallback));
-}
-
-void
-Volume::StartFormat(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "format", "", aCallback));
-}
-
-void
-Volume::StartShare(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "share", "ums", aCallback));
-}
-
-void
-Volume::StartUnshare(VolumeResponseCallback* aCallback)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- StartCommand(new VolumeActionCommand(this, "unshare", "ums", aCallback));
-}
-
-void
-Volume::StartCommand(VolumeCommand* aCommand)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- VolumeManager::PostCommand(aCommand);
-}
-
-//static
-void
-Volume::RegisterVolumeObserver(Volume::EventObserver* aObserver, const char* aName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- sEventObserverList.AddObserver(aObserver);
-
- DBG("Added Volume Observer '%s' @%p, length = %u",
- aName, aObserver, sEventObserverList.Length());
-
- // Send an initial event to the observer (for each volume)
- size_t numVolumes = VolumeManager::NumVolumes();
- for (size_t volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- aObserver->Notify(vol);
- }
-}
-
-//static
-void
-Volume::UnregisterVolumeObserver(Volume::EventObserver* aObserver, const char* aName)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- sEventObserverList.RemoveObserver(aObserver);
-
- DBG("Removed Volume Observer '%s' @%p, length = %u",
- aName, aObserver, sEventObserverList.Length());
-}
-
-//static
-void
-Volume::UpdateMountLock(const nsACString& aVolumeName,
- const int32_t& aMountGeneration,
- const bool& aMountLocked)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
- if (!vol || (vol->mMountGeneration != aMountGeneration)) {
- return;
- }
- if (vol->mMountLocked != aMountLocked) {
- vol->mMountLocked = aMountLocked;
- DBG("Volume::UpdateMountLock for '%s' to %d\n", vol->NameStr(), (int)aMountLocked);
- sEventObserverList.Broadcast(vol);
- }
-}
-
-void
-Volume::HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer& aTokenizer)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // The volume name will have already been parsed, and the tokenizer will point
- // to the token after the volume name
- switch (aResponseCode) {
- case ::ResponseCode::VolumeListResult: {
- // Each line will look something like:
- //
- // sdcard /mnt/sdcard 1
- //
- nsDependentCSubstring mntPoint(aTokenizer.nextToken());
- SetMountPoint(mntPoint);
- nsresult errCode;
- nsCString state(aTokenizer.nextToken());
- if (state.EqualsLiteral("X")) {
- // Special state for creating fake volumes which can't be shared.
- mCanBeShared = false;
- SetState(nsIVolume::STATE_MOUNTED);
- } else {
- SetState((STATE)state.ToInteger(&errCode));
- }
- break;
- }
-
- case ::ResponseCode::VolumeStateChange: {
- // Format of the line looks something like:
- //
- // Volume sdcard /mnt/sdcard state changed from 7 (Shared-Unmounted) to 1 (Idle-Unmounted)
- //
- // So we parse out the state after the string " to "
- while (aTokenizer.hasMoreTokens()) {
- nsAutoCString token(aTokenizer.nextToken());
- if (token.EqualsLiteral("to")) {
- nsresult errCode;
- token = aTokenizer.nextToken();
- STATE newState = (STATE)(token.ToInteger(&errCode));
- if (newState == nsIVolume::STATE_MOUNTED) {
- // We set the state to STATE_CHECKMNT here, and the once the
- // AutoMounter detects that the volume is actually accessible
- // then the AutoMounter will set the volume as STATE_MOUNTED.
- SetState(nsIVolume::STATE_CHECKMNT);
- } else {
- if (State() == nsIVolume::STATE_CHECKING && newState == nsIVolume::STATE_IDLE) {
- LOG("Mount of volume '%s' failed", NameStr());
- SetState(nsIVolume::STATE_MOUNT_FAIL);
- } else {
- SetState(newState);
- }
- }
- break;
- }
- }
- break;
- }
-
- case ::ResponseCode::VolumeDiskInserted:
- SetMediaPresent(true);
- break;
-
- case ::ResponseCode::VolumeDiskRemoved: // fall-thru
- case ::ResponseCode::VolumeBadRemoval:
- SetMediaPresent(false);
- break;
-
- default:
- LOG("Volume: %s unrecognized reponse code (ignored)", NameStr());
- break;
- }
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/Volume.h b/dom/system/gonk/Volume.h
deleted file mode 100644
index 821292a9a..000000000
--- a/dom/system/gonk/Volume.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volume_h__
-#define mozilla_system_volume_h__
-
-#include "VolumeCommand.h"
-#include "nsIVolume.h"
-#include "nsString.h"
-#include "mozilla/Observer.h"
-#include "nsISupportsImpl.h"
-#include "nsWhitespaceTokenizer.h"
-
-namespace mozilla {
-namespace system {
-
-/***************************************************************************
-*
-* There is an instance of the Volume class for each volume reported
-* from vold.
-*
-* Each volume originates from the /system/etv/vold.fstab file.
-*
-***************************************************************************/
-
-class Volume;
-
-#define DEBUG_VOLUME_OBSERVER 0
-
-#if DEBUG_VOLUME_OBSERVER
-class VolumeObserverList : public mozilla::ObserverList<Volume*>
-{
-public:
- void Broadcast(Volume* const& aVolume);
-};
-#else
-typedef mozilla::ObserverList<Volume*> VolumeObserverList;
-#endif
-
-class Volume final
-{
-public:
- NS_INLINE_DECL_REFCOUNTING(Volume)
-
- Volume(const nsCSubstring& aVolumeName);
-
- typedef long STATE; // States are now defined in nsIVolume.idl
-
- static const char* StateStr(STATE aState) { return NS_VolumeStateStr(aState); }
- const char* StateStr() const { return StateStr(mState); }
- STATE State() const { return mState; }
-
- const nsCString& Name() const { return mName; }
- const char* NameStr() const { return mName.get(); }
-
- void Dump(const char* aLabel) const;
-
- // The mount point is the name of the directory where the volume is mounted.
- // (i.e. path that leads to the files stored on the volume).
- const nsCString& MountPoint() const { return mMountPoint; }
-
- uint32_t Id() const { return mId; }
-
- int32_t MountGeneration() const { return mMountGeneration; }
- bool IsMountLocked() const { return mMountLocked; }
- bool MediaPresent() const { return mMediaPresent; }
- bool CanBeShared() const { return mCanBeShared; }
- bool CanBeFormatted() const { return CanBeShared(); }
- bool CanBeMounted() const { return CanBeShared(); }
- bool IsSharingEnabled() const { return mCanBeShared && mSharingEnabled; }
- bool IsFormatRequested() const { return CanBeFormatted() && mFormatRequested; }
- bool IsMountRequested() const { return CanBeMounted() && mMountRequested; }
- bool IsUnmountRequested() const { return CanBeMounted() && mUnmountRequested; }
- bool IsSharing() const { return mIsSharing; }
- bool IsFormatting() const { return mIsFormatting; }
- bool IsUnmounting() const { return mIsUnmounting; }
- bool IsRemovable() const { return mIsRemovable; }
- bool IsHotSwappable() const { return mIsHotSwappable; }
-
- void SetFakeVolume(const nsACString& aMountPoint);
-
- void SetSharingEnabled(bool aSharingEnabled);
- void SetFormatRequested(bool aFormatRequested);
- void SetMountRequested(bool aMountRequested);
- void SetUnmountRequested(bool aUnmountRequested);
-
- typedef mozilla::Observer<Volume *> EventObserver;
-
- // NOTE: that observers must live in the IOThread.
- static void RegisterVolumeObserver(EventObserver* aObserver, const char* aName);
- static void UnregisterVolumeObserver(EventObserver* aObserver, const char* aName);
-
-protected:
- ~Volume() {}
-
-private:
- friend class AutoMounter; // Calls StartXxx
- friend class nsVolume; // Calls UpdateMountLock
- friend class VolumeManager; // Calls HandleVoldResponse
- friend class VolumeListCallback; // Calls SetMountPoint, SetState
-
- // The StartXxx functions will queue up a command to the VolumeManager.
- // You can queue up as many commands as you like, and aCallback will
- // be called as each one completes.
- void StartMount(VolumeResponseCallback* aCallback);
- void StartUnmount(VolumeResponseCallback* aCallback);
- void StartFormat(VolumeResponseCallback* aCallback);
- void StartShare(VolumeResponseCallback* aCallback);
- void StartUnshare(VolumeResponseCallback* aCallback);
-
- void SetIsSharing(bool aIsSharing);
- void SetIsFormatting(bool aIsFormatting);
- void SetIsUnmounting(bool aIsUnmounting);
- void SetIsRemovable(bool aIsRemovable);
- void SetIsHotSwappable(bool aIsHotSwappable);
- void SetState(STATE aNewState);
- void SetMediaPresent(bool aMediaPresent);
- void SetMountPoint(const nsCSubstring& aMountPoint);
- void StartCommand(VolumeCommand* aCommand);
-
- void ResolveAndSetMountPoint(const nsCSubstring& aMountPoint);
-
- bool BoolConfigValue(const nsCString& aConfigValue, bool& aBoolValue);
- void SetConfig(const nsCString& aConfigName, const nsCString& aConfigValue);
-
- void HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer& aTokenizer);
-
- static void UpdateMountLock(const nsACString& aVolumeName,
- const int32_t& aMountGeneration,
- const bool& aMountLocked);
-
- bool mMediaPresent;
- STATE mState;
- const nsCString mName;
- nsCString mMountPoint;
- int32_t mMountGeneration;
- bool mMountLocked;
- bool mSharingEnabled;
- bool mFormatRequested;
- bool mMountRequested;
- bool mUnmountRequested;
- bool mCanBeShared;
- bool mIsSharing;
- bool mIsFormatting;
- bool mIsUnmounting;
- bool mIsRemovable;
- bool mIsHotSwappable;
- uint32_t mId; // Unique ID (used by MTP)
-
- static VolumeObserverList sEventObserverList;
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumemanager_h__
diff --git a/dom/system/gonk/VolumeCommand.cpp b/dom/system/gonk/VolumeCommand.cpp
deleted file mode 100644
index 8095956a7..000000000
--- a/dom/system/gonk/VolumeCommand.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsString.h"
-#include "nsWhitespaceTokenizer.h"
-
-#include "Volume.h"
-#include "VolumeCommand.h"
-#include "VolumeManager.h"
-#include "VolumeManagerLog.h"
-
-namespace mozilla {
-namespace system {
-
-/***************************************************************************
-*
-* The VolumeActionCommand class is used to send commands which apply
-* to a particular volume.
-*
-* The following commands would fit into this category:
-*
-* volume mount <volname>
-* volume unmount <volname> [force]
-* volume format <volname>
-* volume share <volname> <method>
-* volume unshare <volname> <method>
-* volume shared <volname> <method>
-*
-* A typical response looks like:
-*
-* # vdc volume unshare sdcard ums
-* 605 Volume sdcard /mnt/sdcard state changed from 7 (Shared-Unmounted) to 1 (Idle-Unmounted)
-* 200 volume operation succeeded
-*
-* Note that the 600 series of responses are considered unsolicited and
-* are dealt with directly by the VolumeManager. This command will only
-* see the terminating response code (200 in the example above).
-*
-***************************************************************************/
-
-VolumeActionCommand::VolumeActionCommand(Volume* aVolume,
- const char* aAction,
- const char* aExtraArgs,
- VolumeResponseCallback* aCallback)
- : VolumeCommand(aCallback),
- mVolume(aVolume)
-{
- nsAutoCString cmd;
-
- cmd = "volume ";
- cmd += aAction;
- cmd += " ";
- cmd += aVolume->Name().get();
-
- // vold doesn't like trailing white space, so only add it if we really need to.
- if (aExtraArgs && (*aExtraArgs != '\0')) {
- cmd += " ";
- cmd += aExtraArgs;
- }
- SetCmd(cmd);
-}
-
-/***************************************************************************
-*
-* The VolumeListCommand class is used to send the "volume list" command to
-* vold.
-*
-* A typical response looks like:
-*
-* # vdc volume list
-* 110 sdcard /mnt/sdcard 4
-* 110 sdcard1 /mnt/sdcard/external_sd 4
-* 200 Volumes listed.
-*
-***************************************************************************/
-
-VolumeListCommand::VolumeListCommand(VolumeResponseCallback* aCallback)
- : VolumeCommand(NS_LITERAL_CSTRING("volume list"), aCallback)
-{
-}
-
-} // system
-} // mozilla
-
diff --git a/dom/system/gonk/VolumeCommand.h b/dom/system/gonk/VolumeCommand.h
deleted file mode 100644
index 022965b5e..000000000
--- a/dom/system/gonk/VolumeCommand.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumecommand_h__
-#define mozilla_system_volumecommand_h__
-
-#include "nsString.h"
-#include "nsISupportsImpl.h"
-#include "mozilla/RefPtr.h"
-#include <algorithm>
-#include <vold/ResponseCode.h>
-
-namespace mozilla {
-namespace system {
-
-class Volume;
-class VolumeCommand;
-
-/***************************************************************************
-*
-* The VolumeResponseCallback class is an abstract base class. The ResponseReceived
-* method will be called for each response received.
-*
-* Depending on the command, there may be multiple responses for the
-* command. Done() will return true if this is the last response.
-*
-* The responses from vold are all of the form:
-*
-* <ResponseCode> <String>
-*
-* Valid Response codes can be found in the vold/ResponseCode.h header.
-*
-***************************************************************************/
-
-class VolumeResponseCallback
-{
-protected:
- virtual ~VolumeResponseCallback() {}
-
-public:
- NS_INLINE_DECL_REFCOUNTING(VolumeResponseCallback)
- VolumeResponseCallback()
- : mResponseCode(0), mPending(false) {}
-
- bool Done() const
- {
- // Response codes from the 200, 400, and 500 series all indicated that
- // the command has completed.
-
- return (mResponseCode >= ::ResponseCode::CommandOkay)
- && (mResponseCode < ::ResponseCode::UnsolicitedInformational);
- }
-
- bool WasSuccessful() const
- {
- return mResponseCode == ::ResponseCode::CommandOkay;
- }
-
- bool IsPending() const { return mPending; }
- int ResponseCode() const { return mResponseCode; }
- const nsCString &ResponseStr() const { return mResponseStr; }
-
-protected:
- virtual void ResponseReceived(const VolumeCommand* aCommand) = 0;
-
-private:
- friend class VolumeCommand; // Calls HandleResponse and SetPending
-
- void HandleResponse(const VolumeCommand* aCommand,
- int aResponseCode,
- nsACString& aResponseStr)
- {
- mResponseCode = aResponseCode;
-#if ANDROID_VERSION >= 17
- // There's a sequence number here that we don't care about
- // We expect it to be 0. See VolumeCommand::SetCmd
- mResponseStr = Substring(aResponseStr, 2);
-#else
- mResponseStr = aResponseStr;
-#endif
- if (mResponseCode >= ::ResponseCode::CommandOkay) {
- // This is a final response.
- mPending = false;
- }
- ResponseReceived(aCommand);
- }
-
- void SetPending(bool aPending) { mPending = aPending; }
-
- int mResponseCode; // The response code parsed from vold
- nsCString mResponseStr; // The rest of the line.
- bool mPending; // Waiting for response?
-};
-
-/***************************************************************************
-*
-* The VolumeCommand class is an abstract base class used to encapsulate
-* volume commands send to vold.
-*
-* See VolumeManager.h for a list of the volume commands.
-*
-* Commands sent to vold need an explicit null character so we add one
-* to the command to ensure that it's included in the length.
-*
-* All of these commands are asynchronous in nature, and the
-* ResponseReceived callback will be called when a response is available.
-*
-***************************************************************************/
-
-class VolumeCommand
-{
-protected:
- virtual ~VolumeCommand() {}
-
-public:
- NS_INLINE_DECL_REFCOUNTING(VolumeCommand)
-
- VolumeCommand(VolumeResponseCallback* aCallback)
- : mBytesConsumed(0),
- mCallback(aCallback)
- {
- SetCmd(NS_LITERAL_CSTRING(""));
- }
-
- VolumeCommand(const nsACString& aCommand, VolumeResponseCallback* aCallback)
- : mBytesConsumed(0),
- mCallback(aCallback)
- {
- SetCmd(aCommand);
- }
-
- void SetCmd(const nsACString& aCommand)
- {
- mCmd.Truncate();
-#if ANDROID_VERSION >= 17
- // JB requires a sequence number at the beginning of messages.
- // It doesn't matter what we use, so we use 0.
- mCmd = "0 ";
-#endif
- mCmd.Append(aCommand);
- // Add a null character. We want this to be included in the length since
- // vold uses it to determine the end of the command.
- mCmd.Append('\0');
- }
-
- const char* CmdStr() const { return mCmd.get(); }
- const char* Data() const { return mCmd.Data() + mBytesConsumed; }
- size_t BytesConsumed() const { return mBytesConsumed; }
-
- size_t BytesRemaining() const
- {
- return mCmd.Length() - std::min(mCmd.Length(), mBytesConsumed);
- }
-
- void ConsumeBytes(size_t aNumBytes)
- {
- mBytesConsumed += std::min(BytesRemaining(), aNumBytes);
- }
-
-private:
- friend class VolumeManager; // Calls SetPending & HandleResponse
-
- void SetPending(bool aPending)
- {
- if (mCallback) {
- mCallback->SetPending(aPending);
- }
- }
-
- void HandleResponse(int aResponseCode, nsACString& aResponseStr)
- {
- if (mCallback) {
- mCallback->HandleResponse(this, aResponseCode, aResponseStr);
- }
- }
-
- nsCString mCmd; // Command being sent
- size_t mBytesConsumed; // How many bytes have been sent
-
- // Called when a response to the command is received.
- RefPtr<VolumeResponseCallback> mCallback;
-};
-
-class VolumeActionCommand : public VolumeCommand
-{
-public:
- VolumeActionCommand(Volume* aVolume, const char* aAction,
- const char* aExtraArgs, VolumeResponseCallback* aCallback);
-
-private:
- RefPtr<Volume> mVolume;
-};
-
-class VolumeListCommand : public VolumeCommand
-{
-public:
- VolumeListCommand(VolumeResponseCallback* aCallback);
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumecommand_h__
diff --git a/dom/system/gonk/VolumeManager.cpp b/dom/system/gonk/VolumeManager.cpp
deleted file mode 100644
index ddfa7af09..000000000
--- a/dom/system/gonk/VolumeManager.cpp
+++ /dev/null
@@ -1,591 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "VolumeManager.h"
-
-#include "Volume.h"
-#include "VolumeCommand.h"
-#include "VolumeManagerLog.h"
-#include "VolumeServiceTest.h"
-
-#include "nsWhitespaceTokenizer.h"
-#include "nsXULAppAPI.h"
-
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "mozilla/Scoped.h"
-#include "mozilla/StaticPtr.h"
-
-#include <android/log.h>
-#include <cutils/sockets.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-
-namespace mozilla {
-namespace system {
-
-static StaticRefPtr<VolumeManager> sVolumeManager;
-
-VolumeManager::STATE VolumeManager::mState = VolumeManager::UNINITIALIZED;
-VolumeManager::StateObserverList VolumeManager::mStateObserverList;
-
-/***************************************************************************/
-
-VolumeManager::VolumeManager()
- : LineWatcher('\0', kRcvBufSize),
- mSocket(-1),
- mCommandPending(false)
-{
- DBG("VolumeManager constructor called");
-}
-
-VolumeManager::~VolumeManager()
-{
-}
-
-//static
-void
-VolumeManager::Dump(const char* aLabel)
-{
- if (!sVolumeManager) {
- LOG("%s: sVolumeManager == null", aLabel);
- return;
- }
-
- VolumeArray::size_type numVolumes = NumVolumes();
- VolumeArray::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = GetVolume(volIndex);
- vol->Dump(aLabel);
- }
-}
-
-//static
-size_t
-VolumeManager::NumVolumes()
-{
- if (!sVolumeManager) {
- return 0;
- }
- return sVolumeManager->mVolumeArray.Length();
-}
-
-//static
-already_AddRefed<Volume>
-VolumeManager::GetVolume(size_t aIndex)
-{
- MOZ_ASSERT(aIndex < NumVolumes());
- RefPtr<Volume> vol = sVolumeManager->mVolumeArray[aIndex];
- return vol.forget();
-}
-
-//static
-VolumeManager::STATE
-VolumeManager::State()
-{
- return mState;
-}
-
-//static
-const char *
-VolumeManager::StateStr(VolumeManager::STATE aState)
-{
- switch (aState) {
- case UNINITIALIZED: return "Uninitialized";
- case STARTING: return "Starting";
- case VOLUMES_READY: return "Volumes Ready";
- }
- return "???";
-}
-
-
-//static
-void
-VolumeManager::SetState(STATE aNewState)
-{
- if (mState != aNewState) {
- LOG("changing state from '%s' to '%s'",
- StateStr(mState), StateStr(aNewState));
- mState = aNewState;
- mStateObserverList.Broadcast(StateChangedEvent());
- }
-}
-
-//static
-void
-VolumeManager::RegisterStateObserver(StateObserver* aObserver)
-{
- mStateObserverList.AddObserver(aObserver);
-}
-
-//static
-void VolumeManager::UnregisterStateObserver(StateObserver* aObserver)
-{
- mStateObserverList.RemoveObserver(aObserver);
-}
-
-//static
-already_AddRefed<Volume>
-VolumeManager::FindVolumeByName(const nsCSubstring& aName)
-{
- if (!sVolumeManager) {
- return nullptr;
- }
- VolumeArray::size_type numVolumes = NumVolumes();
- VolumeArray::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = GetVolume(volIndex);
- if (vol->Name().Equals(aName)) {
- return vol.forget();
- }
- }
- return nullptr;
-}
-
-//static
-already_AddRefed<Volume>
-VolumeManager::FindAddVolumeByName(const nsCSubstring& aName)
-{
- RefPtr<Volume> vol = FindVolumeByName(aName);
- if (vol) {
- return vol.forget();
- }
- // No volume found, create and add a new one.
- vol = new Volume(aName);
- sVolumeManager->mVolumeArray.AppendElement(vol);
- return vol.forget();
-}
-
-//static
-bool
-VolumeManager::RemoveVolumeByName(const nsCSubstring& aName)
-{
- if (!sVolumeManager) {
- return false;
- }
- VolumeArray::size_type numVolumes = NumVolumes();
- VolumeArray::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = GetVolume(volIndex);
- if (vol->Name().Equals(aName)) {
- sVolumeManager->mVolumeArray.RemoveElementAt(volIndex);
- return true;
- }
- }
- // No volume found. Return false to indicate this.
- return false;
-}
-
-
-//static
-void VolumeManager::InitConfig()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- // This function uses /system/etc/volume.cfg to add additional volumes
- // to the Volume Manager.
- //
- // This is useful on devices like the Nexus 4, which have no physical sd card
- // or dedicated partition.
- //
- // The format of the volume.cfg file is as follows:
- // create volume-name mount-point
- // configure volume-name preference preference-value
- // Blank lines and lines starting with the hash character "#" will be ignored.
-
- ScopedCloseFile fp;
- int n = 0;
- char line[255];
- const char *filename = "/system/etc/volume.cfg";
- if (!(fp = fopen(filename, "r"))) {
- LOG("Unable to open volume configuration file '%s' - ignoring", filename);
- return;
- }
- while(fgets(line, sizeof(line), fp)) {
- n++;
-
- if (line[0] == '#')
- continue;
-
- nsCString commandline(line);
- nsCWhitespaceTokenizer tokenizer(commandline);
- if (!tokenizer.hasMoreTokens()) {
- // Blank line - ignore
- continue;
- }
-
- nsCString command(tokenizer.nextToken());
- if (command.EqualsLiteral("create")) {
- if (!tokenizer.hasMoreTokens()) {
- ERR("No vol_name in %s line %d", filename, n);
- continue;
- }
- nsCString volName(tokenizer.nextToken());
- if (!tokenizer.hasMoreTokens()) {
- ERR("No mount point for volume '%s'. %s line %d",
- volName.get(), filename, n);
- continue;
- }
- nsCString mountPoint(tokenizer.nextToken());
- RefPtr<Volume> vol = FindAddVolumeByName(volName);
- vol->SetFakeVolume(mountPoint);
- continue;
- }
- if (command.EqualsLiteral("configure")) {
- if (!tokenizer.hasMoreTokens()) {
- ERR("No vol_name in %s line %d", filename, n);
- continue;
- }
- nsCString volName(tokenizer.nextToken());
- if (!tokenizer.hasMoreTokens()) {
- ERR("No configuration name specified for volume '%s'. %s line %d",
- volName.get(), filename, n);
- continue;
- }
- nsCString configName(tokenizer.nextToken());
- if (!tokenizer.hasMoreTokens()) {
- ERR("No value for configuration name '%s'. %s line %d",
- configName.get(), filename, n);
- continue;
- }
- nsCString configValue(tokenizer.nextToken());
- RefPtr<Volume> vol = FindVolumeByName(volName);
- if (vol) {
- vol->SetConfig(configName, configValue);
- } else {
- ERR("Invalid volume name '%s'.", volName.get());
- }
- continue;
- }
- if (command.EqualsLiteral("ignore")) {
- // This command is useful to remove volumes which are being tracked by
- // vold, but for which we have no interest.
- if (!tokenizer.hasMoreTokens()) {
- ERR("No vol_name in %s line %d", filename, n);
- continue;
- }
- nsCString volName(tokenizer.nextToken());
- RemoveVolumeByName(volName);
- continue;
- }
- ERR("Unrecognized command: '%s'", command.get());
- }
-}
-
-void
-VolumeManager::DefaultConfig()
-{
-
- VolumeManager::VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- if (numVolumes == 0) {
- return;
- }
- if (numVolumes == 1) {
- // This is to cover early shipping phones like the Buri,
- // which had no internal storage, and only external sdcard.
- //
- // Phones line the nexus-4 which only have an internal
- // storage area will need to have a volume.cfg file with
- // removable set to false.
- RefPtr<Volume> vol = VolumeManager::GetVolume(0);
- vol->SetIsRemovable(true);
- vol->SetIsHotSwappable(true);
- return;
- }
- VolumeManager::VolumeArray::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- if (!vol->Name().EqualsLiteral("sdcard")) {
- vol->SetIsRemovable(true);
- vol->SetIsHotSwappable(true);
- }
- }
-}
-
-class VolumeListCallback : public VolumeResponseCallback
-{
- virtual void ResponseReceived(const VolumeCommand* aCommand)
- {
- switch (ResponseCode()) {
- case ::ResponseCode::VolumeListResult: {
- // Each line will look something like:
- //
- // sdcard /mnt/sdcard 1
- //
- // So for each volume that we get back, we update any volumes that
- // we have of the same name, or add new ones if they don't exist.
- nsCWhitespaceTokenizer tokenizer(ResponseStr());
- nsDependentCSubstring volName(tokenizer.nextToken());
- RefPtr<Volume> vol = VolumeManager::FindAddVolumeByName(volName);
- vol->HandleVoldResponse(ResponseCode(), tokenizer);
- break;
- }
-
- case ::ResponseCode::CommandOkay: {
- // We've received the list of volumes. Now read the Volume.cfg
- // file to perform customizations, and then tell everybody
- // that we're ready for business.
- VolumeManager::DefaultConfig();
- VolumeManager::InitConfig();
- VolumeManager::Dump("READY");
- VolumeManager::SetState(VolumeManager::VOLUMES_READY);
- break;
- }
- }
- }
-};
-
-bool
-VolumeManager::OpenSocket()
-{
- SetState(STARTING);
- if ((mSocket.rwget() = socket_local_client("vold",
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM)) < 0) {
- ERR("Error connecting to vold: (%s) - will retry", strerror(errno));
- return false;
- }
- // add FD_CLOEXEC flag
- int flags = fcntl(mSocket.get(), F_GETFD);
- if (flags == -1) {
- return false;
- }
- flags |= FD_CLOEXEC;
- if (fcntl(mSocket.get(), F_SETFD, flags) == -1) {
- return false;
- }
- // set non-blocking
- if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) {
- return false;
- }
- if (!MessageLoopForIO::current()->
- WatchFileDescriptor(mSocket.get(),
- true,
- MessageLoopForIO::WATCH_READ,
- &mReadWatcher,
- this)) {
- return false;
- }
-
- LOG("Connected to vold");
- PostCommand(new VolumeListCommand(new VolumeListCallback));
- return true;
-}
-
-//static
-void
-VolumeManager::PostCommand(VolumeCommand* aCommand)
-{
- if (!sVolumeManager) {
- ERR("VolumeManager not initialized. Dropping command '%s'", aCommand->Data());
- return;
- }
- aCommand->SetPending(true);
-
- DBG("Sending command '%s'", aCommand->Data());
- // vold can only process one command at a time, so add our command
- // to the end of the command queue.
- sVolumeManager->mCommands.push(aCommand);
- if (!sVolumeManager->mCommandPending) {
- // There aren't any commands currently being processed, so go
- // ahead and kick this one off.
- sVolumeManager->mCommandPending = true;
- sVolumeManager->WriteCommandData();
- }
-}
-
-/***************************************************************************
-* The WriteCommandData initiates sending of a command to vold. Since
-* we're running on the IOThread and not allowed to block, WriteCommandData
-* will write as much data as it can, and if not all of the data can be
-* written then it will setup a file descriptor watcher and
-* OnFileCanWriteWithoutBlocking will call WriteCommandData to write out
-* more of the command data.
-*/
-void
-VolumeManager::WriteCommandData()
-{
- if (mCommands.size() == 0) {
- return;
- }
-
- VolumeCommand* cmd = mCommands.front();
- if (cmd->BytesRemaining() == 0) {
- // All bytes have been written. We're waiting for a response.
- return;
- }
- // There are more bytes left to write. Try to write them all.
- ssize_t bytesWritten = write(mSocket.get(), cmd->Data(), cmd->BytesRemaining());
- if (bytesWritten < 0) {
- ERR("Failed to write %d bytes to vold socket", cmd->BytesRemaining());
- Restart();
- return;
- }
- DBG("Wrote %d bytes (of %d)", bytesWritten, cmd->BytesRemaining());
- cmd->ConsumeBytes(bytesWritten);
- if (cmd->BytesRemaining() == 0) {
- return;
- }
- // We were unable to write all of the command bytes. Setup a watcher
- // so we'll get called again when we can write without blocking.
- if (!MessageLoopForIO::current()->
- WatchFileDescriptor(mSocket.get(),
- false, // one-shot
- MessageLoopForIO::WATCH_WRITE,
- &mWriteWatcher,
- this)) {
- ERR("Failed to setup write watcher for vold socket");
- Restart();
- }
-}
-
-void
-VolumeManager::OnLineRead(int aFd, nsDependentCSubstring& aMessage)
-{
- MOZ_ASSERT(aFd == mSocket.get());
- char* endPtr;
- int responseCode = strtol(aMessage.Data(), &endPtr, 10);
- if (*endPtr == ' ') {
- endPtr++;
- }
-
- // Now fish out the rest of the line after the response code
- nsDependentCString responseLine(endPtr, aMessage.Length() - (endPtr - aMessage.Data()));
- DBG("Rcvd: %d '%s'", responseCode, responseLine.Data());
-
- if (responseCode >= ::ResponseCode::UnsolicitedInformational) {
- // These are unsolicited broadcasts. We intercept these and process
- // them ourselves
- HandleBroadcast(responseCode, responseLine);
- } else {
- // Everything else is considered to be part of the command response.
- if (mCommands.size() > 0) {
- VolumeCommand* cmd = mCommands.front();
- cmd->HandleResponse(responseCode, responseLine);
- if (responseCode >= ::ResponseCode::CommandOkay) {
- // That's a terminating response. We can remove the command.
- mCommands.pop();
- mCommandPending = false;
- // Start the next command, if there is one.
- WriteCommandData();
- }
- } else {
- ERR("Response with no command");
- }
- }
-}
-
-void
-VolumeManager::OnFileCanWriteWithoutBlocking(int aFd)
-{
- MOZ_ASSERT(aFd == mSocket.get());
- WriteCommandData();
-}
-
-void
-VolumeManager::HandleBroadcast(int aResponseCode, nsCString& aResponseLine)
-{
- // Format of the line is something like:
- //
- // Volume sdcard /mnt/sdcard state changed from 7 (Shared-Unmounted) to 1 (Idle-Unmounted)
- //
- // So we parse out the volume name and the state after the string " to "
- nsCWhitespaceTokenizer tokenizer(aResponseLine);
- tokenizer.nextToken(); // The word "Volume"
- nsDependentCSubstring volName(tokenizer.nextToken());
-
- RefPtr<Volume> vol = FindVolumeByName(volName);
- if (!vol) {
- return;
- }
- vol->HandleVoldResponse(aResponseCode, tokenizer);
-}
-
-void
-VolumeManager::Restart()
-{
- mReadWatcher.StopWatchingFileDescriptor();
- mWriteWatcher.StopWatchingFileDescriptor();
-
- while (!mCommands.empty()) {
- mCommands.pop();
- }
- mCommandPending = false;
- mSocket.dispose();
- Start();
-}
-
-//static
-void
-VolumeManager::Start()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (!sVolumeManager) {
- return;
- }
- SetState(STARTING);
- if (!sVolumeManager->OpenSocket()) {
- // Socket open failed, try again in a second.
- MessageLoopForIO::current()->
- PostDelayedTask(NewRunnableFunction(VolumeManager::Start),
- 1000);
- }
-}
-
-void
-VolumeManager::OnError()
-{
- Restart();
-}
-
-/***************************************************************************/
-
-static void
-InitVolumeManagerIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(!sVolumeManager);
-
- sVolumeManager = new VolumeManager();
- VolumeManager::Start();
-
- InitVolumeServiceTestIOThread();
-}
-
-static void
-ShutdownVolumeManagerIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- sVolumeManager = nullptr;
-}
-
-/**************************************************************************
-*
-* Public API
-*
-* Since the VolumeManager runs in IO Thread context, we need to switch
-* to IOThread context before we can do anything.
-*
-**************************************************************************/
-
-void
-InitVolumeManager()
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(InitVolumeManagerIOThread));
-}
-
-void
-ShutdownVolumeManager()
-{
- ShutdownVolumeServiceTest();
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(ShutdownVolumeManagerIOThread));
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/VolumeManager.h b/dom/system/gonk/VolumeManager.h
deleted file mode 100644
index 7c0503389..000000000
--- a/dom/system/gonk/VolumeManager.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumemanager_h__
-#define mozilla_system_volumemanager_h__
-
-#include <vector>
-#include <queue>
-
-#include "base/message_loop.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/Observer.h"
-#include "nsISupportsImpl.h"
-#include "nsString.h"
-#include "nsTArray.h"
-
-#include "Volume.h"
-#include "VolumeCommand.h"
-
-namespace mozilla {
-namespace system {
-
-/***************************************************************************
-*
-* All of the public API mentioned in this file (unless otherwise
-* mentioned) must run from the IOThread.
-*
-***************************************************************************/
-
-/***************************************************************************
-*
-* The VolumeManager class is a front-end for android's vold service.
-*
-* Vold uses a unix socket interface and accepts null-terminated string
-* commands. The following commands were determined by examining the vold
-* source code:
-*
-* volume list
-* volume mount <volname>
-* volume unmount <volname> [force]
-* volume debug [on|off]
-* volume format <volname>
-* volume share <volname> <method>
-* volume unshare <volname> <method>
-* volume shared <volname> <method>
-*
-* <volname> is the name of the volume as used in /system/etc/vold.fstab
-* <method> is ums
-*
-* dump
-*
-* share status <method> (Determines if a particular sharing method is available)
-* (GB only - not available in ICS)
-*
-* storage users (??? always crashes vold ???)
-*
-* asec list
-* asec ...lots more...
-*
-* obb list
-* obb ...lots more...
-*
-* xwarp enable
-* xwarp disable
-* xwarp status
-*
-* There is also a command line tool called vdc, which can be used to send
-* the above commands to vold.
-*
-* Currently, only the volume list, share/unshare, and mount/unmount
-* commands are being used.
-*
-***************************************************************************/
-
-class VolumeManager final : public MessageLoopForIO::LineWatcher
-{
- virtual ~VolumeManager();
-
-public:
- NS_INLINE_DECL_REFCOUNTING(VolumeManager)
-
- typedef nsTArray<RefPtr<Volume>> VolumeArray;
-
- VolumeManager();
-
- //-----------------------------------------------------------------------
- //
- // State related methods.
- //
- // The VolumeManager starts off in the STARTING state. Once a connection
- // is established with vold, it asks for a list of volumes, and once the
- // volume list has been received, then the VolumeManager enters the
- // VOLUMES_READY state.
- //
- // If vold crashes, then the VolumeManager will once again enter the
- // STARTING state and try to reestablish a connection with vold.
-
- enum STATE
- {
- UNINITIALIZED,
- STARTING,
- VOLUMES_READY
- };
-
- static STATE State();
- static const char* StateStr(STATE aState);
- static const char* StateStr() { return StateStr(State()); }
-
- class StateChangedEvent
- {
- public:
- StateChangedEvent() {}
- };
-
- typedef mozilla::Observer<StateChangedEvent> StateObserver;
- typedef mozilla::ObserverList<StateChangedEvent> StateObserverList;
-
- static void RegisterStateObserver(StateObserver* aObserver);
- static void UnregisterStateObserver(StateObserver* aObserver);
-
- //-----------------------------------------------------------------------
-
- static void Start();
- static void Dump(const char* aLabel);
-
- static VolumeArray::size_type NumVolumes();
- static already_AddRefed<Volume> GetVolume(VolumeArray::index_type aIndex);
- static already_AddRefed<Volume> FindVolumeByName(const nsCSubstring& aName);
- static already_AddRefed<Volume> FindAddVolumeByName(const nsCSubstring& aName);
- static bool RemoveVolumeByName(const nsCSubstring& aName);
- static void InitConfig();
-
- static void PostCommand(VolumeCommand* aCommand);
-
-protected:
-
- virtual void OnLineRead(int aFd, nsDependentCSubstring& aMessage);
- virtual void OnFileCanWriteWithoutBlocking(int aFd);
- virtual void OnError();
-
- static void DefaultConfig();
-
-private:
- bool OpenSocket();
-
- friend class VolumeListCallback; // Calls SetState
-
- static void SetState(STATE aNewState);
-
- void Restart();
- void WriteCommandData();
- void HandleBroadcast(int aResponseCode, nsCString& aResponseLine);
-
- typedef std::queue<RefPtr<VolumeCommand> > CommandQueue;
-
- static STATE mState;
- static StateObserverList mStateObserverList;
-
- static const int kRcvBufSize = 1024;
- ScopedClose mSocket;
- VolumeArray mVolumeArray;
- CommandQueue mCommands;
- bool mCommandPending;
- MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
- MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
- RefPtr<VolumeResponseCallback> mBroadcastCallback;
-};
-
-/***************************************************************************
-*
-* The initialization/shutdown functions do not need to be called from
-* the IOThread context.
-*
-***************************************************************************/
-
-/**
- * Initialize the Volume Manager. On initialization, the VolumeManager will
- * attempt to connect with vold and collect the list of volumes that vold
- * knows about.
- */
-void InitVolumeManager();
-
-/**
- * Shuts down the Volume Manager.
- */
-void ShutdownVolumeManager();
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumemanager_h__
diff --git a/dom/system/gonk/VolumeManagerLog.h b/dom/system/gonk/VolumeManagerLog.h
deleted file mode 100644
index 793f4889c..000000000
--- a/dom/system/gonk/VolumeManagerLog.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumemanagerlog_h__
-#define mozilla_system_volumemanagerlog_h__
-
-#undef USE_DEBUG
-#define USE_DEBUG 0
-
-#if !defined(VOLUME_MANAGER_LOG_TAG)
-#define VOLUME_MANAGER_LOG_TAG "VolumeManager"
-#endif
-
-#undef LOG
-#undef ERR
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, VOLUME_MANAGER_LOG_TAG, ## args)
-#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, VOLUME_MANAGER_LOG_TAG, ## args)
-
-#undef DBG
-#if USE_DEBUG
-#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, VOLUME_MANAGER_LOG_TAG, ## args)
-#else
-#define DBG(args...)
-#endif
-
-#endif // mozilla_system_volumemanagerlog_h__
diff --git a/dom/system/gonk/VolumeServiceIOThread.cpp b/dom/system/gonk/VolumeServiceIOThread.cpp
deleted file mode 100644
index 7eda843c0..000000000
--- a/dom/system/gonk/VolumeServiceIOThread.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "VolumeServiceIOThread.h"
-#include "base/message_loop.h"
-#include "nsVolumeService.h"
-#include "nsXULAppAPI.h"
-#include "Volume.h"
-#include "VolumeManager.h"
-
-namespace mozilla {
-namespace system {
-
-VolumeServiceIOThread::VolumeServiceIOThread(nsVolumeService* aVolumeService)
- : mVolumeService(aVolumeService)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- VolumeManager::RegisterStateObserver(this);
- Volume::RegisterVolumeObserver(this, "VolumeServiceIOThread");
- UpdateAllVolumes();
-}
-
-VolumeServiceIOThread::~VolumeServiceIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- Volume::UnregisterVolumeObserver(this, "VolumeServiceIOThread");
- VolumeManager::UnregisterStateObserver(this);
-}
-
-void
-VolumeServiceIOThread::Notify(Volume* const & aVolume)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
- mVolumeService->UpdateVolumeIOThread(aVolume);
-}
-
-void
-VolumeServiceIOThread::Notify(const VolumeManager::StateChangedEvent& aEvent)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- UpdateAllVolumes();
-}
-
-void
-VolumeServiceIOThread::UpdateAllVolumes()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
- VolumeManager::VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
- VolumeManager::VolumeArray::index_type volIndex;
-
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
- mVolumeService->UpdateVolumeIOThread(vol);
- }
-}
-
-static StaticRefPtr<VolumeServiceIOThread> sVolumeServiceIOThread;
-
-void
-InitVolumeServiceIOThread(nsVolumeService* const & aVolumeService)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- sVolumeServiceIOThread = new VolumeServiceIOThread(aVolumeService);
-}
-
-void
-ShutdownVolumeServiceIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- sVolumeServiceIOThread = nullptr;
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/VolumeServiceIOThread.h b/dom/system/gonk/VolumeServiceIOThread.h
deleted file mode 100644
index 0c2a6a62f..000000000
--- a/dom/system/gonk/VolumeServiceIOThread.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumeserviceiothread_h__
-#define mozilla_system_volumeserviceiothread_h__
-
-#include "Volume.h"
-#include "VolumeManager.h"
-#include "mozilla/RefPtr.h"
-
-namespace mozilla {
-namespace system {
-
-class nsVolumeService;
-
-/***************************************************************************
-* The nsVolumeServiceIOThread is a companion class to the nsVolumeService
-* class, but whose methods are called from IOThread.
-*/
-class VolumeServiceIOThread : public VolumeManager::StateObserver,
- public Volume::EventObserver
-{
- ~VolumeServiceIOThread();
-
-public:
- NS_INLINE_DECL_REFCOUNTING(VolumeServiceIOThread)
-
- VolumeServiceIOThread(nsVolumeService* aVolumeService);
-
-private:
- void UpdateAllVolumes();
-
- virtual void Notify(const VolumeManager::StateChangedEvent& aEvent);
- virtual void Notify(Volume* const & aVolume);
-
- RefPtr<nsVolumeService> mVolumeService;
-};
-
-void InitVolumeServiceIOThread(nsVolumeService* const & aVolumeService);
-void ShutdownVolumeServiceIOThread();
-void FormatVolume(const nsCString& aVolume);
-void MountVolume(const nsCString& aVolume);
-void UnmountVolume(const nsCString& aVolume);
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumeserviceiothread_h__
diff --git a/dom/system/gonk/VolumeServiceTest.cpp b/dom/system/gonk/VolumeServiceTest.cpp
deleted file mode 100644
index 4082e3889..000000000
--- a/dom/system/gonk/VolumeServiceTest.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "VolumeServiceTest.h"
-
-#include "base/message_loop.h"
-#include "nsCOMPtr.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "nsIVolume.h"
-#include "nsIVolumeService.h"
-#include "nsIVolumeStat.h"
-#include "nsXULAppAPI.h"
-
-#include "mozilla/Services.h"
-
-#undef VOLUME_MANAGER_LOG_TAG
-#define VOLUME_MANAGER_LOG_TAG "VolumeServiceTest"
-#include "VolumeManagerLog.h"
-
-using namespace mozilla::services;
-
-namespace mozilla {
-namespace system {
-
-#define TEST_NSVOLUME_OBSERVER 0
-
-#if TEST_NSVOLUME_OBSERVER
-
-/***************************************************************************
-* A test class to verify that the Observer stuff is working properly.
-*/
-class VolumeTestObserver : public nsIObserver
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- VolumeTestObserver()
- {
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- if (!obs) {
- return;
- }
- obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false);
- }
- ~VolumeTestObserver()
- {
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- if (!obs) {
- return;
- }
- obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
- }
-
- void LogVolume(nsIVolume* vol)
- {
- nsString volName;
- nsString mountPoint;
- int32_t volState;
-
- vol->GetName(volName);
- vol->GetMountPoint(mountPoint);
- vol->GetState(&volState);
-
- LOG(" Volume: %s MountPoint: %s State: %s",
- NS_LossyConvertUTF16toASCII(volName).get(),
- NS_LossyConvertUTF16toASCII(mountPoint).get(),
- NS_VolumeStateStr(volState));
-
- nsCOMPtr<nsIVolumeStat> stat;
- nsresult rv = vol->GetStats(getter_AddRefs(stat));
- if (NS_SUCCEEDED(rv)) {
- int64_t totalBytes;
- int64_t freeBytes;
-
- stat->GetTotalBytes(&totalBytes);
- stat->GetFreeBytes(&freeBytes);
-
- LOG(" Total Space: %llu Mb Free Bytes: %llu Mb",
- totalBytes / (1024LL * 1024LL), freeBytes / (1024LL * 1024LL));
- }
- else {
- LOG(" Unable to retrieve stats");
- }
- }
-};
-static nsCOMPtr<VolumeTestObserver> sTestObserver;
-
-NS_IMPL_ISUPPORTS(VolumeTestObserver, nsIObserver)
-
-NS_IMETHODIMP
-VolumeTestObserver::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- LOG("TestObserver: topic: %s", aTopic);
-
- if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) {
- return NS_OK;
- }
- nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
- if (vol) {
- LogVolume(vol);
- }
-
- // Since this observe method was called then we know that the service
- // has been initialized so we can do the VolumeService tests.
-
- nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
- if (!vs) {
- ERR("do_GetService('%s') failed", NS_VOLUMESERVICE_CONTRACTID);
- return NS_ERROR_FAILURE;
- }
-
- nsresult rv = vs->GetVolumeByName(NS_LITERAL_STRING("sdcard"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- LOG("GetVolumeByName( 'sdcard' ) succeeded (expected)");
- LogVolume(vol);
- } else {
- ERR("GetVolumeByName( 'sdcard' ) failed (unexpected)");
- }
-
- rv = vs->GetVolumeByName(NS_LITERAL_STRING("foo"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- ERR("GetVolumeByName( 'foo' ) succeeded (unexpected)");
- } else {
- LOG("GetVolumeByName( 'foo' ) failed (expected)");
- }
-
- rv = vs->GetVolumeByPath(NS_LITERAL_STRING("/mnt/sdcard"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- LOG("GetVolumeByPath( '/mnt/sdcard' ) succeeded (expected)");
- LogVolume(vol);
- } else {
- ERR("GetVolumeByPath( '/mnt/sdcard' ) failed (unexpected");
- }
-
- rv = vs->GetVolumeByPath(NS_LITERAL_STRING("/mnt/sdcard/foo"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- LOG("GetVolumeByPath( '/mnt/sdcard/foo' ) succeeded (expected)");
- LogVolume(vol);
- } else {
- LOG("GetVolumeByPath( '/mnt/sdcard/foo' ) failed (unexpected)");
- }
-
- rv = vs->GetVolumeByPath(NS_LITERAL_STRING("/mnt/sdcardfoo"), getter_AddRefs(vol));
- if (NS_SUCCEEDED(rv)) {
- ERR("GetVolumeByPath( '/mnt/sdcardfoo' ) succeeded (unexpected)");
- } else {
- LOG("GetVolumeByPath( '/mnt/sdcardfoo' ) failed (expected)");
- }
-
- return NS_OK;
-}
-
-class InitVolumeServiceTestIO : public Runnable
-{
-public:
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- DBG("InitVolumeServiceTest called");
- nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
- if (!vs) {
- ERR("do_GetService('%s') failed", NS_VOLUMESERVICE_CONTRACTID);
- return NS_ERROR_FAILURE;
- }
- sTestObserver = new VolumeTestObserver();
-
- return NS_OK;
- }
-};
-#endif // TEST_NSVOLUME_OBSERVER
-
-void
-InitVolumeServiceTestIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
-#if TEST_NSVOLUME_OBSERVER
- // Now that the volume manager is initialized we can go
- // ahead and do our test (on main thread).
- NS_DispatchToMainThread(new InitVolumeServiceTestIO());
-#endif
-}
-
-void
-ShutdownVolumeServiceTest()
-{
-#if TEST_NSVOLUME_OBSERVER
- DBG("ShutdownVolumeServiceTestIOThread called");
- sTestObserver = nullptr;
-#endif
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/VolumeServiceTest.h b/dom/system/gonk/VolumeServiceTest.h
deleted file mode 100644
index 71a92bf6c..000000000
--- a/dom/system/gonk/VolumeServiceTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_volumeservicetest_h__
-#define mozilla_system_volumeservicetest_h__
-
-
-namespace mozilla {
-namespace system {
-
-void InitVolumeServiceTestIOThread();
-void ShutdownVolumeServiceTest();
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_volumeservicetest_h__
-
diff --git a/dom/system/gonk/android_audio/AudioSystem.h b/dom/system/gonk/android_audio/AudioSystem.h
deleted file mode 100644
index d5841eaaa..000000000
--- a/dom/system/gonk/android_audio/AudioSystem.h
+++ /dev/null
@@ -1,1134 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_AUDIOSYSTEM_H_
-#define ANDROID_AUDIOSYSTEM_H_
-
-#pragma GCC visibility push(default)
-
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-#include "IAudioFlinger.h"
-
-#ifndef VANILLA_ANDROID
-/* request to open a direct output with get_output() (by opposition to
- * sharing an output with other AudioTracks)
- */
-typedef enum {
- AUDIO_POLICY_OUTPUT_FLAG_INDIRECT = 0x0,
- AUDIO_POLICY_OUTPUT_FLAG_DIRECT = 0x1
-} audio_policy_output_flags_t;
-
-/* device categories used for audio_policy->set_force_use() */
-typedef enum {
- AUDIO_POLICY_FORCE_NONE,
- AUDIO_POLICY_FORCE_SPEAKER,
- AUDIO_POLICY_FORCE_HEADPHONES,
- AUDIO_POLICY_FORCE_BT_SCO,
- AUDIO_POLICY_FORCE_BT_A2DP,
- AUDIO_POLICY_FORCE_WIRED_ACCESSORY,
- AUDIO_POLICY_FORCE_BT_CAR_DOCK,
- AUDIO_POLICY_FORCE_BT_DESK_DOCK,
- AUDIO_POLICY_FORCE_ANALOG_DOCK,
- AUDIO_POLICY_FORCE_DIGITAL_DOCK,
- AUDIO_POLICY_FORCE_NO_BT_A2DP,
- AUDIO_POLICY_FORCE_CFG_CNT,
- AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
-
- AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
-} audio_policy_forced_cfg_t;
-
-/* usages used for audio_policy->set_force_use() */
-typedef enum {
- AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
- AUDIO_POLICY_FORCE_FOR_MEDIA,
- AUDIO_POLICY_FORCE_FOR_RECORD,
- AUDIO_POLICY_FORCE_FOR_DOCK,
-
- AUDIO_POLICY_FORCE_USE_CNT,
- AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
-} audio_policy_force_use_t;
-
-typedef enum {
- AUDIO_STREAM_DEFAULT = -1,
- AUDIO_STREAM_VOICE_CALL = 0,
- AUDIO_STREAM_SYSTEM = 1,
- AUDIO_STREAM_RING = 2,
- AUDIO_STREAM_MUSIC = 3,
- AUDIO_STREAM_ALARM = 4,
- AUDIO_STREAM_NOTIFICATION = 5,
- AUDIO_STREAM_BLUETOOTH_SCO = 6,
- AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */
- AUDIO_STREAM_DTMF = 8,
- AUDIO_STREAM_TTS = 9,
-#if ANDROID_VERSION < 19
- AUDIO_STREAM_FM = 10,
-#endif
-
- AUDIO_STREAM_CNT,
- AUDIO_STREAM_MAX = AUDIO_STREAM_CNT - 1,
-} audio_stream_type_t;
-
-/* PCM sub formats */
-typedef enum {
- AUDIO_FORMAT_PCM_SUB_16_BIT = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */
- AUDIO_FORMAT_PCM_SUB_8_BIT = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */
- AUDIO_FORMAT_PCM_SUB_32_BIT = 0x3, /* PCM signed .31 fixed point */
- AUDIO_FORMAT_PCM_SUB_8_24_BIT = 0x4, /* PCM signed 7.24 fixed point */
-} audio_format_pcm_sub_fmt_t;
-
-/* Audio format consists in a main format field (upper 8 bits) and a sub format
- * field (lower 24 bits).
- *
- * The main format indicates the main codec type. The sub format field
- * indicates options and parameters for each format. The sub format is mainly
- * used for record to indicate for instance the requested bitrate or profile.
- * It can also be used for certain formats to give informations not present in
- * the encoded audio stream (e.g. octet alignement for AMR).
- */
-typedef enum {
- AUDIO_FORMAT_INVALID = 0xFFFFFFFFUL,
- AUDIO_FORMAT_DEFAULT = 0,
- AUDIO_FORMAT_PCM = 0x00000000UL, /* DO NOT CHANGE */
- AUDIO_FORMAT_MP3 = 0x01000000UL,
- AUDIO_FORMAT_AMR_NB = 0x02000000UL,
- AUDIO_FORMAT_AMR_WB = 0x03000000UL,
- AUDIO_FORMAT_AAC = 0x04000000UL,
- AUDIO_FORMAT_HE_AAC_V1 = 0x05000000UL,
- AUDIO_FORMAT_HE_AAC_V2 = 0x06000000UL,
- AUDIO_FORMAT_VORBIS = 0x07000000UL,
- AUDIO_FORMAT_MAIN_MASK = 0xFF000000UL,
- AUDIO_FORMAT_SUB_MASK = 0x00FFFFFFUL,
-
- /* Aliases */
- AUDIO_FORMAT_PCM_16_BIT = (AUDIO_FORMAT_PCM |
- AUDIO_FORMAT_PCM_SUB_16_BIT),
- AUDIO_FORMAT_PCM_8_BIT = (AUDIO_FORMAT_PCM |
- AUDIO_FORMAT_PCM_SUB_8_BIT),
- AUDIO_FORMAT_PCM_32_BIT = (AUDIO_FORMAT_PCM |
- AUDIO_FORMAT_PCM_SUB_32_BIT),
- AUDIO_FORMAT_PCM_8_24_BIT = (AUDIO_FORMAT_PCM |
- AUDIO_FORMAT_PCM_SUB_8_24_BIT),
-} audio_format_t;
-
-typedef enum {
- /* output channels */
- AUDIO_CHANNEL_OUT_FRONT_LEFT = 0x1,
- AUDIO_CHANNEL_OUT_FRONT_RIGHT = 0x2,
- AUDIO_CHANNEL_OUT_FRONT_CENTER = 0x4,
- AUDIO_CHANNEL_OUT_LOW_FREQUENCY = 0x8,
- AUDIO_CHANNEL_OUT_BACK_LEFT = 0x10,
- AUDIO_CHANNEL_OUT_BACK_RIGHT = 0x20,
- AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40,
- AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80,
- AUDIO_CHANNEL_OUT_BACK_CENTER = 0x100,
- AUDIO_CHANNEL_OUT_SIDE_LEFT = 0x200,
- AUDIO_CHANNEL_OUT_SIDE_RIGHT = 0x400,
- AUDIO_CHANNEL_OUT_TOP_CENTER = 0x800,
- AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT = 0x1000,
- AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER = 0x2000,
- AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT = 0x4000,
- AUDIO_CHANNEL_OUT_TOP_BACK_LEFT = 0x8000,
- AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 0x10000,
- AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000,
-
- AUDIO_CHANNEL_OUT_MONO = AUDIO_CHANNEL_OUT_FRONT_LEFT,
- AUDIO_CHANNEL_OUT_STEREO = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT),
- AUDIO_CHANNEL_OUT_QUAD = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_BACK_LEFT |
- AUDIO_CHANNEL_OUT_BACK_RIGHT),
- AUDIO_CHANNEL_OUT_SURROUND = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_CENTER |
- AUDIO_CHANNEL_OUT_BACK_CENTER),
- AUDIO_CHANNEL_OUT_5POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_CENTER |
- AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
- AUDIO_CHANNEL_OUT_BACK_LEFT |
- AUDIO_CHANNEL_OUT_BACK_RIGHT),
- // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1
- AUDIO_CHANNEL_OUT_7POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_CENTER |
- AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
- AUDIO_CHANNEL_OUT_BACK_LEFT |
- AUDIO_CHANNEL_OUT_BACK_RIGHT |
- AUDIO_CHANNEL_OUT_SIDE_LEFT |
- AUDIO_CHANNEL_OUT_SIDE_RIGHT),
- AUDIO_CHANNEL_OUT_ALL = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_CENTER |
- AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
- AUDIO_CHANNEL_OUT_BACK_LEFT |
- AUDIO_CHANNEL_OUT_BACK_RIGHT |
- AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER |
- AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER |
- AUDIO_CHANNEL_OUT_BACK_CENTER|
- AUDIO_CHANNEL_OUT_SIDE_LEFT|
- AUDIO_CHANNEL_OUT_SIDE_RIGHT|
- AUDIO_CHANNEL_OUT_TOP_CENTER|
- AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT|
- AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER|
- AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT|
- AUDIO_CHANNEL_OUT_TOP_BACK_LEFT|
- AUDIO_CHANNEL_OUT_TOP_BACK_CENTER|
- AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
-
- /* input channels */
- AUDIO_CHANNEL_IN_LEFT = 0x4,
- AUDIO_CHANNEL_IN_RIGHT = 0x8,
- AUDIO_CHANNEL_IN_FRONT = 0x10,
- AUDIO_CHANNEL_IN_BACK = 0x20,
- AUDIO_CHANNEL_IN_LEFT_PROCESSED = 0x40,
- AUDIO_CHANNEL_IN_RIGHT_PROCESSED = 0x80,
- AUDIO_CHANNEL_IN_FRONT_PROCESSED = 0x100,
- AUDIO_CHANNEL_IN_BACK_PROCESSED = 0x200,
- AUDIO_CHANNEL_IN_PRESSURE = 0x400,
- AUDIO_CHANNEL_IN_X_AXIS = 0x800,
- AUDIO_CHANNEL_IN_Y_AXIS = 0x1000,
- AUDIO_CHANNEL_IN_Z_AXIS = 0x2000,
- AUDIO_CHANNEL_IN_VOICE_UPLINK = 0x4000,
- AUDIO_CHANNEL_IN_VOICE_DNLINK = 0x8000,
-
- AUDIO_CHANNEL_IN_MONO = AUDIO_CHANNEL_IN_FRONT,
- AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT),
- AUDIO_CHANNEL_IN_ALL = (AUDIO_CHANNEL_IN_LEFT |
- AUDIO_CHANNEL_IN_RIGHT |
- AUDIO_CHANNEL_IN_FRONT |
- AUDIO_CHANNEL_IN_BACK|
- AUDIO_CHANNEL_IN_LEFT_PROCESSED |
- AUDIO_CHANNEL_IN_RIGHT_PROCESSED |
- AUDIO_CHANNEL_IN_FRONT_PROCESSED |
- AUDIO_CHANNEL_IN_BACK_PROCESSED|
- AUDIO_CHANNEL_IN_PRESSURE |
- AUDIO_CHANNEL_IN_X_AXIS |
- AUDIO_CHANNEL_IN_Y_AXIS |
- AUDIO_CHANNEL_IN_Z_AXIS |
- AUDIO_CHANNEL_IN_VOICE_UPLINK |
- AUDIO_CHANNEL_IN_VOICE_DNLINK),
-} audio_channels_t;
-
-#if ANDROID_VERSION >= 17
-typedef enum {
- AUDIO_MODE_INVALID = -2,
- AUDIO_MODE_CURRENT = -1,
- AUDIO_MODE_NORMAL = 0,
- AUDIO_MODE_RINGTONE = 1,
- AUDIO_MODE_IN_CALL = 2,
- AUDIO_MODE_IN_COMMUNICATION = 3,
-
- AUDIO_MODE_CNT,
- AUDIO_MODE_MAX = AUDIO_MODE_CNT - 1,
-} audio_mode_t;
-#endif
-#endif
-
-#if ANDROID_VERSION < 17
-typedef enum {
- AUDIO_DEVICE_NONE = 0x0,
- /* output devices */
- AUDIO_DEVICE_OUT_EARPIECE = 0x1,
- AUDIO_DEVICE_OUT_SPEAKER = 0x2,
- AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400,
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800,
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000,
- AUDIO_DEVICE_OUT_FM = 0x2000,
- AUDIO_DEVICE_OUT_ANC_HEADSET = 0x4000,
- AUDIO_DEVICE_OUT_ANC_HEADPHONE = 0x8000,
- AUDIO_DEVICE_OUT_FM_TX = 0x10000,
- AUDIO_DEVICE_OUT_DIRECTOUTPUT = 0x20000,
- AUDIO_DEVICE_OUT_PROXY = 0x40000,
- AUDIO_DEVICE_OUT_DEFAULT = 0x80000,
- AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE |
- AUDIO_DEVICE_OUT_SPEAKER |
- AUDIO_DEVICE_OUT_WIRED_HEADSET |
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
- AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_FM |
- AUDIO_DEVICE_OUT_ANC_HEADSET |
- AUDIO_DEVICE_OUT_ANC_HEADPHONE |
- AUDIO_DEVICE_OUT_FM_TX |
- AUDIO_DEVICE_OUT_DIRECTOUTPUT |
- AUDIO_DEVICE_OUT_PROXY |
- AUDIO_DEVICE_OUT_DEFAULT),
- AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
- AUDIO_DEVICE_OUT_ALL_SCO = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
- /* input devices */
- AUDIO_DEVICE_IN_COMMUNICATION = 0x100000,
- AUDIO_DEVICE_IN_AMBIENT = 0x200000,
- AUDIO_DEVICE_IN_BUILTIN_MIC = 0x400000,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x800000,
- AUDIO_DEVICE_IN_WIRED_HEADSET = 0x1000000,
- AUDIO_DEVICE_IN_AUX_DIGITAL = 0x2000000,
- AUDIO_DEVICE_IN_VOICE_CALL = 0x4000000,
- AUDIO_DEVICE_IN_BACK_MIC = 0x8000000,
- AUDIO_DEVICE_IN_ANC_HEADSET = 0x10000000,
- AUDIO_DEVICE_IN_FM_RX = 0x20000000,
- AUDIO_DEVICE_IN_FM_RX_A2DP = 0x40000000,
- AUDIO_DEVICE_IN_DEFAULT = 0x80000000,
-
- AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
- AUDIO_DEVICE_IN_AMBIENT |
- AUDIO_DEVICE_IN_BUILTIN_MIC |
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_IN_WIRED_HEADSET |
- AUDIO_DEVICE_IN_AUX_DIGITAL |
- AUDIO_DEVICE_IN_VOICE_CALL |
- AUDIO_DEVICE_IN_BACK_MIC |
- AUDIO_DEVICE_IN_ANC_HEADSET |
- AUDIO_DEVICE_IN_FM_RX |
- AUDIO_DEVICE_IN_FM_RX_A2DP |
- AUDIO_DEVICE_IN_DEFAULT),
- AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
-} audio_devices_t;
-#elif ANDROID_VERSION < 21
-enum {
- AUDIO_DEVICE_NONE = 0x0,
- /* reserved bits */
- AUDIO_DEVICE_BIT_IN = 0x80000000,
- AUDIO_DEVICE_BIT_DEFAULT = 0x40000000,
- /* output devices */
- AUDIO_DEVICE_OUT_EARPIECE = 0x1,
- AUDIO_DEVICE_OUT_SPEAKER = 0x2,
- AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400,
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800,
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000,
- AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000,
- AUDIO_DEVICE_OUT_USB_DEVICE = 0x4000,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 0x8000,
- AUDIO_DEVICE_OUT_ANC_HEADSET = 0x10000,
- AUDIO_DEVICE_OUT_ANC_HEADPHONE = 0x20000,
- AUDIO_DEVICE_OUT_PROXY = 0x40000,
- AUDIO_DEVICE_OUT_FM = 0x80000,
- AUDIO_DEVICE_OUT_FM_TX = 0x100000,
- AUDIO_DEVICE_OUT_DEFAULT = AUDIO_DEVICE_BIT_DEFAULT,
- AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE |
- AUDIO_DEVICE_OUT_SPEAKER |
- AUDIO_DEVICE_OUT_WIRED_HEADSET |
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
- AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_USB_ACCESSORY |
- AUDIO_DEVICE_OUT_USB_DEVICE |
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
- AUDIO_DEVICE_OUT_ANC_HEADSET |
- AUDIO_DEVICE_OUT_ANC_HEADPHONE |
- AUDIO_DEVICE_OUT_PROXY |
- AUDIO_DEVICE_OUT_FM |
- AUDIO_DEVICE_OUT_FM_TX |
- AUDIO_DEVICE_OUT_DEFAULT),
- AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
- AUDIO_DEVICE_OUT_ALL_SCO = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
- AUDIO_DEVICE_OUT_ALL_USB = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
- AUDIO_DEVICE_OUT_USB_DEVICE),
-
- /* input devices */
- AUDIO_DEVICE_IN_COMMUNICATION = AUDIO_DEVICE_BIT_IN | 0x1,
- AUDIO_DEVICE_IN_AMBIENT = AUDIO_DEVICE_BIT_IN | 0x2,
- AUDIO_DEVICE_IN_BUILTIN_MIC = AUDIO_DEVICE_BIT_IN | 0x4,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,
- AUDIO_DEVICE_IN_WIRED_HEADSET = AUDIO_DEVICE_BIT_IN | 0x10,
- AUDIO_DEVICE_IN_AUX_DIGITAL = AUDIO_DEVICE_BIT_IN | 0x20,
- AUDIO_DEVICE_IN_VOICE_CALL = AUDIO_DEVICE_BIT_IN | 0x40,
- AUDIO_DEVICE_IN_BACK_MIC = AUDIO_DEVICE_BIT_IN | 0x80,
- AUDIO_DEVICE_IN_REMOTE_SUBMIX = AUDIO_DEVICE_BIT_IN | 0x100,
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x200,
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x400,
- AUDIO_DEVICE_IN_USB_ACCESSORY = AUDIO_DEVICE_BIT_IN | 0x800,
- AUDIO_DEVICE_IN_USB_DEVICE = AUDIO_DEVICE_BIT_IN | 0x1000,
- AUDIO_DEVICE_IN_ANC_HEADSET = AUDIO_DEVICE_BIT_IN | 0x2000,
- AUDIO_DEVICE_IN_PROXY = AUDIO_DEVICE_BIT_IN | 0x4000,
- AUDIO_DEVICE_IN_FM_RX = AUDIO_DEVICE_BIT_IN | 0x8000,
- AUDIO_DEVICE_IN_FM_RX_A2DP = AUDIO_DEVICE_BIT_IN | 0x10000,
- AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
-
- AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
- AUDIO_DEVICE_IN_AMBIENT |
- AUDIO_DEVICE_IN_BUILTIN_MIC |
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_IN_WIRED_HEADSET |
- AUDIO_DEVICE_IN_AUX_DIGITAL |
- AUDIO_DEVICE_IN_VOICE_CALL |
- AUDIO_DEVICE_IN_BACK_MIC |
- AUDIO_DEVICE_IN_REMOTE_SUBMIX |
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_IN_USB_ACCESSORY |
- AUDIO_DEVICE_IN_USB_DEVICE |
- AUDIO_DEVICE_IN_ANC_HEADSET |
- AUDIO_DEVICE_IN_FM_RX |
- AUDIO_DEVICE_IN_FM_RX_A2DP |
- AUDIO_DEVICE_IN_PROXY |
- AUDIO_DEVICE_IN_DEFAULT),
- AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
-};
-
-typedef uint32_t audio_devices_t;
-#else
-enum {
- AUDIO_DEVICE_NONE = 0x0,
- /* reserved bits */
- AUDIO_DEVICE_BIT_IN = 0x80000000,
- AUDIO_DEVICE_BIT_DEFAULT = 0x40000000,
- /* output devices */
- AUDIO_DEVICE_OUT_EARPIECE = 0x1,
- AUDIO_DEVICE_OUT_SPEAKER = 0x2,
- AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4,
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400,
- AUDIO_DEVICE_OUT_HDMI = AUDIO_DEVICE_OUT_AUX_DIGITAL,
- /* uses an analog connection (multiplexed over the USB connector pins for instance) */
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800,
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000,
- /* USB accessory mode: your Android device is a USB device and the dock is a USB host */
- AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000,
- /* USB host mode: your Android device is a USB host and the dock is a USB device */
- AUDIO_DEVICE_OUT_USB_DEVICE = 0x4000,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 0x8000,
- /* Telephony voice TX path */
- AUDIO_DEVICE_OUT_TELEPHONY_TX = 0x10000,
- /* Analog jack with line impedance detected */
- AUDIO_DEVICE_OUT_LINE = 0x20000,
- /* HDMI Audio Return Channel */
- AUDIO_DEVICE_OUT_HDMI_ARC = 0x40000,
- /* S/PDIF out */
- AUDIO_DEVICE_OUT_SPDIF = 0x80000,
- /* FM transmitter out */
- AUDIO_DEVICE_OUT_FM = 0x100000,
- /* Line out for av devices */
- AUDIO_DEVICE_OUT_AUX_LINE = 0x200000,
- /* limited-output speaker device for acoustic safety */
- AUDIO_DEVICE_OUT_SPEAKER_SAFE = 0x400000,
- AUDIO_DEVICE_OUT_DEFAULT = AUDIO_DEVICE_BIT_DEFAULT,
- AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE |
- AUDIO_DEVICE_OUT_SPEAKER |
- AUDIO_DEVICE_OUT_WIRED_HEADSET |
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
- AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_USB_ACCESSORY |
- AUDIO_DEVICE_OUT_USB_DEVICE |
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
- AUDIO_DEVICE_OUT_TELEPHONY_TX |
- AUDIO_DEVICE_OUT_LINE |
- AUDIO_DEVICE_OUT_HDMI_ARC |
- AUDIO_DEVICE_OUT_SPDIF |
- AUDIO_DEVICE_OUT_FM |
- AUDIO_DEVICE_OUT_AUX_LINE |
- AUDIO_DEVICE_OUT_SPEAKER_SAFE |
- AUDIO_DEVICE_OUT_DEFAULT),
- AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
- AUDIO_DEVICE_OUT_ALL_SCO = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
- AUDIO_DEVICE_OUT_ALL_USB = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
- AUDIO_DEVICE_OUT_USB_DEVICE),
- /* input devices */
- AUDIO_DEVICE_IN_COMMUNICATION = AUDIO_DEVICE_BIT_IN | 0x1,
- AUDIO_DEVICE_IN_AMBIENT = AUDIO_DEVICE_BIT_IN | 0x2,
- AUDIO_DEVICE_IN_BUILTIN_MIC = AUDIO_DEVICE_BIT_IN | 0x4,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,
- AUDIO_DEVICE_IN_WIRED_HEADSET = AUDIO_DEVICE_BIT_IN | 0x10,
- AUDIO_DEVICE_IN_AUX_DIGITAL = AUDIO_DEVICE_BIT_IN | 0x20,
- AUDIO_DEVICE_IN_HDMI = AUDIO_DEVICE_IN_AUX_DIGITAL,
- /* Telephony voice RX path */
- AUDIO_DEVICE_IN_VOICE_CALL = AUDIO_DEVICE_BIT_IN | 0x40,
- AUDIO_DEVICE_IN_BACK_MIC = AUDIO_DEVICE_BIT_IN | 0x80,
- AUDIO_DEVICE_IN_REMOTE_SUBMIX = AUDIO_DEVICE_BIT_IN | 0x100,
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x200,
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x400,
- AUDIO_DEVICE_IN_USB_ACCESSORY = AUDIO_DEVICE_BIT_IN | 0x800,
- AUDIO_DEVICE_IN_USB_DEVICE = AUDIO_DEVICE_BIT_IN | 0x1000,
- /* FM tuner input */
- AUDIO_DEVICE_IN_FM_TUNER = AUDIO_DEVICE_BIT_IN | 0x2000,
- /* TV tuner input */
- AUDIO_DEVICE_IN_TV_TUNER = AUDIO_DEVICE_BIT_IN | 0x4000,
- /* Analog jack with line impedance detected */
- AUDIO_DEVICE_IN_LINE = AUDIO_DEVICE_BIT_IN | 0x8000,
- /* S/PDIF in */
- AUDIO_DEVICE_IN_SPDIF = AUDIO_DEVICE_BIT_IN | 0x10000,
- AUDIO_DEVICE_IN_BLUETOOTH_A2DP = AUDIO_DEVICE_BIT_IN | 0x20000,
- AUDIO_DEVICE_IN_LOOPBACK = AUDIO_DEVICE_BIT_IN | 0x40000,
- AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
- AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
- AUDIO_DEVICE_IN_AMBIENT |
- AUDIO_DEVICE_IN_BUILTIN_MIC |
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
- AUDIO_DEVICE_IN_WIRED_HEADSET |
- AUDIO_DEVICE_IN_AUX_DIGITAL |
- AUDIO_DEVICE_IN_VOICE_CALL |
- AUDIO_DEVICE_IN_BACK_MIC |
- AUDIO_DEVICE_IN_REMOTE_SUBMIX |
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
- AUDIO_DEVICE_IN_USB_ACCESSORY |
- AUDIO_DEVICE_IN_USB_DEVICE |
- AUDIO_DEVICE_IN_FM_TUNER |
- AUDIO_DEVICE_IN_TV_TUNER |
- AUDIO_DEVICE_IN_LINE |
- AUDIO_DEVICE_IN_SPDIF |
- AUDIO_DEVICE_IN_BLUETOOTH_A2DP |
- AUDIO_DEVICE_IN_LOOPBACK |
- AUDIO_DEVICE_IN_DEFAULT),
- AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
- AUDIO_DEVICE_IN_ALL_USB = (AUDIO_DEVICE_IN_USB_ACCESSORY |
- AUDIO_DEVICE_IN_USB_DEVICE),
-};
-
-typedef uint32_t audio_devices_t;
-#endif
-
-static inline bool audio_is_output_device(uint32_t device)
-{
-#if ANDROID_VERSION < 17
- if ((__builtin_popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0))
- return true;
- else
- return false;
-#else
- if (((device & AUDIO_DEVICE_BIT_IN) == 0) &&
- (__builtin_popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0))
- return true;
- else
- return false;
-#endif
-}
-
-/* device connection states used for audio_policy->set_device_connection_state()
- * */
-typedef enum {
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-
- AUDIO_POLICY_DEVICE_STATE_CNT,
- AUDIO_POLICY_DEVICE_STATE_MAX = AUDIO_POLICY_DEVICE_STATE_CNT - 1,
-} audio_policy_dev_state_t;
-
-namespace android {
-
-typedef void (*audio_error_callback)(status_t err);
-typedef int audio_io_handle_t;
-
-class IAudioPolicyService;
-class String8;
-
-class AudioSystem
-{
-public:
-
- enum stream_type {
- DEFAULT =-1,
- VOICE_CALL = 0,
- SYSTEM = 1,
- RING = 2,
- MUSIC = 3,
- ALARM = 4,
- NOTIFICATION = 5,
- BLUETOOTH_SCO = 6,
- ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be routed to speaker
- DTMF = 8,
- TTS = 9,
- FM = 10,
- NUM_STREAM_TYPES
- };
-
- // Audio sub formats (see AudioSystem::audio_format).
- enum pcm_sub_format {
- PCM_SUB_16_BIT = 0x1, // must be 1 for backward compatibility
- PCM_SUB_8_BIT = 0x2, // must be 2 for backward compatibility
- };
-
- // MP3 sub format field definition : can use 11 LSBs in the same way as MP3 frame header to specify
- // bit rate, stereo mode, version...
- enum mp3_sub_format {
- //TODO
- };
-
- // AMR NB/WB sub format field definition: specify frame block interleaving, bandwidth efficient or octet aligned,
- // encoding mode for recording...
- enum amr_sub_format {
- //TODO
- };
-
- // AAC sub format field definition: specify profile or bitrate for recording...
- enum aac_sub_format {
- //TODO
- };
-
- // VORBIS sub format field definition: specify quality for recording...
- enum vorbis_sub_format {
- //TODO
- };
-
- // Audio format consists in a main format field (upper 8 bits) and a sub format field (lower 24 bits).
- // The main format indicates the main codec type. The sub format field indicates options and parameters
- // for each format. The sub format is mainly used for record to indicate for instance the requested bitrate
- // or profile. It can also be used for certain formats to give informations not present in the encoded
- // audio stream (e.g. octet alignement for AMR).
- enum audio_format {
- INVALID_FORMAT = -1,
- FORMAT_DEFAULT = 0,
- PCM = 0x00000000, // must be 0 for backward compatibility
- MP3 = 0x01000000,
- AMR_NB = 0x02000000,
- AMR_WB = 0x03000000,
- AAC = 0x04000000,
- HE_AAC_V1 = 0x05000000,
- HE_AAC_V2 = 0x06000000,
- VORBIS = 0x07000000,
- EVRC = 0x08000000,
- QCELP = 0x09000000,
- VOIP_PCM_INPUT = 0x0A000000,
- MAIN_FORMAT_MASK = 0xFF000000,
- SUB_FORMAT_MASK = 0x00FFFFFF,
- // Aliases
- PCM_16_BIT = (PCM|PCM_SUB_16_BIT),
- PCM_8_BIT = (PCM|PCM_SUB_8_BIT)
- };
-
-
- // Channel mask definitions must be kept in sync with JAVA values in /media/java/android/media/AudioFormat.java
- enum audio_channels {
- // output channels
- CHANNEL_OUT_FRONT_LEFT = 0x4,
- CHANNEL_OUT_FRONT_RIGHT = 0x8,
- CHANNEL_OUT_FRONT_CENTER = 0x10,
- CHANNEL_OUT_LOW_FREQUENCY = 0x20,
- CHANNEL_OUT_BACK_LEFT = 0x40,
- CHANNEL_OUT_BACK_RIGHT = 0x80,
- CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100,
- CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200,
- CHANNEL_OUT_BACK_CENTER = 0x400,
- CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT,
- CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT),
- CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
- CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER),
- CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
- CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
- CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
- CHANNEL_OUT_ALL = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
- CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | CHANNEL_OUT_BACK_CENTER),
-
- // input channels
- CHANNEL_IN_LEFT = 0x4,
- CHANNEL_IN_RIGHT = 0x8,
- CHANNEL_IN_FRONT = 0x10,
- CHANNEL_IN_BACK = 0x20,
- CHANNEL_IN_LEFT_PROCESSED = 0x40,
- CHANNEL_IN_RIGHT_PROCESSED = 0x80,
- CHANNEL_IN_FRONT_PROCESSED = 0x100,
- CHANNEL_IN_BACK_PROCESSED = 0x200,
- CHANNEL_IN_PRESSURE = 0x400,
- CHANNEL_IN_X_AXIS = 0x800,
- CHANNEL_IN_Y_AXIS = 0x1000,
- CHANNEL_IN_Z_AXIS = 0x2000,
- CHANNEL_IN_VOICE_UPLINK = 0x4000,
- CHANNEL_IN_VOICE_DNLINK = 0x8000,
- CHANNEL_IN_MONO = CHANNEL_IN_FRONT,
- CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT),
- CHANNEL_IN_ALL = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK|
- CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED | CHANNEL_IN_FRONT_PROCESSED | CHANNEL_IN_BACK_PROCESSED|
- CHANNEL_IN_PRESSURE | CHANNEL_IN_X_AXIS | CHANNEL_IN_Y_AXIS | CHANNEL_IN_Z_AXIS |
- CHANNEL_IN_VOICE_UPLINK | CHANNEL_IN_VOICE_DNLINK)
- };
-
- enum audio_mode {
- MODE_INVALID = -2,
- MODE_CURRENT = -1,
- MODE_NORMAL = 0,
- MODE_RINGTONE,
- MODE_IN_CALL,
- MODE_IN_COMMUNICATION,
- NUM_MODES // not a valid entry, denotes end-of-list
- };
-
- enum audio_in_acoustics {
- AGC_ENABLE = 0x0001,
- AGC_DISABLE = 0,
- NS_ENABLE = 0x0002,
- NS_DISABLE = 0,
- TX_IIR_ENABLE = 0x0004,
- TX_DISABLE = 0
- };
-
- // special audio session values
- enum audio_sessions {
- SESSION_OUTPUT_STAGE = -1, // session for effects attached to a particular output stream
- // (value must be less than 0)
- SESSION_OUTPUT_MIX = 0, // session for effects applied to output mix. These effects can
- // be moved by audio policy manager to another output stream
- // (value must be 0)
- };
-
- /* These are static methods to control the system-wide AudioFlinger
- * only privileged processes can have access to them
- */
-
- // mute/unmute microphone
- static status_t muteMicrophone(bool state);
- static status_t isMicrophoneMuted(bool *state);
-
- // set/get master volume
- static status_t setMasterVolume(float value);
- static status_t getMasterVolume(float* volume);
- // mute/unmute audio outputs
- static status_t setMasterMute(bool mute);
- static status_t getMasterMute(bool* mute);
-
- // set/get stream volume on specified output
- static status_t setStreamVolume(int stream, float value, int output);
- static status_t getStreamVolume(int stream, float* volume, int output);
-
- // mute/unmute stream
- static status_t setStreamMute(int stream, bool mute);
- static status_t getStreamMute(int stream, bool* mute);
-
- // set audio mode in audio hardware (see AudioSystem::audio_mode)
- static status_t setMode(int mode);
-
- // returns true in *state if tracks are active on the specified stream
- static status_t isStreamActive(int stream, bool *state);
-
- // set/get audio hardware parameters. The function accepts a list of parameters
- // key value pairs in the form: key1=value1;key2=value2;...
- // Some keys are reserved for standard parameters (See AudioParameter class).
- static status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
- static String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
-
- static void setErrorCallback(audio_error_callback cb);
-
- // helper function to obtain AudioFlinger service handle
- static const sp<IAudioFlinger>& get_audio_flinger();
-
- static float linearToLog(int volume);
- static int logToLinear(float volume);
-
- static status_t getOutputSamplingRate(int* samplingRate, int stream = DEFAULT);
- static status_t getOutputFrameCount(int* frameCount, int stream = DEFAULT);
- static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT);
-
- static bool routedToA2dpOutput(int streamType);
-
- static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
- size_t* buffSize);
-
- static status_t setVoiceVolume(float volume);
-
- // return the number of audio frames written by AudioFlinger to audio HAL and
- // audio dsp to DAC since the output on which the specificed stream is playing
- // has exited standby.
- // returned status (from utils/Errors.h) can be:
- // - NO_ERROR: successful operation, halFrames and dspFrames point to valid data
- // - INVALID_OPERATION: Not supported on current hardware platform
- // - BAD_VALUE: invalid parameter
- // NOTE: this feature is not supported on all hardware platforms and it is
- // necessary to check returned status before using the returned values.
- static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = DEFAULT);
-
- static unsigned int getInputFramesLost(audio_io_handle_t ioHandle);
-
- static int newAudioSessionId();
- //
- // AudioPolicyService interface
- //
-
- enum audio_devices {
- // output devices
- DEVICE_OUT_EARPIECE = 0x1,
- DEVICE_OUT_SPEAKER = 0x2,
- DEVICE_OUT_WIRED_HEADSET = 0x4,
- DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- DEVICE_OUT_AUX_DIGITAL = 0x400,
- DEVICE_OUT_DEFAULT = 0x8000,
- DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET |
- DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- DEVICE_OUT_BLUETOOTH_SCO_CARKIT | DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_DEFAULT),
- DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-
- // input devices
- DEVICE_IN_COMMUNICATION = 0x10000,
- DEVICE_IN_AMBIENT = 0x20000,
- DEVICE_IN_BUILTIN_MIC = 0x40000,
- DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000,
- DEVICE_IN_WIRED_HEADSET = 0x100000,
- DEVICE_IN_AUX_DIGITAL = 0x200000,
- DEVICE_IN_VOICE_CALL = 0x400000,
- DEVICE_IN_BACK_MIC = 0x800000,
- DEVICE_IN_DEFAULT = 0x80000000,
-
- DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | DEVICE_IN_BUILTIN_MIC |
- DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | DEVICE_IN_AUX_DIGITAL |
- DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC | DEVICE_IN_DEFAULT)
- };
-
- // device connection states used for setDeviceConnectionState()
- enum device_connection_state {
- DEVICE_STATE_UNAVAILABLE,
- DEVICE_STATE_AVAILABLE,
- NUM_DEVICE_STATES
- };
-
- // request to open a direct output with getOutput() (by opposition to sharing an output with other AudioTracks)
- enum output_flags {
- OUTPUT_FLAG_INDIRECT = 0x0,
- OUTPUT_FLAG_DIRECT = 0x1
- };
-
- // device categories used for setForceUse()
- enum forced_config {
- FORCE_NONE,
- FORCE_SPEAKER,
- FORCE_HEADPHONES,
- FORCE_BT_SCO,
- FORCE_BT_A2DP,
- FORCE_WIRED_ACCESSORY,
- FORCE_BT_CAR_DOCK,
- FORCE_BT_DESK_DOCK,
- FORCE_ANALOG_DOCK,
- FORCE_DIGITAL_DOCK,
- FORCE_NO_BT_A2DP,
- NUM_FORCE_CONFIG,
- FORCE_DEFAULT = FORCE_NONE
- };
-
- // usages used for setForceUse()
- enum force_use {
- FOR_COMMUNICATION,
- FOR_MEDIA,
- FOR_RECORD,
- FOR_DOCK,
- NUM_FORCE_USE
- };
-
- // types of io configuration change events received with ioConfigChanged()
- enum io_config_event {
- OUTPUT_OPENED,
- OUTPUT_CLOSED,
- OUTPUT_CONFIG_CHANGED,
- INPUT_OPENED,
- INPUT_CLOSED,
- INPUT_CONFIG_CHANGED,
- STREAM_CONFIG_CHANGED,
- NUM_CONFIG_EVENTS
- };
-
- // audio output descritor used to cache output configurations in client process to avoid frequent calls
- // through IAudioFlinger
- class OutputDescriptor {
- public:
- OutputDescriptor()
- : samplingRate(0), format(0), channels(0), frameCount(0), latency(0) {}
-
- uint32_t samplingRate;
- int32_t format;
- int32_t channels;
- size_t frameCount;
- uint32_t latency;
- };
-
- //
- // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
- //
- static status_t setDeviceConnectionState(audio_devices device, device_connection_state state, const char *device_address);
- static device_connection_state getDeviceConnectionState(audio_devices device, const char *device_address);
- static status_t setPhoneState(int state);
-#if ANDROID_VERSION >= 17
- static status_t setPhoneState(audio_mode_t state);
-#endif
- static status_t setRingerMode(uint32_t mode, uint32_t mask);
-#ifdef VANILLA_ANDROID
- static status_t setForceUse(force_use usage, forced_config config);
- static forced_config getForceUse(force_use usage);
- static audio_io_handle_t getOutput(stream_type stream,
- uint32_t samplingRate = 0,
- uint32_t format = FORMAT_DEFAULT,
- uint32_t channels = CHANNEL_OUT_STEREO,
- output_flags flags = OUTPUT_FLAG_INDIRECT);
- static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address);
- static status_t setFmVolume(float volume);
- static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address);
-#else
- static status_t setForceUse(force_use usage, forced_config config) __attribute__((weak));
- static forced_config getForceUse(force_use usage) __attribute__((weak));
- static audio_io_handle_t getOutput(stream_type stream,
- uint32_t samplingRate = 0,
- uint32_t format = FORMAT_DEFAULT,
- uint32_t channels = CHANNEL_OUT_STEREO,
- output_flags flags = OUTPUT_FLAG_INDIRECT) __attribute__((weak));
-
- static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) __attribute__((weak));
- static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) __attribute__((weak));
- static audio_io_handle_t getOutput(audio_stream_type_t stream,
- uint32_t samplingRate = 0,
- uint32_t format = AUDIO_FORMAT_DEFAULT,
- uint32_t channels = AUDIO_CHANNEL_OUT_STEREO,
- audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_INDIRECT) __attribute__((weak));
- static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address) __attribute__((weak));
- static status_t setFmVolume(float volume) __attribute__((weak));
- static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address) __attribute__((weak));
-
-#endif
- static status_t startOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
- int session = 0);
- static status_t stopOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
- int session = 0);
- static void releaseOutput(audio_io_handle_t output);
- static audio_io_handle_t getInput(int inputSource,
- uint32_t samplingRate = 0,
- uint32_t format = FORMAT_DEFAULT,
- uint32_t channels = CHANNEL_IN_MONO,
- audio_in_acoustics acoustics = (audio_in_acoustics)0);
- static status_t startInput(audio_io_handle_t input);
- static status_t stopInput(audio_io_handle_t input);
- static void releaseInput(audio_io_handle_t input);
- static status_t initStreamVolume(stream_type stream,
- int indexMin,
- int indexMax);
- static status_t initStreamVolume(audio_stream_type_t stream,
- int indexMin,
- int indexMax);
- static status_t setStreamVolumeIndex(stream_type stream, int index);
- static status_t setStreamVolumeIndex(audio_stream_type_t stream, int index);
-#if ANDROID_VERSION >= 17
- static status_t setStreamVolumeIndex(audio_stream_type_t stream,
- int index,
- audio_devices_t device);
- static status_t getStreamVolumeIndex(audio_stream_type_t stream,
- int *index,
- audio_devices_t device);
-#endif
- static status_t getStreamVolumeIndex(stream_type stream, int *index);
- static status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index);
-
- static uint32_t getStrategyForStream(stream_type stream);
-#if ANDROID_VERSION >= 17
- static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
-#endif
-
- static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
- static status_t registerEffect(effect_descriptor_t *desc,
- audio_io_handle_t output,
- uint32_t strategy,
- int session,
- int id);
- static status_t unregisterEffect(int id);
-
- static const sp<IAudioPolicyService>& get_audio_policy_service();
-
- // ----------------------------------------------------------------------------
-
- static uint32_t popCount(uint32_t u);
- static bool isOutputDevice(audio_devices device);
- static bool isInputDevice(audio_devices device);
- static bool isA2dpDevice(audio_devices device);
- static bool isBluetoothScoDevice(audio_devices device);
- static bool isSeperatedStream(stream_type stream);
- static bool isLowVisibility(stream_type stream);
- static bool isOutputChannel(uint32_t channel);
- static bool isInputChannel(uint32_t channel);
- static bool isValidFormat(uint32_t format);
- static bool isLinearPCM(uint32_t format);
- static bool isModeInCall();
-
-#if ANDROID_VERSION >= 21
- class AudioPortCallback : public RefBase
- {
- public:
-
- AudioPortCallback() {}
- virtual ~AudioPortCallback() {}
-
- virtual void onAudioPortListUpdate() = 0;
- virtual void onAudioPatchListUpdate() = 0;
- virtual void onServiceDied() = 0;
-
- };
-
- static void setAudioPortCallback(sp<AudioPortCallback> callBack);
-#endif
-
-private:
-
- class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
- {
- public:
- AudioFlingerClient() {
- }
-
- // DeathRecipient
- virtual void binderDied(const wp<IBinder>& who);
-
- // IAudioFlingerClient
-
- // indicate a change in the configuration of an output or input: keeps the cached
- // values for output/input parameters upto date in client process
- virtual void ioConfigChanged(int event, int ioHandle, void *param2);
- };
-
- class AudioPolicyServiceClient: public IBinder::DeathRecipient
- {
- public:
- AudioPolicyServiceClient() {
- }
-
- // DeathRecipient
- virtual void binderDied(const wp<IBinder>& who);
- };
-
- static sp<AudioFlingerClient> gAudioFlingerClient;
- static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient;
- friend class AudioFlingerClient;
- friend class AudioPolicyServiceClient;
-
- static Mutex gLock;
- static sp<IAudioFlinger> gAudioFlinger;
- static audio_error_callback gAudioErrorCallback;
-
- static size_t gInBuffSize;
- // previous parameters for recording buffer size queries
- static uint32_t gPrevInSamplingRate;
- static int gPrevInFormat;
- static int gPrevInChannelCount;
-
- static sp<IAudioPolicyService> gAudioPolicyService;
-
- // mapping between stream types and outputs
- static DefaultKeyedVector<int, audio_io_handle_t> gStreamOutputMap;
- // list of output descritor containing cached parameters (sampling rate, framecount, channel count...)
- static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
-};
-
-class AudioParameter {
-
-public:
- AudioParameter() {}
- AudioParameter(const String8& keyValuePairs);
- virtual ~AudioParameter();
-
- // reserved parameter keys for changing standard parameters with setParameters() function.
- // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
- // configuration changes and act accordingly.
- // keyRouting: to change audio routing, value is an int in AudioSystem::audio_devices
- // keySamplingRate: to change sampling rate routing, value is an int
- // keyFormat: to change audio format, value is an int in AudioSystem::audio_format
- // keyChannels: to change audio channel configuration, value is an int in AudioSystem::audio_channels
- // keyFrameCount: to change audio output frame count, value is an int
- // keyInputSource: to change audio input source, value is an int in audio_source
- // (defined in media/mediarecorder.h)
- static const char *keyRouting;
- static const char *keySamplingRate;
- static const char *keyFormat;
- static const char *keyChannels;
- static const char *keyFrameCount;
- static const char *keyInputSource;
-
- String8 toString();
-
- status_t add(const String8& key, const String8& value);
- status_t addInt(const String8& key, const int value);
- status_t addFloat(const String8& key, const float value);
-
- status_t remove(const String8& key);
-
- status_t get(const String8& key, String8& value);
- status_t getInt(const String8& key, int& value);
- status_t getFloat(const String8& key, float& value);
- status_t getAt(size_t index, String8& key, String8& value);
-
- size_t size() { return mParameters.size(); }
-
-private:
- String8 mKeyValuePairs;
- KeyedVector <String8, String8> mParameters;
-};
-
-}; // namespace android
-
-#pragma GCC visibility pop
-
-#endif /*ANDROID_AUDIOSYSTEM_H_*/
diff --git a/dom/system/gonk/android_audio/AudioTrack.h b/dom/system/gonk/android_audio/AudioTrack.h
deleted file mode 100644
index 6f8c6bb28..000000000
--- a/dom/system/gonk/android_audio/AudioTrack.h
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef ANDROID_AUDIOTRACK_H
-#define ANDROID_AUDIOTRACK_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "IAudioFlinger.h"
-#include "IAudioTrack.h"
-#include "AudioSystem.h"
-
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-#include <utils/threads.h>
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class audio_track_cblk_t;
-
-// ----------------------------------------------------------------------------
-
-class AudioTrack
-{
-public:
- enum channel_index {
- MONO = 0,
- LEFT = 0,
- RIGHT = 1
- };
-
- /* Events used by AudioTrack callback function (audio_track_cblk_t).
- */
- enum event_type {
- EVENT_MORE_DATA = 0, // Request to write more data to PCM buffer.
- EVENT_UNDERRUN = 1, // PCM buffer underrun occured.
- EVENT_LOOP_END = 2, // Sample loop end was reached; playback restarted from loop start if loop count was not 0.
- EVENT_MARKER = 3, // Playback head is at the specified marker position (See setMarkerPosition()).
- EVENT_NEW_POS = 4, // Playback head is at a new position (See setPositionUpdatePeriod()).
- EVENT_BUFFER_END = 5 // Playback head is at the end of the buffer.
- };
-
- /* Create Buffer on the stack and pass it to obtainBuffer()
- * and releaseBuffer().
- */
-
- class Buffer
- {
- public:
- enum {
- MUTE = 0x00000001
- };
- uint32_t flags;
- int channelCount;
- int format;
- size_t frameCount;
- size_t size;
- union {
- void* raw;
- short* i16;
- int8_t* i8;
- };
- };
-
-
- /* As a convenience, if a callback is supplied, a handler thread
- * is automatically created with the appropriate priority. This thread
- * invokes the callback when a new buffer becomes availlable or an underrun condition occurs.
- * Parameters:
- *
- * event: type of event notified (see enum AudioTrack::event_type).
- * user: Pointer to context for use by the callback receiver.
- * info: Pointer to optional parameter according to event type:
- * - EVENT_MORE_DATA: pointer to AudioTrack::Buffer struct. The callback must not write
- * more bytes than indicated by 'size' field and update 'size' if less bytes are
- * written.
- * - EVENT_UNDERRUN: unused.
- * - EVENT_LOOP_END: pointer to an int indicating the number of loops remaining.
- * - EVENT_MARKER: pointer to an uin32_t containing the marker position in frames.
- * - EVENT_NEW_POS: pointer to an uin32_t containing the new position in frames.
- * - EVENT_BUFFER_END: unused.
- */
-
- typedef void (*callback_t)(int event, void* user, void *info);
-
- /* Returns the minimum frame count required for the successful creation of
- * an AudioTrack object.
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - NO_INIT: audio server or audio hardware not initialized
- */
-
- static status_t getMinFrameCount(int* frameCount,
- int streamType =-1,
- uint32_t sampleRate = 0);
-
- /* Constructs an uninitialized AudioTrack. No connection with
- * AudioFlinger takes place.
- */
- AudioTrack();
-
- /* Creates an audio track and registers it with AudioFlinger.
- * Once created, the track needs to be started before it can be used.
- * Unspecified values are set to the audio hardware's current
- * values.
- *
- * Parameters:
- *
- * streamType: Select the type of audio stream this track is attached to
- * (e.g. AudioSystem::MUSIC).
- * sampleRate: Track sampling rate in Hz.
- * format: Audio format (e.g AudioSystem::PCM_16_BIT for signed
- * 16 bits per sample).
- * channels: Channel mask: see AudioSystem::audio_channels.
- * frameCount: Total size of track PCM buffer in frames. This defines the
- * latency of the track.
- * flags: Reserved for future use.
- * cbf: Callback function. If not null, this function is called periodically
- * to request new PCM data.
- * notificationFrames: The callback function is called each time notificationFrames PCM
- * frames have been comsumed from track input buffer.
- * user Context for use by the callback receiver.
- */
-
- AudioTrack( int streamType,
- uint32_t sampleRate = 0,
- int format = 0,
- int channels = 0,
- int frameCount = 0,
- uint32_t flags = 0,
- callback_t cbf = 0,
- void* user = 0,
- int notificationFrames = 0,
- int sessionId = 0);
-
- /* Creates an audio track and registers it with AudioFlinger. With this constructor,
- * The PCM data to be rendered by AudioTrack is passed in a shared memory buffer
- * identified by the argument sharedBuffer. This prototype is for static buffer playback.
- * PCM data must be present into memory before the AudioTrack is started.
- * The Write() and Flush() methods are not supported in this case.
- * It is recommented to pass a callback function to be notified of playback end by an
- * EVENT_UNDERRUN event.
- */
-
- AudioTrack( int streamType,
- uint32_t sampleRate = 0,
- int format = 0,
- int channels = 0,
- const sp<IMemory>& sharedBuffer = 0,
- uint32_t flags = 0,
- callback_t cbf = 0,
- void* user = 0,
- int notificationFrames = 0,
- int sessionId = 0);
-
- /* Terminates the AudioTrack and unregisters it from AudioFlinger.
- * Also destroys all resources assotiated with the AudioTrack.
- */
- ~AudioTrack();
-
-
- /* Initialize an uninitialized AudioTrack.
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful intialization
- * - INVALID_OPERATION: AudioTrack is already intitialized
- * - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
- * - NO_INIT: audio server or audio hardware not initialized
- * */
- status_t set(int streamType =-1,
- uint32_t sampleRate = 0,
- int format = 0,
- int channels = 0,
- int frameCount = 0,
- uint32_t flags = 0,
- callback_t cbf = 0,
- void* user = 0,
- int notificationFrames = 0,
- const sp<IMemory>& sharedBuffer = 0,
- bool threadCanCallJava = false,
- int sessionId = 0);
-
-
- /* Result of constructing the AudioTrack. This must be checked
- * before using any AudioTrack API (except for set()), using
- * an uninitialized AudioTrack produces undefined results.
- * See set() method above for possible return codes.
- */
- status_t initCheck() const;
-
- /* Returns this track's latency in milliseconds.
- * This includes the latency due to AudioTrack buffer size, AudioMixer (if any)
- * and audio hardware driver.
- */
- uint32_t latency() const;
-
- /* getters, see constructor */
-
- int streamType() const;
- int format() const;
- int channelCount() const;
- uint32_t frameCount() const;
- int frameSize() const;
- sp<IMemory>& sharedBuffer();
-
-
- /* After it's created the track is not active. Call start() to
- * make it active. If set, the callback will start being called.
- */
- void start();
-
- /* Stop a track. If set, the callback will cease being called and
- * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
- * and will fill up buffers until the pool is exhausted.
- */
- void stop();
- bool stopped() const;
-
- /* flush a stopped track. All pending buffers are discarded.
- * This function has no effect if the track is not stoped.
- */
- void flush();
-
- /* Pause a track. If set, the callback will cease being called and
- * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
- * and will fill up buffers until the pool is exhausted.
- */
- void pause();
-
- /* mute or unmutes this track.
- * While mutted, the callback, if set, is still called.
- */
- void mute(bool);
- bool muted() const;
-
-
- /* set volume for this track, mostly used for games' sound effects
- * left and right volumes. Levels must be <= 1.0.
- */
- status_t setVolume(float left, float right);
- void getVolume(float* left, float* right);
-
- /* set the send level for this track. An auxiliary effect should be attached
- * to the track with attachEffect(). Level must be <= 1.0.
- */
- status_t setAuxEffectSendLevel(float level);
- void getAuxEffectSendLevel(float* level);
-
- /* set sample rate for this track, mostly used for games' sound effects
- */
- status_t setSampleRate(int sampleRate);
- uint32_t getSampleRate();
-
- /* Enables looping and sets the start and end points of looping.
- *
- * Parameters:
- *
- * loopStart: loop start expressed as the number of PCM frames played since AudioTrack start.
- * loopEnd: loop end expressed as the number of PCM frames played since AudioTrack start.
- * loopCount: number of loops to execute. Calling setLoop() with loopCount == 0 cancels any pending or
- * active loop. loopCount = -1 means infinite looping.
- *
- * For proper operation the following condition must be respected:
- * (loopEnd-loopStart) <= framecount()
- */
- status_t setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount);
- status_t getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount);
-
-
- /* Sets marker position. When playback reaches the number of frames specified, a callback with event
- * type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker notification
- * callback.
- * If the AudioTrack has been opened with no callback function associated, the operation will fail.
- *
- * Parameters:
- *
- * marker: marker position expressed in frames.
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the AudioTrack has no callback installed.
- */
- status_t setMarkerPosition(uint32_t marker);
- status_t getMarkerPosition(uint32_t *marker);
-
-
- /* Sets position update period. Every time the number of frames specified has been played,
- * a callback with event type EVENT_NEW_POS is called.
- * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
- * callback.
- * If the AudioTrack has been opened with no callback function associated, the operation will fail.
- *
- * Parameters:
- *
- * updatePeriod: position update notification period expressed in frames.
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the AudioTrack has no callback installed.
- */
- status_t setPositionUpdatePeriod(uint32_t updatePeriod);
- status_t getPositionUpdatePeriod(uint32_t *updatePeriod);
-
-
- /* Sets playback head position within AudioTrack buffer. The new position is specified
- * in number of frames.
- * This method must be called with the AudioTrack in paused or stopped state.
- * Note that the actual position set is <position> modulo the AudioTrack buffer size in frames.
- * Therefore using this method makes sense only when playing a "static" audio buffer
- * as opposed to streaming.
- * The getPosition() method on the other hand returns the total number of frames played since
- * playback start.
- *
- * Parameters:
- *
- * position: New playback head position within AudioTrack buffer.
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the AudioTrack is not stopped.
- * - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack buffer
- */
- status_t setPosition(uint32_t position);
- status_t getPosition(uint32_t *position);
-
- /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids
- * rewriting the buffer before restarting playback after a stop.
- * This method must be called with the AudioTrack in paused or stopped state.
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the AudioTrack is not stopped.
- */
- status_t reload();
-
- /* returns a handle on the audio output used by this AudioTrack.
- *
- * Parameters:
- * none.
- *
- * Returned value:
- * handle on audio hardware output
- */
- audio_io_handle_t getOutput();
-
- /* returns the unique ID associated to this track.
- *
- * Parameters:
- * none.
- *
- * Returned value:
- * AudioTrack ID.
- */
- int getSessionId();
-
-
- /* Attach track auxiliary output to specified effect. Used effectId = 0
- * to detach track from effect.
- *
- * Parameters:
- *
- * effectId: effectId obtained from AudioEffect::id().
- *
- * Returned status (from utils/Errors.h) can be:
- * - NO_ERROR: successful operation
- * - INVALID_OPERATION: the effect is not an auxiliary effect.
- * - BAD_VALUE: The specified effect ID is invalid
- */
- status_t attachAuxEffect(int effectId);
-
- /* obtains a buffer of "frameCount" frames. The buffer must be
- * filled entirely. If the track is stopped, obtainBuffer() returns
- * STOPPED instead of NO_ERROR as long as there are buffers availlable,
- * at which point NO_MORE_BUFFERS is returned.
- * Buffers will be returned until the pool (buffercount())
- * is exhausted, at which point obtainBuffer() will either block
- * or return WOULD_BLOCK depending on the value of the "blocking"
- * parameter.
- */
-
- enum {
- NO_MORE_BUFFERS = 0x80000001,
- STOPPED = 1
- };
-
- status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
- void releaseBuffer(Buffer* audioBuffer);
-
-
- /* As a convenience we provide a write() interface to the audio buffer.
- * This is implemented on top of lockBuffer/unlockBuffer. For best
- * performance
- *
- */
- ssize_t write(const void* buffer, size_t size);
-
- /*
- * Dumps the state of an audio track.
- */
- status_t dump(int fd, const Vector<String16>& args) const;
-
-private:
- /* copying audio tracks is not allowed */
- AudioTrack(const AudioTrack& other);
- AudioTrack& operator = (const AudioTrack& other);
-
- /* a small internal class to handle the callback */
- class AudioTrackThread : public Thread
- {
- public:
- AudioTrackThread(AudioTrack& receiver, bool bCanCallJava = false);
- private:
- friend class AudioTrack;
- virtual bool threadLoop();
- virtual status_t readyToRun();
- virtual void onFirstRef();
- AudioTrack& mReceiver;
- Mutex mLock;
- };
-
- bool processAudioBuffer(const sp<AudioTrackThread>& thread);
- status_t createTrack(int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- const sp<IMemory>& sharedBuffer,
- audio_io_handle_t output,
- bool enforceFrameCount);
-
- sp<IAudioTrack> mAudioTrack;
- sp<IMemory> mCblkMemory;
- sp<AudioTrackThread> mAudioTrackThread;
-
- float mVolume[2];
- float mSendLevel;
- uint32_t mFrameCount;
-
- audio_track_cblk_t* mCblk;
- uint8_t mStreamType;
- uint8_t mFormat;
- uint8_t mChannelCount;
- uint8_t mMuted;
- uint32_t mChannels;
- status_t mStatus;
- uint32_t mLatency;
-
- volatile int32_t mActive;
-
- callback_t mCbf;
- void* mUserData;
- uint32_t mNotificationFramesReq; // requested number of frames between each notification callback
- uint32_t mNotificationFramesAct; // actual number of frames between each notification callback
- sp<IMemory> mSharedBuffer;
- int mLoopCount;
- uint32_t mRemainingFrames;
- uint32_t mMarkerPosition;
- bool mMarkerReached;
- uint32_t mNewPosition;
- uint32_t mUpdatePeriod;
- uint32_t mFlags;
- int mSessionId;
- int mAuxEffectId;
- uint32_t mPadding[8];
-};
-
-
-}; // namespace android
-
-#endif // ANDROID_AUDIOTRACK_H
diff --git a/dom/system/gonk/android_audio/EffectApi.h b/dom/system/gonk/android_audio/EffectApi.h
deleted file mode 100644
index 729545d0c..000000000
--- a/dom/system/gonk/android_audio/EffectApi.h
+++ /dev/null
@@ -1,798 +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 ANDROID_EFFECTAPI_H_
-#define ANDROID_EFFECTAPI_H_
-
-#include <errno.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-/////////////////////////////////////////////////
-// Effect control interface
-/////////////////////////////////////////////////
-
-// The effect control interface is exposed by each effect engine implementation. It consists of
-// a set of functions controlling the configuration, activation and process of the engine.
-// The functions are grouped in a structure of type effect_interface_s:
-// struct effect_interface_s {
-// effect_process_t process;
-// effect_command_t command;
-// };
-
-
-// effect_interface_t: Effect control interface handle.
-// The effect_interface_t serves two purposes regarding the implementation of the effect engine:
-// - 1 it is the address of a pointer to an effect_interface_s structure where the functions
-// of the effect control API for a particular effect are located.
-// - 2 it is the address of the context of a particular effect instance.
-// A typical implementation in the effect library would define a structure as follows:
-// struct effect_module_s {
-// const struct effect_interface_s *itfe;
-// effect_config_t config;
-// effect_context_t context;
-// }
-// The implementation of EffectCreate() function would then allocate a structure of this
-// type and return its address as effect_interface_t
-typedef struct effect_interface_s **effect_interface_t;
-
-
-// Effect API version 1.0
-#define EFFECT_API_VERSION 0x0100 // Format 0xMMmm MM: Major version, mm: minor version
-
-// Maximum length of character strings in structures defines by this API.
-#define EFFECT_STRING_LEN_MAX 64
-
-//
-//--- Effect descriptor structure effect_descriptor_t
-//
-
-// Unique effect ID (can be generated from the following site:
-// http://www.itu.int/ITU-T/asn1/uuid.html)
-// This format is used for both "type" and "uuid" fields of the effect descriptor structure.
-// - When used for effect type and the engine is implementing and effect corresponding to a standard
-// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface.
-// - When used as uuid, it should be a unique UUID for this particular implementation.
-typedef struct effect_uuid_s {
- uint32_t timeLow;
- uint16_t timeMid;
- uint16_t timeHiAndVersion;
- uint16_t clockSeq;
- uint8_t node[6];
-} effect_uuid_t;
-
-// NULL UUID definition (matches SL_IID_NULL_)
-#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \
- { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } }
-static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER;
-const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_;
-const char * const EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210";
-
-// The effect descriptor contains necessary information to facilitate the enumeration of the effect
-// engines present in a library.
-typedef struct effect_descriptor_s {
- effect_uuid_t type; // UUID of to the OpenSL ES interface implemented by this effect
- effect_uuid_t uuid; // UUID for this particular implementation
- uint16_t apiVersion; // Version of the effect API implemented: matches EFFECT_API_VERSION
- uint32_t flags; // effect engine capabilities/requirements flags (see below)
- uint16_t cpuLoad; // CPU load indication (see below)
- uint16_t memoryUsage; // Data Memory usage (see below)
- char name[EFFECT_STRING_LEN_MAX]; // human readable effect name
- char implementor[EFFECT_STRING_LEN_MAX]; // human readable effect implementor name
-} effect_descriptor_t;
-
-// CPU load and memory usage indication: each effect implementation must provide an indication of
-// its CPU and memory usage for the audio effect framework to limit the number of effects
-// instantiated at a given time on a given platform.
-// The CPU load is expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) with 0 WS.
-// The memory usage is expressed in KB and includes only dynamically allocated memory
-
-// Definitions for flags field of effect descriptor.
-// +---------------------------+-----------+-----------------------------------
-// | description | bits | values
-// +---------------------------+-----------+-----------------------------------
-// | connection mode | 0..1 | 0 insert: after track process
-// | | | 1 auxiliary: connect to track auxiliary
-// | | | output and use send level
-// | | | 2 replace: replaces track process function;
-// | | | must implement SRC, volume and mono to stereo.
-// | | | 3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | insertion preference | 2..4 | 0 none
-// | | | 1 first of the chain
-// | | | 2 last of the chain
-// | | | 3 exclusive (only effect in the insert chain)
-// | | | 4..7 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Volume management | 5..6 | 0 none
-// | | | 1 implements volume control
-// | | | 2 requires volume indication
-// | | | 3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Device indication | 7..8 | 0 none
-// | | | 1 requires device updates
-// | | | 2..3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Sample input mode | 9..10 | 0 direct: process() function or EFFECT_CMD_CONFIGURE
-// | | | command must specify a buffer descriptor
-// | | | 1 provider: process() function uses the
-// | | | bufferProvider indicated by the
-// | | | EFFECT_CMD_CONFIGURE command to request input.
-// | | | buffers.
-// | | | 2 both: both input modes are supported
-// | | | 3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Sample output mode | 11..12 | 0 direct: process() function or EFFECT_CMD_CONFIGURE
-// | | | command must specify a buffer descriptor
-// | | | 1 provider: process() function uses the
-// | | | bufferProvider indicated by the
-// | | | EFFECT_CMD_CONFIGURE command to request output
-// | | | buffers.
-// | | | 2 both: both output modes are supported
-// | | | 3 reserved
-// +---------------------------+-----------+-----------------------------------
-// | Hardware acceleration | 13..15 | 0 No hardware acceleration
-// | | | 1 non tunneled hw acceleration: the process() function
-// | | | reads the samples, send them to HW accelerated
-// | | | effect processor, reads back the processed samples
-// | | | and returns them to the output buffer.
-// | | | 2 tunneled hw acceleration: the process() function is
-// | | | transparent. The effect interface is only used to
-// | | | control the effect engine. This mode is relevant for
-// | | | global effects actually applied by the audio
-// | | | hardware on the output stream.
-// +---------------------------+-----------+-----------------------------------
-// | Audio Mode indication | 16..17 | 0 none
-// | | | 1 requires audio mode updates
-// | | | 2..3 reserved
-// +---------------------------+-----------+-----------------------------------
-
-// Insert mode
-#define EFFECT_FLAG_TYPE_MASK 0x00000003
-#define EFFECT_FLAG_TYPE_INSERT 0x00000000
-#define EFFECT_FLAG_TYPE_AUXILIARY 0x00000001
-#define EFFECT_FLAG_TYPE_REPLACE 0x00000002
-
-// Insert preference
-#define EFFECT_FLAG_INSERT_MASK 0x0000001C
-#define EFFECT_FLAG_INSERT_ANY 0x00000000
-#define EFFECT_FLAG_INSERT_FIRST 0x00000004
-#define EFFECT_FLAG_INSERT_LAST 0x00000008
-#define EFFECT_FLAG_INSERT_EXCLUSIVE 0x0000000C
-
-
-// Volume control
-#define EFFECT_FLAG_VOLUME_MASK 0x00000060
-#define EFFECT_FLAG_VOLUME_CTRL 0x00000020
-#define EFFECT_FLAG_VOLUME_IND 0x00000040
-#define EFFECT_FLAG_VOLUME_NONE 0x00000000
-
-// Device indication
-#define EFFECT_FLAG_DEVICE_MASK 0x00000180
-#define EFFECT_FLAG_DEVICE_IND 0x00000080
-#define EFFECT_FLAG_DEVICE_NONE 0x00000000
-
-// Sample input modes
-#define EFFECT_FLAG_INPUT_MASK 0x00000600
-#define EFFECT_FLAG_INPUT_DIRECT 0x00000000
-#define EFFECT_FLAG_INPUT_PROVIDER 0x00000200
-#define EFFECT_FLAG_INPUT_BOTH 0x00000400
-
-// Sample output modes
-#define EFFECT_FLAG_OUTPUT_MASK 0x00001800
-#define EFFECT_FLAG_OUTPUT_DIRECT 0x00000000
-#define EFFECT_FLAG_OUTPUT_PROVIDER 0x00000800
-#define EFFECT_FLAG_OUTPUT_BOTH 0x00001000
-
-// Hardware acceleration mode
-#define EFFECT_FLAG_HW_ACC_MASK 0x00006000
-#define EFFECT_FLAG_HW_ACC_SIMPLE 0x00002000
-#define EFFECT_FLAG_HW_ACC_TUNNEL 0x00004000
-
-// Audio mode indication
-#define EFFECT_FLAG_AUDIO_MODE_MASK 0x00018000
-#define EFFECT_FLAG_AUDIO_MODE_IND 0x00008000
-#define EFFECT_FLAG_AUDIO_MODE_NONE 0x00000000
-
-// Forward definition of type audio_buffer_t
-typedef struct audio_buffer_s audio_buffer_t;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: process
-//
-// Description: Effect process function. Takes input samples as specified
-// (count and location) in input buffer descriptor and output processed
-// samples as specified in output buffer descriptor. If the buffer descriptor
-// is not specified the function must use either the buffer or the
-// buffer provider function installed by the EFFECT_CMD_CONFIGURE command.
-// The effect framework will call the process() function after the EFFECT_CMD_ENABLE
-// command is received and until the EFFECT_CMD_DISABLE is received. When the engine
-// receives the EFFECT_CMD_DISABLE command it should turn off the effect gracefully
-// and when done indicate that it is OK to stop calling the process() function by
-// returning the -ENODATA status.
-//
-// NOTE: the process() function implementation should be "real-time safe" that is
-// it should not perform blocking calls: malloc/free, sleep, read/write/open/close,
-// pthread_cond_wait/pthread_mutex_lock...
-//
-// Input:
-// effect_interface_t: handle to the effect interface this function
-// is called on.
-// inBuffer: buffer descriptor indicating where to read samples to process.
-// If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command.
-//
-// inBuffer: buffer descriptor indicating where to write processed samples.
-// If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command.
-//
-// Output:
-// returned value: 0 successful operation
-// -ENODATA the engine has finished the disable phase and the framework
-// can stop calling process()
-// -EINVAL invalid interface handle or
-// invalid input/output buffer description
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_process_t)(effect_interface_t self,
- audio_buffer_t *inBuffer,
- audio_buffer_t *outBuffer);
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: command
-//
-// Description: Send a command and receive a response to/from effect engine.
-//
-// Input:
-// effect_interface_t: handle to the effect interface this function
-// is called on.
-// cmdCode: command code: the command can be a standardized command defined in
-// effect_command_e (see below) or a proprietary command.
-// cmdSize: size of command in bytes
-// pCmdData: pointer to command data
-// pReplyData: pointer to reply data
-//
-// Input/Output:
-// replySize: maximum size of reply data as input
-// actual size of reply data as output
-//
-// Output:
-// returned value: 0 successful operation
-// -EINVAL invalid interface handle or
-// invalid command/reply size or format according to command code
-// The return code should be restricted to indicate problems related to the this
-// API specification. Status related to the execution of a particular command should be
-// indicated as part of the reply field.
-//
-// *pReplyData updated with command response
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_command_t)(effect_interface_t self,
- uint32_t cmdCode,
- uint32_t cmdSize,
- void *pCmdData,
- uint32_t *replySize,
- void *pReplyData);
-
-
-// Effect control interface definition
-struct effect_interface_s {
- effect_process_t process;
- effect_command_t command;
-};
-
-
-//
-//--- Standardized command codes for command() function
-//
-enum effect_command_e {
- EFFECT_CMD_INIT, // initialize effect engine
- EFFECT_CMD_CONFIGURE, // configure effect engine (see effect_config_t)
- EFFECT_CMD_RESET, // reset effect engine
- EFFECT_CMD_ENABLE, // enable effect process
- EFFECT_CMD_DISABLE, // disable effect process
- EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t)
- EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred
- EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred
- EFFECT_CMD_GET_PARAM, // get parameter
- EFFECT_CMD_SET_DEVICE, // set audio device (see audio_device_e)
- EFFECT_CMD_SET_VOLUME, // set volume
- EFFECT_CMD_SET_AUDIO_MODE, // set the audio mode (normal, ring, ...)
- EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
-};
-
-//==================================================================================================
-// command: EFFECT_CMD_INIT
-//--------------------------------------------------------------------------------------------------
-// description:
-// Initialize effect engine: All configurations return to default
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_CONFIGURE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Apply new audio parameters configurations for input and output buffers
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(effect_config_t)
-// data: effect_config_t
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_RESET
-//--------------------------------------------------------------------------------------------------
-// description:
-// Reset the effect engine. Keep configuration but resets state and buffer content
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: 0
-// data: N/A
-//==================================================================================================
-// command: EFFECT_CMD_ENABLE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Enable the process. Called by the framework before the first call to process()
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_DISABLE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Disable the process. Called by the framework after the last call to process()
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_SET_PARAM
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set a parameter and apply it immediately
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(effect_param_t) + size of param and value
-// data: effect_param_t + param + value. See effect_param_t definition below for value offset
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_SET_PARAM_DEFERRED
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set a parameter but apply it only when receiving EFFECT_CMD_SET_PARAM_COMMIT command
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(effect_param_t) + size of param and value
-// data: effect_param_t + param + value. See effect_param_t definition below for value offset
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: 0
-// data: N/A
-//==================================================================================================
-// command: EFFECT_CMD_SET_PARAM_COMMIT
-//--------------------------------------------------------------------------------------------------
-// description:
-// Apply all previously received EFFECT_CMD_SET_PARAM_DEFERRED commands
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: 0
-// data: N/A
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(int)
-// data: status
-//==================================================================================================
-// command: EFFECT_CMD_GET_PARAM
-//--------------------------------------------------------------------------------------------------
-// description:
-// Get a parameter value
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(effect_param_t) + size of param
-// data: effect_param_t + param
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: sizeof(effect_param_t) + size of param and value
-// data: effect_param_t + param + value. See effect_param_t definition below for value offset
-//==================================================================================================
-// command: EFFECT_CMD_SET_DEVICE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set the rendering device the audio output path is connected to. See audio_device_e for device
-// values.
-// The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this
-// command when the device changes
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(uint32_t)
-// data: audio_device_e
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: 0
-// data: N/A
-//==================================================================================================
-// command: EFFECT_CMD_SET_VOLUME
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set and get volume. Used by audio framework to delegate volume control to effect engine.
-// The effect implementation must set EFFECT_FLAG_VOLUME_IND or EFFECT_FLAG_VOLUME_CTRL flag in
-// its descriptor to receive this command before every call to process() function
-// If EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must return
-// the volume that should be applied before the effect is processed. The overall volume (the volume
-// actually applied by the effect engine multiplied by the returned value) should match the value
-// indicated in the command.
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: n * sizeof(uint32_t)
-// data: volume for each channel defined in effect_config_t for output buffer expressed in
-// 8.24 fixed point format
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: n * sizeof(uint32_t) / 0
-// data: - if EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor:
-// volume for each channel defined in effect_config_t for output buffer expressed in
-// 8.24 fixed point format
-// - if EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor:
-// N/A
-// It is legal to receive a null pointer as pReplyData in which case the effect framework has
-// delegated volume control to another effect
-//==================================================================================================
-// command: EFFECT_CMD_SET_AUDIO_MODE
-//--------------------------------------------------------------------------------------------------
-// description:
-// Set the audio mode. The effect implementation must set EFFECT_FLAG_AUDIO_MODE_IND flag in its
-// descriptor to receive this command when the audio mode changes.
-//--------------------------------------------------------------------------------------------------
-// command format:
-// size: sizeof(uint32_t)
-// data: audio_mode_e
-//--------------------------------------------------------------------------------------------------
-// reply format:
-// size: 0
-// data: N/A
-//==================================================================================================
-// command: EFFECT_CMD_FIRST_PROPRIETARY
-//--------------------------------------------------------------------------------------------------
-// description:
-// All proprietary effect commands must use command codes above this value. The size and format of
-// command and response fields is free in this case
-//==================================================================================================
-
-
-// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t
-// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with
-// regard to the channel mask definition in audio_channels_e e.g :
-// Stereo: left, right
-// 5 point 1: front left, front right, front center, low frequency, back left, back right
-// The buffer size is expressed in frame count, a frame being composed of samples for all
-// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by
-// definition
-struct audio_buffer_s {
- size_t frameCount; // number of frames in buffer
- union {
- void* raw; // raw pointer to start of buffer
- int32_t* s32; // pointer to signed 32 bit data at start of buffer
- int16_t* s16; // pointer to signed 16 bit data at start of buffer
- uint8_t* u8; // pointer to unsigned 8 bit data at start of buffer
- };
-};
-
-// The buffer_provider_s structure contains functions that can be used
-// by the effect engine process() function to query and release input
-// or output audio buffer.
-// The getBuffer() function is called to retrieve a buffer where data
-// should read from or written to by process() function.
-// The releaseBuffer() function MUST be called when the buffer retrieved
-// with getBuffer() is not needed anymore.
-// The process function should use the buffer provider mechanism to retrieve
-// input or output buffer if the inBuffer or outBuffer passed as argument is NULL
-// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_CONFIGURE
-// command did not specify an audio buffer.
-
-typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer);
-
-typedef struct buffer_provider_s {
- buffer_function_t getBuffer; // retrieve next buffer
- buffer_function_t releaseBuffer; // release used buffer
- void *cookie; // for use by client of buffer provider functions
-} buffer_provider_t;
-
-
-// The buffer_config_s structure specifies the input or output audio format
-// to be used by the effect engine. It is part of the effect_config_t
-// structure that defines both input and output buffer configurations and is
-// passed by the EFFECT_CMD_CONFIGURE command.
-typedef struct buffer_config_s {
- audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly
- uint32_t samplingRate; // sampling rate
- uint32_t channels; // channel mask (see audio_channels_e)
- buffer_provider_t bufferProvider; // buffer provider
- uint8_t format; // Audio format (see audio_format_e)
- uint8_t accessMode; // read/write or accumulate in buffer (effect_buffer_access_e)
- uint16_t mask; // indicates which of the above fields is valid
-} buffer_config_t;
-
-// Sample format
-enum audio_format_e {
- SAMPLE_FORMAT_PCM_S15, // PCM signed 16 bits
- SAMPLE_FORMAT_PCM_U8, // PCM unsigned 8 bits
- SAMPLE_FORMAT_PCM_S7_24, // PCM signed 7.24 fixed point representation
- SAMPLE_FORMAT_OTHER // other format (e.g. compressed)
-};
-
-// Channel mask
-enum audio_channels_e {
- CHANNEL_FRONT_LEFT = 0x1, // front left channel
- CHANNEL_FRONT_RIGHT = 0x2, // front right channel
- CHANNEL_FRONT_CENTER = 0x4, // front center channel
- CHANNEL_LOW_FREQUENCY = 0x8, // low frequency channel
- CHANNEL_BACK_LEFT = 0x10, // back left channel
- CHANNEL_BACK_RIGHT = 0x20, // back right channel
- CHANNEL_FRONT_LEFT_OF_CENTER = 0x40, // front left of center channel
- CHANNEL_FRONT_RIGHT_OF_CENTER = 0x80, // front right of center channel
- CHANNEL_BACK_CENTER = 0x100, // back center channel
- CHANNEL_MONO = CHANNEL_FRONT_LEFT,
- CHANNEL_STEREO = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT),
- CHANNEL_QUAD = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
- CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT),
- CHANNEL_SURROUND = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
- CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER),
- CHANNEL_5POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
- CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT),
- CHANNEL_7POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
- CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT |
- CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER),
-};
-
-// Render device
-enum audio_device_e {
- DEVICE_EARPIECE = 0x1, // earpiece
- DEVICE_SPEAKER = 0x2, // speaker
- DEVICE_WIRED_HEADSET = 0x4, // wired headset, with microphone
- DEVICE_WIRED_HEADPHONE = 0x8, // wired headphone, without microphone
- DEVICE_BLUETOOTH_SCO = 0x10, // generic bluetooth SCO
- DEVICE_BLUETOOTH_SCO_HEADSET = 0x20, // bluetooth SCO headset
- DEVICE_BLUETOOTH_SCO_CARKIT = 0x40, // bluetooth SCO car kit
- DEVICE_BLUETOOTH_A2DP = 0x80, // generic bluetooth A2DP
- DEVICE_BLUETOOTH_A2DP_HEADPHONES = 0x100, // bluetooth A2DP headphones
- DEVICE_BLUETOOTH_A2DP_SPEAKER = 0x200, // bluetooth A2DP speakers
- DEVICE_AUX_DIGITAL = 0x400, // digital output
- DEVICE_EXTERNAL_SPEAKER = 0x800 // external speaker (stereo and High quality)
-};
-
-#if ANDROID_VERSION < 17
-// Audio mode
-enum audio_mode_e {
- AUDIO_MODE_NORMAL, // device idle
- AUDIO_MODE_RINGTONE, // device ringing
- AUDIO_MODE_IN_CALL // audio call connected (VoIP or telephony)
-};
-#endif
-
-// Values for "accessMode" field of buffer_config_t:
-// overwrite, read only, accumulate (read/modify/write)
-enum effect_buffer_access_e {
- EFFECT_BUFFER_ACCESS_WRITE,
- EFFECT_BUFFER_ACCESS_READ,
- EFFECT_BUFFER_ACCESS_ACCUMULATE
-
-};
-
-// Values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field
-// in buffer_config_t must be taken into account when executing the EFFECT_CMD_CONFIGURE command
-#define EFFECT_CONFIG_BUFFER 0x0001 // buffer field must be taken into account
-#define EFFECT_CONFIG_SMP_RATE 0x0002 // samplingRate field must be taken into account
-#define EFFECT_CONFIG_CHANNELS 0x0004 // channels field must be taken into account
-#define EFFECT_CONFIG_FORMAT 0x0008 // format field must be taken into account
-#define EFFECT_CONFIG_ACC_MODE 0x0010 // accessMode field must be taken into account
-#define EFFECT_CONFIG_PROVIDER 0x0020 // bufferProvider field must be taken into account
-#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | EFFECT_CONFIG_SMP_RATE | \
- EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT | \
- EFFECT_CONFIG_ACC_MODE | EFFECT_CONFIG_PROVIDER)
-
-
-// effect_config_s structure describes the format of the pCmdData argument of EFFECT_CMD_CONFIGURE
-// command to configure audio parameters and buffers for effect engine input and output.
-typedef struct effect_config_s {
- buffer_config_t inputCfg;
- buffer_config_t outputCfg;;
-} effect_config_t;
-
-
-// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM
-// command and pCmdData and pReplyData of EFFECT_CMD_GET_PARAM command.
-// psize and vsize represent the actual size of parameter and value.
-//
-// NOTE: the start of value field inside the data field is always on a 32 bit boundary:
-//
-// +-----------+
-// | status | sizeof(int)
-// +-----------+
-// | psize | sizeof(int)
-// +-----------+
-// | vsize | sizeof(int)
-// +-----------+
-// | | | |
-// ~ parameter ~ > psize |
-// | | | > ((psize - 1)/sizeof(int) + 1) * sizeof(int)
-// +-----------+ |
-// | padding | |
-// +-----------+
-// | | |
-// ~ value ~ > vsize
-// | | |
-// +-----------+
-
-typedef struct effect_param_s {
- int32_t status; // Transaction status (unused for command, used for reply)
- uint32_t psize; // Parameter size
- uint32_t vsize; // Value size
- char data[]; // Start of Parameter + Value data
-} effect_param_t;
-
-
-/////////////////////////////////////////////////
-// Effect library interface
-/////////////////////////////////////////////////
-
-// An effect library is required to implement and expose the following functions
-// to enable effect enumeration and instantiation. The name of these functions must be as
-// specified here as the effect framework will get the function address with dlsym():
-//
-// - effect_QueryNumberEffects_t EffectQueryNumberEffects;
-// - effect_QueryEffect_t EffectQueryEffect;
-// - effect_CreateEffect_t EffectCreate;
-// - effect_ReleaseEffect_t EffectRelease;
-
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: EffectQueryNumberEffects
-//
-// Description: Returns the number of different effects exposed by the
-// library. Each effect must have a unique effect uuid (see
-// effect_descriptor_t). This function together with EffectQueryEffect()
-// is used to enumerate all effects present in the library.
-//
-// Input/Output:
-// pNumEffects: address where the number of effects should be returned.
-//
-// Output:
-// returned value: 0 successful operation.
-// -ENODEV library failed to initialize
-// -EINVAL invalid pNumEffects
-// *pNumEffects: updated with number of effects in library
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_QueryNumberEffects_t)(uint32_t *pNumEffects);
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: EffectQueryEffect
-//
-// Description: Returns the descriptor of the effect engine which index is
-// given as first argument.
-// See effect_descriptor_t for details on effect descriptors.
-// This function together with EffectQueryNumberEffects() is used to enumerate all
-// effects present in the library. The enumeration sequence is:
-// EffectQueryNumberEffects(&num_effects);
-// for (i = 0; i < num_effects; i++)
-// EffectQueryEffect(i,...);
-//
-// Input/Output:
-// index: index of the effect
-// pDescriptor: address where to return the effect descriptor.
-//
-// Output:
-// returned value: 0 successful operation.
-// -ENODEV library failed to initialize
-// -EINVAL invalid pDescriptor or index
-// -ENOSYS effect list has changed since last execution of
-// EffectQueryNumberEffects()
-// -ENOENT no more effect available
-// *pDescriptor: updated with the effect descriptor.
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_QueryEffect_t)(uint32_t index,
- effect_descriptor_t *pDescriptor);
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: EffectCreate
-//
-// Description: Creates an effect engine of the specified type and returns an
-// effect control interface on this engine. The function will allocate the
-// resources for an instance of the requested effect engine and return
-// a handle on the effect control interface.
-//
-// Input:
-// uuid: pointer to the effect uuid.
-// sessionId: audio session to which this effect instance will be attached. All effects
-// created with the same session ID are connected in series and process the same signal
-// stream. Knowing that two effects are part of the same effect chain can help the
-// library implement some kind of optimizations.
-// ioId: identifies the output or input stream this effect is directed to at audio HAL.
-// For future use especially with tunneled HW accelerated effects
-//
-// Input/Output:
-// pInterface: address where to return the effect interface.
-//
-// Output:
-// returned value: 0 successful operation.
-// -ENODEV library failed to initialize
-// -EINVAL invalid pEffectUuid or pInterface
-// -ENOENT no effect with this uuid found
-// *pInterface: updated with the effect interface handle.
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_CreateEffect_t)(effect_uuid_t *uuid,
- int32_t sessionId,
- int32_t ioId,
- effect_interface_t *pInterface);
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Function: EffectRelease
-//
-// Description: Releases the effect engine whose handle is given as argument.
-// All resources allocated to this particular instance of the effect are
-// released.
-//
-// Input:
-// interface: handle on the effect interface to be released.
-//
-// Output:
-// returned value: 0 successful operation.
-// -ENODEV library failed to initialize
-// -EINVAL invalid interface handle
-//
-////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_ReleaseEffect_t)(effect_interface_t interface);
-
-
-#if __cplusplus
-} // extern "C"
-#endif
-
-
-#endif /*ANDROID_EFFECTAPI_H_*/
diff --git a/dom/system/gonk/android_audio/IAudioFlinger.h b/dom/system/gonk/android_audio/IAudioFlinger.h
deleted file mode 100644
index b10d3ab93..000000000
--- a/dom/system/gonk/android_audio/IAudioFlinger.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef ANDROID_IAUDIOFLINGER_H
-#define ANDROID_IAUDIOFLINGER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include "IAudioTrack.h"
-#include "IAudioRecord.h"
-#include "IAudioFlingerClient.h"
-#include "EffectApi.h"
-#include "IEffect.h"
-#include "IEffectClient.h"
-#include <utils/String8.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IAudioFlinger : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AudioFlinger);
-
- /* create an audio track and registers it with AudioFlinger.
- * return null if the track cannot be created.
- */
- virtual sp<IAudioTrack> createTrack(
- pid_t pid,
- int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- const sp<IMemory>& sharedBuffer,
- int output,
- int *sessionId,
- status_t *status) = 0;
-
- virtual sp<IAudioRecord> openRecord(
- pid_t pid,
- int input,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- int *sessionId,
- status_t *status) = 0;
-
- /* query the audio hardware state. This state never changes,
- * and therefore can be cached.
- */
- virtual uint32_t sampleRate(int output) const = 0;
- virtual int channelCount(int output) const = 0;
- virtual int format(int output) const = 0;
- virtual size_t frameCount(int output) const = 0;
- virtual uint32_t latency(int output) const = 0;
-
- /* set/get the audio hardware state. This will probably be used by
- * the preference panel, mostly.
- */
- virtual status_t setMasterVolume(float value) = 0;
- virtual status_t setMasterMute(bool muted) = 0;
-
- virtual float masterVolume() const = 0;
- virtual bool masterMute() const = 0;
-
- /* set/get stream type state. This will probably be used by
- * the preference panel, mostly.
- */
- virtual status_t setStreamVolume(int stream, float value, int output) = 0;
- virtual status_t setStreamMute(int stream, bool muted) = 0;
-
- virtual float streamVolume(int stream, int output) const = 0;
- virtual bool streamMute(int stream) const = 0;
-
- // set audio mode
- virtual status_t setMode(int mode) = 0;
-
- // mic mute/state
- virtual status_t setMicMute(bool state) = 0;
- virtual bool getMicMute() const = 0;
-
- // is any track active on this stream?
- virtual bool isStreamActive(int stream) const = 0;
-
- virtual status_t setParameters(int ioHandle, const String8& keyValuePairs) = 0;
- virtual String8 getParameters(int ioHandle, const String8& keys) = 0;
-
- // register a current process for audio output change notifications
- virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
-
- // retrieve the audio recording buffer size
- virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0;
-
- virtual int openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- uint32_t flags) = 0;
- virtual int openDuplicateOutput(int output1, int output2) = 0;
- virtual status_t closeOutput(int output) = 0;
- virtual status_t suspendOutput(int output) = 0;
- virtual status_t restoreOutput(int output) = 0;
-
- virtual int openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t acoustics) = 0;
- virtual status_t closeInput(int input) = 0;
-
- virtual status_t setStreamOutput(uint32_t stream, int output) = 0;
-
- virtual status_t setVoiceVolume(float volume) = 0;
-
- virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) = 0;
-
- virtual unsigned int getInputFramesLost(int ioHandle) = 0;
-
- virtual int newAudioSessionId() = 0;
-
- virtual status_t loadEffectLibrary(const char *libPath, int *handle) = 0;
-
- virtual status_t unloadEffectLibrary(int handle) = 0;
-
- virtual status_t queryNumberEffects(uint32_t *numEffects) = 0;
-
- virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) = 0;
-
- virtual status_t getEffectDescriptor(effect_uuid_t *pEffectUUID, effect_descriptor_t *pDescriptor) = 0;
-
- virtual sp<IEffect> createEffect(pid_t pid,
- effect_descriptor_t *pDesc,
- const sp<IEffectClient>& client,
- int32_t priority,
- int output,
- int sessionId,
- status_t *status,
- int *id,
- int *enabled) = 0;
-
- virtual status_t moveEffects(int session, int srcOutput, int dstOutput) = 0;
-};
-
-
-// ----------------------------------------------------------------------------
-
-class BnAudioFlinger : public BnInterface<IAudioFlinger>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IAUDIOFLINGER_H
diff --git a/dom/system/gonk/android_audio/IAudioFlingerClient.h b/dom/system/gonk/android_audio/IAudioFlingerClient.h
deleted file mode 100644
index aa0cdcff1..000000000
--- a/dom/system/gonk/android_audio/IAudioFlingerClient.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_IAUDIOFLINGERCLIENT_H
-#define ANDROID_IAUDIOFLINGERCLIENT_H
-
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <utils/KeyedVector.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IAudioFlingerClient : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AudioFlingerClient);
-
- // Notifies a change of audio input/output configuration.
- virtual void ioConfigChanged(int event, int ioHandle, void *param2) = 0;
-
-};
-
-
-// ----------------------------------------------------------------------------
-
-class BnAudioFlingerClient : public BnInterface<IAudioFlingerClient>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IAUDIOFLINGERCLIENT_H
diff --git a/dom/system/gonk/android_audio/IAudioRecord.h b/dom/system/gonk/android_audio/IAudioRecord.h
deleted file mode 100644
index 46735def2..000000000
--- a/dom/system/gonk/android_audio/IAudioRecord.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef IAUDIORECORD_H_
-#define IAUDIORECORD_H_
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IAudioRecord : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AudioRecord);
-
- /* After it's created the track is not active. Call start() to
- * make it active. If set, the callback will start being called.
- */
- virtual status_t start() = 0;
-
- /* Stop a track. If set, the callback will cease being called and
- * obtainBuffer will return an error. Buffers that are already released
- * will be processed, unless flush() is called.
- */
- virtual void stop() = 0;
-
- /* get this tracks control block */
- virtual sp<IMemory> getCblk() const = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnAudioRecord : public BnInterface<IAudioRecord>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif /*IAUDIORECORD_H_*/
diff --git a/dom/system/gonk/android_audio/IAudioTrack.h b/dom/system/gonk/android_audio/IAudioTrack.h
deleted file mode 100644
index 47d530be5..000000000
--- a/dom/system/gonk/android_audio/IAudioTrack.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef ANDROID_IAUDIOTRACK_H
-#define ANDROID_IAUDIOTRACK_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IAudioTrack : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AudioTrack);
-
- /* After it's created the track is not active. Call start() to
- * make it active. If set, the callback will start being called.
- */
- virtual status_t start() = 0;
-
- /* Stop a track. If set, the callback will cease being called and
- * obtainBuffer will return an error. Buffers that are already released
- * will be processed, unless flush() is called.
- */
- virtual void stop() = 0;
-
- /* flush a stopped track. All pending buffers are discarded.
- * This function has no effect if the track is not stoped.
- */
- virtual void flush() = 0;
-
- /* mute or unmutes this track.
- * While mutted, the callback, if set, is still called.
- */
- virtual void mute(bool) = 0;
-
- /* Pause a track. If set, the callback will cease being called and
- * obtainBuffer will return an error. Buffers that are already released
- * will be processed, unless flush() is called.
- */
- virtual void pause() = 0;
-
- /* Attach track auxiliary output to specified effect. Use effectId = 0
- * to detach track from effect.
- */
- virtual status_t attachAuxEffect(int effectId) = 0;
-
- /* get this tracks control block */
- virtual sp<IMemory> getCblk() const = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnAudioTrack : public BnInterface<IAudioTrack>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IAUDIOTRACK_H
diff --git a/dom/system/gonk/android_audio/IEffect.h b/dom/system/gonk/android_audio/IEffect.h
deleted file mode 100644
index ff04869e0..000000000
--- a/dom/system/gonk/android_audio/IEffect.h
+++ /dev/null
@@ -1,60 +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 ANDROID_IEFFECT_H
-#define ANDROID_IEFFECT_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-
-namespace android {
-
-class IEffect: public IInterface
-{
-public:
- DECLARE_META_INTERFACE(Effect);
-
- virtual status_t enable() = 0;
-
- virtual status_t disable() = 0;
-
- virtual status_t command(uint32_t cmdCode,
- uint32_t cmdSize,
- void *pCmdData,
- uint32_t *pReplySize,
- void *pReplyData) = 0;
-
- virtual void disconnect() = 0;
-
- virtual sp<IMemory> getCblk() const = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnEffect: public BnInterface<IEffect>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IEFFECT_H
diff --git a/dom/system/gonk/android_audio/IEffectClient.h b/dom/system/gonk/android_audio/IEffectClient.h
deleted file mode 100644
index 2f78c98f1..000000000
--- a/dom/system/gonk/android_audio/IEffectClient.h
+++ /dev/null
@@ -1,54 +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 ANDROID_IEFFECTCLIENT_H
-#define ANDROID_IEFFECTCLIENT_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-
-namespace android {
-
-class IEffectClient: public IInterface
-{
-public:
- DECLARE_META_INTERFACE(EffectClient);
-
- virtual void controlStatusChanged(bool controlGranted) = 0;
- virtual void enableStatusChanged(bool enabled) = 0;
- virtual void commandExecuted(uint32_t cmdCode,
- uint32_t cmdSize,
- void *pCmdData,
- uint32_t replySize,
- void *pReplyData) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnEffectClient: public BnInterface<IEffectClient>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IEFFECTCLIENT_H
diff --git a/dom/system/gonk/moz.build b/dom/system/gonk/moz.build
deleted file mode 100644
index 229baaab4..000000000
--- a/dom/system/gonk/moz.build
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# Copyright 2013 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-XPIDL_SOURCES += [
- 'nsIAudioManager.idl',
- 'nsINetworkInterface.idl',
- 'nsINetworkInterfaceListService.idl',
- 'nsINetworkManager.idl',
- 'nsINetworkService.idl',
- 'nsINetworkWorker.idl',
- 'nsISystemWorkerManager.idl',
- 'nsITetheringService.idl',
- 'nsIVolume.idl',
- 'nsIVolumeMountLock.idl',
- 'nsIVolumeService.idl',
- 'nsIVolumeStat.idl',
- 'nsIWorkerHolder.idl',
-]
-
-XPIDL_MODULE = 'dom_system_gonk'
-
-EXPORTS += [
- 'GeolocationUtil.h',
- 'GonkGPSGeolocationProvider.h',
- 'nsVolume.h',
- 'nsVolumeService.h',
- 'SystemProperty.h',
-]
-UNIFIED_SOURCES += [
- 'AudioChannelManager.cpp',
- 'AudioManager.cpp',
- 'AutoMounter.cpp',
- 'AutoMounterSetting.cpp',
- 'GeolocationUtil.cpp',
- 'GonkGPSGeolocationProvider.cpp',
- 'MozMtpDatabase.cpp',
- 'MozMtpServer.cpp',
- 'MozMtpStorage.cpp',
- 'NetIdManager.cpp',
- 'NetworkUtils.cpp',
- 'NetworkWorker.cpp',
- 'nsVolume.cpp',
- 'nsVolumeMountLock.cpp',
- 'nsVolumeService.cpp',
- 'nsVolumeStat.cpp',
- 'OpenFileFinder.cpp',
- 'SystemProperty.cpp',
- 'SystemWorkerManager.cpp',
- 'TimeZoneSettingObserver.cpp',
- 'Volume.cpp',
- 'VolumeCommand.cpp',
- 'VolumeManager.cpp',
- 'VolumeServiceIOThread.cpp',
- 'VolumeServiceTest.cpp',
-]
-
-if CONFIG['ANDROID_VERSION'] >= '17':
- LOCAL_INCLUDES += ['%' + '%s/frameworks/av/media/mtp' % CONFIG['ANDROID_SOURCE']]
-else:
- LOCAL_INCLUDES += ['%' + '%s/frameworks/base/media/mtp' % CONFIG['ANDROID_SOURCE']]
-
-if CONFIG['ENABLE_TESTS']:
- XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']
-
-EXTRA_COMPONENTS += [
- 'NetworkInterfaceListService.js',
- 'NetworkInterfaceListService.manifest',
- 'NetworkManager.js',
- 'NetworkManager.manifest',
- 'NetworkService.js',
- 'NetworkService.manifest',
- 'TetheringService.js',
- 'TetheringService.manifest',
-]
-EXTRA_JS_MODULES += [
- 'systemlibs.js',
-]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-DEFINES['HAVE_ANDROID_OS'] = True
-
-LOCAL_INCLUDES += [
- '/dom/base',
- '/dom/bluetooth/common',
- '/dom/geolocation',
- '/dom/wifi',
-]
-
-FINAL_LIBRARY = 'xul'
-
-FINAL_TARGET_FILES.modules.workers += [
- 'worker_buf.js',
-]
diff --git a/dom/system/gonk/mozstumbler/MozStumbler.cpp b/dom/system/gonk/mozstumbler/MozStumbler.cpp
deleted file mode 100644
index 61e09e705..000000000
--- a/dom/system/gonk/mozstumbler/MozStumbler.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MozStumbler.h"
-#include "nsDataHashtable.h"
-#include "nsGeoPosition.h"
-#include "nsNetCID.h"
-#include "nsPrintfCString.h"
-#include "StumblerLogging.h"
-#include "WriteStumbleOnThread.h"
-#include "../GeolocationUtil.h"
-
-#include "nsIInterfaceRequestor.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsIMobileConnectionInfo.h"
-#include "nsIMobileConnectionService.h"
-#include "nsIMobileCellInfo.h"
-#include "nsIMobileNetworkInfo.h"
-#include "nsINetworkInterface.h"
-#include "nsIRadioInterfaceLayer.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-
-NS_IMPL_ISUPPORTS(StumblerInfo, nsICellInfoListCallback, nsIWifiScanResultsReady)
-
-class RequestCellInfoEvent : public Runnable {
-public:
- RequestCellInfoEvent(StumblerInfo *callback)
- : mRequestCallback(callback)
- {}
-
- NS_IMETHOD Run() override {
- MOZ_ASSERT(NS_IsMainThread());
- // Get Cell Info
- nsCOMPtr<nsIMobileConnectionService> service =
- do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID);
-
- if (!service) {
- STUMBLER_ERR("Stumbler-can not get nsIMobileConnectionService \n");
- return NS_OK;
- }
- nsCOMPtr<nsIMobileConnection> connection;
- uint32_t numberOfRilServices = 1, cellInfoNum = 0;
-
- service->GetNumItems(&numberOfRilServices);
- for (uint32_t rilNum = 0; rilNum < numberOfRilServices; rilNum++) {
- service->GetItemByServiceId(rilNum /* Client Id */, getter_AddRefs(connection));
- if (!connection) {
- STUMBLER_ERR("Stumbler-can not get nsIMobileConnection by ServiceId %d \n", rilNum);
- } else {
- cellInfoNum++;
- connection->GetCellInfoList(mRequestCallback);
- }
- }
- mRequestCallback->SetCellInfoResponsesExpected(cellInfoNum);
-
- // Get Wifi AP Info
- nsCOMPtr<nsIInterfaceRequestor> ir = do_GetService("@mozilla.org/telephony/system-worker-manager;1");
- nsCOMPtr<nsIWifi> wifi = do_GetInterface(ir);
- if (!wifi) {
- mRequestCallback->SetWifiInfoResponseReceived();
- STUMBLER_ERR("Stumbler-can not get nsIWifi interface\n");
- return NS_OK;
- }
- wifi->GetWifiScanResults(mRequestCallback);
- return NS_OK;
- }
-private:
- RefPtr<StumblerInfo> mRequestCallback;
-};
-
-void
-MozStumble(nsGeoPosition* position)
-{
- if (WriteStumbleOnThread::IsFileWaitingForUpload()) {
- nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
- MOZ_ASSERT(target);
- // Knowing that file is waiting to upload, and no collection will take place,
- // just trigger the thread with an empty string.
- nsCOMPtr<nsIRunnable> event = new WriteStumbleOnThread(EmptyCString());
- target->Dispatch(event, NS_DISPATCH_NORMAL);
- return;
- }
-
- nsCOMPtr<nsIDOMGeoPositionCoords> coords;
- position->GetCoords(getter_AddRefs(coords));
- if (!coords) {
- return;
- }
-
- double latitude, longitude;
- coords->GetLatitude(&latitude);
- coords->GetLongitude(&longitude);
-
- const double kMinChangeInMeters = 30;
- static int64_t lastTime_ms = 0;
- static double sLastLat = 0;
- static double sLastLon = 0;
- double delta = -1.0;
- int64_t timediff = (PR_Now() / PR_USEC_PER_MSEC) - lastTime_ms;
-
- if (0 != sLastLon || 0 != sLastLat) {
- delta = CalculateDeltaInMeter(latitude, longitude, sLastLat, sLastLon);
- }
- STUMBLER_DBG("Stumbler-Location. [%f , %f] time_diff:%lld, delta : %f\n",
- longitude, latitude, timediff, delta);
-
- // Consecutive GPS locations must be 30 meters and 3 seconds apart
- if (lastTime_ms == 0 || ((timediff >= STUMBLE_INTERVAL_MS) && (delta > kMinChangeInMeters))){
- lastTime_ms = (PR_Now() / PR_USEC_PER_MSEC);
- sLastLat = latitude;
- sLastLon = longitude;
- RefPtr<StumblerInfo> requestCallback = new StumblerInfo(position);
- RefPtr<RequestCellInfoEvent> runnable = new RequestCellInfoEvent(requestCallback);
- NS_DispatchToMainThread(runnable);
- } else {
- STUMBLER_DBG("Stumbler-GPS locations less than 30 meters and 3 seconds. Ignore!\n");
- }
-}
-
-void
-StumblerInfo::SetWifiInfoResponseReceived()
-{
- mIsWifiInfoResponseReceived = true;
-
- if (mIsWifiInfoResponseReceived && mCellInfoResponsesReceived == mCellInfoResponsesExpected) {
- STUMBLER_DBG("Call DumpStumblerInfo from SetWifiInfoResponseReceived\n");
- DumpStumblerInfo();
- }
-}
-
-void
-StumblerInfo::SetCellInfoResponsesExpected(uint8_t count)
-{
- mCellInfoResponsesExpected = count;
- STUMBLER_DBG("SetCellInfoNum (%d)\n", count);
-
- if (mIsWifiInfoResponseReceived && mCellInfoResponsesReceived == mCellInfoResponsesExpected) {
- STUMBLER_DBG("Call DumpStumblerInfo from SetCellInfoResponsesExpected\n");
- DumpStumblerInfo();
- }
-}
-
-
-#define TEXT_LAT NS_LITERAL_CSTRING("latitude")
-#define TEXT_LON NS_LITERAL_CSTRING("longitude")
-#define TEXT_ACC NS_LITERAL_CSTRING("accuracy")
-#define TEXT_ALT NS_LITERAL_CSTRING("altitude")
-#define TEXT_ALTACC NS_LITERAL_CSTRING("altitudeAccuracy")
-#define TEXT_HEAD NS_LITERAL_CSTRING("heading")
-#define TEXT_SPD NS_LITERAL_CSTRING("speed")
-
-nsresult
-StumblerInfo::LocationInfoToString(nsACString& aLocDesc)
-{
- nsCOMPtr<nsIDOMGeoPositionCoords> coords;
- mPosition->GetCoords(getter_AddRefs(coords));
- if (!coords) {
- return NS_ERROR_FAILURE;
- }
-
- nsDataHashtable<nsCStringHashKey, double> info;
-
- double val;
- coords->GetLatitude(&val);
- info.Put(TEXT_LAT, val);
- coords->GetLongitude(&val);
- info.Put(TEXT_LON, val);
- coords->GetAccuracy(&val);
- info.Put(TEXT_ACC, val);
- coords->GetAltitude(&val);
- info.Put(TEXT_ALT, val);
- coords->GetAltitudeAccuracy(&val);
- info.Put(TEXT_ALTACC, val);
- coords->GetHeading(&val);
- info.Put(TEXT_HEAD, val);
- coords->GetSpeed(&val);
- info.Put(TEXT_SPD, val);
-
- for (auto it = info.Iter(); !it.Done(); it.Next()) {
- const nsACString& key = it.Key();
- val = it.UserData();
- if (!IsNaN(val)) {
- aLocDesc += nsPrintfCString("\"%s\":%f,", key.BeginReading(), val);
- }
- }
-
- aLocDesc += nsPrintfCString("\"timestamp\":%lld,", PR_Now() / PR_USEC_PER_MSEC).get();
- return NS_OK;
-}
-
-#define TEXT_RADIOTYPE NS_LITERAL_CSTRING("radioType")
-#define TEXT_MCC NS_LITERAL_CSTRING("mobileCountryCode")
-#define TEXT_MNC NS_LITERAL_CSTRING("mobileNetworkCode")
-#define TEXT_LAC NS_LITERAL_CSTRING("locationAreaCode")
-#define TEXT_CID NS_LITERAL_CSTRING("cellId")
-#define TEXT_PSC NS_LITERAL_CSTRING("psc")
-#define TEXT_STRENGTH_ASU NS_LITERAL_CSTRING("asu")
-#define TEXT_STRENGTH_DBM NS_LITERAL_CSTRING("signalStrength")
-#define TEXT_REGISTERED NS_LITERAL_CSTRING("serving")
-#define TEXT_TIMEING_ADVANCE NS_LITERAL_CSTRING("timingAdvance")
-
-template <class T> void
-ExtractCommonNonCDMACellInfoItems(nsCOMPtr<T>& cell, nsDataHashtable<nsCStringHashKey, int32_t>& info)
-{
- int32_t mcc, mnc, cid, sig;
-
- cell->GetMcc(&mcc);
- cell->GetMnc(&mnc);
- cell->GetCid(&cid);
- cell->GetSignalStrength(&sig);
-
- info.Put(TEXT_MCC, mcc);
- info.Put(TEXT_MNC, mnc);
- info.Put(TEXT_CID, cid);
- info.Put(TEXT_STRENGTH_ASU, sig);
-}
-
-void
-StumblerInfo::CellNetworkInfoToString(nsACString& aCellDesc)
-{
- aCellDesc += "\"cellTowers\": [";
-
- for (uint32_t idx = 0; idx < mCellInfo.Length() ; idx++) {
- const char* radioType = 0;
- int32_t type;
- mCellInfo[idx]->GetType(&type);
- bool registered;
- mCellInfo[idx]->GetRegistered(&registered);
- if (idx) {
- aCellDesc += ",{";
- } else {
- aCellDesc += "{";
- }
-
- STUMBLER_DBG("type=%d\n", type);
-
- nsDataHashtable<nsCStringHashKey, int32_t> info;
- info.Put(TEXT_REGISTERED, registered);
-
- if(type == nsICellInfo::CELL_INFO_TYPE_GSM) {
- radioType = "gsm";
- nsCOMPtr<nsIGsmCellInfo> gsmCellInfo = do_QueryInterface(mCellInfo[idx]);
- ExtractCommonNonCDMACellInfoItems(gsmCellInfo, info);
- int32_t lac;
- gsmCellInfo->GetLac(&lac);
- info.Put(TEXT_LAC, lac);
- } else if (type == nsICellInfo::CELL_INFO_TYPE_WCDMA) {
- radioType = "wcdma";
- nsCOMPtr<nsIWcdmaCellInfo> wcdmaCellInfo = do_QueryInterface(mCellInfo[idx]);
- ExtractCommonNonCDMACellInfoItems(wcdmaCellInfo, info);
- int32_t lac, psc;
- wcdmaCellInfo->GetLac(&lac);
- wcdmaCellInfo->GetPsc(&psc);
- info.Put(TEXT_LAC, lac);
- info.Put(TEXT_PSC, psc);
- } else if (type == nsICellInfo::CELL_INFO_TYPE_CDMA) {
- radioType = "cdma";
- nsCOMPtr<nsICdmaCellInfo> cdmaCellInfo = do_QueryInterface(mCellInfo[idx]);
- int32_t mnc, lac, cid, sig;
- cdmaCellInfo->GetSystemId(&mnc);
- cdmaCellInfo->GetNetworkId(&lac);
- cdmaCellInfo->GetBaseStationId(&cid);
- info.Put(TEXT_MNC, mnc);
- info.Put(TEXT_LAC, lac);
- info.Put(TEXT_CID, cid);
-
- cdmaCellInfo->GetEvdoDbm(&sig);
- if (sig < 0 || sig == nsICellInfo::UNKNOWN_VALUE) {
- cdmaCellInfo->GetCdmaDbm(&sig);
- }
- if (sig > -1 && sig != nsICellInfo::UNKNOWN_VALUE) {
- sig *= -1;
- info.Put(TEXT_STRENGTH_DBM, sig);
- }
- } else if (type == nsICellInfo::CELL_INFO_TYPE_LTE) {
- radioType = "lte";
- nsCOMPtr<nsILteCellInfo> lteCellInfo = do_QueryInterface(mCellInfo[idx]);
- ExtractCommonNonCDMACellInfoItems(lteCellInfo, info);
- int32_t lac, timingAdvance, pcid, rsrp;
- lteCellInfo->GetTac(&lac);
- lteCellInfo->GetTimingAdvance(&timingAdvance);
- lteCellInfo->GetPcid(&pcid);
- lteCellInfo->GetRsrp(&rsrp);
- info.Put(TEXT_LAC, lac);
- info.Put(TEXT_TIMEING_ADVANCE, timingAdvance);
- info.Put(TEXT_PSC, pcid);
- if (rsrp != nsICellInfo::UNKNOWN_VALUE) {
- info.Put(TEXT_STRENGTH_DBM, rsrp * -1);
- }
- }
-
- aCellDesc += nsPrintfCString("\"%s\":\"%s\"", TEXT_RADIOTYPE.get(), radioType);
- for (auto it = info.Iter(); !it.Done(); it.Next()) {
- const nsACString& key = it.Key();
- int32_t value = it.UserData();
- if (value != nsICellInfo::UNKNOWN_VALUE) {
- aCellDesc += nsPrintfCString(",\"%s\":%d", key.BeginReading(), value);
- }
- }
-
- aCellDesc += "}";
- }
- aCellDesc += "]";
-}
-
-void
-StumblerInfo::DumpStumblerInfo()
-{
- if (!mIsWifiInfoResponseReceived || mCellInfoResponsesReceived != mCellInfoResponsesExpected) {
- STUMBLER_DBG("CellInfoReceived=%d (Expected=%d), WifiInfoResponseReceived=%d\n",
- mCellInfoResponsesReceived, mCellInfoResponsesExpected, mIsWifiInfoResponseReceived);
- return;
- }
- mIsWifiInfoResponseReceived = false;
- mCellInfoResponsesReceived = 0;
-
- nsAutoCString desc;
- nsresult rv = LocationInfoToString(desc);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("LocationInfoToString failed, skip this dump");
- return;
- }
-
- CellNetworkInfoToString(desc);
- desc += mWifiDesc;
-
- STUMBLER_DBG("dispatch write event to thread\n");
- nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
- MOZ_ASSERT(target);
-
- nsCOMPtr<nsIRunnable> event = new WriteStumbleOnThread(desc);
- target->Dispatch(event, NS_DISPATCH_NORMAL);
-}
-
-NS_IMETHODIMP
-StumblerInfo::NotifyGetCellInfoList(uint32_t count, nsICellInfo** aCellInfos)
-{
- MOZ_ASSERT(NS_IsMainThread());
- STUMBLER_DBG("There are %d cellinfo in the result\n", count);
-
- for (uint32_t i = 0; i < count; i++) {
- mCellInfo.AppendElement(aCellInfos[i]);
- }
- mCellInfoResponsesReceived++;
- DumpStumblerInfo();
- return NS_OK;
-}
-
-NS_IMETHODIMP StumblerInfo::NotifyGetCellInfoListFailed(const nsAString& error)
-{
- MOZ_ASSERT(NS_IsMainThread());
- mCellInfoResponsesReceived++;
- STUMBLER_ERR("NotifyGetCellInfoListFailedm CellInfoReadyNum=%d, mCellInfoResponsesExpected=%d, mIsWifiInfoResponseReceived=%d",
- mCellInfoResponsesReceived, mCellInfoResponsesExpected, mIsWifiInfoResponseReceived);
- DumpStumblerInfo();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-StumblerInfo::Onready(uint32_t count, nsIWifiScanResult** results)
-{
- MOZ_ASSERT(NS_IsMainThread());
- STUMBLER_DBG("There are %d wifiAPinfo in the result\n",count);
-
- mWifiDesc += ",\"wifiAccessPoints\": [";
- bool firstItem = true;
- for (uint32_t i = 0 ; i < count ; i++) {
- nsString ssid;
- results[i]->GetSsid(ssid);
- if (ssid.IsEmpty()) {
- STUMBLER_DBG("no ssid, skip this AP\n");
- continue;
- }
-
- if (ssid.Length() >= 6) {
- if (StringEndsWith(ssid, NS_LITERAL_STRING("_nomap"))) {
- STUMBLER_DBG("end with _nomap. skip this AP(ssid :%s)\n", ssid.get());
- continue;
- }
- }
-
- if (firstItem) {
- mWifiDesc += "{";
- firstItem = false;
- } else {
- mWifiDesc += ",{";
- }
-
- // mac address
- nsString bssid;
- results[i]->GetBssid(bssid);
- // 00:00:00:00:00:00 --> 000000000000
- bssid.StripChars(":");
- mWifiDesc += "\"macAddress\":\"";
- mWifiDesc += NS_ConvertUTF16toUTF8(bssid);
-
- uint32_t signal;
- results[i]->GetSignalStrength(&signal);
- mWifiDesc += "\",\"signalStrength\":";
- mWifiDesc.AppendInt(signal);
-
- mWifiDesc += "}";
- }
- mWifiDesc += "]";
-
- mIsWifiInfoResponseReceived = true;
- DumpStumblerInfo();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-StumblerInfo::Onfailure()
-{
- MOZ_ASSERT(NS_IsMainThread());
- STUMBLER_ERR("GetWifiScanResults Onfailure\n");
- mIsWifiInfoResponseReceived = true;
- DumpStumblerInfo();
- return NS_OK;
-}
-
diff --git a/dom/system/gonk/mozstumbler/MozStumbler.h b/dom/system/gonk/mozstumbler/MozStumbler.h
deleted file mode 100644
index 41ee4e5e1..000000000
--- a/dom/system/gonk/mozstumbler/MozStumbler.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_mozstumbler_h__
-#define mozilla_system_mozstumbler_h__
-
-#include "nsIDOMEventTarget.h"
-#include "nsICellInfo.h"
-#include "nsIWifi.h"
-
-#define STUMBLE_INTERVAL_MS 3000
-
-class nsGeoPosition;
-
-void MozStumble(nsGeoPosition* position);
-
-class StumblerInfo final : public nsICellInfoListCallback,
- public nsIWifiScanResultsReady
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSICELLINFOLISTCALLBACK
- NS_DECL_NSIWIFISCANRESULTSREADY
-
- explicit StumblerInfo(nsGeoPosition* position)
- : mPosition(position), mCellInfoResponsesExpected(0), mCellInfoResponsesReceived(0), mIsWifiInfoResponseReceived(0)
- {}
- void SetWifiInfoResponseReceived();
- void SetCellInfoResponsesExpected(uint8_t count);
-
-private:
- ~StumblerInfo() {}
- void DumpStumblerInfo();
- nsresult LocationInfoToString(nsACString& aLocDesc);
- void CellNetworkInfoToString(nsACString& aCellDesc);
- nsTArray<RefPtr<nsICellInfo>> mCellInfo;
- nsCString mWifiDesc;
- RefPtr<nsGeoPosition> mPosition;
- int mCellInfoResponsesExpected;
- int mCellInfoResponsesReceived;
- bool mIsWifiInfoResponseReceived;
-};
-#endif // mozilla_system_mozstumbler_h__
-
diff --git a/dom/system/gonk/mozstumbler/StumblerLogging.cpp b/dom/system/gonk/mozstumbler/StumblerLogging.cpp
deleted file mode 100644
index acf23b3b1..000000000
--- a/dom/system/gonk/mozstumbler/StumblerLogging.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "StumblerLogging.h"
-
-mozilla::LogModule* GetLog()
-{
- static mozilla::LazyLogModule log("mozstumbler");
- return log;
-}
diff --git a/dom/system/gonk/mozstumbler/StumblerLogging.h b/dom/system/gonk/mozstumbler/StumblerLogging.h
deleted file mode 100644
index 038f44f8f..000000000
--- a/dom/system/gonk/mozstumbler/StumblerLogging.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef STUMBLERLOGGING_H
-#define STUMBLERLOGGING_H
-
-#include "mozilla/Logging.h"
-
-mozilla::LogModule* GetLog();
-
-#define STUMBLER_DBG(arg, ...) MOZ_LOG(GetLog(), mozilla::LogLevel::Debug, ("STUMBLER - %s: " arg, __func__, ##__VA_ARGS__))
-#define STUMBLER_LOG(arg, ...) MOZ_LOG(GetLog(), mozilla::LogLevel::Info, ("STUMBLER - %s: " arg, __func__, ##__VA_ARGS__))
-#define STUMBLER_ERR(arg, ...) MOZ_LOG(GetLog(), mozilla::LogLevel::Error, ("STUMBLER -%s: " arg, __func__, ##__VA_ARGS__))
-
-#endif
diff --git a/dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp b/dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp
deleted file mode 100644
index d97aa9712..000000000
--- a/dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "UploadStumbleRunnable.h"
-#include "StumblerLogging.h"
-#include "mozilla/dom/Event.h"
-#include "nsIInputStream.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsIURLFormatter.h"
-#include "nsIXMLHttpRequest.h"
-#include "nsNetUtil.h"
-#include "nsVariant.h"
-
-UploadStumbleRunnable::UploadStumbleRunnable(nsIInputStream* aUploadData)
-: mUploadInputStream(aUploadData)
-{
-}
-
-NS_IMETHODIMP
-UploadStumbleRunnable::Run()
-{
- MOZ_ASSERT(NS_IsMainThread());
- nsresult rv = Upload();
- if (NS_FAILED(rv)) {
- WriteStumbleOnThread::UploadEnded(false);
- }
- return NS_OK;
-}
-
-nsresult
-UploadStumbleRunnable::Upload()
-{
- nsresult rv;
- RefPtr<nsVariant> variant = new nsVariant();
-
- rv = variant->SetAsISupports(mUploadInputStream);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIXMLHttpRequest> xhr = do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIScriptSecurityManager> secman =
- do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIPrincipal> systemPrincipal;
- rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIURLFormatter> formatter =
- do_CreateInstance("@mozilla.org/toolkit/URLFormatterService;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- nsString url;
- rv = formatter->FormatURLPref(NS_LITERAL_STRING("geo.stumbler.url"), url);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = xhr->Open(NS_LITERAL_CSTRING("POST"), NS_ConvertUTF16toUTF8(url), false, EmptyString(), EmptyString());
- NS_ENSURE_SUCCESS(rv, rv);
-
- xhr->SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), NS_LITERAL_CSTRING("gzip"));
- xhr->SetMozBackgroundRequest(true);
- // 60s timeout
- xhr->SetTimeout(60 * 1000);
-
- nsCOMPtr<EventTarget> target(do_QueryInterface(xhr));
- RefPtr<nsIDOMEventListener> listener = new UploadEventListener(xhr);
-
- const char* const sEventStrings[] = {
- // nsIXMLHttpRequestEventTarget event types
- "abort",
- "error",
- "load",
- "timeout"
- };
-
- for (uint32_t index = 0; index < MOZ_ARRAY_LENGTH(sEventStrings); index++) {
- nsAutoString eventType = NS_ConvertASCIItoUTF16(sEventStrings[index]);
- rv = target->AddEventListener(eventType, listener, false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = xhr->Send(variant);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-NS_IMPL_ISUPPORTS(UploadEventListener, nsIDOMEventListener)
-
-UploadEventListener::UploadEventListener(nsIXMLHttpRequest* aXHR)
-: mXHR(aXHR)
-{
-}
-
-NS_IMETHODIMP
-UploadEventListener::HandleEvent(nsIDOMEvent* aEvent)
-{
- nsString type;
- if (NS_FAILED(aEvent->GetType(type))) {
- STUMBLER_ERR("Failed to get event type");
- WriteStumbleOnThread::UploadEnded(false);
- return NS_ERROR_FAILURE;
- }
-
- if (type.EqualsLiteral("load")) {
- STUMBLER_DBG("Got load Event\n");
- } else if (type.EqualsLiteral("error") && mXHR) {
- STUMBLER_ERR("Upload Error");
- } else {
- STUMBLER_DBG("Receive %s Event", NS_ConvertUTF16toUTF8(type).get());
- }
-
- uint32_t statusCode = 0;
- bool doDelete = false;
- if (!mXHR) {
- return NS_OK;
- }
- nsresult rv = mXHR->GetStatus(&statusCode);
- if (NS_SUCCEEDED(rv)) {
- STUMBLER_DBG("statuscode %d \n", statusCode);
- }
-
- if (200 == statusCode || 400 == statusCode) {
- doDelete = true;
- }
-
- WriteStumbleOnThread::UploadEnded(doDelete);
- nsCOMPtr<EventTarget> target(do_QueryInterface(mXHR));
-
- const char* const sEventStrings[] = {
- // nsIXMLHttpRequestEventTarget event types
- "abort",
- "error",
- "load",
- "timeout"
- };
-
- for (uint32_t index = 0; index < MOZ_ARRAY_LENGTH(sEventStrings); index++) {
- nsAutoString eventType = NS_ConvertASCIItoUTF16(sEventStrings[index]);
- rv = target->RemoveEventListener(eventType, this, false);
- }
-
- mXHR = nullptr;
- return NS_OK;
-}
diff --git a/dom/system/gonk/mozstumbler/UploadStumbleRunnable.h b/dom/system/gonk/mozstumbler/UploadStumbleRunnable.h
deleted file mode 100644
index 462665a86..000000000
--- a/dom/system/gonk/mozstumbler/UploadStumbleRunnable.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#ifndef UPLOADSTUMBLERUNNABLE_H
-#define UPLOADSTUMBLERUNNABLE_H
-
-#include "nsIDOMEventListener.h"
-
-class nsIXMLHttpRequest;
-class nsIInputStream;
-
-/*
- This runnable is managed by WriteStumbleOnThread only, see that class
- for how this is scheduled.
- */
-class UploadStumbleRunnable final : public Runnable
-{
-public:
- explicit UploadStumbleRunnable(nsIInputStream* aUploadInputStream);
-
- NS_IMETHOD Run() override;
-private:
- virtual ~UploadStumbleRunnable() {}
- nsCOMPtr<nsIInputStream> mUploadInputStream;
- nsresult Upload();
-};
-
-
-class UploadEventListener : public nsIDOMEventListener
-{
-public:
- UploadEventListener(nsIXMLHttpRequest* aXHR);
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIDOMEVENTLISTENER
-
-protected:
- virtual ~UploadEventListener() {}
- nsCOMPtr<nsIXMLHttpRequest> mXHR;
-};
-
-#endif
diff --git a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp b/dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp
deleted file mode 100644
index e58e771c4..000000000
--- a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "WriteStumbleOnThread.h"
-#include "StumblerLogging.h"
-#include "UploadStumbleRunnable.h"
-#include "nsDumpUtils.h"
-#include "nsGZFileWriter.h"
-#include "nsIFileStreams.h"
-#include "nsIInputStream.h"
-#include "nsPrintfCString.h"
-
-#define MAXFILESIZE_KB (15 * 1024)
-#define ONEDAY_IN_MSEC (24 * 60 * 60 * 1000)
-#define MAX_UPLOAD_ATTEMPTS 20
-
-mozilla::Atomic<bool> WriteStumbleOnThread::sIsFileWaitingForUpload(false);
-mozilla::Atomic<bool> WriteStumbleOnThread::sIsAlreadyRunning(false);
-WriteStumbleOnThread::UploadFreqGuard WriteStumbleOnThread::sUploadFreqGuard = {0};
-
-#define FILENAME_INPROGRESS NS_LITERAL_CSTRING("stumbles.json.gz")
-#define FILENAME_COMPLETED NS_LITERAL_CSTRING("stumbles.done.json.gz")
-#define OUTPUT_DIR NS_LITERAL_CSTRING("mozstumbler")
-
-class DeleteRunnable : public Runnable
-{
- public:
- DeleteRunnable() {}
-
- NS_IMETHOD
- Run() override
- {
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED,
- getter_AddRefs(tmpFile),
- OUTPUT_DIR,
- nsDumpUtils::CREATE);
- if (NS_SUCCEEDED(rv)) {
- tmpFile->Remove(true);
- }
- // critically, this sets this flag to false so writing can happen again
- WriteStumbleOnThread::sIsAlreadyRunning = false;
- WriteStumbleOnThread::sIsFileWaitingForUpload = false;
- return NS_OK;
- }
-
- private:
- ~DeleteRunnable() {}
-};
-
-bool
-WriteStumbleOnThread::IsFileWaitingForUpload()
-{
- return sIsFileWaitingForUpload;
-}
-
-void
-WriteStumbleOnThread::UploadEnded(bool deleteUploadFile)
-{
- if (!deleteUploadFile) {
- sIsAlreadyRunning = false;
- return;
- }
-
- nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
- MOZ_ASSERT(target);
- nsCOMPtr<nsIRunnable> event = new DeleteRunnable();
- target->Dispatch(event, NS_DISPATCH_NORMAL);
-}
-
-void
-WriteStumbleOnThread::WriteJSON(Partition aPart)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv;
- rv = nsDumpUtils::OpenTempFile(FILENAME_INPROGRESS, getter_AddRefs(tmpFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Open a file for stumble failed");
- return;
- }
-
- RefPtr<nsGZFileWriter> gzWriter = new nsGZFileWriter(nsGZFileWriter::Append);
- rv = gzWriter->Init(tmpFile);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("gzWriter init failed");
- return;
- }
-
- /*
- The json format is like below.
- {items:[
- {item},
- {item},
- {item}
- ]}
- */
-
- // Need to add "]}" after the last item
- if (aPart == Partition::End) {
- rv = gzWriter->Write("]}");
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("gzWriter Write failed");
- }
-
- rv = gzWriter->Finish();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream finish failed");
- }
-
- nsCOMPtr<nsIFile> targetFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, getter_AddRefs(targetFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- nsAutoString targetFilename;
- rv = targetFile->GetLeafName(targetFilename);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Get Filename failed");
- return;
- }
- rv = targetFile->Remove(true);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Remove File failed");
- return;
- }
- // Rename tmpfile
- rv = tmpFile->MoveTo(/* directory */ nullptr, targetFilename);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Rename File failed");
- return;
- }
- return;
- }
-
- // Need to add "{items:[" before the first item
- if (aPart == Partition::Begining) {
- rv = gzWriter->Write("{\"items\":[{");
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream write begining failed");
- }
- } else if (aPart == Partition::Middle) {
- rv = gzWriter->Write(",{");
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream write middle failed");
- }
- }
- rv = gzWriter->Write(mDesc.get());
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream write mDesc failed");
- }
- // one item is ended with '}' (e.g. {item})
- rv = gzWriter->Write("}");
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream write end failed");
- }
-
- rv = gzWriter->Finish();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("ostream finish failed");
- }
-
- // check if it is the end of this file
- int64_t fileSize = 0;
- rv = tmpFile->GetFileSize(&fileSize);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("GetFileSize failed");
- return;
- }
- if (fileSize >= MAXFILESIZE_KB) {
- WriteJSON(Partition::End);
- return;
- }
-}
-
-WriteStumbleOnThread::Partition
-WriteStumbleOnThread::GetWritePosition()
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_INPROGRESS, getter_AddRefs(tmpFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("Open a file for stumble failed");
- return Partition::Unknown;
- }
-
- int64_t fileSize = 0;
- rv = tmpFile->GetFileSize(&fileSize);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("GetFileSize failed");
- return Partition::Unknown;
- }
-
- if (fileSize == 0) {
- return Partition::Begining;
- } else if (fileSize >= MAXFILESIZE_KB) {
- return Partition::End;
- } else {
- return Partition::Middle;
- }
-}
-
-NS_IMETHODIMP
-WriteStumbleOnThread::Run()
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- bool b = sIsAlreadyRunning.exchange(true);
- if (b) {
- return NS_OK;
- }
-
- UploadFileStatus status = GetUploadFileStatus();
-
- if (UploadFileStatus::NoFile != status) {
- if (UploadFileStatus::ExistsAndReadyToUpload == status) {
- sIsFileWaitingForUpload = true;
- Upload();
- return NS_OK;
- }
- } else {
- Partition partition = GetWritePosition();
- if (partition == Partition::Unknown) {
- STUMBLER_ERR("GetWritePosition failed, skip once");
- } else {
- WriteJSON(partition);
- }
- }
-
- sIsFileWaitingForUpload = false;
- sIsAlreadyRunning = false;
- return NS_OK;
-}
-
-
-/*
- If the upload file exists, then check if it is one day old.
- • if it is a day old -> ExistsAndReadyToUpload
- • if it is less than the current day old -> Exists
- • otherwise -> NoFile
-
- The Exists case means that the upload and the stumbling is rate limited
- per-day to the size of the one file.
- */
-WriteStumbleOnThread::UploadFileStatus
-WriteStumbleOnThread::GetUploadFileStatus()
-{
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, getter_AddRefs(tmpFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- int64_t fileSize;
- rv = tmpFile->GetFileSize(&fileSize);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("GetFileSize failed");
- return UploadFileStatus::NoFile;
- }
- if (fileSize <= 0) {
- tmpFile->Remove(true);
- return UploadFileStatus::NoFile;
- }
-
- PRTime lastModifiedTime;
- tmpFile->GetLastModifiedTime(&lastModifiedTime);
- if ((PR_Now() / PR_USEC_PER_MSEC) - lastModifiedTime >= ONEDAY_IN_MSEC) {
- return UploadFileStatus::ExistsAndReadyToUpload;
- }
- return UploadFileStatus::Exists;
-}
-
-void
-WriteStumbleOnThread::Upload()
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- time_t seconds = time(0);
- int day = seconds / (60 * 60 * 24);
-
- if (sUploadFreqGuard.daySinceEpoch < day) {
- sUploadFreqGuard.daySinceEpoch = day;
- sUploadFreqGuard.attempts = 0;
- }
-
- sUploadFreqGuard.attempts++;
- if (sUploadFreqGuard.attempts > MAX_UPLOAD_ATTEMPTS) {
- STUMBLER_ERR("Too many upload attempts today");
- sIsAlreadyRunning = false;
- return;
- }
-
- nsCOMPtr<nsIFile> tmpFile;
- nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, getter_AddRefs(tmpFile),
- OUTPUT_DIR, nsDumpUtils::CREATE);
- int64_t fileSize;
- rv = tmpFile->GetFileSize(&fileSize);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- STUMBLER_ERR("GetFileSize failed");
- sIsAlreadyRunning = false;
- return;
- }
-
- if (fileSize <= 0) {
- sIsAlreadyRunning = false;
- return;
- }
-
- // prepare json into nsIInputStream
- nsCOMPtr<nsIInputStream> inStream;
- rv = NS_NewLocalFileInputStream(getter_AddRefs(inStream), tmpFile);
- if (NS_FAILED(rv)) {
- sIsAlreadyRunning = false;
- return;
- }
-
- RefPtr<nsIRunnable> uploader = new UploadStumbleRunnable(inStream);
- NS_DispatchToMainThread(uploader);
-}
diff --git a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.h b/dom/system/gonk/mozstumbler/WriteStumbleOnThread.h
deleted file mode 100644
index 104cf9bdd..000000000
--- a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef WriteStumbleOnThread_H
-#define WriteStumbleOnThread_H
-
-#include "mozilla/Atomics.h"
-
-class DeleteRunnable;
-
-/*
- This class is the entry point to stumbling, in that it
- receives the location+cell+wifi string and writes it
- to disk, or instead, it calls UploadStumbleRunnable
- to upload the data.
-
- Writes will happen until the file is a max size, then stop.
- Uploads will happen only when the file is one day old.
- The purpose of these decisions is to have very simple rate-limiting
- on the writes, as well as the uploads.
-
- There is only one file active; it is either being used for writing,
- or for uploading. If the file is ready for uploading, no further
- writes will take place until this file has been uploaded.
- This can mean writing might not take place for days until the uploaded
- file is processed. This is correct by-design.
-
- A notable limitation is that the upload is triggered by a location event,
- this is used as an arbitrary and simple trigger. In future, there are
- better events that can be used, such as detecting network activity.
-
- This thread is guarded so that only one instance is active (see the
- mozilla::Atomics used for this).
- */
-class WriteStumbleOnThread : public mozilla::Runnable
-{
-public:
- explicit WriteStumbleOnThread(const nsCString& aDesc)
- : mDesc(aDesc)
- {}
-
- NS_IMETHOD Run() override;
-
- static void UploadEnded(bool deleteUploadFile);
-
- // Used externally to determine if cell+wifi scans should happen
- // (returns false for that case).
- static bool IsFileWaitingForUpload();
-
-private:
- friend class DeleteRunnable;
-
- enum class Partition {
- Begining,
- Middle,
- End,
- Unknown
- };
-
- enum class UploadFileStatus {
- NoFile, Exists, ExistsAndReadyToUpload
- };
-
- ~WriteStumbleOnThread() {}
-
- Partition GetWritePosition();
- UploadFileStatus GetUploadFileStatus();
- void WriteJSON(Partition aPart);
- void Upload();
-
- nsCString mDesc;
-
- // Only run one instance of this
- static mozilla::Atomic<bool> sIsAlreadyRunning;
-
- static mozilla::Atomic<bool> sIsFileWaitingForUpload;
-
- // Limit the upload attempts per day. If the device is rebooted
- // this resets the allowed attempts, which is acceptable.
- struct UploadFreqGuard {
- int attempts;
- int daySinceEpoch;
- };
- static UploadFreqGuard sUploadFreqGuard;
-
-};
-
-#endif
diff --git a/dom/system/gonk/nsIAudioManager.idl b/dom/system/gonk/nsIAudioManager.idl
deleted file mode 100644
index c2eb62b21..000000000
--- a/dom/system/gonk/nsIAudioManager.idl
+++ /dev/null
@@ -1,58 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, builtinclass, uuid(df31c280-1ef1-11e5-867f-0800200c9a66)]
-interface nsIAudioManager : nsISupports
-{
- /**
- * Microphone muted?
- */
- attribute boolean microphoneMuted;
-
- /**
- * Set the phone's audio mode.
- */
- const long PHONE_STATE_INVALID = -2;
- const long PHONE_STATE_CURRENT = -1;
- const long PHONE_STATE_NORMAL = 0;
- const long PHONE_STATE_RINGTONE = 1;
- const long PHONE_STATE_IN_CALL = 2;
- const long PHONE_STATE_IN_COMMUNICATION = 3;
-
- attribute long phoneState;
-
- /**
- * Configure a particular device ("force") to be used for one of the uses
- * (communication, media playback, etc.)
- */
- const long FORCE_NONE = 0; // the default
- const long FORCE_SPEAKER = 1;
- const long FORCE_HEADPHONES = 2;
- const long FORCE_BT_SCO = 3;
- const long FORCE_BT_A2DP = 4;
- const long FORCE_WIRED_ACCESSORY = 5;
- const long FORCE_BT_CAR_DOCK = 6;
- const long FORCE_BT_DESK_DOCK = 7;
- const long FORCE_ANALOG_DOCK = 8;
- const long FORCE_DIGITAL_DOCK = 9;
- const long FORCE_NO_BT_A2DP = 10;
- const long USE_COMMUNICATION = 0;
- const long USE_MEDIA = 1;
- const long USE_RECORD = 2;
- const long USE_DOCK = 3;
-
- void setForceForUse(in long usage, in long force);
- long getForceForUse(in long usage);
-
- /**
- * These functions would be used when we enable the new volume control API
- * (mozAudioChannelManager). The range of volume index is from 0 to N.
- * More details on : https://gist.github.com/evanxd/41d8e2d91c5201a42bfa
- */
- void setAudioChannelVolume(in unsigned long channel, in unsigned long index);
- unsigned long getAudioChannelVolume(in unsigned long channel);
- unsigned long getMaxAudioChannelVolume(in unsigned long channel);
-};
diff --git a/dom/system/gonk/nsIDataCallInterfaceService.idl b/dom/system/gonk/nsIDataCallInterfaceService.idl
deleted file mode 100644
index c387879fa..000000000
--- a/dom/system/gonk/nsIDataCallInterfaceService.idl
+++ /dev/null
@@ -1,268 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(6b66446a-7000-438f-8e1b-b56b4cbf4fa9)]
-interface nsIDataCall : nsISupports
-{
- /**
- * Data call fail cause. One of the nsIDataCallInterface.DATACALL_FAIL_*
- * values.
- */
- readonly attribute long failCause;
-
- /**
- * If failCause != nsIDataCallInterface.DATACALL_FAIL_NONE, this field
- * indicates the suggested retry back-off timer. The unit is milliseconds.
- */
- readonly attribute long suggestedRetryTime;
-
- /**
- * Context ID, uniquely identifies this call.
- */
- readonly attribute long cid;
-
- /**
- * Data call network state. One of the nsIDataCallInterface.DATACALL_STATE_*
- * values.
- */
- readonly attribute long active;
-
- /**
- * Data call connection type. One of the
- * nsIDataCallInterface.DATACALL_PDP_TYPE_* values.
- */
- readonly attribute long pdpType;
-
- /**
- * The network interface name.
- */
- readonly attribute DOMString ifname;
-
- /**
- * A space-delimited list of addresses with optional "/" prefix length.
- */
- readonly attribute DOMString addresses;
-
- /**
- * A space-delimited list of DNS server addresses.
- */
- readonly attribute DOMString dnses;
-
- /**
- * A space-delimited list of default gateway addresses.
- */
- readonly attribute DOMString gateways;
-
- /**
- * A space-delimited list of Proxy Call State Control Function addresses for
- * IMS client.
- */
- readonly attribute DOMString pcscf;
-
- /**
- * MTU received from network, -1 if not set or invalid.
- */
- readonly attribute long mtu;
-};
-
-[scriptable, uuid(e119c54b-9354-4ad6-a1ee-18608bde9320)]
-interface nsIDataCallInterfaceListener : nsISupports
-{
- /**
- * Notify data call interface listeners about unsolicited data call state
- * changes.
- */
- void notifyDataCallListChanged(in uint32_t count,
- [array, size_is(count)] in nsIDataCall
- dataCalls);
-};
-
-[scriptable, uuid(db0b640a-3b3a-4f48-84dc-256e176876c2)]
-interface nsIDataCallCallback : nsISupports
-{
- /**
- * Called when setupDataCall() returns succesfully.
- */
- void notifySetupDataCallSuccess(in nsIDataCall dataCall);
-
- /**
- * Called when getDataCallList() returns succesfully.
- */
- void notifyGetDataCallListSuccess(in uint32_t count,
- [array, size_is(count)] in nsIDataCall
- dataCalls);
- /**
- * Called when request returns succesfully.
- */
- void notifySuccess();
-
- /**
- * Called when request returns error.
- */
- void notifyError(in AString errorMsg);
-};
-
-[scriptable, uuid(ec219021-8623-4b9f-aba5-4db58c60684f)]
-interface nsIDataCallInterface : nsISupports
-{
- /**
- * Data fail causes, defined in TS 24.008.
- */
- const long DATACALL_FAIL_NONE = 0;
- const long DATACALL_FAIL_OPERATOR_BARRED = 0x08;
- const long DATACALL_FAIL_INSUFFICIENT_RESOURCES = 0x1A;
- const long DATACALL_FAIL_MISSING_UKNOWN_APN = 0x1B;
- const long DATACALL_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C;
- const long DATACALL_FAIL_USER_AUTHENTICATION = 0x1D;
- const long DATACALL_FAIL_ACTIVATION_REJECT_GGSN = 0x1E;
- const long DATACALL_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F;
- const long DATACALL_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20;
- const long DATACALL_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21;
- const long DATACALL_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22;
- const long DATACALL_FAIL_NSAPI_IN_USE = 0x23;
- const long DATACALL_FAIL_ONLY_IPV4_ALLOWED = 0x32;
- const long DATACALL_FAIL_ONLY_IPV6_ALLOWED = 0x33;
- const long DATACALL_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34;
- const long DATACALL_FAIL_PROTOCOL_ERRORS = 0x6F;
- /* Not mentioned in the specification */
- const long DATACALL_FAIL_VOICE_REGISTRATION_FAIL = -1;
- const long DATACALL_FAIL_DATA_REGISTRATION_FAIL = -2;
- const long DATACALL_FAIL_SIGNAL_LOST = -3;
- const long DATACALL_FAIL_PREF_RADIO_TECH_CHANGED = -4;
- const long DATACALL_FAIL_RADIO_POWER_OFF = -5;
- const long DATACALL_FAIL_TETHERED_CALL_ACTIVE = -6;
- const long DATACALL_FAIL_ERROR_UNSPECIFIED = 0xFFFF;
-
- /**
- * Data call network state.
- */
- const long DATACALL_STATE_INACTIVE = 0;
- const long DATACALL_STATE_ACTIVE_DOWN = 1;
- const long DATACALL_STATE_ACTIVE_UP = 2;
-
- /**
- * Data call authentication type. Must match the values in ril_consts
- * RIL_DATACALL_AUTH_TO_GECKO array.
- */
- const long DATACALL_AUTH_NONE = 0;
- const long DATACALL_AUTH_PAP = 1;
- const long DATACALL_AUTH_CHAP = 2;
- const long DATACALL_AUTH_PAP_OR_CHAP = 3;
-
- /**
- * Data call protocol type. Must match the values in ril_consts
- * RIL_DATACALL_PDP_TYPES array.
- */
- const long DATACALL_PDP_TYPE_IPV4 = 0;
- const long DATACALL_PDP_TYPE_IPV4V6 = 1;
- const long DATACALL_PDP_TYPE_IPV6 = 2;
-
- /**
- * Reason for deactivating data call.
- */
- const long DATACALL_DEACTIVATE_NO_REASON = 0;
- const long DATACALL_DEACTIVATE_RADIO_SHUTDOWN = 1;
-
- /**
- * Setup data call.
- *
- * @param apn
- * Apn to connect to.
- * @param username
- * Username for apn.
- * @param password
- * Password for apn.
- * @param authType
- * Authentication type. One of the DATACALL_AUTH_* values.
- * @param pdpType
- * Connection type. One of the DATACALL_PDP_TYPE_* values.
- * @param nsIDataCallCallback
- * Called when request is finished.
- *
- * If successful, the notifySetupDataCallSuccess() will be called with the
- * new nsIDataCall.
- *
- * Otherwise, the notifyError() will be called, and the error will be either
- * 'RadioNotAvailable', 'OpNotAllowedBeforeRegToNw',
- * 'OpNotAllowedDuringVoiceCall', 'RequestNotSupported' or 'GenericFailure'.
- */
- void setupDataCall(in AString apn, in AString username,
- in AString password, in long authType,
- in long pdpType,
- in nsIDataCallCallback callback);
-
- /**
- * Deactivate data call.
- *
- * @param cid
- * Context id.
- * @param reason
- * Disconnect Reason. One of the DATACALL_DEACTIVATE_* values.
- * @param nsIDataCallCallback
- * Called when request is finished.
- *
- * If successful, the notifySuccess() will be called.
- *
- * Otherwise, the notifyError() will be called, and the error will be either
- * 'RadioNotAvailable' or 'GenericFailure'.
- */
- void deactivateDataCall(in long cid,
- in long reason,
- in nsIDataCallCallback callback);
-
- /**
- * Get current data call list.
- *
- * @param nsIDataCallCallback
- * Called when request is finished.
- *
- * If successful, the notifyGetDataCallListSuccess() will be called with the
- * list of nsIDataCall(s).
- *
- * Otherwise, the notifyError() will be called, and the error will be either
- * 'RadioNotAvailable' or 'GenericFailure'.
- */
- void getDataCallList(in nsIDataCallCallback callback);
-
- /**
- * Set data registration state.
- *
- * @param attach
- * whether to attach data registration or not.
- * @param nsIDataCallCallback
- * Called when request is finished.
- *
- * If successful, the notifySuccess() will be called.
- *
- * Otherwise, the notifyError() will be called, and the error will be either
- * 'RadioNotAvailable', 'SubscriptionNotAvailable' or 'GenericFailure'.
- */
- void setDataRegistration(in boolean attach,
- in nsIDataCallCallback callback);
-
- /**
- * Register to receive unsolicited events from this nsIDataCallInterface.
- */
- void registerListener(in nsIDataCallInterfaceListener listener);
-
- /**
- * Unregister to stop receiving unsolicited events from this
- * nsIDataCallInterface.
- */
- void unregisterListener(in nsIDataCallInterfaceListener listener);
-};
-
-[scriptable, uuid(64700406-7429-4743-a6ae-f82e9877fd0d)]
-interface nsIDataCallInterfaceService : nsISupports
-{
- /**
- * Get the corresponding data call interface.
- *
- * @param clientId
- * clientId of the data call interface to get.
- */
- nsIDataCallInterface getDataCallInterface(in long clientId);
-}; \ No newline at end of file
diff --git a/dom/system/gonk/nsIDataCallManager.idl b/dom/system/gonk/nsIDataCallManager.idl
deleted file mode 100644
index de8477801..000000000
--- a/dom/system/gonk/nsIDataCallManager.idl
+++ /dev/null
@@ -1,81 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsINetworkInterface.idl"
-
-[scriptable, uuid(b8bcd6aa-5b06-4362-a68c-317878429e51)]
-interface nsIRilNetworkInfo : nsINetworkInfo
-{
- readonly attribute unsigned long serviceId;
- readonly attribute DOMString iccId;
-
- /* The following attributes are for MMS proxy settings. */
- readonly attribute DOMString mmsc; // Empty string if not set.
- readonly attribute DOMString mmsProxy; // Empty string if not set.
- readonly attribute long mmsPort; // -1 if not set.
-
- /**
- * Get the list of pcscf addresses, could be IPv4 or IPv6.
- *
- * @param count
- * The length of the list of pcscf addresses.
- *
- * @returns the list of pcscf addresses.
- */
- void getPcscf([optional] out unsigned long count,
- [array, size_is(count), retval] out wstring pcscf);
-};
-
-[scriptable, function, uuid(cb2f0f5b-67f4-4c14-93e8-01e66b630464)]
-interface nsIDeactivateDataCallsCallback : nsISupports
-{
- /**
- * Callback function used to notify when all data calls are disconnected.
- */
- void notifyDataCallsDisconnected();
-};
-
-[scriptable, uuid(e3feec20-36b4-47de-a7a5-e32a65f20186)]
-interface nsIDataCallHandler : nsISupports
-{
- /**
- * PDP APIs
- *
- * @param networkType
- * Mobile network type, that is,
- * nsINetworkInterface.NETWORK_TYPE_MOBILE or one of the
- * nsINetworkInterface.NETWORK_TYPE_MOBILE_* values.
- */
- void setupDataCallByType(in long networkType);
- void deactivateDataCallByType(in long networkType);
- long getDataCallStateByType(in long networkType);
-
- /**
- * Deactivate all data calls.
- *
- * @param callback
- * Callback to notify when all data calls are disconnected.
- */
- void deactivateDataCalls(in nsIDeactivateDataCallsCallback callback);
-
- /**
- * Called to reconsider data call state.
- */
- void updateRILNetworkInterface();
-};
-
-[scriptable, uuid(2c46e37d-88dc-4d25-bb37-e1c0d3e9cb5f)]
-interface nsIDataCallManager : nsISupports
-{
- readonly attribute long dataDefaultServiceId;
-
- /**
- * Get the corresponding data call handler.
- *
- * @param clientId
- * clientId of the data call handler to get.
- */
- nsIDataCallHandler getDataCallHandler(in unsigned long clientId);
-}; \ No newline at end of file
diff --git a/dom/system/gonk/nsIGonkDataCallInterfaceService.idl b/dom/system/gonk/nsIGonkDataCallInterfaceService.idl
deleted file mode 100644
index 240ca6bab..000000000
--- a/dom/system/gonk/nsIGonkDataCallInterfaceService.idl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDataCallInterfaceService.idl"
-
-[scriptable, uuid(f008d00c-e2b8-49b2-8f88-19111577938e)]
-interface nsIGonkDataCallInterfaceService : nsIDataCallInterfaceService
-{
- /**
- * Called by RadioInterface or lower layer to notify about data call list
- * changes.
- */
- void notifyDataCallListChanged(in unsigned long clientId,
- in uint32_t count,
- [array, size_is(count)] in nsIDataCall
- dataCalls);
-}; \ No newline at end of file
diff --git a/dom/system/gonk/nsINetworkInterface.idl b/dom/system/gonk/nsINetworkInterface.idl
deleted file mode 100644
index bd40e751a..000000000
--- a/dom/system/gonk/nsINetworkInterface.idl
+++ /dev/null
@@ -1,108 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(4816a559-5620-4cb5-8433-ff0b25e6622f)]
-interface nsINetworkInfo : nsISupports
-{
- const long NETWORK_STATE_UNKNOWN = -1;
- const long NETWORK_STATE_CONNECTING = 0;
- const long NETWORK_STATE_CONNECTED = 1;
- const long NETWORK_STATE_DISCONNECTING = 2;
- const long NETWORK_STATE_DISCONNECTED = 3;
- const long NETWORK_STATE_ENABLED = 4;
- const long NETWORK_STATE_DISABLED = 5;
-
- /**
- * Current network state, one of the NETWORK_STATE_* constants.
- *
- * When this changes, network interface implementations notify with
- * updateNetworkInterface() API.
- */
- readonly attribute long state;
-
- const long NETWORK_TYPE_UNKNOWN = -1;
- const long NETWORK_TYPE_WIFI = 0;
- const long NETWORK_TYPE_MOBILE = 1;
- const long NETWORK_TYPE_MOBILE_MMS = 2;
- const long NETWORK_TYPE_MOBILE_SUPL = 3;
- const long NETWORK_TYPE_WIFI_P2P = 4;
- const long NETWORK_TYPE_MOBILE_IMS = 5;
- const long NETWORK_TYPE_MOBILE_DUN = 6;
- const long NETWORK_TYPE_MOBILE_FOTA = 7;
- const long NETWORK_TYPE_ETHERNET = 8;
-
- /**
- * Network type. One of the NETWORK_TYPE_* constants.
- */
- readonly attribute long type;
-
- /**
- * Interface name of the network interface this network info belongs to.
- */
- readonly attribute DOMString name;
-
- /**
- * Get the list of ip addresses and prefix lengths, ip address could be IPv4
- * or IPv6, typically 1 IPv4 or 1 IPv6 or one of each.
- *
- * @param ips
- * The list of ip addresses retrieved.
- * @param prefixLengths
- * The list of prefix lengths retrieved.
- *
- * @returns the length of the lists.
- */
- void getAddresses([array, size_is(count)] out wstring ips,
- [array, size_is(count)] out unsigned long prefixLengths,
- [retval] out unsigned long count);
-
- /**
- * Get the list of gateways, could be IPv4 or IPv6, typically 1 IPv4 or 1
- * IPv6 or one of each.
- *
- * @param count
- * The length of the list of gateways
- *
- * @returns the list of gateways.
- */
- void getGateways([optional] out unsigned long count,
- [array, size_is(count), retval] out wstring gateways);
-
- /**
- * Get the list of dnses, could be IPv4 or IPv6.
- *
- * @param count
- * The length of the list of dnses.
- *
- * @returns the list of dnses.
- */
- void getDnses([optional] out unsigned long count,
- [array, size_is(count), retval] out wstring dnses);
-};
-
-[scriptable, uuid(8b1345fa-b34c-41b3-8d21-09f961bf8887)]
-interface nsINetworkInterface : nsISupports
-{
- /**
- * The network information about this network interface.
- */
- readonly attribute nsINetworkInfo info;
-
- /**
- * The host name of the http proxy server.
- */
- readonly attribute DOMString httpProxyHost;
-
- /*
- * The port number of the http proxy server.
- */
- readonly attribute long httpProxyPort;
-
- /*
- * The Maximun Transmit Unit for this network interface, -1 if not set.
- */
- readonly attribute long mtu;
-};
diff --git a/dom/system/gonk/nsINetworkInterfaceListService.idl b/dom/system/gonk/nsINetworkInterfaceListService.idl
deleted file mode 100644
index 0c224842e..000000000
--- a/dom/system/gonk/nsINetworkInterfaceListService.idl
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsINetworkInfo;
-
-[scriptable, uuid(55779d32-1e28-4f43-af87-09d04bc3cce9)]
-interface nsINetworkInterfaceList : nsISupports
-{
- /**
- * Number of the network interfaces that is available.
- */
- long getNumberOfInterface();
-
- /**
- * Get the i-th interface info info from the list.
- * @param interfaceIndex index of interface, from 0 to number of interface - 1.
- */
- nsINetworkInfo getInterfaceInfo(in long interfaceIndex);
-};
-
-[scriptable, uuid(21d7fc8b-28c4-4a4f-a15e-1f9defbc2cec)]
-interface nsINetworkInterfaceListService : nsISupports
-{
- const long LIST_NOT_INCLUDE_MMS_INTERFACES = (1 << 0);
- const long LIST_NOT_INCLUDE_SUPL_INTERFACES = (1 << 1);
- const long LIST_NOT_INCLUDE_IMS_INTERFACES = (1 << 2);
- const long LIST_NOT_INCLUDE_DUN_INTERFACES = (1 << 3);
- const long LIST_NOT_INCLUDE_FOTA_INTERFACES = (1 << 4);
-
- /**
- * Obtain a list of network interfaces that satisfy the specified condition.
- * @param condition flags that specify the interfaces to be returned. This
- * can be OR combination of LIST_* flags, or zero to make all available
- * interfaces returned.
- */
- nsINetworkInterfaceList getDataInterfaceList(in long condition);
-};
diff --git a/dom/system/gonk/nsINetworkManager.idl b/dom/system/gonk/nsINetworkManager.idl
deleted file mode 100644
index 0da123796..000000000
--- a/dom/system/gonk/nsINetworkManager.idl
+++ /dev/null
@@ -1,135 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsINetworkInfo;
-interface nsINetworkInterface;
-
-/**
- * Manage network interfaces.
- */
-[scriptable, uuid(1ba9346b-53b5-4660-9dc6-58f0b258d0a6)]
-interface nsINetworkManager : nsISupports
-{
- /**
- * Register the given network interface with the network manager.
- *
- * Consumers will be notified with the 'network-interface-registered'
- * observer notification.
- *
- * Throws if there's already an interface registered with the same network id.
- *
- * @param network
- * Network interface to register.
- */
- void registerNetworkInterface(in nsINetworkInterface network);
-
- /**
- * Update the routes and DNSes according the state of the given network.
- *
- * Consumers will be notified with the 'network-connection-state-changed'
- * observer notification.
- *
- * Throws an exception if the specified network interface object isn't
- * registered.
- *
- * @param network
- * Network interface to update.
- */
- void updateNetworkInterface(in nsINetworkInterface network);
-
- /**
- * Unregister the given network interface from the network manager.
- *
- * Consumers will be notified with the 'network-interface-unregistered'
- * observer notification.
- *
- * Throws an exception if the specified network interface object isn't
- * registered.
- *
- * @param network
- * Network interface to unregister.
- */
- void unregisterNetworkInterface(in nsINetworkInterface network);
-
- /**
- * Object containing all known network information, keyed by their
- * network id. Network id is composed of a sub-id + '-' + network
- * type. For mobile network types, sub-id is 'ril' + service id; for
- * non-mobile network types, sub-id is always 'device'.
- */
- readonly attribute jsval allNetworkInfo;
-
- /**
- * Priority list of network types. An array of
- * nsINetworkInterface::NETWORK_TYPE_* constants.
- *
- * The piror position of the type indicates the higher priority. The priority
- * is used to determine route when there are multiple connected networks.
- */
- attribute jsval networkTypePriorityList;
-
- /**
- * The preferred network type. One of the
- * nsINetworkInterface::NETWORK_TYPE_* constants.
- *
- * This attribute is used for setting default route to favor
- * interfaces with given type. This can be overriden by calling
- * overrideDefaultRoute().
- */
- attribute long preferredNetworkType;
-
- /**
- * The network information of the network interface handling all network
- * traffic.
- *
- * When this changes, the 'network-active-changed' observer
- * notification is dispatched.
- */
- readonly attribute nsINetworkInfo activeNetworkInfo;
-
- /**
- * Override the default behaviour for preferredNetworkType and route
- * all network traffic through the the specified interface.
- *
- * Consumers can observe changes to the active network by subscribing to
- * the 'network-active-changed' observer notification.
- *
- * @param network
- * Network to route all network traffic to. If this is null,
- * a previous override is canceled.
- */
- long overrideActive(in nsINetworkInterface network);
-
- /**
- * Add host route to the specified network into routing table.
- *
- * @param network
- * The network information for the host to be routed to.
- * @param host
- * The host to be added.
- * The host will be resolved in advance if it's not an ip-address.
- *
- * @return a Promise
- * resolved if added; rejected, otherwise.
- */
- jsval addHostRoute(in nsINetworkInfo network,
- in DOMString host);
-
- /**
- * Remove host route to the specified network from routing table.
- *
- * @param network
- * The network information for the routing to be removed from.
- * @param host
- * The host routed to the network.
- * The host will be resolved in advance if it's not an ip-address.
- *
- * @return a Promise
- * resolved if removed; rejected, otherwise.
- */
- jsval removeHostRoute(in nsINetworkInfo network,
- in DOMString host);
-};
diff --git a/dom/system/gonk/nsINetworkService.idl b/dom/system/gonk/nsINetworkService.idl
deleted file mode 100644
index 50a468494..000000000
--- a/dom/system/gonk/nsINetworkService.idl
+++ /dev/null
@@ -1,619 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, function, uuid(91824160-fb25-11e1-a21f-0800200c9a66)]
-interface nsIWifiTetheringCallback : nsISupports
-{
- /**
- * Callback function used to report status to WifiManager.
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void wifiTetheringEnabledChange(in jsval error);
-};
-
-[scriptable, function, uuid(9c128e68-5e4b-4626-bb88-84ec54cce5d8)]
-interface nsINetworkStatsCallback : nsISupports
-{
- void networkStatsAvailable(in boolean success,
- in unsigned long rxBytes,
- in unsigned long txBytes,
- in unsigned long long timestamp);
-};
-
-[scriptable, function, uuid(0706bfa2-ac2d-11e2-9a8d-7b6d988d4767)]
-interface nsINetworkUsageAlarmCallback : nsISupports
-{
- void networkUsageAlarmResult(in jsval error);
-};
-
-[scriptable, function, uuid(9ede8720-f8bc-11e2-b778-0800200c9a66)]
-interface nsIWifiOperationModeCallback : nsISupports
-{
- /**
- * Callback function used to report result to WifiManager.
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void wifiOperationModeResult(in jsval error);
-};
-
-[scriptable, function, uuid(097878b0-19fc-11e3-8ffd-0800200c9a66)]
-interface nsISetDhcpServerCallback : nsISupports
-{
- /**
- * Callback function used to report the DHCP server set result
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void dhcpServerResult(in jsval error);
-};
-
-[scriptable, function, uuid(32407c50-46c7-11e3-8f96-0800200c9a66)]
-interface nsIUsbTetheringCallback : nsISupports
-{
- /**
- * Callback function used to report status of enabling usb tethering.
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void usbTetheringEnabledChange(in jsval error);
-};
-
-[scriptable, function, uuid(055fd560-46ad-11e3-8f96-0800200c9a66)]
-interface nsIEnableUsbRndisCallback : nsISupports
-{
- /**
- * Callback function used to report the status of enabling/disabling usb rndis.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- * @param enable
- * Boolean to indicate if we are enabling or disabling usb rndis.
- */
- void enableUsbRndisResult(in boolean success, in boolean enable);
-};
-
-[scriptable, function, uuid(4f08cc30-46ad-11e3-8f96-0800200c9a66)]
-interface nsIUpdateUpStreamCallback : nsISupports
-{
- /**
- * Callback function used to report the result of updating upstream.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- * @param externalIfname
- * The external interface name.
- */
- void updateUpStreamResult(in boolean success, in DOMString externalIfname);
-};
-
-[scriptable, function, uuid(eedca6c0-1310-11e4-9191-0800200c9a66)]
-interface nsISetDnsCallback : nsISupports
-{
- /**
- * Callback function used to report the result of setting DNS server.
- *
- * @param error
- * An error message if the operation wasn't successful,
- * or `null` if it was.
- */
- void setDnsResult(in jsval error);
-};
-
-[scriptable, function, uuid(5d0e1a60-1187-11e4-9191-0800200c9a66)]
-interface nsINativeCommandCallback : nsISupports
-{
- /**
- * Callback function used to report the result of a network native command.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- */
- void nativeCommandResult(in boolean success);
-};
-
-[scriptable, function, uuid(694abb80-1187-11e4-9191-0800200c9a66)]
-interface nsIDhcpRequestCallback : nsISupports
-{
- /**
- * Callback function used to report the result of DHCP client request.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- *
- * @param dhcpInfo
- * An object to represent the successful DHCP request:
- *
- * - gateway_str: string
- * - dns1_str: string
- * - dns2_str: string
- * - mask_str: string
- * - server_str: string
- * - vendor_str: string
- * - lease: long
- * - mask: long
- * - ipaddr: long
- * - gateway: long
- * - dns1: long
- * - dns2: long
- * - server: long
- */
- void dhcpRequestResult(in boolean success, in jsval dhcpInfo);
-};
-
-[scriptable, function, uuid(88e3ee22-f1b3-4fa0-8a5d-793fb827c42c)]
-interface nsIGetInterfacesCallback : nsISupports
-{
- /**
- * Callback function used to return the list of existing network interfaces.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- * @param interfaceList
- * An array of interface name.
- */
- void getInterfacesResult(in boolean success, in jsval interfaceList);
-};
-
-[scriptable, function, uuid(064e02a3-d2c0-42c5-a293-1efa84056100)]
-interface nsIGetInterfaceConfigCallback : nsISupports
-{
- /**
- * Callback function used to return the network config of a given interface.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- * @param result
- * .ip: Ip address.
- * .prefix: mask length.
- * .link: network link properties.
- * .mac: mac address.
- */
- void getInterfaceConfigResult(in boolean success, in jsval result);
-};
-
-[scriptable, function, uuid(b370f360-6ba8-4517-a4f9-31e8f004ee91)]
-interface nsISetInterfaceConfigCallback : nsISupports
-{
- /**
- * Callback function used to set network config for a specified interface.
- *
- * @param success
- * Boolean to indicate the operation is successful or not.
- */
- void setInterfaceConfigResult(in boolean success);
-};
-
-/**
- * Provide network services.
- */
-[scriptable, uuid(e16fe98f-9f63-48fe-82ba-8d1a1b7c6a57)]
-interface nsINetworkService : nsISupports
-{
- const long MODIFY_ROUTE_ADD = 0;
- const long MODIFY_ROUTE_REMOVE = 1;
-
- /**
- * Enable or disable Wifi Tethering
- *
- * @param enabled
- * Boolean that indicates whether tethering should be enabled (true) or disabled (false).
- * @param config
- * The Wifi Tethering configuration from settings db.
- * @param callback
- * Callback function used to report status to WifiManager.
- */
- void setWifiTethering(in boolean enabled,
- in jsval config,
- in nsIWifiTetheringCallback callback);
-
- /**
- * Enable or disable DHCP server
- *
- * @param enabled
- * Boolean that indicates enabling or disabling DHCP server.
- *
- * @param config
- * Config used to enable the DHCP server. It contains
- * .startIp start of the ip lease range (string)
- * .endIp end of the ip lease range (string)
- * .serverIp ip of the DHCP server (string)
- * .maskLength the length of the subnet mask
- * .ifname the interface name
- *
- * As for disabling the DHCP server, put this value |null|.
- *
- * @param callback
- * Callback function used to report status.
- */
- void setDhcpServer(in boolean enabled,
- in jsval config,
- in nsISetDhcpServerCallback callback);
-
-
- /**
- * Retrieve network interface stats.
- *
- * @param networkName
- * Select the Network interface to request estats.
- *
- * @param callback
- * Callback to notify result and provide stats, connectionType
- * and the date when stats are retrieved
- */
- void getNetworkInterfaceStats(in DOMString networkName, in nsINetworkStatsCallback callback);
-
- /**
- * Set Alarm of usage per interface
- *
- * @param networkName
- * Select the Network interface to set an alarm.
- *
- * @param threshold
- * Amount of data that will trigger the alarm.
- *
- * @param callback
- * Callback to notify the result.
- *
- * @return false if there is no interface registered for the networkType param.
- */
- boolean setNetworkInterfaceAlarm(in DOMString networkName,
- in long long threshold,
- in nsINetworkUsageAlarmCallback callback);
-
- /**
- * Reload Wifi firmware to specific operation mode.
- *
- * @param interfaceName
- * Wifi Network interface name.
- *
- * @param mode
- * AP - Access pointer mode.
- * P2P - Peer to peer connection mode.
- * STA - Station mode.
- *
- * @param callback
- * Callback to notify Wifi firmware reload result.
- */
- void setWifiOperationMode(in DOMString interfaceName,
- in DOMString mode,
- in nsIWifiOperationModeCallback callback);
-
- /**
- * Set USB tethering.
- *
- * @param enabled
- * Boolean to indicate we are going to enable or disable usb tethering.
- * @param config
- * The usb tethering configuration.
- * @param callback
- * Callback function used to report the result enabling/disabling usb tethering.
- */
- void setUSBTethering(in boolean enabled,
- in jsval config,
- in nsIUsbTetheringCallback callback);
-
- /**
- * Reset routing table.
- *
- * @param interfaceName
- * The name of the network interface we want to remove from the routing
- * table.
- *
- * @param callback
- * Callback to notify the result of resetting routing table.
- */
- void resetRoutingTable(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Set DNS.
- *
- * @param interfaceName
- * The network interface name of the DNS we want to set.
- * @param dnsesCount
- * Number of elements in dnses.
- * @param dnses
- * Dnses to set.
- * @param gatewaysCount
- * Number of elements in gateways.
- * @param gateways
- * Gateways for the dnses, the most suitable, usually the one with the
- * same address family, will be selected for each dns.
- *
- * @param callback
- * Callback to notify the result of setting DNS server.
- */
- void setDNS(in DOMString interfaceName,
- in unsigned long dnsesCount,
- [array, size_is(dnsesCount)] in wstring dnses,
- in unsigned long gatewaysCount,
- [array, size_is(gatewaysCount)] in wstring gateways,
- in nsISetDnsCallback callback);
-
- /**
- * Set default route.
- *
- * @param interfaceName
- * The network interface name of the default route we want to set.
- * @param count
- * Number of elements in gateways.
- * @param gateways
- * Default gateways for setting default route.
- *
- * @param callback
- * Callback to notify the result of setting default route.
- */
- void setDefaultRoute(in DOMString interfaceName,
- in unsigned long count,
- [array, size_is(count)] in wstring gateways,
- in nsINativeCommandCallback callback);
-
- /**
- * Remove default route.
- *
- * @param interfaceName
- * The network interface name of the default route we want to remove.
- * @param count
- * Number of elements in gateways.
- * @param gatways
- * Default gateways for removing default route.
- *
- * @param callback
- * Callback to notify the result of removing default route.
- */
- void removeDefaultRoute(in DOMString interfaceName,
- in unsigned long count,
- [array, size_is(count)] in wstring gateways,
- in nsINativeCommandCallback callback);
-
- /**
- * Modify route.
- *
- * @param action
- * nsINetworkService.MODIFY_ROUTE_ADD to add route and
- * nsINetworkService.MODIFY_ROUTE_REMOVE to remove.
- * @param interfaceName
- * Network interface name for the output of the host route.
- * @param host
- * Host ip we want to remove route for.
- * @param prefixLength
- * The prefix length of the route we'd like to modify.
- * @param [optional] gateway
- * Gateway ip for the output of the host route.
- *
- * @return A deferred promise that resolves on success or rejects with a
- * specified reason otherwise.
- */
- jsval modifyRoute(in long action,
- in DOMString interfaceName,
- in DOMString host,
- in long prefixLength,
- [optional] in DOMString gateway);
-
- /**
- * Add route to secondary routing table.
- *
- * @param interfaceName
- * The network interface for this route.
- * @param route
- * The route info should have the following fields:
- * .ip: destination ip address
- * .prefix: destination prefix
- * .gateway: gateway ip address
- */
- void addSecondaryRoute(in DOMString interfaceName, in jsval route,
- in nsINativeCommandCallback callback);
-
- /**
- * Remove route from secondary routing table.
- *
- * @param interfaceName
- * The network interface for the route we want to remove.
- * @param route
- * The route info should have the following fields:
- * .ip: destination ip address
- * .prefix: destination prefix
- * .gateway: gateway ip address
- */
- void removeSecondaryRoute(in DOMString interfaceName, in jsval route,
- in nsINativeCommandCallback callback);
-
- /**
- * Enable or disable usb rndis.
- *
- * @param enable
- * Boolean to indicate we want enable or disable usb rndis.
- * @param callback
- * Callback function to report the result.
- */
- void enableUsbRndis(in boolean enable,
- in nsIEnableUsbRndisCallback callback);
-
- /**
- * Update upstream.
- *
- * @param previous
- * The previous internal and external interface.
- * @param current
- * The current internal and external interface.
- * @param callback
- * Callback function to report the result.
- */
- void updateUpStream(in jsval previous,
- in jsval current,
- in nsIUpdateUpStreamCallback callback);
-
- /*
- * Obtain interfaces list.
- *
- * @param callback
- * Callback function to return the result.
- */
- void getInterfaces(in nsIGetInterfacesCallback callback);
-
- /**
- * Get config of a network interface.
- *
- * @param ifname
- * Target interface.
- * @param callback
- * Callback function to report the result.
- */
- void getInterfaceConfig(in DOMString ifname, in nsIGetInterfaceConfigCallback callback);
-
- /**
- * Set config for a network interface.
- *
- * @param config
- * .ifname: Target interface.
- * .ip: Ip address.
- * .prefix: mask length.
- * .link: network link properties.
- * @param callback
- * Callback function to report the result.
- */
- void setInterfaceConfig(in jsval config, in nsISetInterfaceConfigCallback callback);
-
- /**
- * Configure a network interface.
- *
- * @param config
- * An object containing the detail that we want to configure the interface:
- *
- * - ifname: string
- * - ipaddr: long
- * - mask: long
- * - gateway: long
- * - dns1: long
- * - dns2: long
- *
- * @param callback
- * Callback to notify the result of configurating network interface.
- */
- void configureInterface(in jsval config,
- in nsINativeCommandCallback callback);
-
- /**
- * Issue a DHCP client request.
- *
- * @param networkInterface
- * The network interface which we wnat to do the DHCP request on.
- *
- * @param callback
- * Callback to notify the result of the DHCP request.
- */
- void dhcpRequest(in DOMString interfaceName,
- in nsIDhcpRequestCallback callback);
-
- /**
- * Stop Dhcp daemon.
- *
- * @param ifname
- * Target interface.
- *
- * @param callback
- * Callback to notify the result of stopping dhcp request.
- */
- void stopDhcp(in DOMString ifname,
- in nsINativeCommandCallback callback);
-
- /**
- * Enable a network interface.
- *
- * @param networkInterface
- * The network interface name which we want to enable.
- *
- * @param callback
- * Callback to notify the result of disabling network interface.
- */
- void enableInterface(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Disable a network interface.
- *
- * @param networkInterface
- * The network interface name which we want to disable.
- *
- * @param callback
- * Callback to notify the result of disabling network interface.
- */
- void disableInterface(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Reset all connections on a specified network interface.
- *
- * @param interfaceName
- * The network interface name which we want to reset.
- *
- * @param callback
- * Callback to notify the result of resetting connections.
- */
- void resetConnections(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Create network (required to call prior to any networking operation).
- *
- * @param interfaceName
- * The network interface name which we want to create network for.
- *
- * @param callback
- * Callback to notify the result of creating network.
- */
- void createNetwork(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Destroy network.
- *
- * @param interfaceName
- * The network interface name of the network we want to destroy.
- *
- * @param callback
- * Callback to notify the result of destroying network.
- */
- void destroyNetwork(in DOMString interfaceName,
- in nsINativeCommandCallback callback);
-
- /**
- * Query the netId associated with given network interface name.
- *
- * @param interfaceName
- * The network interface name which we want to query.
- *
- * @return A deferred promise that resolves with a string to indicate.
- * the queried netId on success and rejects if the interface name
- * is invalid.
- *
- */
- jsval getNetId(in DOMString interfaceName);
-
- /**
- * Set maximum transmission unit on a network interface.
- *
- * @param interfaceName
- * The name of the network interface that we want to set mtu.
- * @param mtu
- * Size of maximum tranmission unit.
- *
- * @param callback
- * Callback to notify the result of setting mtu.
- */
- void setMtu(in DOMString interfaceName, in long mtu,
- in nsINativeCommandCallback callback);
-};
diff --git a/dom/system/gonk/nsINetworkWorker.idl b/dom/system/gonk/nsINetworkWorker.idl
deleted file mode 100644
index 8fe19be69..000000000
--- a/dom/system/gonk/nsINetworkWorker.idl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(98e31d3b-6cad-4cab-b4b3-4afff566ea65)]
-interface nsINetworkEventListener : nsISupports {
- void onEvent(in jsval result);
-};
-
-[scriptable, uuid(f9d9c694-0aac-4f9a-98ac-7788f954239a)]
-interface nsINetworkWorker : nsISupports {
- void start(in nsINetworkEventListener listener);
- void shutdown();
- [implicit_jscontext]
- void postMessage(in jsval options);
-};
diff --git a/dom/system/gonk/nsIRadioInterfaceLayer.idl b/dom/system/gonk/nsIRadioInterfaceLayer.idl
deleted file mode 100644
index 168fe3894..000000000
--- a/dom/system/gonk/nsIRadioInterfaceLayer.idl
+++ /dev/null
@@ -1,53 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIIccInfo;
-interface nsIMobileConnectionInfo;
-interface nsIMobileMessageCallback;
-
-[scriptable, function, uuid(3bc96351-53b0-47a1-a888-c74c64b60f25)]
-interface nsIRilSendWorkerMessageCallback : nsISupports
-{
- boolean handleResponse(in jsval response);
-};
-
-[scriptable, uuid(1a3ef88a-e4d1-11e4-8512-176220f2b32b)]
-interface nsIRadioInterface : nsISupports
-{
- /**
- * PDP APIs
- *
- * @param networkType
- * Mobile network type, that is, nsINetworkInterface.NETWORK_TYPE_MOBILE
- * or one of the nsINetworkInterface.NETWORK_TYPE_MOBILE_* values.
- */
- void setupDataCallByType(in long networkType);
- void deactivateDataCallByType(in long networkType);
- long getDataCallStateByType(in long networkType);
-
- void updateRILNetworkInterface();
-
- void sendWorkerMessage(in DOMString type,
- [optional] in jsval message,
- [optional] in nsIRilSendWorkerMessageCallback callback);
-};
-
-%{C++
-#define NS_RADIOINTERFACELAYER_CID \
- { 0x2d831c8d, 0x6017, 0x435b, \
- { 0xa8, 0x0c, 0xe5, 0xd4, 0x22, 0x81, 0x0c, 0xea } }
-#define NS_RADIOINTERFACELAYER_CONTRACTID "@mozilla.org/ril;1"
-%}
-
-[scriptable, uuid(09730e0d-75bb-4f21-8540-062a2eadc8ff)]
-interface nsIRadioInterfaceLayer : nsISupports
-{
- readonly attribute unsigned long numRadioInterfaces;
-
- nsIRadioInterface getRadioInterface(in unsigned long clientId);
-
- void setMicrophoneMuted(in boolean muted);
-};
diff --git a/dom/system/gonk/nsISystemWorkerManager.idl b/dom/system/gonk/nsISystemWorkerManager.idl
deleted file mode 100644
index a77e253e4..000000000
--- a/dom/system/gonk/nsISystemWorkerManager.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-/**
- * Information about networks that is exposed to network manager API consumers.
- */
-[scriptable, builtinclass, uuid(4984b669-0ee0-4809-ae96-3358a325a6b0)]
-interface nsISystemWorkerManager : nsISupports
-{
- [implicit_jscontext]
- void registerRilWorker(in unsigned long aClientId,
- in jsval aWorker);
-};
diff --git a/dom/system/gonk/nsITetheringService.idl b/dom/system/gonk/nsITetheringService.idl
deleted file mode 100644
index 530ab0069..000000000
--- a/dom/system/gonk/nsITetheringService.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsINetworkInterface;
-interface nsIWifiTetheringCallback;
-
-[scriptable, uuid(779de2d3-6d29-4ee6-b069-6251839f757a)]
-interface nsITetheringService : nsISupports
-{
- const long TETHERING_STATE_INACTIVE = 0;
- const long TETHERING_STATE_WIFI = 1;
- const long TETHERING_STATE_USB = 2;
-
- /**
- * Current tethering state. One of the TETHERING_STATE_* constants.
- */
- readonly attribute long state;
-
- /**
- * Enable or disable Wifi Tethering.
- *
- * @param enabled
- * Boolean that indicates whether tethering should be enabled (true) or
- * disabled (false).
- * @param interfaceName
- * The Wifi network interface name for internal interface.
- * @param config
- * The Wifi Tethering configuration from settings db.
- * @param callback
- * Callback function used to report status to WifiManager.
- */
- void setWifiTethering(in boolean enabled,
- in DOMString interfaceName,
- in jsval config,
- in nsIWifiTetheringCallback callback);
-}; \ No newline at end of file
diff --git a/dom/system/gonk/nsIVolume.idl b/dom/system/gonk/nsIVolume.idl
deleted file mode 100644
index 60785f0a4..000000000
--- a/dom/system/gonk/nsIVolume.idl
+++ /dev/null
@@ -1,114 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsIVolumeStat.idl"
-
-[scriptable, uuid(EE752CB8-8FD7-11E4-A602-70221D5D46B0)]
-interface nsIVolume : nsISupports
-{
- // These MUST match the states from android's system/vold/Volume.h header
- // Note: Changes made to the STATE_xxx names should also be reflected in the
- // NS_VolumeStateStr function found in Volume.cpp
- const long STATE_INIT = -1;
- const long STATE_NOMEDIA = 0;
- const long STATE_IDLE = 1;
- const long STATE_PENDING = 2;
- const long STATE_CHECKING = 3;
- const long STATE_MOUNTED = 4;
- const long STATE_UNMOUNTING = 5;
- const long STATE_FORMATTING = 6;
- const long STATE_SHARED = 7;
- const long STATE_SHAREDMNT = 8;
- const long STATE_CHECKMNT = 100;
- const long STATE_MOUNT_FAIL = 101;
-
- // The name of the volume. Often there is only one volume, called sdcard.
- // But some phones support multiple volumes.
- readonly attribute DOMString name;
-
- // The mount point is the path on the system where the volume is mounted
- // and is only valid when state == STATE_MOUNTED.
- readonly attribute DOMString mountPoint;
-
- // Reflects the current state of the volume, using STATE_xxx constants
- // from above.
- readonly attribute long state;
-
- // mountGeneration is a unique number which is used distinguish between
- // periods of time that a volume is in the mounted state. Each time a
- // volume transitions to the mounted state, the mountGeneration will
- // be different from the last time it transitioned to the mounted state.
- readonly attribute long mountGeneration;
-
- // While a volume is mounted, it can be locked, preventing it from being
- // shared with the PC. To lock a volume, acquire an MozWakeLock
- // using the name of this attribute. Note that mountLockName changes
- // every time the mountGeneration changes, so you'll need to reacquire
- // the wakelock every time the volume becomes mounted.
- readonly attribute DOMString mountLockName;
-
- // Determines if a mountlock is currently being held against this volume.
- readonly attribute boolean isMountLocked;
-
- // Determines if media is actually present or not. Note, that when an sdcard
- // is ejected, it may go through several tranistory states before finally
- // arriving at STATE_NOMEDIA. So isMediaPresent may be false even when the
- // current state isn't STATE_NOMEDIA.
- readonly attribute boolean isMediaPresent;
-
- // Determines if the volume is currently being shared. This covers off
- // more than just state == STATE_SHARED. isSharing will return true from the
- // time that the volume leaves the mounted state, until it gets back to
- // mounted, nomedia, or formatting states. This attribute is to allow
- // device storage to suppress unwanted 'unavailable' status when
- // transitioning from mounted to sharing and back again.
- readonly attribute boolean isSharing;
-
- // Determines if the volume is currently formatting. This sets true once
- // mFormatRequest == true and mState == STATE_MOUNTED, and sets false
- // once the volume has been formatted and mounted again.
- readonly attribute boolean isFormatting;
-
- readonly attribute boolean isUnmounting;
-
- nsIVolumeStat getStats();
-
- // Formats the volume in IO thread, if the volume is ready to be formatted.
- // Automounter will unmount it, format it and then mount it again.
- void format();
-
- // Mounts the volume in IO thread, if the volume is already unmounted.
- // Automounter will mount it. Otherwise Automounter will skip this.
- void mount();
-
- // Unmounts the volume in IO thread, if the volume is already mounted.
- // Automounter will unmount it. Otherwise Automounter will skip this.
- void unmount();
-
- // Whether this is a fake volume.
- readonly attribute boolean isFake;
-
- // Whether this is a removable volume
- readonly attribute boolean isRemovable;
-
- // Whether this is a hot-swappable volume
- readonly attribute boolean isHotSwappable;
-
-};
-
-%{C++
-// For use with the ObserverService
-#define NS_VOLUME_STATE_CHANGED "volume-state-changed"
-#define NS_VOLUME_REMOVED "volume-removed"
-
-namespace mozilla {
-namespace system {
-
-// Convert a state into a loggable/printable string.
-const char* NS_VolumeStateStr(int32_t aState);
-
-} // system
-} // mozilla
-%}
diff --git a/dom/system/gonk/nsIVolumeMountLock.idl b/dom/system/gonk/nsIVolumeMountLock.idl
deleted file mode 100644
index 0a9a1a5c2..000000000
--- a/dom/system/gonk/nsIVolumeMountLock.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(44449f34-5ca1-4aff-bce6-22c79263de24)]
-interface nsIVolumeMountLock : nsISupports
-{
- void unlock();
-};
-
diff --git a/dom/system/gonk/nsIVolumeService.idl b/dom/system/gonk/nsIVolumeService.idl
deleted file mode 100644
index d3752e201..000000000
--- a/dom/system/gonk/nsIVolumeService.idl
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsIVolume.idl"
-#include "nsIVolumeMountLock.idl"
-
-interface nsIArray;
-
-[scriptable, uuid(cfbf9880-cba5-11e4-8830-0800200c9a66)]
-interface nsIVolumeService : nsISupports
-{
- nsIVolume getVolumeByName(in DOMString volName);
- nsIVolume getVolumeByPath(in DOMString path);
- nsIVolume createOrGetVolumeByPath(in DOMString path);
-
- nsIVolumeMountLock createMountLock(in DOMString volName);
-
- nsIArray getVolumeNames();
-
- void Dump(in DOMString label);
-
- /* for test case only to simulate sdcard insertion/removal */
- void createFakeVolume(in DOMString name, in DOMString path);
- void SetFakeVolumeState(in DOMString name, in long state);
-
- /* for test case only to test removal of storage area */
- void removeFakeVolume(in DOMString name);
-};
-
-%{C++
-#define NS_VOLUMESERVICE_CID \
- {0x7c179fb7, 0x67a0, 0x43a3, {0x93, 0x37, 0x29, 0x4e, 0x03, 0x60, 0xb8, 0x58}}
-#define NS_VOLUMESERVICE_CONTRACTID "@mozilla.org/telephony/volume-service;1"
-%}
diff --git a/dom/system/gonk/nsIVolumeStat.idl b/dom/system/gonk/nsIVolumeStat.idl
deleted file mode 100644
index 1d725689d..000000000
--- a/dom/system/gonk/nsIVolumeStat.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(b4c050d0-c57a-11e1-9b21-0800200c9a66)]
-interface nsIVolumeStat : nsISupports
-{
- readonly attribute long long totalBytes;
- readonly attribute long long freeBytes;
-};
diff --git a/dom/system/gonk/nsIWorkerHolder.idl b/dom/system/gonk/nsIWorkerHolder.idl
deleted file mode 100644
index e5cc82c9e..000000000
--- a/dom/system/gonk/nsIWorkerHolder.idl
+++ /dev/null
@@ -1,11 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(c04f3102-1ce8-4d57-9c27-8aece9c2740a)]
-interface nsIWorkerHolder : nsISupports
-{
- readonly attribute jsval worker;
-};
diff --git a/dom/system/gonk/nsVolume.cpp b/dom/system/gonk/nsVolume.cpp
deleted file mode 100644
index 77a1628e4..000000000
--- a/dom/system/gonk/nsVolume.cpp
+++ /dev/null
@@ -1,467 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsVolume.h"
-
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "nsIPowerManagerService.h"
-#include "nsISupportsUtils.h"
-#include "nsIVolume.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "nsVolumeStat.h"
-#include "nsXULAppAPI.h"
-#include "Volume.h"
-#include "AutoMounter.h"
-#include "VolumeManager.h"
-
-#undef VOLUME_MANAGER_LOG_TAG
-#define VOLUME_MANAGER_LOG_TAG "nsVolume"
-#include "VolumeManagerLog.h"
-
-namespace mozilla {
-namespace system {
-
-const char *
-NS_VolumeStateStr(int32_t aState)
-{
- switch (aState) {
- case nsIVolume::STATE_INIT: return "Init";
- case nsIVolume::STATE_NOMEDIA: return "NoMedia";
- case nsIVolume::STATE_IDLE: return "Idle";
- case nsIVolume::STATE_PENDING: return "Pending";
- case nsIVolume::STATE_CHECKING: return "Checking";
- case nsIVolume::STATE_MOUNTED: return "Mounted";
- case nsIVolume::STATE_UNMOUNTING: return "Unmounting";
- case nsIVolume::STATE_FORMATTING: return "Formatting";
- case nsIVolume::STATE_SHARED: return "Shared";
- case nsIVolume::STATE_SHAREDMNT: return "Shared-Mounted";
- case nsIVolume::STATE_CHECKMNT: return "Check-Mounted";
- case nsIVolume::STATE_MOUNT_FAIL: return "Mount-Fail";
- }
- return "???";
-}
-
-// While nsVolumes can only be used on the main thread, in the
-// UpdateVolumeRunnable constructor (which is called from IOThread) we
-// allocate an nsVolume which is then passed to MainThread. Since we
-// have a situation where we allocate on one thread and free on another
-// we use a thread safe AddRef implementation.
-NS_IMPL_ISUPPORTS(nsVolume, nsIVolume)
-
-nsVolume::nsVolume(const Volume* aVolume)
- : mName(NS_ConvertUTF8toUTF16(aVolume->Name())),
- mMountPoint(NS_ConvertUTF8toUTF16(aVolume->MountPoint())),
- mState(aVolume->State()),
- mMountGeneration(aVolume->MountGeneration()),
- mMountLocked(aVolume->IsMountLocked()),
- mIsFake(!aVolume->CanBeShared()),
- mIsMediaPresent(aVolume->MediaPresent()),
- mIsSharing(aVolume->IsSharing()),
- mIsFormatting(aVolume->IsFormatting()),
- mIsUnmounting(aVolume->IsUnmounting()),
- mIsRemovable(aVolume->IsRemovable()),
- mIsHotSwappable(aVolume->IsHotSwappable())
-{
-}
-
-nsVolume::nsVolume(const nsVolume* aVolume)
- : mName(aVolume->mName),
- mMountPoint(aVolume->mMountPoint),
- mState(aVolume->mState),
- mMountGeneration(aVolume->mMountGeneration),
- mMountLocked(aVolume->mMountLocked),
- mIsFake(aVolume->mIsFake),
- mIsMediaPresent(aVolume->mIsMediaPresent),
- mIsSharing(aVolume->mIsSharing),
- mIsFormatting(aVolume->mIsFormatting),
- mIsUnmounting(aVolume->mIsUnmounting),
- mIsRemovable(aVolume->mIsRemovable),
- mIsHotSwappable(aVolume->mIsHotSwappable)
-{
-}
-
-void nsVolume::Dump(const char* aLabel) const
-{
- LOG("%s: Volume: %s is %s and %s @ %s gen %d locked %d",
- aLabel,
- NameStr().get(),
- StateStr(),
- IsMediaPresent() ? "inserted" : "missing",
- MountPointStr().get(),
- MountGeneration(),
- (int)IsMountLocked());
- LOG("%s: IsSharing %s IsFormating %s IsUnmounting %s",
- aLabel,
- (IsSharing() ? "y" : "n"),
- (IsFormatting() ? "y" : "n"),
- (IsUnmounting() ? "y" : "n"));
-}
-
-bool nsVolume::Equals(nsIVolume* aVolume)
-{
- nsString volName;
- aVolume->GetName(volName);
- if (!mName.Equals(volName)) {
- return false;
- }
-
- nsString volMountPoint;
- aVolume->GetMountPoint(volMountPoint);
- if (!mMountPoint.Equals(volMountPoint)) {
- return false;
- }
-
- int32_t volState;
- aVolume->GetState(&volState);
- if (mState != volState){
- return false;
- }
-
- int32_t volMountGeneration;
- aVolume->GetMountGeneration(&volMountGeneration);
- if (mMountGeneration != volMountGeneration) {
- return false;
- }
-
- bool volIsMountLocked;
- aVolume->GetIsMountLocked(&volIsMountLocked);
- if (mMountLocked != volIsMountLocked) {
- return false;
- }
-
- bool isFake;
- aVolume->GetIsFake(&isFake);
- if (mIsFake != isFake) {
- return false;
- }
-
- bool isSharing;
- aVolume->GetIsSharing(&isSharing);
- if (mIsSharing != isSharing) {
- return false;
- }
-
- bool isFormatting;
- aVolume->GetIsFormatting(&isFormatting);
- if (mIsFormatting != isFormatting) {
- return false;
- }
-
- bool isUnmounting;
- aVolume->GetIsUnmounting(&isUnmounting);
- if (mIsUnmounting != isUnmounting) {
- return false;
- }
-
- bool isRemovable;
- aVolume->GetIsRemovable(&isRemovable);
- if (mIsRemovable != isRemovable) {
- return false;
- }
-
- bool isHotSwappable;
- aVolume->GetIsHotSwappable(&isHotSwappable);
- if (mIsHotSwappable != isHotSwappable) {
- return false;
- }
-
- return true;
-}
-
-NS_IMETHODIMP nsVolume::GetIsMediaPresent(bool* aIsMediaPresent)
-{
- *aIsMediaPresent = mIsMediaPresent;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsMountLocked(bool* aIsMountLocked)
-{
- *aIsMountLocked = mMountLocked;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsSharing(bool* aIsSharing)
-{
- *aIsSharing = mIsSharing;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsFormatting(bool* aIsFormatting)
-{
- *aIsFormatting = mIsFormatting;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsUnmounting(bool* aIsUnmounting)
-{
- *aIsUnmounting = mIsUnmounting;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetName(nsAString& aName)
-{
- aName = mName;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetMountGeneration(int32_t* aMountGeneration)
-{
- *aMountGeneration = mMountGeneration;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetMountLockName(nsAString& aMountLockName)
-{
- aMountLockName = NS_LITERAL_STRING("volume-") + Name();
- aMountLockName.AppendPrintf("-%d", mMountGeneration);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetMountPoint(nsAString& aMountPoint)
-{
- aMountPoint = mMountPoint;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetState(int32_t* aState)
-{
- *aState = mState;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetStats(nsIVolumeStat **aResult)
-{
- if (mState != STATE_MOUNTED) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- NS_IF_ADDREF(*aResult = new nsVolumeStat(mMountPoint));
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsFake(bool *aIsFake)
-{
- *aIsFake = mIsFake;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsRemovable(bool *aIsRemovable)
-{
- *aIsRemovable = mIsRemovable;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::GetIsHotSwappable(bool *aIsHotSwappable)
-{
- *aIsHotSwappable = mIsHotSwappable;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolume::Format()
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(FormatVolumeIOThread, NameStr()));
-
- return NS_OK;
-}
-
-/* static */
-void nsVolume::FormatVolumeIOThread(const nsCString& aVolume)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
-
- AutoMounterFormatVolume(aVolume);
-}
-
-NS_IMETHODIMP nsVolume::Mount()
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(MountVolumeIOThread, NameStr()));
-
- return NS_OK;
-}
-
-/* static */
-void nsVolume::MountVolumeIOThread(const nsCString& aVolume)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
-
- AutoMounterMountVolume(aVolume);
-}
-
-NS_IMETHODIMP nsVolume::Unmount()
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(UnmountVolumeIOThread, NameStr()));
-
- return NS_OK;
-}
-
-/* static */
-void nsVolume::UnmountVolumeIOThread(const nsCString& aVolume)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
-
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
- return;
- }
-
- AutoMounterUnmountVolume(aVolume);
-}
-
-void
-nsVolume::LogState() const
-{
- if (mState == nsIVolume::STATE_MOUNTED) {
- LOG("nsVolume: %s state %s @ '%s' gen %d locked %d fake %d "
- "media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
- NameStr().get(), StateStr(), MountPointStr().get(),
- MountGeneration(), (int)IsMountLocked(), (int)IsFake(),
- (int)IsMediaPresent(), (int)IsSharing(),
- (int)IsFormatting(), (int)IsUnmounting(),
- (int)IsRemovable(), (int)IsHotSwappable());
- return;
- }
-
- LOG("nsVolume: %s state %s", NameStr().get(), StateStr());
-}
-
-void nsVolume::UpdateMountLock(nsVolume* aOldVolume)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- bool oldMountLocked = aOldVolume ? aOldVolume->mMountLocked : false;
- if (mState != nsIVolume::STATE_MOUNTED) {
- // Since we're not in the mounted state, we need to
- // forgot whatever mount generation we may have had.
- mMountGeneration = -1;
- mMountLocked = oldMountLocked;
- return;
- }
-
- int32_t oldMountGeneration = aOldVolume ? aOldVolume->mMountGeneration : -1;
- if (mMountGeneration == oldMountGeneration) {
- // No change in mount generation, nothing else to do
- mMountLocked = oldMountLocked;
- return;
- }
-
- if (!XRE_IsParentProcess()) {
- // Child processes just track the state, not maintain it.
- return;
- }
-
- // Notify the Volume on IOThread whether the volume is locked or not.
- nsCOMPtr<nsIPowerManagerService> pmService =
- do_GetService(POWERMANAGERSERVICE_CONTRACTID);
- if (!pmService) {
- return;
- }
- nsString mountLockName;
- GetMountLockName(mountLockName);
- nsString mountLockState;
- pmService->GetWakeLockState(mountLockName, mountLockState);
- UpdateMountLock(mountLockState);
-}
-
-void
-nsVolume::UpdateMountLock(const nsAString& aMountLockState)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
-
- // There are 3 states, unlocked, locked-background, and locked-foreground
- // I figured it was easier to use negtive logic and compare for unlocked.
- UpdateMountLock(!aMountLockState.EqualsLiteral("unlocked"));
-}
-
-void
-nsVolume::UpdateMountLock(bool aMountLocked)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
-
- if (aMountLocked == mMountLocked) {
- return;
- }
- // The locked/unlocked state changed. Tell IOThread about it.
- mMountLocked = aMountLocked;
- LogState();
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(Volume::UpdateMountLock,
- NS_LossyConvertUTF16toASCII(Name()),
- MountGeneration(), aMountLocked));
-}
-
-void
-nsVolume::SetIsFake(bool aIsFake)
-{
- mIsFake = aIsFake;
- if (mIsFake) {
- // The media is always present for fake volumes.
- mIsMediaPresent = true;
- MOZ_ASSERT(!mIsSharing);
- }
-}
-
-void
-nsVolume::SetIsRemovable(bool aIsRemovable)
-{
- mIsRemovable = aIsRemovable;
- if (!mIsRemovable) {
- mIsHotSwappable = false;
- }
-}
-
-void
-nsVolume::SetIsHotSwappable(bool aIsHotSwappable)
-{
- mIsHotSwappable = aIsHotSwappable;
- if (mIsHotSwappable) {
- mIsRemovable = true;
- }
-}
-
-void
-nsVolume::SetState(int32_t aState)
-{
- static int32_t sMountGeneration = 0;
-
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(IsFake());
-
- if (aState == mState) {
- return;
- }
-
- if (aState == nsIVolume::STATE_MOUNTED) {
- mMountGeneration = ++sMountGeneration;
- }
-
- mState = aState;
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/nsVolume.h b/dom/system/gonk/nsVolume.h
deleted file mode 100644
index 88be425f6..000000000
--- a/dom/system/gonk/nsVolume.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_nsvolume_h__
-#define mozilla_system_nsvolume_h__
-
-#include "nsCOMPtr.h"
-#include "nsIVolume.h"
-#include "nsString.h"
-#include "nsTArray.h"
-
-namespace mozilla {
-namespace system {
-
-class Volume;
-
-class nsVolume : public nsIVolume
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIVOLUME
-
- // This constructor is used by the UpdateVolumeRunnable constructor
- nsVolume(const Volume* aVolume);
-
- // This constructor is used by nsVolumeService::SetFakeVolumeState
- nsVolume(const nsVolume* aVolume);
-
- // This constructor is used by ContentChild::RecvFileSystemUpdate which is
- // used to update the volume cache maintained in the child process.
- nsVolume(const nsAString& aName, const nsAString& aMountPoint,
- const int32_t& aState, const int32_t& aMountGeneration,
- const bool& aIsMediaPresent, const bool& aIsSharing,
- const bool& aIsFormatting, const bool& aIsFake,
- const bool& aIsUnmounting, const bool& aIsRemovable,
- const bool& aIsHotSwappable)
- : mName(aName),
- mMountPoint(aMountPoint),
- mState(aState),
- mMountGeneration(aMountGeneration),
- mMountLocked(false),
- mIsFake(aIsFake),
- mIsMediaPresent(aIsMediaPresent),
- mIsSharing(aIsSharing),
- mIsFormatting(aIsFormatting),
- mIsUnmounting(aIsUnmounting),
- mIsRemovable(aIsRemovable),
- mIsHotSwappable(aIsHotSwappable)
- {
- }
-
- bool Equals(nsIVolume* aVolume);
- void UpdateMountLock(nsVolume* aOldVolume);
-
- void LogState() const;
-
- const nsString& Name() const { return mName; }
- nsCString NameStr() const { return NS_LossyConvertUTF16toASCII(mName); }
-
- void Dump(const char* aLabel) const;
-
- int32_t MountGeneration() const { return mMountGeneration; }
- bool IsMountLocked() const { return mMountLocked; }
-
- const nsString& MountPoint() const { return mMountPoint; }
- nsCString MountPointStr() const { return NS_LossyConvertUTF16toASCII(mMountPoint); }
-
- int32_t State() const { return mState; }
- const char* StateStr() const { return NS_VolumeStateStr(mState); }
-
- bool IsFake() const { return mIsFake; }
- bool IsMediaPresent() const { return mIsMediaPresent; }
- bool IsSharing() const { return mIsSharing; }
- bool IsFormatting() const { return mIsFormatting; }
- bool IsUnmounting() const { return mIsUnmounting; }
- bool IsRemovable() const { return mIsRemovable; }
- bool IsHotSwappable() const { return mIsHotSwappable; }
-
- typedef nsTArray<RefPtr<nsVolume> > Array;
-
-private:
- virtual ~nsVolume() {} // MozExternalRefCountType complains if this is non-virtual
-
- friend class nsVolumeService; // Calls the following XxxMountLock functions
- void UpdateMountLock(const nsAString& aMountLockState);
- void UpdateMountLock(bool aMountLocked);
-
- void SetIsFake(bool aIsFake);
- void SetIsRemovable(bool aIsRemovable);
- void SetIsHotSwappable(bool aIsHotSwappble);
- void SetState(int32_t aState);
- static void FormatVolumeIOThread(const nsCString& aVolume);
- static void MountVolumeIOThread(const nsCString& aVolume);
- static void UnmountVolumeIOThread(const nsCString& aVolume);
-
- nsString mName;
- nsString mMountPoint;
- int32_t mState;
- int32_t mMountGeneration;
- bool mMountLocked;
- bool mIsFake;
- bool mIsMediaPresent;
- bool mIsSharing;
- bool mIsFormatting;
- bool mIsUnmounting;
- bool mIsRemovable;
- bool mIsHotSwappable;
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_nsvolume_h__
diff --git a/dom/system/gonk/nsVolumeMountLock.cpp b/dom/system/gonk/nsVolumeMountLock.cpp
deleted file mode 100644
index 288c0f689..000000000
--- a/dom/system/gonk/nsVolumeMountLock.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsVolumeMountLock.h"
-
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/Services.h"
-
-#include "nsIObserverService.h"
-#include "nsIPowerManagerService.h"
-#include "nsIVolume.h"
-#include "nsIVolumeService.h"
-#include "nsString.h"
-#include "nsXULAppAPI.h"
-
-#undef VOLUME_MANAGER_LOG_TAG
-#define VOLUME_MANAGER_LOG_TAG "nsVolumeMountLock"
-#include "VolumeManagerLog.h"
-#include "nsServiceManagerUtils.h"
-#include "mozilla/dom/power/PowerManagerService.h"
-
-using namespace mozilla::dom;
-using namespace mozilla::services;
-
-namespace mozilla {
-namespace system {
-
-NS_IMPL_ISUPPORTS(nsVolumeMountLock, nsIVolumeMountLock,
- nsIObserver, nsISupportsWeakReference)
-
-// static
-already_AddRefed<nsVolumeMountLock>
-nsVolumeMountLock::Create(const nsAString& aVolumeName)
-{
- DBG("nsVolumeMountLock::Create called");
-
- RefPtr<nsVolumeMountLock> mountLock = new nsVolumeMountLock(aVolumeName);
- nsresult rv = mountLock->Init();
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- return mountLock.forget();
-}
-
-nsVolumeMountLock::nsVolumeMountLock(const nsAString& aVolumeName)
- : mVolumeName(aVolumeName),
- mVolumeGeneration(-1),
- mUnlocked(false)
-{
-}
-
-//virtual
-nsVolumeMountLock::~nsVolumeMountLock()
-{
- Unlock();
-}
-
-nsresult nsVolumeMountLock::Init()
-{
- LOG("nsVolumeMountLock created for '%s'",
- NS_LossyConvertUTF16toASCII(mVolumeName).get());
-
- // Add ourselves as an Observer. It's important that we use a weak
- // reference here. If we used a strong reference, then that reference
- // would prevent this object from being destructed.
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, true /*weak*/);
-
- // Get the initial mountGeneration and grab a lock.
- nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
- NS_ENSURE_TRUE(vs, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIVolume> vol;
- nsresult rv = vs->GetVolumeByName(mVolumeName, getter_AddRefs(vol));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- rv = vol->GetMountGeneration(&mVolumeGeneration);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return Lock(vol);
-}
-
-NS_IMETHODIMP nsVolumeMountLock::Unlock()
-{
- LOG("nsVolumeMountLock released for '%s'",
- NS_LossyConvertUTF16toASCII(mVolumeName).get());
-
- mUnlocked = true;
- mWakeLock = nullptr;
-
- // While we don't really need to remove weak observers, we do so anyways
- // since it will reduce the number of times Observe gets called.
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolumeMountLock::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
-{
- if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) {
- return NS_OK;
- }
- if (mUnlocked) {
- // We're not locked anymore, so we don't need to look at the notifications.
- return NS_OK;
- }
-
- nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
- if (!vol) {
- return NS_OK;
- }
- nsString volName;
- vol->GetName(volName);
- if (!volName.Equals(mVolumeName)) {
- return NS_OK;
- }
- int32_t state;
- nsresult rv = vol->GetState(&state);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (state != nsIVolume::STATE_MOUNTED) {
- mWakeLock = nullptr;
- mVolumeGeneration = -1;
- return NS_OK;
- }
-
- int32_t mountGeneration;
- rv = vol->GetMountGeneration(&mountGeneration);
- NS_ENSURE_SUCCESS(rv, rv);
-
- DBG("nsVolumeMountLock::Observe mountGeneration = %d mVolumeGeneration = %d",
- mountGeneration, mVolumeGeneration);
-
- if (mVolumeGeneration == mountGeneration) {
- return NS_OK;
- }
-
- // The generation changed, which means that any wakelock we may have
- // been holding is now invalid. Grab a new wakelock for the new generation
- // number.
-
- mWakeLock = nullptr;
- mVolumeGeneration = mountGeneration;
-
- return Lock(vol);
-}
-
-nsresult
-nsVolumeMountLock::Lock(nsIVolume* aVolume)
-{
- RefPtr<power::PowerManagerService> pmService =
- power::PowerManagerService::GetInstance();
- NS_ENSURE_TRUE(pmService, NS_ERROR_FAILURE);
-
- nsString mountLockName;
- aVolume->GetMountLockName(mountLockName);
-
- ErrorResult err;
- mWakeLock = pmService->NewWakeLock(mountLockName, nullptr, err);
- if (err.Failed()) {
- return err.StealNSResult();
- }
-
- LOG("nsVolumeMountLock acquired for '%s' gen %d",
- NS_LossyConvertUTF16toASCII(mVolumeName).get(), mVolumeGeneration);
- return NS_OK;
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/nsVolumeMountLock.h b/dom/system/gonk/nsVolumeMountLock.h
deleted file mode 100644
index caf5b2ad5..000000000
--- a/dom/system/gonk/nsVolumeMountLock.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_nsvolumemountlock_h__
-#define mozilla_system_nsvolumemountlock_h__
-
-#include "nsIVolumeMountLock.h"
-
-#include "mozilla/dom/WakeLock.h"
-#include "nsIObserver.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "nsWeakReference.h"
-
-class nsIVolume;
-
-namespace mozilla {
-namespace system {
-
-/* The VolumeMountLock is designed so that it can be used in the Child or
- * Parent process. While the VolumeMountLock object exists, then the
- * VolumeManager/AutoMounter will prevent a mounted volume from being
- * shared with the PC.
- */
-
-class nsVolumeMountLock final : public nsIVolumeMountLock,
- public nsIObserver,
- public nsSupportsWeakReference
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- NS_DECL_NSIVOLUMEMOUNTLOCK
-
- static already_AddRefed<nsVolumeMountLock> Create(const nsAString& volumeName);
-
- const nsString& VolumeName() const { return mVolumeName; }
-
-private:
- nsVolumeMountLock(const nsAString& aVolumeName);
- ~nsVolumeMountLock();
-
- nsresult Init();
- nsresult Lock(nsIVolume* aVolume);
-
- RefPtr<dom::WakeLock> mWakeLock;
- nsString mVolumeName;
- int32_t mVolumeGeneration;
- bool mUnlocked;
-};
-
-} // namespace system
-} // namespace mozilla
-
-#endif // mozilla_system_nsvolumemountlock_h__
diff --git a/dom/system/gonk/nsVolumeService.cpp b/dom/system/gonk/nsVolumeService.cpp
deleted file mode 100644
index 48d95c26a..000000000
--- a/dom/system/gonk/nsVolumeService.cpp
+++ /dev/null
@@ -1,553 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsVolumeService.h"
-
-#include "Volume.h"
-#include "VolumeManager.h"
-#include "VolumeServiceIOThread.h"
-
-#include "nsCOMPtr.h"
-#include "nsDependentSubstring.h"
-#include "nsIDOMWakeLockListener.h"
-#include "nsIMutableArray.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsIPowerManagerService.h"
-#include "nsISupportsPrimitives.h"
-#include "nsISupportsUtils.h"
-#include "nsIVolume.h"
-#include "nsIVolumeService.h"
-#include "nsLocalFile.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "nsThreadUtils.h"
-#include "nsVolumeMountLock.h"
-#include "nsXULAppAPI.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/Services.h"
-#include "base/task.h"
-
-#undef VOLUME_MANAGER_LOG_TAG
-#define VOLUME_MANAGER_LOG_TAG "nsVolumeService"
-#include "VolumeManagerLog.h"
-
-#include <stdlib.h>
-
-using namespace mozilla::dom;
-using namespace mozilla::services;
-
-namespace mozilla {
-namespace system {
-
-NS_IMPL_ISUPPORTS(nsVolumeService,
- nsIVolumeService,
- nsIDOMMozWakeLockListener)
-
-StaticRefPtr<nsVolumeService> nsVolumeService::sSingleton;
-
-// static
-already_AddRefed<nsVolumeService>
-nsVolumeService::GetSingleton()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!sSingleton) {
- sSingleton = new nsVolumeService();
- }
- RefPtr<nsVolumeService> volumeService = sSingleton.get();
- return volumeService.forget();
-}
-
-// static
-void
-nsVolumeService::Shutdown()
-{
- if (!sSingleton) {
- return;
- }
- if (!XRE_IsParentProcess()) {
- sSingleton = nullptr;
- return;
- }
-
- nsCOMPtr<nsIPowerManagerService> pmService =
- do_GetService(POWERMANAGERSERVICE_CONTRACTID);
- if (pmService) {
- pmService->RemoveWakeLockListener(sSingleton.get());
- }
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(ShutdownVolumeServiceIOThread));
-
- sSingleton = nullptr;
-}
-
-nsVolumeService::nsVolumeService()
- : mArrayMonitor("nsVolumeServiceArray"),
- mGotVolumesFromParent(false)
-{
- sSingleton = this;
-
- if (!XRE_IsParentProcess()) {
- // VolumeServiceIOThread and the WakeLock listener should only run in the
- // parent, so we return early.
- return;
- }
-
- // Startup the IOThread side of things. The actual volume changes
- // are captured by the IOThread and forwarded to main thread.
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(InitVolumeServiceIOThread, this));
-
- nsCOMPtr<nsIPowerManagerService> pmService =
- do_GetService(POWERMANAGERSERVICE_CONTRACTID);
- if (!pmService) {
- return;
- }
- pmService->AddWakeLockListener(this);
-}
-
-nsVolumeService::~nsVolumeService()
-{
-}
-
-// Callback for nsIDOMMozWakeLockListener
-NS_IMETHODIMP
-nsVolumeService::Callback(const nsAString& aTopic, const nsAString& aState)
-{
- CheckMountLock(aTopic, aState);
- return NS_OK;
-}
-
-void nsVolumeService::DumpNoLock(const char* aLabel)
-{
- mArrayMonitor.AssertCurrentThreadOwns();
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
-
- if (numVolumes == 0) {
- LOG("%s: No Volumes!", aLabel);
- return;
- }
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- vol->Dump(aLabel);
- }
-}
-
-NS_IMETHODIMP
-nsVolumeService::Dump(const nsAString& aLabel)
-{
- MonitorAutoLock autoLock(mArrayMonitor);
- DumpNoLock(NS_LossyConvertUTF16toASCII(aLabel).get());
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVolume **aResult)
-{
- MonitorAutoLock autoLock(mArrayMonitor);
-
- RefPtr<nsVolume> vol = FindVolumeByName(aVolName);
- if (!vol) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- vol.forget(aResult);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult)
-{
- NS_ConvertUTF16toUTF8 utf8Path(aPath);
- char realPathBuf[PATH_MAX];
-
- while (realpath(utf8Path.get(), realPathBuf) < 0) {
- if (errno != ENOENT) {
- ERR("GetVolumeByPath: realpath on '%s' failed: %d", utf8Path.get(), errno);
- return NSRESULT_FOR_ERRNO();
- }
- // The pathname we were passed doesn't exist, so we try stripping off trailing
- // components until we get a successful call to realpath, or until we run out
- // of components (if we finally get to /something then we also stop).
- int32_t slashIndex = utf8Path.RFindChar('/');
- if ((slashIndex == kNotFound) || (slashIndex == 0)) {
- errno = ENOENT;
- ERR("GetVolumeByPath: realpath on '%s' failed.", utf8Path.get());
- return NSRESULT_FOR_ERRNO();
- }
- utf8Path.Assign(Substring(utf8Path, 0, slashIndex));
- }
-
- // The volume mount point is always a directory. Something like /mnt/sdcard
- // Once we have a full qualified pathname with symlinks removed (which is
- // what realpath does), we basically check if aPath starts with the mount
- // point, but we don't want to have /mnt/sdcard match /mnt/sdcardfoo but we
- // do want it to match /mnt/sdcard/foo
- // So we add a trailing slash to the mount point and the pathname passed in
- // prior to doing the comparison.
-
- strlcat(realPathBuf, "/", sizeof(realPathBuf));
-
- MonitorAutoLock autoLock(mArrayMonitor);
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- NS_ConvertUTF16toUTF8 volMountPointSlash(vol->MountPoint());
- volMountPointSlash.Append('/');
- nsDependentCSubstring testStr(realPathBuf, volMountPointSlash.Length());
- if (volMountPointSlash.Equals(testStr)) {
- vol.forget(aResult);
- return NS_OK;
- }
- }
- return NS_ERROR_FILE_NOT_FOUND;
-}
-
-NS_IMETHODIMP
-nsVolumeService::CreateOrGetVolumeByPath(const nsAString& aPath, nsIVolume** aResult)
-{
- nsresult rv = GetVolumeByPath(aPath, aResult);
- if (rv == NS_OK) {
- return NS_OK;
- }
-
- // In order to support queries by the updater, we will fabricate a volume
- // from the pathname, so that the caller can determine the volume size.
- nsCOMPtr<nsIVolume> vol = new nsVolume(NS_LITERAL_STRING("fake"),
- aPath, nsIVolume::STATE_MOUNTED,
- -1 /* generation */,
- true /* isMediaPresent*/,
- false /* isSharing */,
- false /* isFormatting */,
- true /* isFake */,
- false /* isUnmounting */,
- false /* isRemovable */,
- false /* isHotSwappable*/);
- vol.forget(aResult);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsVolumeService::GetVolumeNames(nsIArray** aVolNames)
-{
- NS_ENSURE_ARG_POINTER(aVolNames);
- MonitorAutoLock autoLock(mArrayMonitor);
-
- *aVolNames = nullptr;
-
- nsresult rv;
- nsCOMPtr<nsIMutableArray> volNames =
- do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- nsCOMPtr<nsISupportsString> isupportsString =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = isupportsString->SetData(vol->Name());
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = volNames->AppendElement(isupportsString, false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- volNames.forget(aVolNames);
- return NS_OK;
-}
-
-void
-nsVolumeService::GetVolumesForIPC(nsTArray<VolumeInfo>* aResult)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
-
- MonitorAutoLock autoLock(mArrayMonitor);
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- VolumeInfo* volInfo = aResult->AppendElement();
-
- volInfo->name() = vol->mName;
- volInfo->mountPoint() = vol->mMountPoint;
- volInfo->volState() = vol->mState;
- volInfo->mountGeneration() = vol->mMountGeneration;
- volInfo->isMediaPresent() = vol->mIsMediaPresent;
- volInfo->isSharing() = vol->mIsSharing;
- volInfo->isFormatting() = vol->mIsFormatting;
- volInfo->isFake() = vol->mIsFake;
- volInfo->isUnmounting() = vol->mIsUnmounting;
- volInfo->isRemovable() = vol->mIsRemovable;
- volInfo->isHotSwappable() = vol->mIsHotSwappable;
- }
-}
-
-void
-nsVolumeService::RecvVolumesFromParent(const nsTArray<VolumeInfo>& aVolumes)
-{
- if (XRE_IsParentProcess()) {
- // We are the parent. Therefore our volumes are already correct.
- return;
- }
- if (mGotVolumesFromParent) {
- // We've already done this, no need to do it again.
- return;
- }
-
- for (uint32_t i = 0; i < aVolumes.Length(); i++) {
- const VolumeInfo& volInfo(aVolumes[i]);
- RefPtr<nsVolume> vol = new nsVolume(volInfo.name(),
- volInfo.mountPoint(),
- volInfo.volState(),
- volInfo.mountGeneration(),
- volInfo.isMediaPresent(),
- volInfo.isSharing(),
- volInfo.isFormatting(),
- volInfo.isFake(),
- volInfo.isUnmounting(),
- volInfo.isRemovable(),
- volInfo.isHotSwappable());
- UpdateVolume(vol, false);
- }
-}
-
-NS_IMETHODIMP
-nsVolumeService::CreateMountLock(const nsAString& aVolumeName, nsIVolumeMountLock **aResult)
-{
- nsCOMPtr<nsIVolumeMountLock> mountLock = nsVolumeMountLock::Create(aVolumeName);
- if (!mountLock) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- mountLock.forget(aResult);
- return NS_OK;
-}
-
-void
-nsVolumeService::CheckMountLock(const nsAString& aMountLockName,
- const nsAString& aMountLockState)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
-
- RefPtr<nsVolume> vol = FindVolumeByMountLockName(aMountLockName);
- if (vol) {
- vol->UpdateMountLock(aMountLockState);
- }
-}
-
-already_AddRefed<nsVolume>
-nsVolumeService::FindVolumeByMountLockName(const nsAString& aMountLockName)
-{
- MonitorAutoLock autoLock(mArrayMonitor);
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- nsString mountLockName;
- vol->GetMountLockName(mountLockName);
- if (mountLockName.Equals(aMountLockName)) {
- return vol.forget();
- }
- }
- return nullptr;
-}
-
-already_AddRefed<nsVolume>
-nsVolumeService::FindVolumeByName(const nsAString& aName, nsVolume::Array::index_type* aIndex)
-{
- mArrayMonitor.AssertCurrentThreadOwns();
-
- nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
- nsVolume::Array::index_type volIndex;
- for (volIndex = 0; volIndex < numVolumes; volIndex++) {
- RefPtr<nsVolume> vol = mVolumeArray[volIndex];
- if (vol->Name().Equals(aName)) {
- if (aIndex) {
- *aIndex = volIndex;
- }
- return vol.forget();
- }
- }
- return nullptr;
-}
-
-void
-nsVolumeService::UpdateVolume(nsVolume* aVolume, bool aNotifyObservers)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- {
- MonitorAutoLock autoLock(mArrayMonitor);
- nsVolume::Array::index_type volIndex;
- RefPtr<nsVolume> vol = FindVolumeByName(aVolume->Name(), &volIndex);
- if (!vol) {
- mVolumeArray.AppendElement(aVolume);
- } else if (vol->Equals(aVolume) || (!vol->IsFake() && aVolume->IsFake())) {
- // Ignore if nothing changed or if a fake tries to override a real volume.
- return;
- } else {
- mVolumeArray.ReplaceElementAt(volIndex, aVolume);
- }
- aVolume->UpdateMountLock(vol);
- }
-
- if (!aNotifyObservers) {
- return;
- }
-
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- if (!obs) {
- return;
- }
- NS_ConvertUTF8toUTF16 stateStr(aVolume->StateStr());
- obs->NotifyObservers(aVolume, NS_VOLUME_STATE_CHANGED, stateStr.get());
-}
-
-NS_IMETHODIMP
-nsVolumeService::CreateFakeVolume(const nsAString& name, const nsAString& path)
-{
- if (XRE_IsParentProcess()) {
- RefPtr<nsVolume> vol = new nsVolume(name, path, nsIVolume::STATE_INIT,
- -1 /* mountGeneration */,
- true /* isMediaPresent */,
- false /* isSharing */,
- false /* isFormatting */,
- true /* isFake */,
- false /* isUnmounting */,
- false /* isRemovable */,
- false /* isHotSwappable */);
- vol->SetState(nsIVolume::STATE_MOUNTED);
- vol->LogState();
- UpdateVolume(vol.get());
- return NS_OK;
- }
-
- ContentChild::GetSingleton()->SendCreateFakeVolume(nsString(name), nsString(path));
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state)
-{
- if (XRE_IsParentProcess()) {
- RefPtr<nsVolume> vol;
- {
- MonitorAutoLock autoLock(mArrayMonitor);
- vol = FindVolumeByName(name);
- }
- if (!vol || !vol->IsFake()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- // Clone the existing volume so we can replace it
- RefPtr<nsVolume> volume = new nsVolume(vol);
- volume->SetState(state);
- volume->LogState();
- UpdateVolume(volume.get());
- return NS_OK;
- }
-
- ContentChild::GetSingleton()->SendSetFakeVolumeState(nsString(name), state);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsVolumeService::RemoveFakeVolume(const nsAString& name)
-{
- if (XRE_IsParentProcess()) {
- SetFakeVolumeState(name, nsIVolume::STATE_NOMEDIA);
- RemoveVolumeByName(name);
- return NS_OK;
- }
-
- ContentChild::GetSingleton()->SendRemoveFakeVolume(nsString(name));
- return NS_OK;
-}
-
-void
-nsVolumeService::RemoveVolumeByName(const nsAString& aName)
-{
- {
- MonitorAutoLock autoLock(mArrayMonitor);
- nsVolume::Array::index_type volIndex;
- RefPtr<nsVolume> vol = FindVolumeByName(aName, &volIndex);
- if (!vol) {
- return;
- }
- mVolumeArray.RemoveElementAt(volIndex);
- }
-
- if (XRE_IsParentProcess()) {
- nsCOMPtr<nsIObserverService> obs = GetObserverService();
- if (!obs) {
- return;
- }
- obs->NotifyObservers(nullptr, NS_VOLUME_REMOVED, nsString(aName).get());
- }
-}
-
-/***************************************************************************
-* The UpdateVolumeRunnable creates an nsVolume and updates the main thread
-* data structure while running on the main thread.
-*/
-class UpdateVolumeRunnable : public Runnable
-{
-public:
- UpdateVolumeRunnable(nsVolumeService* aVolumeService, const Volume* aVolume)
- : mVolumeService(aVolumeService),
- mVolume(new nsVolume(aVolume))
- {
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- DBG("UpdateVolumeRunnable::Run '%s' state %s gen %d locked %d "
- "media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
- mVolume->NameStr().get(), mVolume->StateStr(),
- mVolume->MountGeneration(), (int)mVolume->IsMountLocked(),
- (int)mVolume->IsMediaPresent(), mVolume->IsSharing(),
- mVolume->IsFormatting(), mVolume->IsUnmounting(),
- (int)mVolume->IsRemovable(), (int)mVolume->IsHotSwappable());
-
- mVolumeService->UpdateVolume(mVolume);
- mVolumeService = nullptr;
- mVolume = nullptr;
- return NS_OK;
- }
-
-private:
- RefPtr<nsVolumeService> mVolumeService;
- RefPtr<nsVolume> mVolume;
-};
-
-void
-nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume)
-{
- DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d "
- "media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
- aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),
- aVolume->MountGeneration(), (int)aVolume->IsMountLocked(),
- (int)aVolume->MediaPresent(), (int)aVolume->IsSharing(),
- (int)aVolume->IsFormatting(), (int)aVolume->IsUnmounting(),
- (int)aVolume->IsRemovable(), (int)aVolume->IsHotSwappable());
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- NS_DispatchToMainThread(new UpdateVolumeRunnable(this, aVolume));
-}
-
-} // namespace system
-} // namespace mozilla
diff --git a/dom/system/gonk/nsVolumeService.h b/dom/system/gonk/nsVolumeService.h
deleted file mode 100644
index 9bddc0b8f..000000000
--- a/dom/system/gonk/nsVolumeService.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_nsvolumeservice_h__
-#define mozilla_system_nsvolumeservice_h__
-
-#include "mozilla/Monitor.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/StaticPtr.h"
-#include "nsCOMPtr.h"
-#include "nsIDOMWakeLockListener.h"
-#include "nsIVolume.h"
-#include "nsIVolumeService.h"
-#include "nsVolume.h"
-
-namespace mozilla {
-
-namespace dom {
-class VolumeInfo;
-} // dom
-
-namespace system {
-
-class Volume;
-
-/***************************************************************************
-* The nsVolumeData class encapsulates the data that is updated/maintained
-* on the main thread in order to support the nsIVolume and nsIVolumeService
-* classes.
-*/
-
-class nsVolumeService final : public nsIVolumeService,
- public nsIDOMMozWakeLockListener
-{
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIVOLUMESERVICE
- NS_DECL_NSIDOMMOZWAKELOCKLISTENER
-
- nsVolumeService();
-
- static already_AddRefed<nsVolumeService> GetSingleton();
- //static nsVolumeService* GetSingleton();
- static void Shutdown();
-
- void DumpNoLock(const char* aLabel);
-
- // To use this function, you have to create a new volume and pass it in.
- void UpdateVolume(nsVolume* aVolume, bool aNotifyObservers = true);
- void UpdateVolumeIOThread(const Volume* aVolume);
-
- void RecvVolumesFromParent(const nsTArray<dom::VolumeInfo>& aVolumes);
- void GetVolumesForIPC(nsTArray<dom::VolumeInfo>* aResult);
-
- void RemoveVolumeByName(const nsAString& aName);
-
-private:
- ~nsVolumeService();
-
- void CheckMountLock(const nsAString& aMountLockName,
- const nsAString& aMountLockState);
- already_AddRefed<nsVolume> FindVolumeByMountLockName(const nsAString& aMountLockName);
-
- already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName,
- nsVolume::Array::index_type* aIndex = nullptr);
-
- Monitor mArrayMonitor;
- nsVolume::Array mVolumeArray;
-
- static StaticRefPtr<nsVolumeService> sSingleton;
- bool mGotVolumesFromParent;
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_nsvolumeservice_h__
diff --git a/dom/system/gonk/nsVolumeStat.cpp b/dom/system/gonk/nsVolumeStat.cpp
deleted file mode 100644
index 11976237f..000000000
--- a/dom/system/gonk/nsVolumeStat.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsVolumeStat.h"
-#include "nsString.h"
-
-namespace mozilla {
-namespace system {
-
-NS_IMPL_ISUPPORTS(nsVolumeStat, nsIVolumeStat)
-
-nsVolumeStat::nsVolumeStat(const nsAString& aPath)
-{
- if (statfs(NS_ConvertUTF16toUTF8(aPath).get(), &mStat) != 0) {
- memset(&mStat, 0, sizeof(mStat));
- }
-}
-
-NS_IMETHODIMP nsVolumeStat::GetTotalBytes(int64_t* aTotalBytes)
-{
- *aTotalBytes = mStat.f_blocks * mStat.f_bsize;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsVolumeStat::GetFreeBytes(int64_t* aFreeBytes)
-{
- *aFreeBytes = mStat.f_bfree * mStat.f_bsize;
- return NS_OK;
-}
-
-} // system
-} // mozilla
diff --git a/dom/system/gonk/nsVolumeStat.h b/dom/system/gonk/nsVolumeStat.h
deleted file mode 100644
index 2ca03ed46..000000000
--- a/dom/system/gonk/nsVolumeStat.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_system_nsvolumestat_h__
-#define mozilla_system_nsvolumestat_h__
-
-#include "nsIVolumeStat.h"
-#include "nsString.h"
-#include <sys/statfs.h>
-
-namespace mozilla {
-namespace system {
-
-class nsVolumeStat final : public nsIVolumeStat
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIVOLUMESTAT
-
- nsVolumeStat(const nsAString& aPath);
-
-protected:
- ~nsVolumeStat() {}
-
-private:
- struct statfs mStat;
-};
-
-} // system
-} // mozilla
-
-#endif // mozilla_system_nsvolumestat_h__
diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js
deleted file mode 100644
index af5b9d8e1..000000000
--- a/dom/system/gonk/ril_consts.js
+++ /dev/null
@@ -1,3338 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 to true to debug all RIL layers
-this.DEBUG_ALL = false;
-
-// Set individually to debug specific layers
-this.DEBUG_WORKER = false || DEBUG_ALL;
-this.DEBUG_CONTENT_HELPER = false || DEBUG_ALL;
-this.DEBUG_RIL = false || DEBUG_ALL;
-
-this.REQUEST_GET_SIM_STATUS = 1;
-this.REQUEST_ENTER_SIM_PIN = 2;
-this.REQUEST_ENTER_SIM_PUK = 3;
-this.REQUEST_ENTER_SIM_PIN2 = 4;
-this.REQUEST_ENTER_SIM_PUK2 = 5;
-this.REQUEST_CHANGE_SIM_PIN = 6;
-this.REQUEST_CHANGE_SIM_PIN2 = 7;
-this.REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE = 8;
-this.REQUEST_GET_CURRENT_CALLS = 9;
-this.REQUEST_DIAL = 10;
-this.REQUEST_GET_IMSI = 11;
-this.REQUEST_HANGUP = 12;
-this.REQUEST_HANGUP_WAITING_OR_BACKGROUND = 13;
-this.REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND = 14;
-this.REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE = 15;
-this.REQUEST_CONFERENCE = 16;
-this.REQUEST_UDUB = 17;
-this.REQUEST_LAST_CALL_FAIL_CAUSE = 18;
-this.REQUEST_SIGNAL_STRENGTH = 19;
-this.REQUEST_VOICE_REGISTRATION_STATE = 20;
-this.REQUEST_DATA_REGISTRATION_STATE = 21;
-this.REQUEST_OPERATOR = 22;
-this.REQUEST_RADIO_POWER = 23;
-this.REQUEST_DTMF = 24;
-this.REQUEST_SEND_SMS = 25;
-this.REQUEST_SEND_SMS_EXPECT_MORE = 26;
-this.REQUEST_SETUP_DATA_CALL = 27;
-this.REQUEST_SIM_IO = 28;
-this.REQUEST_SEND_USSD = 29;
-this.REQUEST_CANCEL_USSD = 30;
-this.REQUEST_GET_CLIR = 31;
-this.REQUEST_SET_CLIR = 32;
-this.REQUEST_QUERY_CALL_FORWARD_STATUS = 33;
-this.REQUEST_SET_CALL_FORWARD = 34;
-this.REQUEST_QUERY_CALL_WAITING = 35;
-this.REQUEST_SET_CALL_WAITING = 36;
-this.REQUEST_SMS_ACKNOWLEDGE = 37;
-this.REQUEST_GET_IMEI = 38;
-this.REQUEST_GET_IMEISV = 39;
-this.REQUEST_ANSWER = 40;
-this.REQUEST_DEACTIVATE_DATA_CALL = 41;
-this.REQUEST_QUERY_FACILITY_LOCK = 42;
-this.REQUEST_SET_FACILITY_LOCK = 43;
-this.REQUEST_CHANGE_BARRING_PASSWORD = 44;
-this.REQUEST_QUERY_NETWORK_SELECTION_MODE = 45;
-this.REQUEST_SET_NETWORK_SELECTION_AUTOMATIC = 46;
-this.REQUEST_SET_NETWORK_SELECTION_MANUAL = 47;
-this.REQUEST_QUERY_AVAILABLE_NETWORKS = 48;
-this.REQUEST_DTMF_START = 49;
-this.REQUEST_DTMF_STOP = 50;
-this.REQUEST_BASEBAND_VERSION = 51;
-this.REQUEST_SEPARATE_CONNECTION = 52;
-this.REQUEST_SET_MUTE = 53;
-this.REQUEST_GET_MUTE = 54;
-this.REQUEST_QUERY_CLIP = 55;
-this.REQUEST_LAST_DATA_CALL_FAIL_CAUSE = 56;
-this.REQUEST_DATA_CALL_LIST = 57;
-this.REQUEST_RESET_RADIO = 58;
-this.REQUEST_OEM_HOOK_RAW = 59;
-this.REQUEST_OEM_HOOK_STRINGS = 60;
-this.REQUEST_SCREEN_STATE = 61;
-this.REQUEST_SET_SUPP_SVC_NOTIFICATION = 62;
-this.REQUEST_WRITE_SMS_TO_SIM = 63;
-this.REQUEST_DELETE_SMS_ON_SIM = 64;
-this.REQUEST_SET_BAND_MODE = 65;
-this.REQUEST_QUERY_AVAILABLE_BAND_MODE = 66;
-this.REQUEST_STK_GET_PROFILE = 67;
-this.REQUEST_STK_SET_PROFILE = 68;
-this.REQUEST_STK_SEND_ENVELOPE_COMMAND = 69;
-this.REQUEST_STK_SEND_TERMINAL_RESPONSE = 70;
-this.REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM = 71;
-this.REQUEST_EXPLICIT_CALL_TRANSFER = 72;
-this.REQUEST_SET_PREFERRED_NETWORK_TYPE = 73;
-this.REQUEST_GET_PREFERRED_NETWORK_TYPE = 74;
-this.REQUEST_GET_NEIGHBORING_CELL_IDS = 75;
-this.REQUEST_SET_LOCATION_UPDATES = 76;
-this.REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE = 77;
-this.REQUEST_CDMA_SET_ROAMING_PREFERENCE = 78;
-this.REQUEST_CDMA_QUERY_ROAMING_PREFERENCE = 79;
-this.REQUEST_SET_TTY_MODE = 80;
-this.REQUEST_QUERY_TTY_MODE = 81;
-this.REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE = 82;
-this.REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE = 83;
-this.REQUEST_CDMA_FLASH = 84;
-this.REQUEST_CDMA_BURST_DTMF = 85;
-this.REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY = 86;
-this.REQUEST_CDMA_SEND_SMS = 87;
-this.REQUEST_CDMA_SMS_ACKNOWLEDGE = 88;
-this.REQUEST_GSM_GET_BROADCAST_SMS_CONFIG = 89;
-this.REQUEST_GSM_SET_BROADCAST_SMS_CONFIG = 90;
-this.REQUEST_GSM_SMS_BROADCAST_ACTIVATION = 91;
-this.REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG = 92;
-this.REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG = 93;
-this.REQUEST_CDMA_SMS_BROADCAST_ACTIVATION = 94;
-this.REQUEST_CDMA_SUBSCRIPTION = 95;
-this.REQUEST_CDMA_WRITE_SMS_TO_RUIM = 96;
-this.REQUEST_CDMA_DELETE_SMS_ON_RUIM = 97;
-this.REQUEST_DEVICE_IDENTITY = 98;
-this.REQUEST_EXIT_EMERGENCY_CALLBACK_MODE = 99;
-this.REQUEST_GET_SMSC_ADDRESS = 100;
-this.REQUEST_SET_SMSC_ADDRESS = 101;
-this.REQUEST_REPORT_SMS_MEMORY_STATUS = 102;
-this.REQUEST_REPORT_STK_SERVICE_IS_RUNNING = 103;
-this.REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE = 104;
-this.REQUEST_ISIM_AUTHENTICATION = 105;
-this.REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU = 106;
-this.REQUEST_STK_SEND_ENVELOPE_WITH_STATUS = 107;
-this.REQUEST_VOICE_RADIO_TECH = 108;
-this.REQUEST_GET_CELL_INFO_LIST = 109;
-this.REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE = 110;
-this.REQUEST_SET_INITIAL_ATTACH_APN = 111;
-this.REQUEST_IMS_REGISTRATION_STATE = 112;
-this.REQUEST_IMS_SEND_SMS = 113;
-this.REQUEST_SIM_TRANSMIT_APDU_BASIC = 114;
-this.REQUEST_SIM_OPEN_CHANNEL = 115;
-this.REQUEST_SIM_CLOSE_CHANNEL = 116;
-this.REQUEST_SIM_TRANSMIT_APDU_CHANNEL = 117;
-this.REQUEST_NV_READ_ITEM = 118;
-this.REQUEST_NV_WRITE_ITEM = 119;
-this.REQUEST_NV_WRITE_CDMA_PRL = 120;
-this.REQUEST_NV_RESET_CONFIG = 121;
-this.REQUEST_SET_UICC_SUBSCRIPTION = 122;
-this.REQUEST_ALLOW_DATA = 123;
-this.REQUEST_GET_HARDWARE_CONFIG = 124;
-this.REQUEST_SIM_AUTHENTICATION = 125;
-this.REQUEST_GET_DC_RT_INFO = 126;
-this.REQUEST_SET_DC_RT_INFO_RATE = 127;
-this.REQUEST_SET_DATA_PROFILE = 128;
-this.REQUEST_SHUTDOWN = 129;
-
-// CAF specific parcel type. It should be synced with latest version. But CAF
-// doesn't have l version for b2g yet, so we set REQUEST_SET_DATA_SUBSCRIPTION
-// to a value that won't get conflict with known AOSP parcel.
-this.REQUEST_SET_DATA_SUBSCRIPTION = 130;
-
-// Mozilla specific parcel type.
-this.REQUEST_GET_UNLOCK_RETRY_COUNT = 150;
-
-// Fugu specific parcel types.
-this.RIL_REQUEST_GPRS_ATTACH = 5018;
-this.RIL_REQUEST_GPRS_DETACH = 5019;
-
-// Galaxy S2 specific parcel type.
-this.REQUEST_DIAL_EMERGENCY_CALL = 10016;
-
-this.RESPONSE_TYPE_SOLICITED = 0;
-this.RESPONSE_TYPE_UNSOLICITED = 1;
-
-this.UNSOLICITED_RESPONSE_BASE = 1000;
-this.UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED = 1000;
-this.UNSOLICITED_RESPONSE_CALL_STATE_CHANGED = 1001;
-this.UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED = 1002;
-this.UNSOLICITED_RESPONSE_NEW_SMS = 1003;
-this.UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT = 1004;
-this.UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM = 1005;
-this.UNSOLICITED_ON_USSD = 1006;
-this.UNSOLICITED_ON_USSD_REQUEST = 1007;
-this.UNSOLICITED_NITZ_TIME_RECEIVED = 1008;
-this.UNSOLICITED_SIGNAL_STRENGTH = 1009;
-this.UNSOLICITED_DATA_CALL_LIST_CHANGED = 1010;
-this.UNSOLICITED_SUPP_SVC_NOTIFICATION = 1011;
-this.UNSOLICITED_STK_SESSION_END = 1012;
-this.UNSOLICITED_STK_PROACTIVE_COMMAND = 1013;
-this.UNSOLICITED_STK_EVENT_NOTIFY = 1014;
-this.UNSOLICITED_STK_CALL_SETUP = 1015;
-this.UNSOLICITED_SIM_SMS_STORAGE_FULL = 1016;
-this.UNSOLICITED_SIM_REFRESH = 1017;
-this.UNSOLICITED_CALL_RING = 1018;
-this.UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED = 1019;
-this.UNSOLICITED_RESPONSE_CDMA_NEW_SMS = 1020;
-this.UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS = 1021;
-this.UNSOLICITED_CDMA_RUIM_SMS_STORAGE_FULL = 1022;
-this.UNSOLICITED_RESTRICTED_STATE_CHANGED = 1023;
-this.UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE = 1024;
-this.UNSOLICITED_CDMA_CALL_WAITING = 1025;
-this.UNSOLICITED_CDMA_OTA_PROVISION_STATUS = 1026;
-this.UNSOLICITED_CDMA_INFO_REC = 1027;
-this.UNSOLICITED_OEM_HOOK_RAW = 1028;
-this.UNSOLICITED_RINGBACK_TONE = 1029;
-this.UNSOLICITED_RESEND_INCALL_MUTE = 1030;
-this.UNSOLICITED_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1031;
-this.UNSOLICITED_CDMA_PRL_CHANGED = 1032;
-this.UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE = 1033;
-this.UNSOLICITED_RIL_CONNECTED = 1034;
-this.UNSOLICITED_VOICE_RADIO_TECH_CHANGED = 1035;
-this.UNSOLICITED_CELL_INFO_LIST = 1036;
-this.UNSOLICITED_RESPONSE_IMS_NETWORK_STATE_CHANGED = 1037;
-this.UNSOLICITED_UICC_SUBSCRIPTION_STATUS_CHANGED = 1038;
-this.UNSOLICITED_SRVCC_STATE_NOTIFY = 1039;
-this.UNSOLICITED_HARDWARE_CONFIG_CHANGED = 1040;
-this.UNSOLICITED_DC_RT_INFO_CHANGED = 1041;
-
-this.ERROR_SUCCESS = 0;
-this.ERROR_RADIO_NOT_AVAILABLE = 1;
-this.ERROR_GENERIC_FAILURE = 2;
-this.ERROR_PASSWORD_INCORRECT = 3;
-this.ERROR_SIM_PIN2 = 4;
-this.ERROR_SIM_PUK2 = 5;
-this.ERROR_REQUEST_NOT_SUPPORTED = 6;
-this.ERROR_CANCELLED = 7;
-this.ERROR_OP_NOT_ALLOWED_DURING_VOICE_CALL = 8;
-this.ERROR_OP_NOT_ALLOWED_BEFORE_REG_TO_NW = 9;
-this.ERROR_SMS_SEND_FAIL_RETRY = 10;
-this.ERROR_SIM_ABSENT = 11;
-this.ERROR_SUBSCRIPTION_NOT_AVAILABLE = 12;
-this.ERROR_MODE_NOT_SUPPORTED = 13;
-this.ERROR_FDN_CHECK_FAILURE = 14;
-this.ERROR_ILLEGAL_SIM_OR_ME = 15;
-this.ERROR_MISSING_RESOURCE = 16;
-this.ERROR_NO_SUCH_ELEMENT = 17;
-
-this.GECKO_ERROR_RADIO_NOT_AVAILABLE = "RadioNotAvailable";
-this.GECKO_ERROR_GENERIC_FAILURE = "GenericFailure";
-this.GECKO_ERROR_PASSWORD_INCORRECT = "IncorrectPassword";
-this.GECKO_ERROR_SIM_PIN2 = "SimPin2";
-this.GECKO_ERROR_SIM_PUK2 = "SimPuk2";
-this.GECKO_ERROR_REQUEST_NOT_SUPPORTED = "RequestNotSupported";
-this.GECKO_ERROR_CANCELLED = "Cancelled";
-this.GECKO_ERROR_OP_NOT_ALLOWED_DURING_VOICE_CALL = "OpNotAllowedDuringVoiceCall";
-this.GECKO_ERROR_OP_NOT_ALLOWED_BEFORE_REG_TO_NW = "OpNotAllowedBeforeRegToNw";
-this.GECKO_ERROR_SMS_SEND_FAIL_RETRY = "SmsSendFailRetry";
-this.GECKO_ERROR_SIM_ABSENT = "SimAbsent";
-this.GECKO_ERROR_SUBSCRIPTION_NOT_AVAILABLE = "SubscriptionNotAvailable";
-this.GECKO_ERROR_MODE_NOT_SUPPORTED = "ModeNotSupported";
-this.GECKO_ERROR_FDN_CHECK_FAILURE = "FdnCheckFailure";
-this.GECKO_ERROR_ILLEGAL_SIM_OR_ME = "IllegalSIMorME";
-this.GECKO_ERROR_MISSING_RESOURCE = "MissingResource";
-this.GECKO_ERROR_NO_SUCH_ELEMENT = "NoSuchElement";
-this.GECKO_ERROR_INVALID_PARAMETER = "InvalidParameter";
-this.GECKO_ERROR_UNSPECIFIED_ERROR = "UnspecifiedError";
-
-this.RIL_ERROR_TO_GECKO_ERROR = {};
-RIL_ERROR_TO_GECKO_ERROR[ERROR_RADIO_NOT_AVAILABLE] = GECKO_ERROR_RADIO_NOT_AVAILABLE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_GENERIC_FAILURE] = GECKO_ERROR_GENERIC_FAILURE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_PASSWORD_INCORRECT] = GECKO_ERROR_PASSWORD_INCORRECT;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SIM_PIN2] = GECKO_ERROR_SIM_PIN2;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SIM_PUK2] = GECKO_ERROR_SIM_PUK2;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_REQUEST_NOT_SUPPORTED] = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_CANCELLED] = GECKO_ERROR_CANCELLED;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_OP_NOT_ALLOWED_DURING_VOICE_CALL] = GECKO_ERROR_OP_NOT_ALLOWED_DURING_VOICE_CALL;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_OP_NOT_ALLOWED_BEFORE_REG_TO_NW] = GECKO_ERROR_OP_NOT_ALLOWED_BEFORE_REG_TO_NW;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SMS_SEND_FAIL_RETRY] = GECKO_ERROR_SMS_SEND_FAIL_RETRY;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SIM_ABSENT] = GECKO_ERROR_SIM_ABSENT;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_SUBSCRIPTION_NOT_AVAILABLE] = GECKO_ERROR_SUBSCRIPTION_NOT_AVAILABLE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_MODE_NOT_SUPPORTED] = GECKO_ERROR_MODE_NOT_SUPPORTED;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_FDN_CHECK_FAILURE] = GECKO_ERROR_FDN_CHECK_FAILURE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_ILLEGAL_SIM_OR_ME] = GECKO_ERROR_ILLEGAL_SIM_OR_ME;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_MISSING_RESOURCE] = GECKO_ERROR_MISSING_RESOURCE;
-RIL_ERROR_TO_GECKO_ERROR[ERROR_NO_SUCH_ELEMENT] = GECKO_ERROR_NO_SUCH_ELEMENT;
-
-// 3GPP 23.040 clause 9.2.3.6 TP-Message-Reference(TP-MR):
-// The number of times the MS automatically repeats the SMS-SUBMIT shall be in
-// the range 1 to 3 but the precise number is an implementation matter.
-this.SMS_RETRY_MAX = 3;
-
-this.RADIO_STATE_OFF = 0;
-this.RADIO_STATE_UNAVAILABLE = 1;
-this.RADIO_STATE_ON = 10; // since RIL v7
-
-this.CARD_STATE_ABSENT = 0;
-this.CARD_STATE_PRESENT = 1;
-this.CARD_STATE_ERROR = 2;
-
-this.CARD_PERSOSUBSTATE_UNKNOWN = 0;
-this.CARD_PERSOSUBSTATE_IN_PROGRESS = 1;
-this.CARD_PERSOSUBSTATE_READY = 2;
-this.CARD_PERSOSUBSTATE_SIM_NETWORK = 3;
-this.CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET = 4;
-this.CARD_PERSOSUBSTATE_SIM_CORPORATE = 5;
-this.CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER = 6;
-this.CARD_PERSOSUBSTATE_SIM_SIM = 7;
-this.CARD_PERSOSUBSTATE_SIM_NETWORK_PUK = 8;
-this.CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK = 9;
-this.CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK = 10;
-this.CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK = 11;
-this.CARD_PERSOSUBSTATE_SIM_SIM_PUK = 12;
-this.CARD_PERSOSUBSTATE_RUIM_NETWORK1 = 13;
-this.CARD_PERSOSUBSTATE_RUIM_NETWORK2 = 14;
-this.CARD_PERSOSUBSTATE_RUIM_HRPD = 15;
-this.CARD_PERSOSUBSTATE_RUIM_CORPORATE = 16;
-this.CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER = 17;
-this.CARD_PERSOSUBSTATE_RUIM_RUIM = 18;
-this.CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK = 19;
-this.CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK = 20;
-this.CARD_PERSOSUBSTATE_RUIM_HRPD_PUK = 21;
-this.CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK = 22;
-this.CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK = 23;
-this.CARD_PERSOSUBSTATE_RUIM_RUIM_PUK = 24;
-
-this.CARD_APPSTATE_ILLEGAL = -1;
-this.CARD_APPSTATE_UNKNOWN = 0;
-this.CARD_APPSTATE_DETECTED = 1;
-this.CARD_APPSTATE_PIN = 2; // If PIN1 or UPin is required.
-this.CARD_APPSTATE_PUK = 3; // If PUK1 or Puk for UPin is required.
-this.CARD_APPSTATE_SUBSCRIPTION_PERSO = 4; // perso_substate should be looked
- // at when app_state is assigned
- // to this value.
-this.CARD_APPSTATE_READY = 5;
-
-this.CARD_PINSTATE_UNKNOWN = 0;
-this.CARD_PINSTATE_ENABLED_NOT_VERIFIED = 1;
-this.CARD_PINSTATE_ENABLED_VERIFIED = 2;
-this.CARD_PINSTATE_DISABLED = 3;
-this.CARD_PINSTATE_ENABLED_BLOCKED = 4;
-this.CARD_PINSTATE_ENABLED_PERM_BLOCKED = 5;
-
-this.CARD_APPTYPE_UNKNOWN = 0;
-this.CARD_APPTYPE_SIM = 1;
-this.CARD_APPTYPE_USIM = 2;
-this.CARD_APPTYPE_RUIM = 3;
-this.CARD_APPTYPE_CSIM = 4;
-this.CARD_APPTYPE_ISIM = 5;
-
-this.CARD_MAX_APPS = 8;
-
-this.GECKO_CARD_TYPE = [
- null,
- "sim",
- "usim",
- "ruim",
- "csim",
- "isim"
-];
-
-
-// Used for QUERY_AVAILABLE_NETWORKS status.
-this.QAN_STATE_UNKNOWN = "unknown";
-this.QAN_STATE_AVAILABLE = "available";
-this.QAN_STATE_CURRENT = "current";
-this.QAN_STATE_FORBIDDEN = "forbidden";
-
-// Must be in sync with MobileNetworkState of MozMobileNetworkInfo.webidl
-this.GECKO_QAN_STATE_UNKNOWN = null;
-this.GECKO_QAN_STATE_AVAILABLE = "available";
-this.GECKO_QAN_STATE_CONNECTED = "connected";
-this.GECKO_QAN_STATE_FORBIDDEN = "forbidden";
-
-this.RIL_QAN_STATE_TO_GECKO_STATE = {};
-this.RIL_QAN_STATE_TO_GECKO_STATE[this.QAN_STATE_UNKNOWN] = this.GECKO_QAN_STATE_UNKNOWN;
-this.RIL_QAN_STATE_TO_GECKO_STATE[this.QAN_STATE_AVAILABLE] = this.GECKO_QAN_STATE_AVAILABLE;
-this.RIL_QAN_STATE_TO_GECKO_STATE[this.QAN_STATE_CURRENT] = this.GECKO_QAN_STATE_CONNECTED;
-this.RIL_QAN_STATE_TO_GECKO_STATE[this.QAN_STATE_FORBIDDEN] = this.GECKO_QAN_STATE_FORBIDDEN;
-
-this.NETWORK_SELECTION_MODE_AUTOMATIC = 0;
-this.NETWORK_SELECTION_MODE_MANUAL = 1;
-
-this.NETWORK_INFO_VOICE_REGISTRATION_STATE = "voiceRegistrationState";
-this.NETWORK_INFO_DATA_REGISTRATION_STATE = "dataRegistrationState";
-this.NETWORK_INFO_OPERATOR = "operator";
-this.NETWORK_INFO_NETWORK_SELECTION_MODE = "networkSelectionMode";
-this.NETWORK_INFO_SIGNAL = "signal";
-this.NETWORK_INFO_MESSAGE_TYPES = [
- NETWORK_INFO_VOICE_REGISTRATION_STATE,
- NETWORK_INFO_DATA_REGISTRATION_STATE,
- NETWORK_INFO_OPERATOR,
- NETWORK_INFO_NETWORK_SELECTION_MODE,
- NETWORK_INFO_SIGNAL
-];
-
-this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM = "wcdma/gsm";
-this.GECKO_PREFERRED_NETWORK_TYPE_GSM_ONLY = "gsm";
-this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_ONLY = "wcdma";
-this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_AUTO = "wcdma/gsm-auto";
-this.GECKO_PREFERRED_NETWORK_TYPE_CDMA_EVDO = "cdma/evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_CDMA_ONLY = "cdma";
-this.GECKO_PREFERRED_NETWORK_TYPE_EVDO_ONLY = "evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_CDMA_EVDO = "wcdma/gsm/cdma/evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_CDMA_EVDO = "lte/cdma/evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM = "lte/wcdma/gsm";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA = "lte/wcdma";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM_CDMA_EVDO = "lte/wcdma/gsm/cdma/evdo";
-this.GECKO_PREFERRED_NETWORK_TYPE_LTE_ONLY = "lte";
-this.RIL_PREFERRED_NETWORK_TYPE_TO_GECKO = [
- GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM,
- GECKO_PREFERRED_NETWORK_TYPE_GSM_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_WCDMA_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_AUTO,
- GECKO_PREFERRED_NETWORK_TYPE_CDMA_EVDO,
- GECKO_PREFERRED_NETWORK_TYPE_CDMA_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_EVDO_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_CDMA_EVDO,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_CDMA_EVDO,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA_GSM_CDMA_EVDO,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_ONLY,
- GECKO_PREFERRED_NETWORK_TYPE_LTE_WCDMA
-];
-
-this.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT = "gsm,wcdma";
-// Index-item pair must be in sync with nsIMobileConnection.MOBILE_NETWORK_TYPE_*
-this.GECKO_SUPPORTED_NETWORK_TYPES = [
- "gsm",
- "wcdma",
- "cdma",
- "evdo",
- "lte"
-];
-
-// Network registration states. See TS 27.007 7.2
-this.NETWORK_CREG_STATE_NOT_SEARCHING = 0;
-this.NETWORK_CREG_STATE_REGISTERED_HOME = 1;
-this.NETWORK_CREG_STATE_SEARCHING = 2;
-this.NETWORK_CREG_STATE_DENIED = 3;
-this.NETWORK_CREG_STATE_UNKNOWN = 4;
-this.NETWORK_CREG_STATE_REGISTERED_ROAMING = 5;
-this.NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS = 10;
-this.NETWORK_CREG_STATE_SEARCHING_EMERGENCY_CALLS = 12;
-this.NETWORK_CREG_STATE_DENIED_EMERGENCY_CALLS = 13;
-this.NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS = 14;
-
-this.NETWORK_CREG_TECH_UNKNOWN = 0;
-this.NETWORK_CREG_TECH_GPRS = 1;
-this.NETWORK_CREG_TECH_EDGE = 2;
-this.NETWORK_CREG_TECH_UMTS = 3;
-this.NETWORK_CREG_TECH_IS95A = 4;
-this.NETWORK_CREG_TECH_IS95B = 5;
-this.NETWORK_CREG_TECH_1XRTT = 6;
-this.NETWORK_CREG_TECH_EVDO0 = 7;
-this.NETWORK_CREG_TECH_EVDOA = 8;
-this.NETWORK_CREG_TECH_HSDPA = 9;
-this.NETWORK_CREG_TECH_HSUPA = 10;
-this.NETWORK_CREG_TECH_HSPA = 11;
-this.NETWORK_CREG_TECH_EVDOB = 12;
-this.NETWORK_CREG_TECH_EHRPD = 13;
-this.NETWORK_CREG_TECH_LTE = 14;
-this.NETWORK_CREG_TECH_HSPAP = 15;
-this.NETWORK_CREG_TECH_GSM = 16;
-this.NETWORK_CREG_TECH_DCHSPAP_1 = 18; // Some devices reports as 18
-this.NETWORK_CREG_TECH_DCHSPAP_2 = 19; // Some others report it as 19
-
-this.CELL_INFO_TYPE_GSM = 1;
-this.CELL_INFO_TYPE_CDMA = 2;
-this.CELL_INFO_TYPE_LTE = 3;
-this.CELL_INFO_TYPE_WCDMA = 4;
-
-this.CALL_STATE_UNKNOWN = -1;
-this.CALL_STATE_ACTIVE = 0;
-this.CALL_STATE_HOLDING = 1;
-this.CALL_STATE_DIALING = 2;
-this.CALL_STATE_ALERTING = 3;
-this.CALL_STATE_INCOMING = 4;
-this.CALL_STATE_WAITING = 5;
-
-this.TOA_INTERNATIONAL = 0x91;
-this.TOA_UNKNOWN = 0x81;
-
-this.CALL_PRESENTATION_ALLOWED = 0;
-this.CALL_PRESENTATION_RESTRICTED = 1;
-this.CALL_PRESENTATION_UNKNOWN = 2;
-this.CALL_PRESENTATION_PAYPHONE = 3;
-
-// Call forwarding actions, see TS 27.007 7.11 "mode"
-this.CALL_FORWARD_ACTION_QUERY_STATUS = 2;
-
-// ICC commands, see TS 27.007 +CRSM commands
-this.ICC_COMMAND_SEEK = 0xa2;
-this.ICC_COMMAND_READ_BINARY = 0xb0;
-this.ICC_COMMAND_READ_RECORD = 0xb2;
-this.ICC_COMMAND_GET_RESPONSE = 0xc0;
-this.ICC_COMMAND_UPDATE_BINARY = 0xd6;
-this.ICC_COMMAND_UPDATE_RECORD = 0xdc;
-
-// ICC constants, GSM SIM file ids from TS 51.011
-this.ICC_EF_ICCID = 0x2fe2;
-this.ICC_EF_IMG = 0x4f20;
-this.ICC_EF_PBR = 0x4f30;
-this.ICC_EF_PLMNsel = 0x6f30; // PLMN for SIM
-this.ICC_EF_SST = 0x6f38;
-this.ICC_EF_UST = 0x6f38; // For USIM
-this.ICC_EF_ADN = 0x6f3a;
-this.ICC_EF_FDN = 0x6f3b;
-this.ICC_EF_SMS = 0x6f3c;
-this.ICC_EF_GID1 = 0x6f3e;
-this.ICC_EF_MSISDN = 0x6f40;
-this.ICC_EF_CBMI = 0x6f45;
-this.ICC_EF_SPN = 0x6f46;
-this.ICC_EF_CBMID = 0x6f48;
-this.ICC_EF_SDN = 0x6f49;
-this.ICC_EF_EXT1 = 0x6f4a;
-this.ICC_EF_EXT2 = 0x6f4b;
-this.ICC_EF_EXT3 = 0x6f4c;
-this.ICC_EF_CBMIR = 0x6f50;
-this.ICC_EF_AD = 0x6fad;
-this.ICC_EF_PHASE = 0x6fae;
-this.ICC_EF_PNN = 0x6fc5;
-this.ICC_EF_OPL = 0x6fc6;
-this.ICC_EF_MBDN = 0x6fc7;
-this.ICC_EF_EXT6 = 0x6fc8; // Ext record for EF[MBDN]
-this.ICC_EF_MBI = 0x6fc9;
-this.ICC_EF_MWIS = 0x6fca;
-this.ICC_EF_CFIS = 0x6fcb;
-this.ICC_EF_SPDI = 0x6fcd;
-
-// CPHS files to be supported
-this.ICC_EF_CPHS_INFO = 0x6f16; // CPHS Information
-this.ICC_EF_CPHS_MBN = 0x6f17; // Mailbox Numbers
-
-// CSIM files
-this.ICC_EF_CSIM_IMSI_M = 0x6f22;
-this.ICC_EF_CSIM_CDMAHOME = 0x6f28;
-this.ICC_EF_CSIM_CST = 0x6f32; // CDMA Service table
-this.ICC_EF_CSIM_SPN = 0x6f41;
-
-this.ICC_PHASE_1 = 0x00;
-this.ICC_PHASE_2 = 0x02;
-this.ICC_PHASE_2_PROFILE_DOWNLOAD_REQUIRED = 0x03;
-
-// Types of files TS 11.11 9.3
-this.TYPE_RFU = 0;
-this.TYPE_MF = 1;
-this.TYPE_DF = 2;
-this.TYPE_EF = 4;
-
-this.RESPONSE_DATA_FILE_SIZE = 2;
-this.RESPONSE_DATA_FILE_ID_1 = 4;
-this.RESPONSE_DATA_FILE_ID_2 = 5;
-this.RESPONSE_DATA_FILE_TYPE = 6;
-this.RESPONSE_DATA_RFU_3 = 7;
-this.RESPONSE_DATA_ACCESS_CONDITION_1 = 8;
-this.RESPONSE_DATA_ACCESS_CONDITION_2 = 9;
-this.RESPONSE_DATA_ACCESS_CONDITION_3 = 10;
-this.RESPONSE_DATA_FILE_STATUS = 11;
-this.RESPONSE_DATA_LENGTH = 12;
-this.RESPONSE_DATA_STRUCTURE = 13;
-this.RESPONSE_DATA_RECORD_LENGTH = 14;
-
-// Structure of files TS 11.11 9.3
-this.EF_STRUCTURE_TRANSPARENT = 0;
-this.EF_STRUCTURE_LINEAR_FIXED = 1;
-this.EF_STRUCTURE_CYCLIC = 3;
-
-// TS 102.221 11.1.1.4.3 Table 11.5: File descriptor byte.
-this.UICC_EF_STRUCTURE = {};
-this.UICC_EF_STRUCTURE[this.EF_STRUCTURE_TRANSPARENT]= 1;
-this.UICC_EF_STRUCTURE[this.EF_STRUCTURE_LINEAR_FIXED]= 2;
-this.UICC_EF_STRUCTURE[this.EF_STRUCTURE_CYCLIC]= 6;
-
-// Status code of EFsms
-// see 3GPP TS 51.011 clause 10.5.3
-this.EFSMS_STATUS_FREE = 0x00;
-this.EFSMS_STATUS_READ = 0x01;
-this.EFSMS_STATUS_TO_BE_READ = 0x03;
-this.EFSMS_STATUS_TO_BE_SENT = 0x07;
-
-// Total size of ADN footer(the size of Alpha identifier excluded).
-// See TS 151.011 clause 10.5.1 EF_ADN.
-this.ADN_FOOTER_SIZE_BYTES = 14;
-// Maximum size of BCD numbers in ADN.
-// See TS 151.011 clause 10.5.1 EF_ADN, 'Length of BCD number/SSC contents'.
-this.ADN_MAX_BCD_NUMBER_BYTES = 11;
-// Maximum digits of the Dialling Number in ADN.
-// See TS 151.011 clause 10.5.1 EF_ADN, 'Dialling Number'.
-this.ADN_MAX_NUMBER_DIGITS = 20;
-// Maximum size of BCD numbers in EXT.
-// See TS 151.011 clause 10.5.10 EF_EXT1, 'Extension data'.
-this.EXT_MAX_BCD_NUMBER_BYTES = 10;
-// Maximum digits of the Dialling Number in EXT.
-// See TS 151.011 clause 10.5.10 EF_EXT1, 'Extension data'.
-this.EXT_MAX_NUMBER_DIGITS = 20;
-
-// READ_RECORD mode, TS 102.221
-this.READ_RECORD_ABSOLUTE_MODE = 4;
-
-// TS 102.221 Table 11.2, return FCP template
-this.GET_RESPONSE_FCP_TEMPLATE = 4;
-
-// GET_RESPONSE mandatory response size for EF, see TS 51.011 clause 9,
-// 'Response data in case of an EF.'
-this.GET_RESPONSE_EF_SIZE_BYTES = 15;
-
-// EF path
-this.EF_PATH_MF_SIM = "3f00";
-this.EF_PATH_DF_PHONEBOOK = "5f3a";
-this.EF_PATH_GRAPHICS = "5f50";
-this.EF_PATH_DF_TELECOM = "7f10";
-this.EF_PATH_DF_GSM = "7f20";
-this.EF_PATH_DF_CDMA = "7f25";
-this.EF_PATH_ADF_USIM = "7fff";
-
-// Status code of sw1 for ICC I/O,
-// see GSM11.11 and TS 51.011 clause 9.4, and ISO 7816-4
-this.ICC_STATUS_NORMAL_ENDING = 0x90;
-this.ICC_STATUS_NORMAL_ENDING_WITH_EXTRA = 0x91;
-this.ICC_STATUS_SAT_BUSY = 0x93;
-this.ICC_STATUS_WITH_SIM_DATA = 0x9e;
-this.ICC_STATUS_WITH_RESPONSE_DATA = 0x9f;
-this.ICC_STATUS_ERROR_WRONG_LENGTH = 0x67;
-this.ICC_STATUS_ERROR_COMMAND_NOT_ALLOWED = 0x69;
-this.ICC_STATUS_ERROR_WRONG_PARAMETERS = 0x6a;
-
-// ICC call barring facility.
-// TS 27.007, clause 7.4, +CLCK
-this.ICC_CB_FACILITY_SIM = "SC";
-this.ICC_CB_FACILITY_FDN = "FD";
-this.ICC_CB_FACILITY_BAOC = "AO";
-this.ICC_CB_FACILITY_BAOIC = "OI";
-this.ICC_CB_FACILITY_BAOICxH = "OX";
-this.ICC_CB_FACILITY_BAIC = "AI";
-this.ICC_CB_FACILITY_BAICr = "IR";
-this.ICC_CB_FACILITY_BA_ALL = "AB";
-this.ICC_CB_FACILITY_BA_MO = "AG";
-this.ICC_CB_FACILITY_BA_MT = "AC";
-
-// ICC service class
-// TS 27.007, clause 7.4, +CLCK
-this.ICC_SERVICE_CLASS_NONE = 0; // no user input
-this.ICC_SERVICE_CLASS_VOICE = (1 << 0);
-this.ICC_SERVICE_CLASS_DATA = (1 << 1);
-this.ICC_SERVICE_CLASS_FAX = (1 << 2);
-this.ICC_SERVICE_CLASS_SMS = (1 << 3);
-this.ICC_SERVICE_CLASS_DATA_SYNC = (1 << 4);
-this.ICC_SERVICE_CLASS_DATA_ASYNC = (1 << 5);
-this.ICC_SERVICE_CLASS_PACKET = (1 << 6);
-this.ICC_SERVICE_CLASS_PAD = (1 << 7);
-this.ICC_SERVICE_CLASS_MAX = (1 << 7); // Max ICC_SERVICE_CLASS value
-
-// ICC lock-selection codes
-// TS 27.007, clause 8.65, +CPINR
-this.ICC_SEL_CODE_SIM_PIN = "SIM PIN";
-this.ICC_SEL_CODE_SIM_PUK = "SIM PUK";
-this.ICC_SEL_CODE_PH_SIM_PIN = "PH-SIM PIN";
-this.ICC_SEL_CODE_PH_FSIM_PIN = "PH-FSIM PIN";
-this.ICC_SEL_CODE_PH_FSIM_PUK = "PH-FSIM PUK";
-this.ICC_SEL_CODE_SIM_PIN2 = "SIM PIN2";
-this.ICC_SEL_CODE_SIM_PUK2 = "SIM PUK2";
-this.ICC_SEL_CODE_PH_NET_PIN = "PH-NET PIN";
-this.ICC_SEL_CODE_PH_NET_PUK = "PH-NET PUK";
-this.ICC_SEL_CODE_PH_NETSUB_PIN = "PH-NETSUB PIN";
-this.ICC_SEL_CODE_PH_NETSUB_PUK = "PH-NETSUB PUK";
-this.ICC_SEL_CODE_PH_SP_PIN = "PH-SP PIN";
-this.ICC_SEL_CODE_PH_SP_PUK = "PH-SP PUK";
-this.ICC_SEL_CODE_PH_CORP_PIN = "PH-CORP PIN";
-this.ICC_SEL_CODE_PH_CORP_PUK = "PH-CORP PUK";
-// TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM @
-// ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_PCK.
-
-this.ICC_USIM_TYPE1_TAG = 0xa8;
-this.ICC_USIM_TYPE2_TAG = 0xa9;
-this.ICC_USIM_TYPE3_TAG = 0xaa;
-this.ICC_USIM_EFADN_TAG = 0xc0;
-this.ICC_USIM_EFIAP_TAG = 0xc1;
-this.ICC_USIM_EFEXT1_TAG = 0xc2;
-this.ICC_USIM_EFSNE_TAG = 0xc3;
-this.ICC_USIM_EFANR_TAG = 0xc4;
-this.ICC_USIM_EFPBC_TAG = 0xc5;
-this.ICC_USIM_EFGRP_TAG = 0xc6;
-this.ICC_USIM_EFAAS_TAG = 0xc7;
-this.ICC_USIM_EFGSD_TAG = 0xc8;
-this.ICC_USIM_EFUID_TAG = 0xc9;
-this.ICC_USIM_EFEMAIL_TAG = 0xca;
-this.ICC_USIM_EFCCP1_TAG = 0xcb;
-
-// ICC image coding scheme
-// TS 31.102, sub-clause 4.6.1.1
-this.ICC_IMG_CODING_SCHEME_BASIC = 0x11;
-this.ICC_IMG_CODING_SCHEME_COLOR = 0x21;
-this.ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY = 0x22;
-
-// Must be in sync with enum IccImageCodingScheme in MozStkCommandEvent.webidl.
-this.GECKO_IMG_CODING_SCHEME_BASIC = "basic";
-this.GECKO_IMG_CODING_SCHEME_COLOR = "color";
-this.GECKO_IMG_CODING_SCHEME_COLOR_TRANSPARENCY = "color-transparency";
-
-this.ICC_IMG_CODING_SCHEME_TO_GECKO = {};
-ICC_IMG_CODING_SCHEME_TO_GECKO[ICC_IMG_CODING_SCHEME_BASIC] = GECKO_IMG_CODING_SCHEME_BASIC;
-ICC_IMG_CODING_SCHEME_TO_GECKO[ICC_IMG_CODING_SCHEME_COLOR] = GECKO_IMG_CODING_SCHEME_COLOR;
-ICC_IMG_CODING_SCHEME_TO_GECKO[ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY] = GECKO_IMG_CODING_SCHEME_COLOR_TRANSPARENCY;
-
-// ICC image header size per coding scheme
-// TS 31.102, Annex B
-this.ICC_IMG_HEADER_SIZE_BASIC = 2;
-this.ICC_IMG_HEADER_SIZE_COLOR = 6;
-
-this.ICC_CLUT_ENTRY_SIZE = 3;
-
-this.USIM_PBR_ANR = "anr";
-this.USIM_PBR_ANR0 = "anr0";
-this.USIM_PBR_EMAIL = "email";
-
-// Current supported fields. Adding more fields to read will increasing I/O
-// time dramatically, do check the performance is acceptable when you add
-// more fields.
-this.USIM_PBR_FIELDS = [USIM_PBR_EMAIL, USIM_PBR_ANR0];
-
-this.USIM_TAG_NAME = {};
-this.USIM_TAG_NAME[ICC_USIM_EFADN_TAG] = "adn";
-this.USIM_TAG_NAME[ICC_USIM_EFIAP_TAG] ="iap";
-this.USIM_TAG_NAME[ICC_USIM_EFEXT1_TAG] = "ext1";
-this.USIM_TAG_NAME[ICC_USIM_EFSNE_TAG] = "sne";
-this.USIM_TAG_NAME[ICC_USIM_EFANR_TAG] = "anr";
-this.USIM_TAG_NAME[ICC_USIM_EFPBC_TAG] = "pbc";
-this.USIM_TAG_NAME[ICC_USIM_EFGRP_TAG] = "grp";
-this.USIM_TAG_NAME[ICC_USIM_EFAAS_TAG] = "aas";
-this.USIM_TAG_NAME[ICC_USIM_EFGSD_TAG] = "gsd";
-this.USIM_TAG_NAME[ICC_USIM_EFUID_TAG] = "uid";
-this.USIM_TAG_NAME[ICC_USIM_EFEMAIL_TAG] = "email";
-this.USIM_TAG_NAME[ICC_USIM_EFCCP1_TAG] = "ccp1";
-
-// Error message for ICC contact.
-this.CONTACT_ERR_REQUEST_NOT_SUPPORTED = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
-this.CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED = "ContactTypeNotSupported";
-this.CONTACT_ERR_FIELD_NOT_SUPPORTED = "FieldNotSupported";
-this.CONTACT_ERR_NO_FREE_RECORD_FOUND = "NoFreeRecordFound";
-this.CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK = "CannotAccessPhoneBook";
-
-// CDMA IMSI_M's byte const.
-// 3GPP2 C.S0065 Sec. 5.2.2
-this.CSIM_IMSI_M_MIN2_BYTE = 1;
-this.CSIM_IMSI_M_MIN1_BYTE = 3;
-this.CSIM_IMSI_M_MNC_BYTE = 6;
-this.CSIM_IMSI_M_PROGRAMMED_BYTE = 7;
-this.CSIM_IMSI_M_MCC_BYTE = 8;
-
-/**
- * Tags for Ber Tlv.
- * See 3GPP TS 101 220 clause 7.2 - Assigned TLV tag values.
- */
-this.BER_UNKNOWN_TAG = 0x00;
-this.BER_FCP_TEMPLATE_TAG = 0x62;
-this.BER_FCP_FILE_SIZE_DATA_TAG = 0x80;
-this.BER_FCP_FILE_SIZE_TOTAL_TAG = 0x81;
-this.BER_FCP_FILE_DESCRIPTOR_TAG = 0x82;
-this.BER_FCP_FILE_IDENTIFIER_TAG = 0x83;
-this.BER_FCP_DF_NAME_TAG = 0x84; // AID.
-this.BER_FCP_PROPRIETARY_PRIMITIVE_TAG = 0x85;
-this.BER_FCP_SFI_SUPPORT_TAG = 0x88;
-this.BER_FCP_LIFE_CYCLE_STATUS_TAG = 0x8a;
-this.BER_FCP_SA_REFERENCE_FORMAT_TAG = 0x8b; // Security Attribute - Reference Format.
-this.BER_FCP_SA_COMPACT_FORMAT_TAG = 0x8c; // Security Attribute - Compact Format.
-this.BER_FCP_SAT_EXPANDED_FORMAT_TAG = 0xab; // Security Attribute Template - Expanded Format.
-this.BER_FCP_PROPRIETARY_TEMPLATE_TAG = 0xa5;
-this.BER_FCP_PIN_STATUS_DATA_OBJECTS_TAG = 0xc6;
-this.BER_PROACTIVE_COMMAND_TAG = 0xd0;
-this.BER_SMS_PP_DOWNLOAD_TAG = 0xd1;
-this.BER_MENU_SELECTION_TAG = 0xd3;
-this.BER_EVENT_DOWNLOAD_TAG = 0xd6;
-this.BER_TIMER_EXPIRATION_TAG = 0xd7;
-
-// Flags in Comprehension TLV.
-this.COMPREHENSIONTLV_FLAG_CR = 0x80; // Comprehension required.
-
-// Tags for Comprehension TLV.
-this.COMPREHENSIONTLV_TAG_COMMAND_DETAILS = 0x01;
-this.COMPREHENSIONTLV_TAG_DEVICE_ID = 0x02;
-this.COMPREHENSIONTLV_TAG_RESULT = 0x03;
-this.COMPREHENSIONTLV_TAG_DURATION = 0x04;
-this.COMPREHENSIONTLV_TAG_ALPHA_ID = 0x05;
-this.COMPREHENSIONTLV_TAG_ADDRESS = 0x06;
-this.COMPREHENSIONTLV_TAG_SUBADDRESS = 0x08;
-this.COMPREHENSIONTLV_TAG_SMS_TPDU = 0x0b;
-this.COMPREHENSIONTLV_TAG_TEXT_STRING = 0x0d;
-this.COMPREHENSIONTLV_TAG_TONE = 0x0e;
-this.COMPREHENSIONTLV_TAG_ITEM = 0x0f;
-this.COMPREHENSIONTLV_TAG_ITEM_ID = 0x10;
-this.COMPREHENSIONTLV_TAG_RESPONSE_LENGTH = 0x11;
-this.COMPREHENSIONTLV_TAG_FILE_LIST = 0x12;
-this.COMPREHENSIONTLV_TAG_LOCATION_INFO = 0x13;
-this.COMPREHENSIONTLV_TAG_IMEI = 0x14;
-this.COMPREHENSIONTLV_TAG_HELP_REQUEST = 0x15;
-this.COMPREHENSIONTLV_TAG_NMR = 0x16;
-this.COMPREHENSIONTLV_TAG_DEFAULT_TEXT = 0x17;
-this.COMPREHENSIONTLV_TAG_NEXT_ACTION_IND = 0x18;
-this.COMPREHENSIONTLV_TAG_CAUSE = 0x1a;
-this.COMPREHENSIONTLV_TAG_LOCATION_STATUS = 0x1b;
-this.COMPREHENSIONTLV_TAG_TRANSACTION_ID = 0x1c;
-this.COMPREHENSIONTLV_TAG_EVENT_LIST = 0x19;
-this.COMPREHENSIONTLV_TAG_ICON_ID = 0x1e;
-this.COMPREHENSIONTLV_TAG_ICON_ID_LIST = 0x1f;
-this.COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER = 0x24;
-this.COMPREHENSIONTLV_TAG_TIMER_VALUE = 0x25;
-this.COMPREHENSIONTLV_TAG_DATE_TIME_ZONE = 0x26;
-this.COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE = 0x2b;
-this.COMPREHENSIONTLV_TAG_LANGUAGE = 0x2d;
-this.COMPREHENSIONTLV_TAG_URL = 0x31;
-this.COMPREHENSIONTLV_TAG_BROWSER_TERMINATION_CAUSE = 0x34;
-this.COMPREHENSIONTLV_TAG_ACCESS_TECH = 0x3f;
-this.COMPREHENSIONTLV_TAG_SERVICE_RECORD = 0x41;
-this.COMPREHENSIONTLV_TAG_IMEISV = 0x62;
-this.COMPREHENSIONTLV_TAG_BATTERY_STATE = 0x63;
-this.COMPREHENSIONTLV_TAG_NETWORK_SEARCH_MODE = 0x65;
-this.COMPREHENSIONTLV_TAG_MEID = 0x6d;
-this.COMPREHENSIONTLV_TAG_BROADCAST_NETWORK_INFO = 0x7a;
-
-// Tags for Service Provider Display Information TLV
-this.SPDI_TAG_SPDI = 0xa3;
-this.SPDI_TAG_PLMN_LIST = 0x80;
-
-// MM INFORMATION message content IEIs
-// See 3GPP TS 24.008 table 9.2.18
-this.PNN_IEI_FULL_NETWORK_NAME = 0x43;
-this.PNN_IEI_SHORT_NETWORK_NAME = 0x45;
-
-// Device identifiers, see TS 11.14, clause 12.7
-this.STK_DEVICE_ID_KEYPAD = 0x01;
-this.STK_DEVICE_ID_DISPLAY = 0x02;
-this.STK_DEVICE_ID_EARPIECE = 0x03;
-this.STK_DEVICE_ID_SIM = 0x81;
-this.STK_DEVICE_ID_ME = 0x82;
-this.STK_DEVICE_ID_NETWORK = 0x83;
-
-// STK Proactive commands.
-this.STK_CMD_REFRESH = 0x01;
-this.STK_CMD_MORE_TIME = 0x02;
-this.STK_CMD_POLL_INTERVAL = 0x03;
-this.STK_CMD_POLL_OFF = 0x04;
-this.STK_CMD_SET_UP_EVENT_LIST = 0x05;
-this.STK_CMD_SET_UP_CALL = 0x10;
-this.STK_CMD_SEND_SS = 0x11;
-this.STK_CMD_SEND_USSD = 0x12;
-this.STK_CMD_SEND_SMS = 0x13;
-this.STK_CMD_SEND_DTMF = 0x14;
-this.STK_CMD_LAUNCH_BROWSER = 0x15;
-this.STK_CMD_PLAY_TONE = 0x20;
-this.STK_CMD_DISPLAY_TEXT = 0x21;
-this.STK_CMD_GET_INKEY = 0x22;
-this.STK_CMD_GET_INPUT = 0x23;
-this.STK_CMD_SELECT_ITEM = 0x24;
-this.STK_CMD_SET_UP_MENU = 0x25;
-this.STK_CMD_PROVIDE_LOCAL_INFO = 0x26;
-this.STK_CMD_TIMER_MANAGEMENT = 0x27;
-this.STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28;
-this.STK_CMD_OPEN_CHANNEL = 0x40;
-this.STK_CMD_CLOSE_CHANNEL = 0x41;
-this.STK_CMD_RECEIVE_DATA = 0x42;
-this.STK_CMD_SEND_DATA = 0x43;
-
-// STK Result code.
-// TS 11.14, clause 12.12
-
-// Results '0X' and '1X' indicate that the command has been performed.
-
-// Command performed successfully.
-this.STK_RESULT_OK = 0x00;
-
-// Command performed with partial comprehension.
-this.STK_RESULT_PRFRMD_WITH_PARTIAL_COMPREHENSION = 0x01;
-
-// Command performed, with missing information.
-this.STK_RESULT_PRFRMD_WITH_MISSING_INFO = 0x02;
-
-// REFRESH performed with additional EFs read.
-this.STK_RESULT_PRFRMD_WITH_ADDITIONAL_EFS_READ = 0x03;
-
-// Command performed successfully, but requested icon could not be
-// displayed.
-this.STK_RESULT_PRFRMD_ICON_NOT_DISPLAYED = 0x04;
-
-// Command performed, but modified by call control by NAA.
-this.STK_RESULT_PRFRMD_MODIFIED_BY_NAA = 0x05;
-
-// Command performed successfully, limited service.
-this.STK_RESULT_PRFRMD_LIMITED_SERVICE = 0x06;
-
-// Command performed with modification.
-this.STK_RESULT_PRFRMD_WITH_MODIFICATION = 0x07;
-
-// REFRESH performed but indicated NAA was not active.
-this.STK_RESULT_PRFRMD_NAA_NOT_ACTIVE = 0x08;
-
-// Command performed successfully; tone not played.
-this.STK_RESULT_PRFRMD_TONE_NOT_PLAYED = 0x09;
-
-// Proactive UICC session terminated by the user.
-this.STK_RESULT_UICC_SESSION_TERM_BY_USER = 0x10;
-
-// Backward move in the proactive UICC session requested by the user.
-this.STK_RESULT_BACKWARD_MOVE_BY_USER = 0x11;
-
-// No response from user.
-this.STK_RESULT_NO_RESPONSE_FROM_USER = 0x12;
-
-// Help information required by the user.
-this.STK_RESULT_HELP_INFO_REQUIRED = 0x13;
-
-// USSD or SS transaction terminated by the user.
-this.STK_RESULT_USSD_SS_SESSION_TERM_BY_USER = 0x14;
-
-// Results '2X' indicate to the UICC that it may be worth re-trying the
-// command at a later opportunity.
-
-// Terminal currently unable to process command.
-this.STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS = 0x20;
-
-// Network currently unable to process command.
-this.STK_RESULT_NETWORK_CRNTLY_UNABLE_TO_PROCESS = 0x21;
-
-// User did not accept the proactive command.
-this.STK_RESULT_USER_NOT_ACCEPT = 0x22;
-
-// User cleared down call before connection or network release.
-this.STK_RESULT_USER_CLEAR_DOWN_CALL = 0x23;
-
-// Action in contradiction with the current timer state.
-this.STK_RESULT_CONTRADICTION_WITH_TIMER = 0x24;
-
-// Interaction with call control by NAA; temporary problem.
-this.STK_RESULT_NAA_CALL_CONTROL_TEMPORARY = 0x25;
-
-// Launch browser generic error code.
-this.STK_RESULT_LAUNCH_BROWSER_ERROR = 0x26;
-
-// MMS temporary problem.
-this.STK_RESULT_MMS_TEMPORARY = 0x27;
-
-// Results '3X' indicate that it is not worth the UICC re-trying with an
-// identical command; as it will only get the same response. However, the
-// decision to retry lies with the application.
-
-// Command beyond terminal's capabilities.
-this.STK_RESULT_BEYOND_TERMINAL_CAPABILITY = 0x30;
-
-// Command type not understood by terminal.
-this.STK_RESULT_CMD_TYPE_NOT_UNDERSTOOD = 0x31;
-
-// Command data not understood by terminal.
-this.STK_RESULT_CMD_DATA_NOT_UNDERSTOOD = 0x32;
-
-// Command number not known by terminal.
-this.STK_RESULT_CMD_NUM_NOT_KNOWN = 0x33;
-
-// SS Return Error.
-this.STK_RESULT_SS_RETURN_ERROR = 0x34;
-
-// SMS RP-ERROR.
-this.STK_RESULT_SMS_RP_ERROR = 0x35;
-
-// Error, required values are missing.
-this.STK_RESULT_REQUIRED_VALUES_MISSING = 0x36;
-
-// USSD Return Error.
-this.STK_RESULT_USSD_RETURN_ERROR = 0x37;
-
-// MultipleCard commands error.
-this.STK_RESULT_MULTI_CARDS_CMD_ERROR = 0x38;
-
-// Interaction with call control by USIM or MO short message control by
-// USIM; permanent problem.
-this.STK_RESULT_USIM_CALL_CONTROL_PERMANENT = 0x39;
-
-// Bearer Independent Protocol error.
-this.STK_RESULT_BIP_ERROR = 0x3a;
-
-// Access Technology unable to process command.
-this.STK_RESULT_ACCESS_TECH_UNABLE_TO_PROCESS = 0x3b;
-
-// Frames error.
-this.STK_RESULT_FRAMES_ERROR = 0x3c;
-
-// MMS Error.
-this.STK_RESULT_MMS_ERROR = 0x3d;
-
-// STK presentation types, TS 11.14, clause 12.6, Command Qualifier: Select Item
-this.STK_PRESENTATION_TYPE_NOT_SPECIFIED = 0x00; // Bit 1 is 0.
-this.STK_PRESENTATION_TYPE_DATA_VALUES = 0x01; // Bit 1 is 1, bit 2 is 0.
-this.STK_PRESENTATION_TYPE_NAVIGATION_OPTIONS = 0x03; // Bit 1 is 1, bit 2 is 1.
-
-// STK Coding Scheme.
-this.STK_TEXT_CODING_GSM_7BIT_PACKED = 0x00;
-this.STK_TEXT_CODING_GSM_8BIT = 0x04;
-this.STK_TEXT_CODING_UCS2 = 0x08;
-
-// STK Event List.
-this.STK_EVENT_TYPE_MT_CALL = 0x00;
-this.STK_EVENT_TYPE_CALL_CONNECTED = 0x01;
-this.STK_EVENT_TYPE_CALL_DISCONNECTED = 0x02;
-this.STK_EVENT_TYPE_LOCATION_STATUS = 0x03;
-this.STK_EVENT_TYPE_USER_ACTIVITY = 0x04;
-this.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE = 0x05;
-this.STK_EVENT_TYPE_CARD_READER_STATUS = 0x06;
-this.STK_EVENT_TYPE_LANGUAGE_SELECTION = 0x07;
-this.STK_EVENT_TYPE_BROWSER_TERMINATION = 0x08;
-this.STK_EVENT_TYPE_DATA_AVAILABLE = 0x09;
-this.STK_EVENT_TYPE_CHANNEL_STATUS = 0x0a;
-this.STK_EVENT_TYPE_SINGLE_ACCESS_TECHNOLOGY_CHANGED = 0x0b;
-this.STK_EVENT_TYPE_DISPLAY_PARAMETER_CHANGED = 0x0c;
-this.STK_EVENT_TYPE_LOCAL_CONNECTION = 0x0d;
-this.STK_EVENT_TYPE_NETWORK_SEARCH_MODE_CHANGED = 0x0e;
-this.STK_EVENT_TYPE_BROWSING_STATUS = 0x0f;
-
-// STK Service state of Location Status.
-this.STK_SERVICE_STATE_NORMAL = 0x00;
-this.STK_SERVICE_STATE_LIMITED = 0x01;
-this.STK_SERVICE_STATE_UNAVAILABLE = 0x02;
-
-// Refresh mode.
-this.STK_REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE = 0x00;
-this.STK_REFRESH_FILE_CHANGE = 0x01;
-this.STK_REFRESH_NAA_INIT_AND_FILE_CHANGE = 0x02;
-this.STK_REFRESH_NAA_INIT = 0x03;
-this.STK_REFRESH_UICC_RESET = 0x04;
-
-// Tone type.
-this.STK_TONE_TYPE_DIAL_TONE = 0x01;
-this.STK_TONE_TYPE_CALLED_SUBSCRIBER_BUSY = 0x02;
-this.STK_TONE_TYPE_CONGESTION = 0x03;
-this.STK_TONE_TYPE_RADIO_PATH_ACK = 0x04;
-this.STK_TONE_TYPE_RADIO_PATH_NOT_AVAILABLE = 0x05;
-this.STK_TONE_TYPE_ERROR = 0x06;
-this.STK_TONE_TYPE_CALL_WAITING_TONE = 0x07;
-this.STK_TONE_TYPE_RINGING_TONE = 0x08;
-this.STK_TONE_TYPE_GENERAL_BEEP = 0x10;
-this.STK_TONE_TYPE_POSITIVE_ACK_TONE = 0x11;
-this.STK_TONE_TYPE_NEGATIVE_ACK_TONE = 0x12;
-
-// Time unit.
-this.STK_TIME_UNIT_MINUTE = 0x00;
-this.STK_TIME_UNIT_SECOND = 0x01;
-this.STK_TIME_UNIT_TENTH_SECOND = 0x02;
-
-// Local Information type.
-this.STK_LOCAL_INFO_NNA = 0x00;
-this.STK_LOCAL_INFO_IMEI = 0x01;
-this.STK_LOCAL_INFO_NMR_FOR_NNA = 0x02;
-this.STK_LOCAL_INFO_DATE_TIME_ZONE = 0x03;
-this.STK_LOCAL_INFO_LANGUAGE = 0x04;
-this.STK_LOCAL_INFO_ACCESS_TECH = 0x06;
-this.STK_LOCAL_INFO_ESN = 0x07;
-this.STK_LOCAL_INFO_IMEISV = 0x08;
-this.STK_LOCAL_INFO_SEARCH_MODE = 0x09;
-this.STK_LOCAL_INFO_CHARGE_STATE = 0x0A;
-this.STK_LOCAL_INFO_MEID = 0x0B;
-this.STK_LOCAL_INFO_BROADCAST_NETWORK_INFO = 0x0D;
-this.STK_LOCAL_INFO_MULTIPLE_ACCESS_TECH = 0x0E;
-this.STK_LOCAL_INFO_INFO_FOR_MULTIPLE_ACCESS_TECH = 0x0F;
-this.STK_LOCAL_INFO_NMR_FOR_MULTIPLE_ACCESS_TECH = 0x10;
-
-// Timer Management.
-this.STK_TIMER_START = 0x00;
-this.STK_TIMER_DEACTIVATE = 0x01;
-this.STK_TMIER_GET_CURRENT_VALUE = 0x02;
-
-// Browser Launch Mode.
-this.STK_BROWSER_MODE_LAUNCH_IF_NOT_ALREADY_LAUNCHED = 0x00;
-this.STK_BROWSER_MODE_USING_EXISTING_BROWSER = 0x02;
-this.STK_BROWSER_MODE_USING_NEW_BROWSER = 0x03;
-
-// Browser Termination Cause.
-this.STK_BROWSER_TERMINATION_CAUSE_USER = 0x00;
-this.STK_BROWSER_TERMINATION_CAUSE_ERROR = 0x01;
-
-// Next Action Indicator.
-this.STK_NEXT_ACTION_NULL = 0x00;
-this.STK_NEXT_ACTION_END_PROACTIVE_SESSION = 0x81;
-
-/**
- * Supported Terminal Facilities.
- *
- * value = 1, supported.
- * 0, not supported.
- */
-this.STK_TERMINAL_SUPPORT_PROFILE_DOWNLOAD = 1;
-this.STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD = 1;
-this.STK_TERMINAL_SUPPORT_CELL_BROADCAST_DATA_DOWNLOAD = 0;
-this.STK_TERMINAL_SUPPORT_MENU_SELECTION = 1;
-this.STK_TERMINAL_SUPPORT_SIM_DATA_DOWNLOAD_ERROR = 0;
-this.STK_TERMINAL_SUPPORT_TIMER_EXPIRATION = 1;
-this.STK_TERMINAL_SUPPORT_USSD_IN_CALL_CONTROL = 0;
-this.STK_TERMINAL_SUPPORT_CALL_CONTROL_IN_REDIAL = 0;
-
-this.STK_TERMINAL_SUPPORT_COMMAND_RESULT = 1;
-this.STK_TERMINAL_SUPPORT_CALL_CONTROL = 1;
-this.STK_TERMINAL_SUPPORT_CALL_ID_INCLUDED = 0;
-this.STK_TERMINAL_SUPPORT_MO_SMS_CONTROL = 0;
-this.STK_TERMINAL_SUPPORT_ALPHA_ID_INDICATION = 0;
-this.STK_TERMINAL_SUPPORT_UCS2_ENTRY = 1;
-this.STK_TERMINAL_SUPPORT_UCS2_DISPLAY = 1;
-this.STK_TERMINAL_SUPPORT_EXTENSION_TEXT = 1;
-
-this.STK_TERMINAL_SUPPORT_PROACTIVE_DISPLAY_TEXT = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_GET_INKEY = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_GET_INPUT = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_MORE_TIME = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_PLAY_TONE = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_POLL_INTERVAL = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_POLL_OFF = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_REFRESH = 1;
-
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SELECT_ITEM = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SMS = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SS = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SEND_USSD = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_CALL = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_MENU = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR = 0;
-
-this.STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_EVENT_LIST = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_MT_CALL = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_CALL_CONNECTED = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_CALL_DISCONNECTED = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_LOCATION_STATUS = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS = 0;
-
-this.STK_TERMINAL_SUPPORT_EVENT_LANGUAGE_SELECTION = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_BROWSER_TERMINATION = 1;
-this.STK_TERMINAL_SUPPORT_EVENT_DATA_AVAILABLE = 0;
-this.STK_TERMINAL_SUPPORT_EVENT_CHANNEL_STATUS = 0;
-
-this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE = 1;
-this.STK_TERMINAL_SUPPORT_GET_INKEY = 1;
-this.STK_TERMINAL_SUPPORT_SET_UP_IDLE_MODE_TEXT = 1;
-this.STK_TERMINAL_SUPPORT_RUN_AT_COMMAND = 0;
-this.STK_TERMINAL_SUPPORT_SET_UP_CALL = 1;
-this.STK_TERMINAL_SUPPORT_CALL_CONTROL_BY_NNA = 0;
-
-this.STK_TERMINAL_SUPPORT_DISPLAY_TEXT = 1;
-this.STK_TERMINAL_SUPPORT_SEND_DTMF_COMMAND = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR = 0;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_LANGUAGE = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_TIME_ADVANCE = 0;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION = 0;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER = 1;
-this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH = 0;
-
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_OPEN_CHANNEL = 1;
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_CLOSE_CHANNEL = 1;
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_RECEIVE_DATA = 1;
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_SEND_DATA = 1;
-this.STK_TERMINAL_SUPPORT_BIP_COMMAND_GET_CHANNEL_STATUS = 0;
-
-/**
- * SAT profile
- *
- * @see ETSI TS 101.267, section 5.2.
- */
-this.STK_TERMINAL_PROFILE_DOWNLOAD =
- (STK_TERMINAL_SUPPORT_PROFILE_DOWNLOAD << 0) |
- (STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD << 1) |
- (STK_TERMINAL_SUPPORT_CELL_BROADCAST_DATA_DOWNLOAD << 2) |
- (STK_TERMINAL_SUPPORT_MENU_SELECTION << 3) |
- (STK_TERMINAL_SUPPORT_SIM_DATA_DOWNLOAD_ERROR << 4) |
- (STK_TERMINAL_SUPPORT_TIMER_EXPIRATION << 5) |
- (STK_TERMINAL_SUPPORT_USSD_IN_CALL_CONTROL << 6) |
- (STK_TERMINAL_SUPPORT_CALL_CONTROL_IN_REDIAL << 7);
-
-this.STK_TERMINAL_PROFILE_OTHER =
- (STK_TERMINAL_SUPPORT_COMMAND_RESULT << 0) |
- (STK_TERMINAL_SUPPORT_CALL_CONTROL << 1) |
- (STK_TERMINAL_SUPPORT_CALL_ID_INCLUDED << 2) |
- (STK_TERMINAL_SUPPORT_MO_SMS_CONTROL << 3) |
- (STK_TERMINAL_SUPPORT_ALPHA_ID_INDICATION << 4) |
- (STK_TERMINAL_SUPPORT_UCS2_ENTRY << 5) |
- (STK_TERMINAL_SUPPORT_UCS2_DISPLAY << 6) |
- (STK_TERMINAL_SUPPORT_EXTENSION_TEXT << 7);
-
-this.STK_TERMINAL_PROFILE_PROACTIVE_1 =
- (STK_TERMINAL_SUPPORT_PROACTIVE_DISPLAY_TEXT << 0) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_GET_INKEY << 1) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_GET_INPUT << 2) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_MORE_TIME << 3) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_PLAY_TONE << 4) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_POLL_INTERVAL << 5) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_POLL_OFF << 6) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_REFRESH << 7);
-
-this.STK_TERMINAL_PROFILE_PROACTIVE_2 =
- (STK_TERMINAL_SUPPORT_PROACTIVE_SELECT_ITEM << 0) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SMS << 1) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SEND_SS << 2) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SEND_USSD << 3) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_CALL << 4) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_MENU << 5) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO << 6) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR << 7);
-
-this.STK_TERMINAL_PROFILE_EVENT =
- (STK_TERMINAL_SUPPORT_PROACTIVE_SET_UP_EVENT_LIST << 0) |
- (STK_TERMINAL_SUPPORT_EVENT_MT_CALL << 1) |
- (STK_TERMINAL_SUPPORT_EVENT_CALL_CONNECTED << 2) |
- (STK_TERMINAL_SUPPORT_EVENT_CALL_DISCONNECTED << 3) |
- (STK_TERMINAL_SUPPORT_EVENT_LOCATION_STATUS << 4) |
- (STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY << 5) |
- (STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE << 6) |
- (STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS << 7);
-
-this.STK_TERMINAL_PROFILE_EVENT_EXT =
- (STK_TERMINAL_SUPPORT_EVENT_LANGUAGE_SELECTION << 0) |
- (STK_TERMINAL_SUPPORT_EVENT_BROWSER_TERMINATION << 1) |
- (STK_TERMINAL_SUPPORT_EVENT_DATA_AVAILABLE << 2) |
- (STK_TERMINAL_SUPPORT_EVENT_CHANNEL_STATUS << 3);
-
-this.STK_TERMINAL_PROFILE_PROACTIVE_3 =
- (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP << 0) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT << 1) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE << 2) |
- (STK_TERMINAL_SUPPORT_GET_INKEY << 3) |
- (STK_TERMINAL_SUPPORT_SET_UP_IDLE_MODE_TEXT << 4) |
- (STK_TERMINAL_SUPPORT_RUN_AT_COMMAND << 5) |
- (STK_TERMINAL_SUPPORT_SET_UP_CALL << 6) |
- (STK_TERMINAL_SUPPORT_CALL_CONTROL_BY_NNA << 7);
-
-this.STK_TERMINAL_PROFILE_PROACTIVE_4 =
- (STK_TERMINAL_SUPPORT_DISPLAY_TEXT << 0) |
- (STK_TERMINAL_SUPPORT_SEND_DTMF_COMMAND << 1) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_NMR << 2) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_LANGUAGE << 3) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_TIME_ADVANCE << 4) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION << 5) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER << 6) |
- (STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH << 7);
-
-this.STK_TERMINAL_PROFILE_BIP_COMMAND =
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_OPEN_CHANNEL << 0) |
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_CLOSE_CHANNEL << 1) |
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_RECEIVE_DATA << 2) |
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_SEND_DATA << 3) |
- (STK_TERMINAL_SUPPORT_BIP_COMMAND_GET_CHANNEL_STATUS << 4);
-
-this.STK_SUPPORTED_TERMINAL_PROFILE = [
- STK_TERMINAL_PROFILE_DOWNLOAD,
- STK_TERMINAL_PROFILE_OTHER,
- STK_TERMINAL_PROFILE_PROACTIVE_1,
- STK_TERMINAL_PROFILE_PROACTIVE_2,
- STK_TERMINAL_PROFILE_EVENT,
- STK_TERMINAL_PROFILE_EVENT_EXT, // Event extension
- 0x00, // Multiple card proactive commands
- STK_TERMINAL_PROFILE_PROACTIVE_3,
- STK_TERMINAL_PROFILE_PROACTIVE_4,
- 0x00, // Softkey support
- 0x00, // Softkey information
- STK_TERMINAL_PROFILE_BIP_COMMAND,
- 0x00, // BIP supported bearers
- 0x00, // Screen height
- 0x00, // Screen width
- 0x00, // 16, Screen effects
- 0x00, // 17, BIP supported transport interface
- 0x00, // 18, RFU
- 0x00, // 19, RFU
- 0x00, // 20, RFU
-];
-
-/**
- * ICC Services Table.
- *
- * @see 3GPP TS 51.011 10.3.7 (SIM) and 3GPP TS 31.102 4.2.8 (USIM).
- */
-this.GECKO_ICC_SERVICES = {
- // @see 3GPP TS 51.011 10.3.7 (SIM).
- sim: {
- ADN: 2,
- FDN: 3,
- PLMNSEL: 7,
- MSISDN: 9,
- EXT1: 10,
- EXT2: 11,
- CBMI: 14,
- GID1: 15,
- SPN: 17,
- SDN: 18,
- EXT3: 19,
- DATA_DOWNLOAD_SMS_CB: 25,
- DATA_DOWNLOAD_SMS_PP: 26,
- CBMIR: 30,
- BDN: 31,
- IMG: 39,
- PNN: 51,
- OPL: 52,
- MDN: 53,
- MWIS: 54,
- SPDI: 56
- },
- // @see 3GPP TS 31.102 4.2.8 (USIM).
- usim: {
- FDN: 2,
- EXT2: 3,
- SDN: 4,
- EXT3: 5,
- BDN: 6,
- CBMI: 15,
- CBMIR: 16,
- GID1: 17,
- SPN: 19,
- MSISDN: 21,
- IMG: 22,
- DATA_DOWNLOAD_SMS_PP: 28,
- DATA_DOWNLOAD_SMS_CB: 29,
- PNN: 45,
- OPL: 46,
- MDN: 47,
- MWIS: 48,
- SPDI: 51
- },
- // @see 3GPP2 C.S0023-D 3.4.18 (RUIM).
- ruim: {
- FDN: 3,
- ENHANCED_PHONEBOOK: 6,
- EXT1: 10,
- EXT2: 11,
- SPN: 17,
- SDN: 18,
- EXT3: 19,
- },
- // @see B.3.1.1 CPHS Information in CPHS Phase 2:
- // Indicates which of the CPHS 'optional' data-fields are present in the SIM card:
- // EF_CPHS_CSP, EF_CPHS_SST, EF_CPHS_MBN, EF_CPHS_ONSF, EF_CPHS_INFO_NUM
- // Note: Mandatory EFs are: (B.3.1 Enhanced SIM Requirements)
- // EF_CPHS_CFF, EF_CPHS_VMI, EF_CPHS_ONS, EF_CPHS_INFO
- cphs: {
- CSP: 1,
- SST: 2,
- MBN: 3,
- ONSF: 4,
- INFO_NUM: 5
- }
-};
-
-/**
- * Cell Broadcast constants
- */
-
-this.CB_FORMAT_GSM = 0;
-this.CB_FORMAT_ETWS = 1;
-this.CB_FORMAT_CMAS = 2;
-this.CB_FORMAT_UMTS = 3;
-
-// CBS Data Coding Scheme: Language groups
-// see 3GPP TS 23.038 section 5
-this.CB_DCS_LANG_GROUP_1 = [
- "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi",
- "no", "el", "tr", "hu", "pl", null
-];
-this.CB_DCS_LANG_GROUP_2 = [
- "cs", "he", "ar", "ru", "is", null, null, null, null, null,
- null, null, null, null, null, null
-];
-
-// See 3GPP TS 23.041 v11.2.0 section 9.4.1.2.2
-this.CB_NON_MMI_SETTABLE_RANGES = [
- /*0x1000 - 0x107F*/4096, 4224, /*0x1080 - 0x10FF*/4224, 4352,
- /*0x1112 - 0x1112*/4370, 4371, /*0x111F - 0x111F*/4383, 4384,
- /*0xF000 - 0xFFFE*/61440, 65535, /*0xFFFF - 0xFFFF*/65535, 65536
-];
-
-// User Data max length in septets
-this.CB_MAX_CONTENT_7BIT = 93;
-// User Data max length in octets
-this.CB_MAX_CONTENT_8BIT = 82;
-// User Data max length in chars
-this.CB_MAX_CONTENT_UCS2 = 41;
-
-// See 3GPP TS 23.041 v11.6.0 senction 9.3.19
-this.CB_MSG_PAGE_INFO_SIZE = 82;
-
-this.CB_MESSAGE_SIZE_ETWS = 56;
-this.CB_MESSAGE_SIZE_GSM = 88;
-this.CB_MESSAGE_SIZE_UMTS_MIN = 90;
-this.CB_MESSAGE_SIZE_UMTS_MAX = 1252;
-
-
-
-// GSM Cell Broadcast Geographical Scope
-// See 3GPP TS 23.041 clause 9.4.1.2.1
-this.CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0;
-this.CB_GSM_GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1;
-this.CB_GSM_GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE = 2;
-this.CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE = 3;
-
-// GSM Cell Broadcast Geographical Scope
-// See 3GPP TS 23.041 clause 9.4.1.2.1
-this.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES = [
- "cell-immediate",
- "plmn",
- "location-area",
- "cell"
-];
-
-// GSM Cell Broadcast Message Identifiers
-// see 3GPP TS 23.041 clause 9.4.1.2.2
-this.CB_GSM_MESSAGEID_ETWS_BEGIN = 0x1100;
-this.CB_GSM_MESSAGEID_ETWS_END = 0x1107;
-
-// ETWS Warning-Type
-// see 3GPP TS 23.041 clause 9.3.24
-this.CB_ETWS_WARNING_TYPE_NAMES = [
- "earthquake",
- "tsunami",
- "earthquake-tsunami",
- "test",
- "other"
-];
-
-// UMTS Message Type
-// see 3GPP TS 25.324 section 11.1
-this.CB_UMTS_MESSAGE_TYPE_CBS = 1;
-this.CB_UMTS_MESSAGE_TYPE_SCHEDULE = 2;
-this.CB_UMTS_MESSAGE_TYPE_CBS41 = 3;
-
-/**
- * Number plan identification defined in
- * |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
- */
-this.CALLED_PARTY_BCD_NPI_UNKNOWN = 0;
-this.CALLED_PARTY_BCD_NPI_ISDN = 1;
-this.CALLED_PARTY_BCD_NPI_DATA = 3;
-this.CALLED_PARTY_BCD_NPI_TELEX = 4;
-this.CALLED_PARTY_BCD_NPI_NATIONAL = 8;
-this.CALLED_PARTY_BCD_NPI_PRIVATE = 9;
-
-/**
- * Array of number plan identification values which can be used to map an
- * enumeration to the corresponding value. The indices should be consistent
- * with nsISmsService::NUMBER_PLAN_IDENTIFICATION_* constants.
- */
-this.CALLED_PARTY_BCD_NPI = [
- CALLED_PARTY_BCD_NPI_UNKNOWN,
- CALLED_PARTY_BCD_NPI_ISDN,
- CALLED_PARTY_BCD_NPI_DATA,
- CALLED_PARTY_BCD_NPI_TELEX,
- CALLED_PARTY_BCD_NPI_NATIONAL,
- CALLED_PARTY_BCD_NPI_PRIVATE
-];
-
-/**
- * GSM PDU constants
- */
-
-// PDU TYPE-OF-ADDRESS
-this.PDU_TOA_UNKNOWN = 0x80; // Unknown. This is used when the user or
- // network has no a priori information
- // about the numbering plan.
-this.PDU_TOA_ISDN = 0x81; // ISDN/Telephone numbering
-this.PDU_TOA_DATA_NUM = 0x83; // Data numbering plan
-this.PDU_TOA_TELEX_NUM = 0x84; // Telex numbering plan
-this.PDU_TOA_NATIONAL_NUM = 0x88; // National numbering plan
-this.PDU_TOA_PRIVATE_NUM = 0x89; // Private numbering plan
-this.PDU_TOA_ERMES_NUM = 0x8A; // Ermes numbering plan
-this.PDU_TOA_INTERNATIONAL = 0x90; // International number
-this.PDU_TOA_NATIONAL = 0xA0; // National number. Prefix or escape digits
- // shall not be included
-this.PDU_TOA_NETWORK_SPEC = 0xB0; // Network specific number This is used to
- // indicate administration/service number
- // specific to the serving network
-this.PDU_TOA_SUBSCRIBER = 0xC0; // Subscriber number. This is used when a
- // specific short number representation is
- // stored in one or more SCs as part of a
- // higher layer application
-this.PDU_TOA_ALPHANUMERIC = 0xD0; // Alphanumeric, (coded according to GSM TS
- // 03.38 7-bit default alphabet)
-this.PDU_TOA_ABBREVIATED = 0xE0; // Abbreviated number
-
-/**
- * First octet of the SMS-DELIVER PDU
- *
- * RP: 0 Reply Path parameter is not set in this PDU
- * 1 Reply Path parameter is set in this PDU
- *
- * UDHI: 0 The UD field contains only the short message
- * 1 The beginning of the UD field contains a header in addition of
- * the short message
- *
- * SRI: (is only set by the SMSC)
- * 0 A status report will not be returned to the SME
- * 1 A status report will be returned to the SME
- *
- * MMS: (is only set by the SMSC)
- * 0 More messages are waiting for the MS in the SMSC
- * 1 No more messages are waiting for the MS in the SMSC
- *
- * MTI: bit1 bit0 Message type
- * 0 0 SMS-DELIVER (SMSC ==> MS)
- * 0 0 SMS-DELIVER REPORT (MS ==> SMSC, is generated
- * automatically by the M20, after receiving a
- * SMS-DELIVER)
- * 0 1 SMS-SUBMIT (MS ==> SMSC)
- * 0 1 SMS-SUBMIT REPORT (SMSC ==> MS)
- * 1 0 SMS-STATUS REPORT (SMSC ==> MS)
- * 1 0 SMS-COMMAND (MS ==> SMSC)
- * 1 1 Reserved
- */
-this.PDU_RP = 0x80; // Reply path. Parameter indicating that
- // reply path exists.
-this.PDU_UDHI = 0x40; // User data header indicator. This bit is
- // set to 1 if the User Data field starts
- // with a header
-this.PDU_SRI_SRR = 0x20; // Status report indication (SMS-DELIVER)
- // or request (SMS-SUBMIT)
-this.PDU_VPF_ABSOLUTE = 0x18;// Validity period aboslute format
- // (SMS-SUBMIT only)
-this.PDU_VPF_RELATIVE = 0x10;// Validity period relative format
- // (SMS-SUBMIT only)
-this.PDU_VPF_ENHANCED = 0x8; // Validity period enhance format
- // (SMS-SUBMIT only)
-this.PDU_MMS_RD = 0x04;// More messages to send. (SMS-DELIVER only) or
- // Reject duplicates (SMS-SUBMIT only)
-
-// MTI - Message Type Indicator
-this.PDU_MTI_SMS_RESERVED = 0x03;
-this.PDU_MTI_SMS_STATUS_REPORT = 0x02;
-this.PDU_MTI_SMS_COMMAND = 0x02;
-this.PDU_MTI_SMS_SUBMIT = 0x01;
-this.PDU_MTI_SMS_DELIVER = 0x00;
-
-// PI - Parameter Indicator
-this.PDU_PI_EXTENSION = 0x80;
-this.PDU_PI_USER_DATA_LENGTH = 0x04;
-this.PDU_PI_DATA_CODING_SCHEME = 0x02;
-this.PDU_PI_PROTOCOL_IDENTIFIER = 0x01;
-this.PDU_PI_RESERVED = 0x78;
-
-// FCS - Failure Cause
-// 0...127 see 3GPP TS 24.011 clause E.2
-// 128...255 see 3GPP TS 23.040 clause 9.2.3.22
-// others see 3GPP TS 27.005 clause 3.2.5
-this.PDU_FCS_OK = 0x00;
-this.PDU_FCS_PROTOCOL_ERROR = 0x6F;
-this.PDU_FCS_MEMORY_CAPACITY_EXCEEDED = 0XD3;
-this.PDU_FCS_USAT_BUSY = 0XD4;
-this.PDU_FCS_USIM_DATA_DOWNLOAD_ERROR = 0xD5;
-this.PDU_FCS_RESERVED = 0xE0;
-this.PDU_FCS_UNSPECIFIED = 0xFF;
-// Special internal value that means we should not acknowledge an
-// incoming text right away, but need to wait for other components
-// (e.g. storage) to complete. This can be any value, so long it
-// doesn't conflict with the PDU_FCS_* constants above.
-this.MOZ_FCS_WAIT_FOR_EXPLICIT_ACK = 0x0F;
-
-// ST - Status
-// Bit 7..0 = 000xxxxx, short message transaction completed
-this.PDU_ST_0_RECEIVED = 0x00;
-this.PDU_ST_0_FORWARDED_NO_CONFIRM = 0x01;
-this.PDU_ST_0_REPLACED_BY_SC = 0x02;
-this.PDU_ST_0_RESERVED_BEGIN = 0x03;
-this.PDU_ST_0_SC_SPECIFIC_BEGIN = 0x10;
-this.PDU_ST_0_SC_SPECIFIC_END = 0x1F;
-// Bit 7..0 = 001xxxxx, temporary error, SC still trying to transfer SM
-this.PDU_ST_1_CONGESTION = 0x20;
-this.PDU_ST_1_SME_BUSY = 0x21;
-this.PDU_ST_1_SME_NO_RESPONSE = 0x22;
-this.PDU_ST_1_SERVICE_REJECTED = 0x23;
-this.PDU_ST_1_QOS_UNAVAILABLE = 0x24;
-this.PDU_ST_1_SME_ERROR = 0x25;
-this.PDU_ST_1_RESERVED_BEGIN = 0x26;
-this.PDU_ST_1_SC_SPECIFIC_BEGIN = 0x30;
-this.PDU_ST_1_SC_SPECIFIC_END = 0x3F;
-// Bit 7..0 = 010xxxxx, permanent error, SC is not making any more transfer
-// attempts
-this.PDU_ST_2_RPC_ERROR = 0x40;
-this.PDU_ST_2_DEST_INCOMPATIBLE = 0x41;
-this.PDU_ST_2_CONNECTION_REJECTED = 0x42;
-this.PDU_ST_2_NOT_OBTAINABLE = 0x43;
-this.PDU_ST_2_QOS_UNAVAILABLE = 0x44;
-this.PDU_ST_2_INTERWORKING_UNAVALIABLE = 0x45;
-this.PDU_ST_2_VALIDITY_EXPIRED = 0x46;
-this.PDU_ST_2_DELETED_BY_SME = 0x47;
-this.PDU_ST_2_DELETED_BY_SC = 0x48;
-this.PDU_ST_2_SM_MISSING = 0x49;
-this.PDU_ST_2_RESERVED_BEGIN = 0x4A;
-this.PDU_ST_2_SC_SPECIFIC_BEGIN = 0x50;
-this.PDU_ST_2_SC_SPECIFIC_END = 0x5F;
-// Bit 7..0 = 011xxxxx, temporary error, SC is not making any more transfer
-// attempts
-this.PDU_ST_3_CONGESTION = 0x60;
-this.PDU_ST_3_SME_BUSY = 0x61;
-this.PDU_ST_3_SME_NO_RESPONSE = 0x62;
-this.PDU_ST_3_SERVICE_REJECTED = 0x63;
-this.PDU_ST_3_QOS_UNAVAILABLE = 0x64;
-this.PDU_ST_3_SME_ERROR = 0x65;
-this.PDU_ST_3_RESERVED_BEGIN = 0x66;
-this.PDU_ST_3_SC_SPECIFIC_BEGIN = 0x70;
-this.PDU_ST_3_SC_SPECIFIC_END = 0x7F;
-
-this.GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE = "not-applicable";
-this.GECKO_SMS_DELIVERY_STATUS_SUCCESS = "success";
-this.GECKO_SMS_DELIVERY_STATUS_PENDING = "pending";
-this.GECKO_SMS_DELIVERY_STATUS_ERROR = "error";
-
-// User Data max length in septets
-this.PDU_MAX_USER_DATA_7BIT = 160;
-// User Data max length in octets
-this.PDU_MAX_USER_DATA_8BIT = 140;
-// User Data max length in chars
-this.PDU_MAX_USER_DATA_UCS2 = 70;
-
-// PID - Protocol Indicator
-this.PDU_PID_DEFAULT = 0x00;
-this.PDU_PID_TELEMATIC_INTERWORKING = 0x20;
-this.PDU_PID_SHORT_MESSAGE_TYPE_0 = 0x40;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_1 = 0x41;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_2 = 0x42;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_3 = 0x43;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_4 = 0x44;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_5 = 0x45;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_6 = 0x46;
-this.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_7 = 0x47;
-this.PDU_PID_ENHANDED_MESSAGE_SERVICE = 0x5E;
-this.PDU_PID_RETURN_CALL_MESSAGE = 0x5F;
-this.PDU_PID_ANSI_136_R_DATA = 0x7C;
-this.PDU_PID_ME_DATA_DOWNLOAD = 0x7D;
-this.PDU_PID_ME_DEPERSONALIZATION = 0x7E;
-this.PDU_PID_USIM_DATA_DOWNLOAD = 0x7F;
-
-// DCS - Data Coding Scheme
-this.PDU_DCS_MSG_CODING_7BITS_ALPHABET = 0x00;
-this.PDU_DCS_MSG_CODING_8BITS_ALPHABET = 0x04;
-this.PDU_DCS_MSG_CODING_16BITS_ALPHABET = 0x08;
-this.PDU_DCS_MSG_CLASS_0 = 0x00;
-this.PDU_DCS_MSG_CLASS_1 = 0x01;
-this.PDU_DCS_MSG_CLASS_2 = 0x02;
-this.PDU_DCS_MSG_CLASS_3 = 0x03;
-this.PDU_DCS_MSG_CLASS_USER_1 = 0x04;
-this.PDU_DCS_MSG_CLASS_USER_2 = 0x05;
-this.PDU_DCS_MSG_CLASS_NORMAL = 0x06;
-this.PDU_DCS_CODING_GROUP_BITS = 0xF0;
-this.PDU_DCS_MSG_CLASS_BITS = 0x03;
-this.PDU_DCS_MWI_ACTIVE_BITS = 0x08;
-this.PDU_DCS_MWI_ACTIVE_VALUE = 0x08;
-this.PDU_DCS_MWI_TYPE_BITS = 0x03;
-this.PDU_DCS_MWI_TYPE_VOICEMAIL = 0x00;
-this.PDU_DCS_MWI_TYPE_FAX = 0x01;
-this.PDU_DCS_MWI_TYPE_EMAIL = 0x02;
-this.PDU_DCS_MWI_TYPE_OTHER = 0x03;
-
-// Set as Array instead of Object for reversed-mapping with Array.indexOf().
-this.GECKO_SMS_MESSAGE_CLASSES = [];
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0] = "class-0";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1] = "class-1";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2] = "class-2";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3] = "class-3";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_USER_1] = "user-1";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_USER_2] = "user-2";
-GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL] = "normal";
-
-// Because service center timestamp omit the century. Yay.
-this.PDU_TIMESTAMP_YEAR_OFFSET = 2000;
-
-// See 9.2.3.24 TP‑User Data (TP‑UD)
-this.PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT = 0x00;
-this.PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION = 0x01;
-this.PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_8BIT = 0x04;
-this.PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_16BIT = 0x05;
-this.PDU_IEI_SMSC_CONTROL_PARAMS = 0x06;
-this.PDU_IEI_UDH_SOURCE_INDICATOR = 0x07;
-this.PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT = 0x08;
-this.PDU_IEI_WIRELESS_CONTROL_MESSAGE_PROTOCOL = 0x09;
-this.PDU_IEI_TEXT_FORMATING = 0x0A;
-this.PDU_IEI_PREDEFINED_SOUND = 0x0B;
-this.PDU_IEI_USER_DATA_SOUND = 0x0C;
-this.PDU_IEI_PREDEFINED_ANIMATION = 0x0D;
-this.PDU_IEI_LARGE_ANIMATION = 0x0E;
-this.PDU_IEI_SMALL_ANIMATION = 0x0F;
-this.PDU_IEI_LARGE_PICTURE = 0x10;
-this.PDU_IEI_SMALL_PICTURE = 0x11;
-this.PDU_IEI_VARIABLE_PICTURE = 0x12;
-this.PDU_IEI_USER_PROMPT_INDICATOR = 0x13;
-this.PDU_IEI_EXTENDED_OBJECT = 0x14;
-this.PDU_IEI_REUSED_EXTENDED_OBJECT = 0x15;
-this.PDU_IEI_COMPRESS_CONTROL = 0x16;
-this.PDU_IEI_OBJECT_DISTRIBUTION_INDICATOR = 0x17;
-this.PDU_IEI_STANDARD_WVG_OBJECT = 0x18;
-this.PDU_IEI_CHARACTER_SIZE_WVG_OBJECT = 0x19;
-this.PDU_IEI_EXTENDED_OBJECT_DATA_REQUEST_COMMAND = 0x1A;
-this.PDU_IEI_RFC822_EMAIL_HEADER = 0x20;
-this.PDU_IEI_HYPERLINK_FORMAT_ELEMENT = 0x21;
-this.PDU_IEI_REPLY_ADDRESS_ELEMENT = 0x22;
-this.PDU_IEI_ENHANCED_VOICE_MAIL_INFORMATION = 0x23;
-this.PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT = 0x24;
-this.PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT = 0x25;
-
-// Application Port Addressing, see 3GPP TS 23.040 9.2.3.24.3
-this.PDU_APA_RESERVED_8BIT_PORTS = 240;
-this.PDU_APA_VALID_16BIT_PORTS = 49152;
-
-// 7bit alphabet escape character. The encoded value of this code point is left
-// undefined in official spec. Its code value is internally assigned to \uffff,
-// <noncharacter-FFFF> in Unicode basic multilingual plane.
-this.PDU_NL_EXTENDED_ESCAPE = 0x1B;
-
-// <SP>, <LF>, <CR> are only defined in locking shift tables.
-this.PDU_NL_SPACE = 0x20;
-this.PDU_NL_LINE_FEED = 0x0A;
-this.PDU_NL_CARRIAGE_RETURN = 0x0D;
-
-// 7bit alphabet page break character, only defined in single shift tables.
-// The encoded value of this code point is left undefined in official spec, but
-// the code point itself maybe be used for example in compressed CBS messages.
-// Its code value is internally assigned to \u000c, ASCII form feed, or new page.
-this.PDU_NL_PAGE_BREAK = 0x0A;
-// 7bit alphabet reserved control character, only defined in single shift
-// tables. The encoded value of this code point is left undefined in official
-// spec. Its code value is internally assigned to \ufffe, <noncharacter-FFFE>
-// in Unicode basic multilingual plane.
-this.PDU_NL_RESERVED_CONTROL = 0x0D;
-
-this.PDU_NL_IDENTIFIER_DEFAULT = 0;
-this.PDU_NL_IDENTIFIER_TURKISH = 1;
-this.PDU_NL_IDENTIFIER_SPANISH = 2;
-this.PDU_NL_IDENTIFIER_PORTUGUESE = 3;
-this.PDU_NL_IDENTIFIER_BENGALI = 4;
-this.PDU_NL_IDENTIFIER_GUJARATI = 5;
-this.PDU_NL_IDENTIFIER_HINDI = 6;
-this.PDU_NL_IDENTIFIER_KANNADA = 7;
-this.PDU_NL_IDENTIFIER_MALAYALAM = 8;
-this.PDU_NL_IDENTIFIER_ORIYA = 9;
-this.PDU_NL_IDENTIFIER_PUNJABI = 10;
-this.PDU_NL_IDENTIFIER_TAMIL = 11;
-this.PDU_NL_IDENTIFIER_TELUGU = 12;
-this.PDU_NL_IDENTIFIER_URDU = 13;
-
-// The mapping of mcc and their extra GSM national language locking / single
-// shift table tuples to enable. The default GSM alphabet and extension table
-// are always enabled and need not to be list here.
-//
-// The content should be updated when a relevant national regulatory body
-// requests. See 'NOTE 2' of 6.2.1.2.5 in 3GPP TS 23.038:
-// "
-// Encoding of a message using the national locking shift mechanism is not
-// intended to be implemented until a formal request is issued by the
-// relevant national regulatory body. This is because a receiving entity
-// not supporting the relevant locking-shift decoding will present different
-// characters from the ones intended by the sending entity.
-// "
-this.PDU_MCC_NL_TABLE_TUPLES_MAPPING = {
- // Configuration for Turkey.
- //
- // The Turkish single shift table contains 7 extra characters
- // (Ğ, İ, Ş, ç, ğ, ı, ş) than the GSM default alphabet extension table. Since
- // all the 7 characters are also included in Turkish locking shift table, it's
- // not necessary to enable Turkish single shift table. Using GSM default
- // alphabet extension table instead saves 3 octets when these extension table
- // characters present in a message.
- 286: [[PDU_NL_IDENTIFIER_TURKISH, PDU_NL_IDENTIFIER_DEFAULT]]
-};
-
-/*
- * 3GPP TS 23.038 - 6.2.1 GSM 7 bit Default Alphabet
- */
-this.PDU_NL_GSM_DEFAULT_ALPHABET =
- // 01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "@\u00a3$\u00a5\u00e8\u00e9\u00f9\u00ec\u00f2\u00c7\n\u00d8\u00f8\r\u00c5\u00e5"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0394_\u03a6\u0393\u039b\u03a9\u03a0\u03a8\u03a3\u0398\u039e\uffff\u00c6\u00e6\u00df\u00c9"
- // 012.34.....56789ABCDEF
- + " !\"#\u00a4%&'()*+,-./"
- // 0123456789ABCDEF
- + "0123456789:;<=>?"
- // 0.....123456789ABCDEF
- + "\u00a1ABCDEFGHIJKLMNO"
- // 0123456789AB.....C.....D.....E.....F.....
- + "PQRSTUVWXYZ\u00c4\u00d6\u00d1\u00dc\u00a7"
- // 0.....123456789ABCDEF
- + "\u00bfabcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u00e4\u00f6\u00f1\u00fc\u00e0";
-
-// National Language Locking Shift Tables, see 3GPP TS 23.038
-this.PDU_NL_LOCKING_SHIFT_TABLES = [
- /**
- * National Language Identifier: 0x00
- * 6.2.1 GSM 7 bit Default Alphabet
- */
- PDU_NL_GSM_DEFAULT_ALPHABET,
-
- /**
- * National Language Identifier: 0x01
- * A.3.1 Turkish National Language Locking Shift Table
- */
- // 01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "@\u00a3$\u00a5\u20ac\u00e9\u00f9\u0131\u00f2\u00c7\n\u011e\u011f\r\u00c5\u00e5"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0394_\u03a6\u0393\u039b\u03a9\u03a0\u03a8\u03a3\u0398\u039e\uffff\u015e\u015f\u00df\u00c9"
- // 012.34.....56789ABCDEF
- + " !\"#\u00a4%&'()*+,-./"
- // 0123456789ABCDEF
- + "0123456789:;<=>?"
- // 0.....123456789ABCDEF
- + "\u0130ABCDEFGHIJKLMNO"
- // 0123456789AB.....C.....D.....E.....F.....
- + "PQRSTUVWXYZ\u00c4\u00d6\u00d1\u00dc\u00a7"
- // 0.....123456789ABCDEF
- + "\u00e7abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u00e4\u00f6\u00f1\u00fc\u00e0",
-
- /**
- * National Language Identifier: 0x02
- * A.3.2 Void
- * Fallback to GSM Default Alphabet
- */
- PDU_NL_GSM_DEFAULT_ALPHABET,
-
- /**
- * National Language Identifier: 0x03
- * A.3.3 Portuguese National Language Locking Shift Table
- */
- // 01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "@\u00a3$\u00a5\u00ea\u00e9\u00fa\u00ed\u00f3\u00e7\n\u00d4\u00f4\r\u00c1\u00e1"
- // 0.....12.....3.....4.....5.....67.8.....9.....AB.....C.....D.....E.....F.....
- + "\u0394_\u00aa\u00c7\u00c0\u221e^\\\u20ac\u00d3|\uffff\u00c2\u00e2\u00ca\u00c9"
- // 012.34.....56789ABCDEF
- + " !\"#\u00ba%&'()*+,-./"
- // 0123456789ABCDEF
- + "0123456789:;<=>?"
- // 0.....123456789ABCDEF
- + "\u00cdABCDEFGHIJKLMNO"
- // 0123456789AB.....C.....D.....E.....F.....
- + "PQRSTUVWXYZ\u00c3\u00d5\u00da\u00dc\u00a7"
- // 0123456789ABCDEF
- + "~abcdefghijklmno"
- // 0123456789AB.....C.....DE.....F.....
- + "pqrstuvwxyz\u00e3\u00f5`\u00fc\u00e0",
-
- /**
- * National Language Identifier: 0x04
- * A.3.4 Bengali National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.EF.....
- "\u0981\u0982\u0983\u0985\u0986\u0987\u0988\u0989\u098a\u098b\n\u098c \r \u098f"
- // 0.....123.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0990 \u0993\u0994\u0995\u0996\u0997\u0998\u0999\u099a\uffff\u099b\u099c\u099d\u099e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u099f\u09a0\u09a1\u09a2\u09a3\u09a4)(\u09a5\u09a6,\u09a7.\u09a8"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u09aa\u09ab?"
- // 0.....1.....2.....3.....4.....56.....789A.....B.....C.....D.....E.....F.....
- + "\u09ac\u09ad\u09ae\u09af\u09b0 \u09b2 \u09b6\u09b7\u09b8\u09b9\u09bc\u09bd"
- // 0.....1.....2.....3.....4.....5.....6.....789.....A.....BCD.....E.....F.....
- + "\u09be\u09bf\u09c0\u09c1\u09c2\u09c3\u09c4 \u09c7\u09c8 \u09cb\u09cc\u09cd"
- // 0.....123456789ABCDEF
- + "\u09ceabcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u09d7\u09dc\u09dd\u09f0\u09f1",
-
- /**
- * National Language Identifier: 0x05
- * A.3.5 Gujarati National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.EF.....
- "\u0a81\u0a82\u0a83\u0a85\u0a86\u0a87\u0a88\u0a89\u0a8a\u0a8b\n\u0a8c\u0a8d\r \u0a8f"
- // 0.....1.....23.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0a90\u0a91 \u0a93\u0a94\u0a95\u0a96\u0a97\u0a98\u0a99\u0a9a\uffff\u0a9b\u0a9c\u0a9d\u0a9e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0a9f\u0aa0\u0aa1\u0aa2\u0aa3\u0aa4)(\u0aa5\u0aa6,\u0aa7.\u0aa8"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0aaa\u0aab?"
- // 0.....1.....2.....3.....4.....56.....7.....89.....A.....B.....C.....D.....E.....F.....
- + "\u0aac\u0aad\u0aae\u0aaf\u0ab0 \u0ab2\u0ab3 \u0ab5\u0ab6\u0ab7\u0ab8\u0ab9\u0abc\u0abd"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89.....A.....B.....CD.....E.....F.....
- + "\u0abe\u0abf\u0ac0\u0ac1\u0ac2\u0ac3\u0ac4\u0ac5 \u0ac7\u0ac8\u0ac9 \u0acb\u0acc\u0acd"
- // 0.....123456789ABCDEF
- + "\u0ad0abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0ae0\u0ae1\u0ae2\u0ae3\u0af1",
-
- /**
- * National Language Identifier: 0x06
- * A.3.6 Hindi National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "\u0901\u0902\u0903\u0905\u0906\u0907\u0908\u0909\u090a\u090b\n\u090c\u090d\r\u090e\u090f"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0910\u0911\u0912\u0913\u0914\u0915\u0916\u0917\u0918\u0919\u091a\uffff\u091b\u091c\u091d\u091e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u091f\u0920\u0921\u0922\u0923\u0924)(\u0925\u0926,\u0927.\u0928"
- // 0123456789ABC.....D.....E.....F
- + "0123456789:;\u0929\u092a\u092b?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u092c\u092d\u092e\u092f\u0930\u0931\u0932\u0933\u0934\u0935\u0936\u0937\u0938\u0939\u093c\u093d"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u093e\u093f\u0940\u0941\u0942\u0943\u0944\u0945\u0946\u0947\u0948\u0949\u094a\u094b\u094c\u094d"
- // 0.....123456789ABCDEF
- + "\u0950abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0972\u097b\u097c\u097e\u097f",
-
- /**
- * National Language Identifier: 0x07
- * A.3.7 Kannada National Language Locking Shift Table
- */
- // 01.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.E.....F.....
- " \u0c82\u0c83\u0c85\u0c86\u0c87\u0c88\u0c89\u0c8a\u0c8b\n\u0c8c \r\u0c8e\u0c8f"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0c90 \u0c92\u0c93\u0c94\u0c95\u0c96\u0c97\u0c98\u0c99\u0c9a\uffff\u0c9b\u0c9c\u0c9d\u0c9e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0c9f\u0ca0\u0ca1\u0ca2\u0ca3\u0ca4)(\u0ca5\u0ca6,\u0ca7.\u0ca8"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0caa\u0cab?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89.....A.....B.....C.....D.....E.....F.....
- + "\u0cac\u0cad\u0cae\u0caf\u0cb0\u0cb1\u0cb2\u0cb3 \u0cb5\u0cb6\u0cb7\u0cb8\u0cb9\u0cbc\u0cbd"
- // 0.....1.....2.....3.....4.....5.....6.....78.....9.....A.....BC.....D.....E.....F.....
- + "\u0cbe\u0cbf\u0cc0\u0cc1\u0cc2\u0cc3\u0cc4 \u0cc6\u0cc7\u0cc8 \u0cca\u0ccb\u0ccc\u0ccd"
- // 0.....123456789ABCDEF
- + "\u0cd5abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0cd6\u0ce0\u0ce1\u0ce2\u0ce3",
-
- /**
- * National Language Identifier: 0x08
- * A.3.8 Malayalam National Language Locking Shift Table
- */
- // 01.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.E.....F.....
- " \u0d02\u0d03\u0d05\u0d06\u0d07\u0d08\u0d09\u0d0a\u0d0b\n\u0d0c \r\u0d0e\u0d0f"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0d10 \u0d12\u0d13\u0d14\u0d15\u0d16\u0d17\u0d18\u0d19\u0d1a\uffff\u0d1b\u0d1c\u0d1d\u0d1e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0d1f\u0d20\u0d21\u0d22\u0d23\u0d24)(\u0d25\u0d26,\u0d27.\u0d28"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0d2a\u0d2b?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....EF.....
- + "\u0d2c\u0d2d\u0d2e\u0d2f\u0d30\u0d31\u0d32\u0d33\u0d34\u0d35\u0d36\u0d37\u0d38\u0d39 \u0d3d"
- // 0.....1.....2.....3.....4.....5.....6.....78.....9.....A.....BC.....D.....E.....F.....
- + "\u0d3e\u0d3f\u0d40\u0d41\u0d42\u0d43\u0d44 \u0d46\u0d47\u0d48 \u0d4a\u0d4b\u0d4c\u0d4d"
- // 0.....123456789ABCDEF
- + "\u0d57abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0d60\u0d61\u0d62\u0d63\u0d79",
-
- /**
- * National Language Identifier: 0x09
- * A.3.9 Oriya National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.EF.....
- "\u0b01\u0b02\u0b03\u0b05\u0b06\u0b07\u0b08\u0b09\u0b0a\u0b0b\n\u0b0c \r \u0b0f"
- // 0.....123.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0b10 \u0b13\u0b14\u0b15\u0b16\u0b17\u0b18\u0b19\u0b1a\uffff\u0b1b\u0b1c\u0b1d\u0b1e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0b1f\u0b20\u0b21\u0b22\u0b23\u0b24)(\u0b25\u0b26,\u0b27.\u0b28"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0b2a\u0b2b?"
- // 0.....1.....2.....3.....4.....56.....7.....89.....A.....B.....C.....D.....E.....F.....
- + "\u0b2c\u0b2d\u0b2e\u0b2f\u0b30 \u0b32\u0b33 \u0b35\u0b36\u0b37\u0b38\u0b39\u0b3c\u0b3d"
- // 0.....1.....2.....3.....4.....5.....6.....789.....A.....BCD.....E.....F.....
- + "\u0b3e\u0b3f\u0b40\u0b41\u0b42\u0b43\u0b44 \u0b47\u0b48 \u0b4b\u0b4c\u0b4d"
- // 0.....123456789ABCDEF
- + "\u0b56abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0b57\u0b60\u0b61\u0b62\u0b63",
-
- /**
- * National Language Identifier: 0x0A
- * A.3.10 Punjabi National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9A.BCD.EF.....
- "\u0a01\u0a02\u0a03\u0a05\u0a06\u0a07\u0a08\u0a09\u0a0a \n \r \u0a0f"
- // 0.....123.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0a10 \u0a13\u0a14\u0a15\u0a16\u0a17\u0a18\u0a19\u0a1a\uffff\u0a1b\u0a1c\u0a1d\u0a1e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0a1f\u0a20\u0a21\u0a22\u0a23\u0a24)(\u0a25\u0a26,\u0a27.\u0a28"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0a2a\u0a2b?"
- // 0.....1.....2.....3.....4.....56.....7.....89.....A.....BC.....D.....E.....F
- + "\u0a2c\u0a2d\u0a2e\u0a2f\u0a30 \u0a32\u0a33 \u0a35\u0a36 \u0a38\u0a39\u0a3c "
- // 0.....1.....2.....3.....4.....56789.....A.....BCD.....E.....F.....
- + "\u0a3e\u0a3f\u0a40\u0a41\u0a42 \u0a47\u0a48 \u0a4b\u0a4c\u0a4d"
- // 0.....123456789ABCDEF
- + "\u0a51abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0a70\u0a71\u0a72\u0a73\u0a74",
-
- /**
- * National Language Identifier: 0x0B
- * A.3.11 Tamil National Language Locking Shift Table
- */
- // 01.....2.....3.....4.....5.....6.....7.....8.....9A.BCD.E.....F.....
- " \u0b82\u0b83\u0b85\u0b86\u0b87\u0b88\u0b89\u0b8a \n \r\u0b8e\u0b8f"
- // 0.....12.....3.....4.....5.....6789.....A.....B.....CD.....EF.....
- + "\u0b90 \u0b92\u0b93\u0b94\u0b95 \u0b99\u0b9a\uffff \u0b9c \u0b9e"
- // 012.....3456.....7.....89ABCDEF.....
- + " !\u0b9f \u0ba3\u0ba4)( , .\u0ba8"
- // 0123456789ABC.....D.....EF
- + "0123456789:;\u0ba9\u0baa ?"
- // 012.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....EF
- + " \u0bae\u0baf\u0bb0\u0bb1\u0bb2\u0bb3\u0bb4\u0bb5\u0bb6\u0bb7\u0bb8\u0bb9 "
- // 0.....1.....2.....3.....4.....5678.....9.....A.....BC.....D.....E.....F.....
- + "\u0bbe\u0bbf\u0bc0\u0bc1\u0bc2 \u0bc6\u0bc7\u0bc8 \u0bca\u0bcb\u0bcc\u0bcd"
- // 0.....123456789ABCDEF
- + "\u0bd0abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0bd7\u0bf0\u0bf1\u0bf2\u0bf9",
-
- /**
- * National Language Identifier: 0x0C
- * A.3.12 Telugu National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....CD.E.....F.....
- "\u0c01\u0c02\u0c03\u0c05\u0c06\u0c07\u0c08\u0c09\u0c0a\u0c0b\n\u0c0c \r\u0c0e\u0c0f"
- // 0.....12.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0c10 \u0c12\u0c13\u0c14\u0c15\u0c16\u0c17\u0c18\u0c19\u0c1a\uffff\u0c1b\u0c1c\u0c1d\u0c1e"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u0c1f\u0c20\u0c21\u0c22\u0c23\u0c24)(\u0c25\u0c26,\u0c27.\u0c28"
- // 0123456789ABCD.....E.....F
- + "0123456789:; \u0c2a\u0c2b?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89.....A.....B.....C.....D.....EF.....
- + "\u0c2c\u0c2d\u0c2e\u0c2f\u0c30\u0c31\u0c32\u0c33 \u0c35\u0c36\u0c37\u0c38\u0c39 \u0c3d"
- // 0.....1.....2.....3.....4.....5.....6.....78.....9.....A.....BC.....D.....E.....F.....
- + "\u0c3e\u0c3f\u0c40\u0c41\u0c42\u0c43\u0c44 \u0c46\u0c47\u0c48 \u0c4a\u0c4b\u0c4c\u0c4d"
- // 0.....123456789ABCDEF
- + "\u0c55abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0c56\u0c60\u0c61\u0c62\u0c63",
-
- /**
- * National Language Identifier: 0x0D
- * A.3.13 Urdu National Language Locking Shift Table
- */
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....
- "\u0627\u0622\u0628\u067b\u0680\u067e\u06a6\u062a\u06c2\u067f\n\u0679\u067d\r\u067a\u067c"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u062b\u062c\u0681\u0684\u0683\u0685\u0686\u0687\u062d\u062e\u062f\uffff\u068c\u0688\u0689\u068a"
- // 012.....3.....4.....5.....6.....7.....89A.....B.....CD.....EF.....
- + " !\u068f\u068d\u0630\u0631\u0691\u0693)(\u0699\u0632,\u0696.\u0698"
- // 0123456789ABC.....D.....E.....F
- + "0123456789:;\u069a\u0633\u0634?"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u0635\u0636\u0637\u0638\u0639\u0641\u0642\u06a9\u06aa\u06ab\u06af\u06b3\u06b1\u0644\u0645\u0646"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....C.....D.....E.....F.....
- + "\u06ba\u06bb\u06bc\u0648\u06c4\u06d5\u06c1\u06be\u0621\u06cc\u06d0\u06d2\u064d\u0650\u064f\u0657"
- // 0.....123456789ABCDEF
- + "\u0654abcdefghijklmno"
- // 0123456789AB.....C.....D.....E.....F.....
- + "pqrstuvwxyz\u0655\u0651\u0653\u0656\u0670"
-];
-
-// National Language Single Shift Tables, see 3GPP TS 23.038
-this.PDU_NL_SINGLE_SHIFT_TABLES = [
- /**
- * National Language Identifier: 0x00
- * 6.2.1.1 GSM 7 bit default alphabet extension table
- */
- // 0123456789A.....BCD.....EF
- " \u000c \ufffe "
- // 0123456789AB.....CDEF
- + " ^ \uffff "
- // 0123456789ABCDEF.
- + " {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "| "
- // 0123456789ABCDEF
- + " "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x01
- * A.2.1 Turkish National Language Single Shift Table
- */
- // 0123456789A.....BCD.....EF
- " \u000c \ufffe "
- // 0123456789AB.....CDEF
- + " ^ \uffff "
- // 0123456789ABCDEF.
- + " {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 01234567.....89.....ABCDEF
- + "| \u011e \u0130 "
- // 0123.....456789ABCDEF
- + " \u015e "
- // 0123.....45.....67.....89.....ABCDEF
- + " \u00e7 \u20ac \u011f \u0131 "
- // 0123.....456789ABCDEF
- + " \u015f ",
-
- /**
- * National Language Identifier: 0x02
- * A.2.2 Spanish National Language Single Shift Table
- */
- // 0123456789.....A.....BCD.....EF
- " \u00e7\u000c \ufffe "
- // 0123456789AB.....CDEF
- + " ^ \uffff "
- // 0123456789ABCDEF.
- + " {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 01.....23456789.....ABCDEF.....
- + "|\u00c1 \u00cd \u00d3"
- // 012345.....6789ABCDEF
- + " \u00da "
- // 01.....2345.....6789.....ABCDEF.....
- + " \u00e1 \u20ac \u00ed \u00f3"
- // 012345.....6789ABCDEF
- + " \u00fa ",
-
- /**
- * National Language Identifier: 0x03
- * A.2.3 Portuguese National Language Single Shift Table
- */
- // 012345.....6789.....A.....B.....C.....D.....E.....F.....
- " \u00ea \u00e7\u000c\u00d4\u00f4\ufffe\u00c1\u00e1"
- // 012.....3.....45.....6.....7.....8.....9.....AB.....CDEF.....
- + " \u03a6\u0393^\u03a9\u03a0\u03a8\u03a3\u0398 \uffff \u00ca"
- // 0123456789ABCDEF.
- + " {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 01.....23456789.....ABCDEF.....
- + "|\u00c0 \u00cd \u00d3"
- // 012345.....6789AB.....C.....DEF
- + " \u00da \u00c3\u00d5 "
- // 01.....2345.....6789.....ABCDEF.....
- + " \u00c2 \u20ac \u00ed \u00f3"
- // 012345.....6789AB.....C.....DEF.....
- + " \u00fa \u00e3\u00f5 \u00e2",
-
- /**
- * National Language Identifier: 0x04
- * A.2.4 Bengali National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u09e6\u09e7\uffff\u09e8\u09e9\u09ea\u09eb"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u09ec\u09ed\u09ee\u09ef\u09df\u09e0\u09e1\u09e2{}\u09e3\u09f2\u09f3\u09f4\u09f5\\"
- // 0.....1.....2.....3.....4.....56789ABCDEF
- + "\u09f6\u09f7\u09f8\u09f9\u09fa [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x05
- * A.2.5 Gujarati National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0ae6\u0ae7\u0ae8\u0ae9"
- // 0.....1.....2.....3.....4.....5.....6789ABCDEF.
- + "\u0aea\u0aeb\u0aec\u0aed\u0aee\u0aef {} \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x06
- * A.2.6 Hindi National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0966\u0967\u0968\u0969"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u096a\u096b\u096c\u096d\u096e\u096f\u0951\u0952{}\u0953\u0954\u0958\u0959\u095a\\"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....BCDEF
- + "\u095b\u095c\u095d\u095e\u095f\u0960\u0961\u0962\u0963\u0970\u0971 [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x07
- * A.2.7 Kannada National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0ce6\u0ce7\u0ce8\u0ce9"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....BCDEF.
- + "\u0cea\u0ceb\u0cec\u0ced\u0cee\u0cef\u0cde\u0cf1{}\u0cf2 \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x08
- * A.2.8 Malayalam National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0d66\u0d67\u0d68\u0d69"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u0d6a\u0d6b\u0d6c\u0d6d\u0d6e\u0d6f\u0d70\u0d71{}\u0d72\u0d73\u0d74\u0d75\u0d7a\\"
- // 0.....1.....2.....3.....4.....56789ABCDEF
- + "\u0d7b\u0d7c\u0d7d\u0d7e\u0d7f [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x09
- * A.2.9 Oriya National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0b66\u0b67\u0b68\u0b69"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....DEF.
- + "\u0b6a\u0b6b\u0b6c\u0b6d\u0b6e\u0b6f\u0b5c\u0b5d{}\u0b5f\u0b70\u0b71 \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x0A
- * A.2.10 Punjabi National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0a66\u0a67\u0a68\u0a69"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....EF.
- + "\u0a6a\u0a6b\u0a6c\u0a6d\u0a6e\u0a6f\u0a59\u0a5a{}\u0a5b\u0a5c\u0a5e\u0a75 \\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x0B
- * A.2.11 Tamil National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0964\u0965\uffff\u0be6\u0be7\u0be8\u0be9"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u0bea\u0beb\u0bec\u0bed\u0bee\u0bef\u0bf3\u0bf4{}\u0bf5\u0bf6\u0bf7\u0bf8\u0bfa\\"
- // 0123456789ABCDEF
- + " [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x0C
- * A.2.12 Telugu National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789AB.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#* \uffff\u0c66\u0c67\u0c68\u0c69"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u0c6a\u0c6b\u0c6c\u0c6d\u0c6e\u0c6f\u0c58\u0c59{}\u0c78\u0c79\u0c7a\u0c7b\u0c7c\\"
- // 0.....1.....2.....3456789ABCDEF
- + "\u0c7d\u0c7e\u0c7f [~] "
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " ",
-
- /**
- * National Language Identifier: 0x0D
- * A.2.13 Urdu National Language Single Shift Table
- */
- // 01.....23.....4.....5.6.....789A.....BCD.....EF
- "@\u00a3$\u00a5\u00bf\"\u00a4%&'\u000c*+\ufffe-/"
- // 0123.....45.....6789.....A.....B.....C.....D.....E.....F.....
- + "<=>\u00a1^\u00a1_#*\u0600\u0601\uffff\u06f0\u06f1\u06f2\u06f3"
- // 0.....1.....2.....3.....4.....5.....6.....7.....89A.....B.....C.....D.....E.....F.
- + "\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u060c\u060d{}\u060e\u060f\u0610\u0611\u0612\\"
- // 0.....1.....2.....3.....4.....5.....6.....7.....8.....9.....A.....B.....CDEF.....
- + "\u0613\u0614\u061b\u061f\u0640\u0652\u0658\u066b\u066c\u0672\u0673\u06cd[~]\u06d4"
- // 0123456789ABCDEF
- + "|ABCDEFGHIJKLMNO"
- // 0123456789ABCDEF
- + "PQRSTUVWXYZ "
- // 012345.....6789ABCDEF
- + " \u20ac "
- // 0123456789ABCDEF
- + " "
-];
-
-// Special SMS Message Indication constants
-this.PDU_MWI_STORE_TYPE_BIT = 0x80;
-this.PDU_MWI_STORE_TYPE_DISCARD = 0x00;
-this.PDU_MWI_STORE_TYPE_STORE = 0x80;
-
-this.GSM_SMS_STRICT_7BIT_CHARMAP = {
-//"\u0024": "\u0024", // "$" => "$", already in default alphabet
-//"\u00a5": "\u00a5", // "¥" => "¥", already in default alphabet
- "\u00c0": "\u0041", // "À" => "A"
- "\u00c1": "\u0041", // "Á" => "A"
- "\u00c2": "\u0041", // "Â" => "A"
- "\u00c3": "\u0041", // "Ã" => "A"
-//"\u00c4": "\u00c4", // "Ä" => "Ä", already in default alphabet
-//"\u00c5": "\u00c5", // "Å" => "Å", already in default alphabet
-//"\u00c6": "\u00c6", // "Æ" => "Æ", already in default alphabet
-//"\u00c7": "\u00c7", // "Ç" => "Ç", already in default alphabet
- "\u00c8": "\u0045", // "È" => "E"
-//"\u00c9": "\u00c9", // "É" => "É", already in default alphabet
- "\u00ca": "\u0045", // "Ê" => "E"
- "\u00cb": "\u0045", // "Ë" => "E"
- "\u00cc": "\u0049", // "Ì" => "I"
- "\u00cd": "\u0049", // "Í" => "I"
- "\u00ce": "\u0049", // "Î" => "I"
- "\u00cf": "\u0049", // "Ï" => "I"
-//"\u00d1": "\u00d1", // "Ñ" => "Ñ", already in default alphabet
- "\u00d2": "\u004f", // "Ò" => "O"
- "\u00d3": "\u004f", // "Ó" => "O"
- "\u00d4": "\u004f", // "Ô" => "O"
- "\u00d5": "\u004f", // "Õ" => "O"
-//"\u00d6": "\u00d6", // "Ö" => "Ö", already in default alphabet
- "\u00d9": "\u0055", // "Ù" => "U"
- "\u00da": "\u0055", // "Ú" => "U"
- "\u00db": "\u0055", // "Û" => "U"
-//"\u00dc": "\u00dc", // "Ü" => "Ü", already in default alphabet
-//"\u00df": "\u00df", // "ß" => "ß", already in default alphabet
-//"\u00e0": "\u00e0", // "à" => "à", already in default alphabet
- "\u00e1": "\u0061", // "á" => "a"
- "\u00e2": "\u0061", // "â" => "a"
- "\u00e3": "\u0061", // "ã" => "a"
-//"\u00e4": "\u00e4", // "ä" => "ä", already in default alphabet
-//"\u00e5": "\u00e5", // "å" => "å", already in default alphabet
-//"\u00e6": "\u00e6", // "æ" => "æ", already in default alphabet
- "\u00e7": "\u00c7", // "ç" => "Ç"
-//"\u00e8": "\u00e8", // "è" => "è", already in default alphabet
-//"\u00e9": "\u00e9", // "é" => "é", already in default alphabet
- "\u00ea": "\u0065", // "ê" => "e"
- "\u00eb": "\u0065", // "ë" => "e"
-//"\u00ec": "\u00ec", // "ì" => "ì", already in default alphabet
- "\u00ed": "\u0069", // "í" => "i"
- "\u00ee": "\u0069", // "î" => "i"
- "\u00ef": "\u0069", // "ï" => "i"
-//"\u00f1": "\u00f1", // "ñ" => "ñ", already in default alphabet
-//"\u00f2": "\u00f2", // "ò" => "ò", already in default alphabet
- "\u00f3": "\u006f", // "ó" => "o"
- "\u00f4": "\u006f", // "ô" => "o"
- "\u00f5": "\u006f", // "õ" => "o"
-//"\u00f6": "\u00f6", // "ö" => "ö", already in default alphabet
-//"\u00f8": "\u00f8", // "ø" => "ø", already in default alphabet
-//"\u00f9": "\u00f9", // "ù" => "ù", already in default alphabet
- "\u00fa": "\u0075", // "ú" => "u"
- "\u00fb": "\u0075", // "û" => "u"
-//"\u00fc": "\u00fc", // "ü" => "ü", already in default alphabet
- "\u00fe": "\u0074", // "þ" => "t"
- "\u0100": "\u0041", // "Ā" => "A"
- "\u0101": "\u0061", // "ā" => "a"
- "\u0106": "\u0043", // "Ć" => "C"
- "\u0107": "\u0063", // "ć" => "c"
- "\u010c": "\u0043", // "Č" => "C"
- "\u010d": "\u0063", // "č" => "c"
- "\u010f": "\u0064", // "ď" => "d"
- "\u0110": "\u0044", // "Đ" => "D"
- "\u0111": "\u0064", // "đ" => "d"
- "\u0112": "\u0045", // "Ē" => "E"
- "\u0113": "\u0065", // "ē" => "e"
- "\u0118": "\u0045", // "Ę" => "E"
- "\u0119": "\u0065", // "ę" => "e"
- "\u0128": "\u0049", // "Ĩ" => "I"
- "\u0129": "\u0069", // "ĩ" => "i"
- "\u012a": "\u0049", // "Ī" => "I"
- "\u012b": "\u0069", // "ī" => "i"
- "\u012e": "\u0049", // "Į" => "I"
- "\u012f": "\u0069", // "į" => "i"
- "\u0141": "\u004c", // "Ł" => "L"
- "\u0142": "\u006c", // "ł" => "l"
- "\u0143": "\u004e", // "Ń" => "N"
- "\u0144": "\u006e", // "ń" => "n"
- "\u0147": "\u004e", // "Ň" => "N"
- "\u0148": "\u006e", // "ň" => "n"
- "\u014c": "\u004f", // "Ō" => "O"
- "\u014d": "\u006f", // "ō" => "o"
- "\u0152": "\u004f", // "Œ" => "O"
- "\u0153": "\u006f", // "œ" => "o"
- "\u0158": "\u0052", // "Ř" => "R"
- "\u0159": "\u0072", // "ř" => "r"
- "\u0160": "\u0053", // "Š" => "S"
- "\u0161": "\u0073", // "š" => "s"
- "\u0165": "\u0074", // "ť" => "t"
- "\u0168": "\u0055", // "Ū" => "U"
- "\u0169": "\u0075", // "ū" => "u"
- "\u016a": "\u0055", // "Ū" => "U"
- "\u016b": "\u0075", // "ū" => "u"
- "\u0178": "\u0059", // "Ÿ" => "Y"
- "\u0179": "\u005a", // "Ź" => "Z"
- "\u017a": "\u007a", // "ź" => "z"
- "\u017b": "\u005a", // "Ż" => "Z"
- "\u017c": "\u007a", // "ż" => "z"
- "\u017d": "\u005a", // "Ž" => "Z"
- "\u017e": "\u007a", // "ž" => "z"
- "\u025b": "\u0045", // "ɛ" => "E"
-//"\u0398": "\u0398", // "Θ" => "Θ", already in default alphabet
- "\u1e7c": "\u0056", // "Ṽ" => "V"
- "\u1e7d": "\u0076", // "ṽ" => "v"
- "\u1ebc": "\u0045", // "Ẽ" => "E"
- "\u1ebd": "\u0065", // "ẽ" => "e"
- "\u1ef8": "\u0059", // "Ỹ" => "Y"
- "\u1ef9": "\u0079", // "ỹ" => "y"
- "\u20a4": "\u00a3", // "₤" => "£"
-//"\u20ac": "\u20ac", // "€" => "€", already in default alphabet
-};
-
-this.RADIOTECH_FAMILY_3GPP = 1; // GSM, WCDMA, LTE
-this.RADIOTECH_FAMILY_3GPP2 = 2; // CDMA, EVDO
-
-this.DATACALL_RADIOTECHNOLOGY_CDMA = 0;
-this.DATACALL_RADIOTECHNOLOGY_GSM = 1;
-
-this.DATACALL_AUTH_NONE = 0;
-this.DATACALL_AUTH_PAP = 1;
-this.DATACALL_AUTH_CHAP = 2;
-this.DATACALL_AUTH_PAP_OR_CHAP = 3;
-
-this.GECKO_DATACALL_AUTH_NONE = "none";
-this.GECKO_DATACALL_AUTH_PAP = "pap";
-this.GECKO_DATACALL_AUTH_CHAP = "chap";
-this.GECKO_DATACALL_AUTH_PAP_OR_CHAP = "papOrChap";
-this.GECKO_DATACALL_AUTH_DEFAULT = GECKO_DATACALL_AUTH_PAP_OR_CHAP;
-this.RIL_DATACALL_AUTH_TO_GECKO = [
- GECKO_DATACALL_AUTH_NONE, // DATACALL_AUTH_NONE
- GECKO_DATACALL_AUTH_PAP, // DATACALL_AUTH_PAP
- GECKO_DATACALL_AUTH_CHAP, // DATACALL_AUTH_CHAP
- GECKO_DATACALL_AUTH_PAP_OR_CHAP // DATACALL_AUTH_PAP_OR_CHAP
-];
-
-this.GECKO_DATACALL_PDP_TYPE_IP = "IP";
-this.GECKO_DATACALL_PDP_TYPE_IPV4V6 = "IPV4V6";
-this.GECKO_DATACALL_PDP_TYPE_IPV6 = "IPV6";
-this.GECKO_DATACALL_PDP_TYPE_DEFAULT = GECKO_DATACALL_PDP_TYPE_IP;
-this.RIL_DATACALL_PDP_TYPES = [
- GECKO_DATACALL_PDP_TYPE_IP,
- GECKO_DATACALL_PDP_TYPE_IPV4V6,
- GECKO_DATACALL_PDP_TYPE_IPV6,
-];
-
-this.DATACALL_PROFILE_DEFAULT = 0;
-this.DATACALL_PROFILE_TETHERED = 1;
-this.DATACALL_PROFILE_OEM_BASE = 1000;
-
-this.DATACALL_DEACTIVATE_NO_REASON = 0;
-this.DATACALL_DEACTIVATE_RADIO_SHUTDOWN = 1;
-
-this.DATACALL_ACTIVE_UNKNOWN = -1;
-this.DATACALL_INACTIVE = 0;
-this.DATACALL_ACTIVE_DOWN = 1;
-this.DATACALL_ACTIVE_UP = 2;
-
-this.DATACALL_FAIL_NONE = 0;
-this.DATACALL_FAIL_OPERATOR_BARRED = 0x08;
-this.DATACALL_FAIL_INSUFFICIENT_RESOURCES = 0x1A;
-this.DATACALL_FAIL_MISSING_UKNOWN_APN = 0x1B;
-this.DATACALL_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C;
-this.DATACALL_FAIL_USER_AUTHENTICATION = 0x1D;
-this.DATACALL_FAIL_ACTIVATION_REJECT_GGSN = 0x1E;
-this.DATACALL_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F;
-this.DATACALL_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20;
-this.DATACALL_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21;
-this.DATACALL_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22;
-this.DATACALL_FAIL_NSAPI_IN_USE = 0x23;
-this.DATACALL_FAIL_ONLY_IPV4_ALLOWED = 0x32;
-this.DATACALL_FAIL_ONLY_IPV6_ALLOWED = 0x33;
-this.DATACALL_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34;
-this.DATACALL_FAIL_PROTOCOL_ERRORS = 0x6F;
-this.DATACALL_FAIL_VOICE_REGISTRATION_FAIL = -1;
-this.DATACALL_FAIL_DATA_REGISTRATION_FAIL = -2;
-this.DATACALL_FAIL_SIGNAL_LOST = -3;
-this.DATACALL_FAIL_PREF_RADIO_TECH_CHANGED = -4;
-this.DATACALL_FAIL_RADIO_POWER_OFF = -5;
-this.DATACALL_FAIL_TETHERED_CALL_ACTIVE = -6;
-this.DATACALL_FAIL_ERROR_UNSPECIFIED = 0xffff;
-
-// Keep consistent with nsINetworkManager.NETWORK_STATE_*.
-this.GECKO_NETWORK_STATE_UNKNOWN = -1;
-this.GECKO_NETWORK_STATE_CONNECTING = 0;
-this.GECKO_NETWORK_STATE_CONNECTED = 1;
-this.GECKO_NETWORK_STATE_DISCONNECTING = 2;
-this.GECKO_NETWORK_STATE_DISCONNECTED = 3;
-
-// 3GPP 24.008 Annex H.
-this.CALL_FAIL_UNOBTAINABLE_NUMBER = 1;
-this.CALL_FAIL_NO_ROUTE_TO_DESTINATION = 3;
-this.CALL_FAIL_CHANNEL_UNACCEPTABLE = 6;
-this.CALL_FAIL_OPERATOR_DETERMINED_BARRING = 8;
-this.CALL_FAIL_NORMAL = 16;
-this.CALL_FAIL_BUSY = 17;
-this.CALL_FAIL_NO_USER_RESPONDING = 18;
-this.CALL_FAIL_USER_ALERTING = 19;
-this.CALL_FAIL_CALL_REJECTED = 21;
-this.CALL_FAIL_NUMBER_CHANGED = 22;
-this.CALL_FAIL_CALL_REJECTED_DESTINATION_FEATURE = 24;
-this.CALL_FAIL_CALL_PRE_EMPTION = 25;
-this.CALL_FAIL_DEST_OUT_OF_ORDER = 27;
-this.CALL_FAIL_INVALID_FORMAT = 28;
-this.CALL_FAIL_FACILITY_REJECTED = 29;
-this.CALL_FAIL_RESPONSE_TO_STATUS_ENQUIRY = 30;
-this.CALL_FAIL_NORMAL_UNSPECIFIED = 31;
-this.CALL_FAIL_CONGESTION = 34;
-this.CALL_FAIL_NETWORK_OUT_OF_ORDER = 38;
-this.CALL_FAIL_NETWORK_TEMP_FAILURE = 41;
-this.CALL_FAIL_SWITCHING_EQUIP_CONGESTION = 42;
-this.CALL_FAIL_ACCESS_INFO_DISCARDED = 43;
-this.CALL_FAIL_REQUESTED_CHANNEL_NOT_AVAILABLE = 44;
-this.CALL_FAIL_RESOURCE_UNAVAILABLE = 47;
-this.CALL_FAIL_QOS_UNAVAILABLE = 49;
-this.CALL_FAIL_REQUESTED_FACILITY_NOT_SUBSCRIBED = 50;
-this.CALL_FAIL_INCOMING_CALLS_BARRED_WITHIN_CUG = 55;
-this.CALL_FAIL_BEARER_CAPABILITY_NOT_AUTHORIZED = 57;
-this.CALL_FAIL_BEARER_CAPABILITY_NOT_AVAILABLE = 58;
-this.CALL_FAIL_SERVICE_NOT_AVAILABLE = 63;
-this.CALL_FAIL_BEARER_NOT_IMPLEMENTED = 65;
-this.CALL_FAIL_ACM_LIMIT_EXCEEDED = 68;
-this.CALL_FAIL_REQUESTED_FACILITY_NOT_IMPLEMENTED = 69;
-this.CALL_FAIL_UNRESTRICTED_BEARER_NOT_AVAILABLE = 70;
-this.CALL_FAIL_SERVICE_NOT_IMPLEMENTED = 79;
-this.CALL_FAIL_INVALID_TRANSACTION_ID = 81;
-this.CALL_FAIL_USER_NOT_CUG_MEMBER = 87;
-this.CALL_FAIL_INCOMPATIBLE_DESTINATION = 88;
-this.CALL_FAIL_INVALID_TRANSIT_NETWORK_SELECTION = 91;
-this.CALL_FAIL_SEMANTICALLY_INCORRECT_MESSAGE = 95;
-this.CALL_FAIL_INVALID_MANDATORY_INFO = 96;
-this.CALL_FAIL_MESSAGE_TYPE_NOT_IMPLEMENTED = 97;
-this.CALL_FAIL_MESSAGE_TYPE_INCOMPATIBLE_PROTOCOL_STATE = 98;
-this.CALL_FAIL_INFO_ELEMENT_NOT_IMPLEMENTED = 99;
-this.CALL_FAIL_CONDITIONAL_IE_ERROR = 100;
-this.CALL_FAIL_MESSAGE_INCOMPABITLE_PROTOCOL_STATE = 101;
-this.CALL_FAIL_RECOVERY_ON_TIMER_EXPIRY = 102;
-this.CALL_FAIL_PROTOCOL_ERROR = 111;
-this.CALL_FAIL_INTERWORKING = 127;
-// AOSP ril.h
-this.CALL_FAIL_CALL_BARRED = 240;
-this.CALL_FAIL_FDN_BLOCKED = 241;
-this.CALL_FAIL_IMSI_UNKNOWN_IN_VLR = 242;
-this.CALL_FAIL_IMEI_NOT_ACCEPTED = 243;
-this.CALL_FAIL_DIAL_MODIFIED_TO_USSD = 244; // STK Call Control
-this.CALL_FAIL_DIAL_MODIFIED_TO_SS = 245;
-this.CALL_FAIL_DIAL_MODIFIED_TO_DIAL = 246;
-this.CALL_FAIL_CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000;
-this.CALL_FAIL_CDMA_DROP = 1001;
-this.CALL_FAIL_CDMA_INTERCEPT = 1002;
-this.CALL_FAIL_CDMA_REORDER = 1003;
-this.CALL_FAIL_CDMA_SO_REJECT = 1004;
-this.CALL_FAIL_CDMA_RETRY_ORDER = 1005;
-this.CALL_FAIL_CDMA_ACCESS_FAILURE = 1006;
-this.CALL_FAIL_CDMA_PREEMPTED = 1007;
-this.CALL_FAIL_CDMA_NOT_EMERGENCY = 1008; // For non-emergency number dialed
- // during emergency callback mode
-this.CALL_FAIL_CDMA_ACCESS_BLOCKED = 1009;
-this.CALL_FAIL_ERROR_UNSPECIFIED = 0xffff;
-
-// See nsIMobileConnection::MOBILE_RADIO_STATE_*
-this.GECKO_RADIOSTATE_UNKNOWN = -1;
-this.GECKO_RADIOSTATE_ENABLED = 0;
-this.GECKO_RADIOSTATE_DISABLED = 1;
-
-// Only used in ril_worker.js
-this.GECKO_CARDSTATE_UNINITIALIZED = 4294967294; // UINT32_MAX - 1
-// See nsIIcc::CARD_STATE_*
-this.GECKO_CARDSTATE_UNDETECTED = 4294967295; // UINT32_MAX
-this.GECKO_CARDSTATE_UNKNOWN = 0;
-this.GECKO_CARDSTATE_READY = 1;
-this.GECKO_CARDSTATE_PIN_REQUIRED = 2;
-this.GECKO_CARDSTATE_PUK_REQUIRED = 3;
-this.GECKO_CARDSTATE_PERMANENT_BLOCKED = 4;
-this.GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS = 5;
-this.GECKO_CARDSTATE_PERSONALIZATION_READY = 6;
-this.GECKO_CARDSTATE_NETWORK_LOCKED = 7;
-this.GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED = 8;
-this.GECKO_CARDSTATE_CORPORATE_LOCKED = 9;
-this.GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED = 10;
-this.GECKO_CARDSTATE_SIM_LOCKED = 11;
-this.GECKO_CARDSTATE_NETWORK_PUK_REQUIRED = 12;
-this.GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED = 13;
-this.GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED = 14;
-this.GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED = 15;
-this.GECKO_CARDSTATE_SIM_PUK_REQUIRED = 16;
-this.GECKO_CARDSTATE_NETWORK1_LOCKED = 17;
-this.GECKO_CARDSTATE_NETWORK2_LOCKED = 18;
-this.GECKO_CARDSTATE_HRPD_NETWORK_LOCKED = 19;
-this.GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED = 20;
-this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED = 21;
-this.GECKO_CARDSTATE_RUIM_LOCKED = 22;
-this.GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED = 23;
-this.GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED = 24;
-this.GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED = 25;
-this.GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED = 26;
-this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = 27;
-this.GECKO_CARDSTATE_RUIM_PUK_REQUIRED = 28;
-this.GECKO_CARDSTATE_ILLEGAL = 29;
-
-// See nsIIcc::CARD_LOCK_TYPE_*
-this.GECKO_CARDLOCK_PIN = 0;
-this.GECKO_CARDLOCK_PIN2 = 1;
-this.GECKO_CARDLOCK_PUK = 2;
-this.GECKO_CARDLOCK_PUK2 = 3;
-this.GECKO_CARDLOCK_NCK = 4;
-this.GECKO_CARDLOCK_NSCK = 5;
-this.GECKO_CARDLOCK_NCK1 = 6;
-this.GECKO_CARDLOCK_NCK2 = 7;
-this.GECKO_CARDLOCK_HNCK = 8;
-this.GECKO_CARDLOCK_CCK = 9;
-this.GECKO_CARDLOCK_SPCK = 10;
-this.GECKO_CARDLOCK_PCK = 11;
-this.GECKO_CARDLOCK_RCCK = 12;
-this.GECKO_CARDLOCK_RSPCK = 13;
-this.GECKO_CARDLOCK_NCK_PUK = 14;
-this.GECKO_CARDLOCK_NSCK_PUK = 15;
-this.GECKO_CARDLOCK_NCK1_PUK = 16;
-this.GECKO_CARDLOCK_NCK2_PUK = 17;
-this.GECKO_CARDLOCK_HNCK_PUK = 18;
-this.GECKO_CARDLOCK_CCK_PUK = 19;
-this.GECKO_CARDLOCK_SPCK_PUK = 20;
-this.GECKO_CARDLOCK_PCK_PUK = 21;
-this.GECKO_CARDLOCK_RCCK_PUK = 22;
-this.GECKO_CARDLOCK_RSPCK_PUK = 23;
-this.GECKO_CARDLOCK_FDN = 24;
-
-this.GECKO_CARDLOCK_TO_FACILITY = {};
-GECKO_CARDLOCK_TO_FACILITY[GECKO_CARDLOCK_PIN] = ICC_CB_FACILITY_SIM;
-GECKO_CARDLOCK_TO_FACILITY[GECKO_CARDLOCK_FDN] = ICC_CB_FACILITY_FDN;
-
-this.GECKO_CARDLOCK_TO_SEL_CODE = {};
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PIN] = ICC_SEL_CODE_SIM_PIN;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PIN2] = ICC_SEL_CODE_SIM_PIN2;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PUK] = ICC_SEL_CODE_SIM_PUK;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PUK2] = ICC_SEL_CODE_SIM_PUK2;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_NCK] = ICC_SEL_CODE_PH_NET_PIN;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_NSCK] = ICC_SEL_CODE_PH_NETSUB_PIN;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_CCK] = ICC_SEL_CODE_PH_CORP_PIN;
-GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_SPCK] = ICC_SEL_CODE_PH_SP_PIN;
-// TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM @
-// ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_PCK.
-
-// See nsIIcc::CARD_CONTACT_TYPE_*
-this.GECKO_CARDCONTACT_TYPE_ADN = 0;
-this.GECKO_CARDCONTACT_TYPE_FDN = 1;
-this.GECKO_CARDCONTACT_TYPE_SDN = 2;
-
-// See nsIIcc::CARD_MVNO_TYPE_*
-this.GECKO_CARDMVNO_TYPE_IMSI = 0;
-this.GECKO_CARDMVNO_TYPE_SPN = 1;
-this.GECKO_CARDMVNO_TYPE_GID = 2;
-
-// See nsIIcc::CARD_SERVICE_*
-this.GECKO_CARDSERVICE_FDN = 0;
-
-// See ril.h RIL_PersoSubstate
-this.PERSONSUBSTATE = {};
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_UNKNOWN] = GECKO_CARDSTATE_UNKNOWN;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_IN_PROGRESS] = GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_READY] = GECKO_CARDSTATE_PERSONALIZATION_READY;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK] = GECKO_CARDSTATE_NETWORK_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET] = GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE] = GECKO_CARDSTATE_CORPORATE_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER] = GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SIM] = GECKO_CARDSTATE_SIM_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_PUK] = GECKO_CARDSTATE_NETWORK_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK] = GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK] = GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK] = GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SIM_PUK] = GECKO_CARDSTATE_SIM_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK1] = GECKO_CARDSTATE_NETWORK1_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK2] = GECKO_CARDSTATE_NETWORK2_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_HRPD] = GECKO_CARDSTATE_HRPD_NETWORK_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_CORPORATE] = GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER] = GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_RUIM] = GECKO_CARDSTATE_RUIM_LOCKED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK] = GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK] = GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_HRPD_PUK] = GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK] = GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK] = GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED;
-PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_RUIM_PUK] = GECKO_CARDSTATE_RUIM_PUK_REQUIRED;
-
-// See nsIMobileConnection::NETWORK_SELECTION_MODE_*
-this.GECKO_NETWORK_SELECTION_UNKNOWN = -1;
-this.GECKO_NETWORK_SELECTION_AUTOMATIC = 0;
-this.GECKO_NETWORK_SELECTION_MANUAL = 1;
-
-this.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN = null;
-this.GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING = "notSearching";
-this.GECKO_MOBILE_CONNECTION_STATE_SEARCHING = "searching";
-this.GECKO_MOBILE_CONNECTION_STATE_REGISTERED = "registered";
-this.GECKO_MOBILE_CONNECTION_STATE_DENIED = "denied";
-
-this.NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE = {};
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_HOME] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_SEARCHING;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED] = GECKO_MOBILE_CONNECTION_STATE_DENIED;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_ROAMING] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_SEARCHING;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_DENIED;
-NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
-
-
-// Should match enum TelephonyCallDisconnectedReason defined in TelephonyCall.webidl
-this.GECKO_CALL_ERROR_BAD_NUMBER = "BadNumberError";
-this.GECKO_CALL_ERROR_NO_ROUTE_TO_DESTINATION = "NoRouteToDestinationError";
-this.GECKO_CALL_ERROR_CHANNEL_UNACCEPTABLE = "ChannelUnacceptableError";
-this.GECKO_CALL_ERROR_OPERATOR_DETERMINED_BARRING = "OperatorDeterminedBarringError";
-this.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING = "NormalCallClearingError";
-this.GECKO_CALL_ERROR_BUSY = "BusyError";
-this.GECKO_CALL_ERROR_NO_USER_RESPONDING = "NoUserRespondingError";
-this.GECKO_CALL_ERROR_USER_ALERTING = "UserAlertingNoAnswerError";
-this.GECKO_CALL_ERROR_REJECTED = "CallRejectedError";
-this.GECKO_CALL_ERROR_NUMBER_CHANGED = "NumberChangedError";
-this.GECKO_CALL_ERROR_REJECTED_DETINATION_FEATURE = "CallRejectedDestinationFeatureError";
-this.GECKO_CALL_ERROR_PRE_EMPTION = "PreEmptionError";
-this.GECKO_CALL_ERROR_DEST_OUT_OF_ORDER = "DestinationOutOfOrderError";
-this.GECKO_CALL_ERROR_INVALID_NUMBER_FORMAT = "InvalidNumberFormatError";
-this.GECKO_CALL_ERROR_FACILITY_REJECTED = "FacilityRejectedError";
-this.GECKO_CALL_ERROR_RESPONSE_TO_STATUS_ENQUIRY = "ResponseToStatusEnquiryError";
-this.GECKO_CALL_ERROR_CONGESTION = "CongestionError";
-this.GECKO_CALL_ERROR_NETWORK_OUT_OF_ORDER = "NetworkOutOfOrderError";
-this.GECKO_CALL_ERROR_NETWORK_TEMP_FAILURE = "NetworkTempFailureError";
-this.GECKO_CALL_ERROR_SWITCHING_EQUIP_CONGESTION = "SwitchingEquipCongestionError";
-this.GECKO_CALL_ERROR_ACCESS_INFO_DISCARDED = "AccessInfoDiscardedError";
-this.GECKO_CALL_ERROR_REQUESTED_CHANNEL_NOT_AVAILABLE = "RequestedChannelNotAvailableError";
-this.GECKO_CALL_ERROR_RESOURCE_UNAVAILABLE = "ResourceUnavailableError";
-this.GECKO_CALL_ERROR_QOS_UNAVAILABLE = "QosUnavailableError";
-this.GECKO_CALL_ERROR_REQUESTED_FACILITY_NOT_SUBSCRIBED = "RequestedFacilityNotSubscribedError";
-this.GECKO_CALL_ERROR_INCOMING_CALLS_BARRED_WITHIN_CUG = "IncomingCallsBarredWithinCugError";
-this.GECKO_CALL_ERROR_BEARER_CAPABILITY_NOT_AUTHORIZED = "BearerCapabilityNotAuthorizedError";
-this.GECKO_CALL_ERROR_BEARER_CAPABILITY_NOT_AVAILABLE = "BearerCapabilityNotAvailableError";
-this.GECKO_CALL_ERROR_BEARER_NOT_IMPLEMENTED = "BearerNotImplementedError";
-this.GECKO_CALL_ERROR_SERVICE_NOT_AVAILABLE = "ServiceNotAvailableError";
-this.GECKO_CALL_ERROR_INCOMING_CALL_EXCEEDED = "IncomingCallExceededError";
-this.GECKO_CALL_ERROR_REQUESTED_FACILITY_NOT_IMPLEMENTED = "RequestedFacilityNotImplementedError";
-this.GECKO_CALL_ERROR_UNRESTRICTED_BEARER_NOT_AVAILABLE = "UnrestrictedBearerNotAvailableError";
-this.GECKO_CALL_ERROR_SERVICE_NOT_IMPLEMENTED = "ServiceNotImplementedError";
-this.GECKO_CALL_ERROR_INVALID_TRANSACTION_ID = "InvalidTransactionIdError";
-this.GECKO_CALL_ERROR_USER_NOT_CUG_MEMBER = "NotCugMemberError";
-this.GECKO_CALL_ERROR_INCOMPATIBLE_DESTINATION = "IncompatibleDestinationError";
-this.GECKO_CALL_ERROR_INVALID_TRANSIT_NETWORK_SELECTION = "InvalidTransitNetworkSelectionError";
-this.GECKO_CALL_ERROR_SEMANTICALLY_INCORRECT_MESSAGE = "SemanticallyIncorrectMessageError";
-this.GECKO_CALL_ERROR_INVALID_MANDATORY_INFO = "InvalidMandatoryInfoError";
-this.GECKO_CALL_ERROR_MESSAGE_TYPE_NOT_IMPLEMENTED = "MessageTypeNotImplementedError";
-this.GECKO_CALL_ERROR_MESSAGE_TYPE_INCOMPATIBLE_PROTOCOL_STATE = "MessageTypeIncompatibleProtocolStateError";
-this.GECKO_CALL_ERROR_INFO_ELEMENT_NOT_IMPLEMENTED = "InfoElementNotImplementedError";
-this.GECKO_CALL_ERROR_CONDITIONAL_IE = "ConditionalIeError";
-this.GECKO_CALL_ERROR_MESSAGE_INCOMPATIBLE_PROTOCOL_STATE = "MessageIncompatibleProtocolStateError";
-this.GECKO_CALL_ERROR_RECOVERY_ON_TIMER_EXPIRY = "RecoveryOnTimerExpiryError";
-this.GECKO_CALL_ERROR_PROTOCOL = "ProtocolError";
-this.GECKO_CALL_ERROR_INTERWORKING = "InterworkingError";
-this.GECKO_CALL_ERROR_BARRED = "BarredError";
-this.GECKO_CALL_ERROR_FDN_BLOCKED = "FDNBlockedError";
-this.GECKO_CALL_ERROR_SUBSCRIBER_UNKNOWN = "SubscriberUnknownError";
-this.GECKO_CALL_ERROR_DEVICE_NOT_ACCEPTED = "DeviceNotAcceptedError";
-this.GECKO_CALL_ERROR_MODIFIED_TO_DIAL_FAILED = "ModifiedDialError";
-this.GECKO_CALL_ERROR_CDMA_LOCKED_UNTIL_POWER_CYCLE = "CdmaLockedUntilPowerCycleError";
-this.GECKO_CALL_ERROR_CDMA_DROP = "CdmaDropError";
-this.GECKO_CALL_ERROR_CDMA_INTERCEPT = "CdmaInterceptError";
-this.GECKO_CALL_ERROR_CDMA_REORDER = "CdmaReorderError";
-this.GECKO_CALL_ERROR_CDMA_SO_REJECT = "CdmaSoRejectError";
-this.GECKO_CALL_ERROR_CDMA_RETRY_ORDER = "CdmaRetryOrderError";
-this.GECKO_CALL_ERROR_CDMA_ACCESS_FAILURE = "CdmaAcessError";
-this.GECKO_CALL_ERROR_CDMA_PREEMPTED = "CdmaPreemptedError";
-this.GECKO_CALL_ERROR_CDMA_NOT_EMERGENCY = "CdmaNotEmergencyError";
-this.GECKO_CALL_ERROR_CDMA_ACCESS_BLOCKED = "CdmaAccessBlockedError";
-this.GECKO_CALL_ERROR_UNSPECIFIED = "UnspecifiedError";
-
-this.RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR = {};
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_UNOBTAINABLE_NUMBER] = GECKO_CALL_ERROR_BAD_NUMBER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NO_ROUTE_TO_DESTINATION] = GECKO_CALL_ERROR_NO_ROUTE_TO_DESTINATION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CHANNEL_UNACCEPTABLE] = GECKO_CALL_ERROR_CHANNEL_UNACCEPTABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_OPERATOR_DETERMINED_BARRING] = GECKO_CALL_ERROR_OPERATOR_DETERMINED_BARRING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NORMAL] = GECKO_CALL_ERROR_NORMAL_CALL_CLEARING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BUSY] = GECKO_CALL_ERROR_BUSY;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NO_USER_RESPONDING] = GECKO_CALL_ERROR_NO_USER_RESPONDING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_USER_ALERTING] = GECKO_CALL_ERROR_USER_ALERTING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CALL_REJECTED] = GECKO_CALL_ERROR_REJECTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NUMBER_CHANGED] = GECKO_CALL_ERROR_NUMBER_CHANGED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CALL_REJECTED_DESTINATION_FEATURE] = GECKO_CALL_ERROR_REJECTED_DETINATION_FEATURE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CALL_PRE_EMPTION] = GECKO_CALL_ERROR_PRE_EMPTION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_DEST_OUT_OF_ORDER] = GECKO_CALL_ERROR_DEST_OUT_OF_ORDER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INVALID_FORMAT] = GECKO_CALL_ERROR_INVALID_NUMBER_FORMAT;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_FACILITY_REJECTED] = GECKO_CALL_ERROR_FACILITY_REJECTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_RESPONSE_TO_STATUS_ENQUIRY] = GECKO_CALL_ERROR_RESPONSE_TO_STATUS_ENQUIRY;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NORMAL_UNSPECIFIED] = GECKO_CALL_ERROR_NORMAL_CALL_CLEARING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CONGESTION] = GECKO_CALL_ERROR_CONGESTION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NETWORK_OUT_OF_ORDER] = GECKO_CALL_ERROR_NETWORK_OUT_OF_ORDER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NETWORK_TEMP_FAILURE] = GECKO_CALL_ERROR_NETWORK_TEMP_FAILURE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_SWITCHING_EQUIP_CONGESTION] = GECKO_CALL_ERROR_SWITCHING_EQUIP_CONGESTION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_ACCESS_INFO_DISCARDED] = GECKO_CALL_ERROR_ACCESS_INFO_DISCARDED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_REQUESTED_CHANNEL_NOT_AVAILABLE] = GECKO_CALL_ERROR_REQUESTED_CHANNEL_NOT_AVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_RESOURCE_UNAVAILABLE] = GECKO_CALL_ERROR_RESOURCE_UNAVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_QOS_UNAVAILABLE] = GECKO_CALL_ERROR_QOS_UNAVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_REQUESTED_FACILITY_NOT_SUBSCRIBED] = GECKO_CALL_ERROR_REQUESTED_FACILITY_NOT_SUBSCRIBED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INCOMING_CALLS_BARRED_WITHIN_CUG] = GECKO_CALL_ERROR_INCOMING_CALLS_BARRED_WITHIN_CUG;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BEARER_CAPABILITY_NOT_AUTHORIZED] = GECKO_CALL_ERROR_BEARER_CAPABILITY_NOT_AUTHORIZED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BEARER_CAPABILITY_NOT_AVAILABLE] = GECKO_CALL_ERROR_BEARER_CAPABILITY_NOT_AVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_SERVICE_NOT_AVAILABLE] = GECKO_CALL_ERROR_SERVICE_NOT_AVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BEARER_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_BEARER_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_ACM_LIMIT_EXCEEDED] = GECKO_CALL_ERROR_INCOMING_CALL_EXCEEDED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_REQUESTED_FACILITY_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_REQUESTED_FACILITY_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_UNRESTRICTED_BEARER_NOT_AVAILABLE] = GECKO_CALL_ERROR_UNRESTRICTED_BEARER_NOT_AVAILABLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_SERVICE_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_SERVICE_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INVALID_TRANSACTION_ID] = GECKO_CALL_ERROR_INVALID_TRANSACTION_ID;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_USER_NOT_CUG_MEMBER] = GECKO_CALL_ERROR_USER_NOT_CUG_MEMBER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INCOMPATIBLE_DESTINATION] = GECKO_CALL_ERROR_INCOMPATIBLE_DESTINATION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INVALID_TRANSIT_NETWORK_SELECTION] = GECKO_CALL_ERROR_INVALID_TRANSIT_NETWORK_SELECTION;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_SEMANTICALLY_INCORRECT_MESSAGE] = GECKO_CALL_ERROR_SEMANTICALLY_INCORRECT_MESSAGE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INVALID_MANDATORY_INFO] = GECKO_CALL_ERROR_INVALID_MANDATORY_INFO;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_MESSAGE_TYPE_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_MESSAGE_TYPE_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_MESSAGE_TYPE_INCOMPATIBLE_PROTOCOL_STATE] = GECKO_CALL_ERROR_MESSAGE_TYPE_INCOMPATIBLE_PROTOCOL_STATE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INFO_ELEMENT_NOT_IMPLEMENTED] = GECKO_CALL_ERROR_INFO_ELEMENT_NOT_IMPLEMENTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CONDITIONAL_IE_ERROR] = GECKO_CALL_ERROR_CONDITIONAL_IE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_MESSAGE_INCOMPABITLE_PROTOCOL_STATE] = GECKO_CALL_ERROR_MESSAGE_INCOMPATIBLE_PROTOCOL_STATE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_RECOVERY_ON_TIMER_EXPIRY] = GECKO_CALL_ERROR_RECOVERY_ON_TIMER_EXPIRY;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_PROTOCOL_ERROR] = GECKO_CALL_ERROR_PROTOCOL;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_INTERWORKING] = GECKO_CALL_ERROR_INTERWORKING;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CALL_BARRED] = GECKO_CALL_ERROR_BARRED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_FDN_BLOCKED] = GECKO_CALL_ERROR_FDN_BLOCKED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_IMSI_UNKNOWN_IN_VLR] = GECKO_CALL_ERROR_SUBSCRIBER_UNKNOWN;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_IMEI_NOT_ACCEPTED] = GECKO_CALL_ERROR_DEVICE_NOT_ACCEPTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_DIAL_MODIFIED_TO_USSD] = GECKO_CALL_ERROR_MODIFIED_TO_DIAL_FAILED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_DIAL_MODIFIED_TO_SS] = GECKO_CALL_ERROR_MODIFIED_TO_DIAL_FAILED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_DIAL_MODIFIED_TO_DIAL] = GECKO_CALL_ERROR_MODIFIED_TO_DIAL_FAILED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_LOCKED_UNTIL_POWER_CYCLE] = GECKO_CALL_ERROR_CDMA_LOCKED_UNTIL_POWER_CYCLE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_DROP] = GECKO_CALL_ERROR_CDMA_DROP;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_INTERCEPT] = GECKO_CALL_ERROR_CDMA_INTERCEPT;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_REORDER] = GECKO_CALL_ERROR_CDMA_REORDER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_SO_REJECT] = GECKO_CALL_ERROR_CDMA_SO_REJECT;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_RETRY_ORDER] = GECKO_CALL_ERROR_CDMA_RETRY_ORDER;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_ACCESS_FAILURE] = GECKO_CALL_ERROR_CDMA_ACCESS_FAILURE;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_PREEMPTED] = GECKO_CALL_ERROR_CDMA_PREEMPTED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_NOT_EMERGENCY] = GECKO_CALL_ERROR_CDMA_NOT_EMERGENCY;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CDMA_ACCESS_BLOCKED] = GECKO_CALL_ERROR_CDMA_ACCESS_BLOCKED;
-RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_ERROR_UNSPECIFIED] = GECKO_CALL_ERROR_UNSPECIFIED;
-
-this.GECKO_DATACALL_ERROR_OPERATOR_BARRED = "OperatorBarredError";
-this.GECKO_DATACALL_ERROR_INSUFFICIENT_RESOURCES = "InsufficientResourcesError";
-this.GECKO_DATACALL_ERROR_MISSING_UKNOWN_APN = "MissingUnknownAPNError";
-this.GECKO_DATACALL_ERROR_UNKNOWN_PDP_ADDRESS_TYPE = "UnknownPDPAddressTypeError";
-this.GECKO_DATACALL_ERROR_USER_AUTHENTICATION = "UserAuthenticationError";
-this.GECKO_DATACALL_ERROR_ACTIVATION_REJECT_GGSN = "ActivationRejectGGSNError";
-this.GECKO_DATACALL_ERROR_ACTIVATION_REJECT_UNSPECIFIED = "ActivationRejectUnspecifiedError";
-this.GECKO_DATACALL_ERROR_SERVICE_OPTION_NOT_SUPPORTED = "ServiceOptionNotSupportedError";
-this.GECKO_DATACALL_ERROR_SERVICE_OPTION_NOT_SUBSCRIBED = "ServiceOptionNotSubscribedError";
-this.GECKO_DATACALL_ERROR_SERVICE_OPTION_OUT_OF_ORDER = "ServiceOptionOutOfOrderError";
-this.GECKO_DATACALL_ERROR_NSAPI_IN_USE = "NSAPIInUseError";
-this.GECKO_DATACALL_ERROR_ONLY_IPV4_ALLOWED = "OnlyIPv4Error";
-this.GECKO_DATACALL_ERROR_ONLY_IPV6_ALLOWED = "OnlyIPv6Error";
-this.GECKO_DATACALL_ERROR_ONLY_SINGLE_BEARER_ALLOWED = "OnlySingleBearerAllowedError";
-this.GECKO_DATACALL_ERROR_PROTOCOL_ERRORS = "ProtocolErrorsError";
-this.GECKO_DATACALL_ERROR_VOICE_REGISTRATION_FAIL = "VoiceRegistrationFailError";
-this.GECKO_DATACALL_ERROR_DATA_REGISTRATION_FAIL = "DataRegistrationFailError";
-this.GECKO_DATACALL_ERROR_SIGNAL_LOST = "SignalLostError";
-this.GECKO_DATACALL_ERROR_PREF_RADIO_TECH_CHANGED = "PrefRadioTechChangedError";
-this.GECKO_DATACALL_ERROR_RADIO_POWER_OFF = "RadioPowerOffError";
-this.GECKO_DATACALL_ERROR_TETHERED_CALL_ACTIVE = "TetheredCallActiveError";
-this.GECKO_DATACALL_ERROR_UNSPECIFIED = "UnspecifiedError";
-
-this.RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR = {};
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_OPERATOR_BARRED] = GECKO_DATACALL_ERROR_OPERATOR_BARRED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_INSUFFICIENT_RESOURCES] = GECKO_DATACALL_ERROR_INSUFFICIENT_RESOURCES;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_MISSING_UKNOWN_APN] = GECKO_DATACALL_ERROR_MISSING_UKNOWN_APN;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_UNKNOWN_PDP_ADDRESS_TYPE] = GECKO_DATACALL_ERROR_UNKNOWN_PDP_ADDRESS_TYPE;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_USER_AUTHENTICATION] = GECKO_DATACALL_ERROR_USER_AUTHENTICATION;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ACTIVATION_REJECT_GGSN] = GECKO_DATACALL_ERROR_ACTIVATION_REJECT_GGSN;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ACTIVATION_REJECT_UNSPECIFIED] = GECKO_DATACALL_ERROR_ACTIVATION_REJECT_UNSPECIFIED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_SERVICE_OPTION_NOT_SUPPORTED] = GECKO_DATACALL_ERROR_SERVICE_OPTION_NOT_SUPPORTED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED] = GECKO_DATACALL_ERROR_SERVICE_OPTION_NOT_SUBSCRIBED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_SERVICE_OPTION_OUT_OF_ORDER] = GECKO_DATACALL_ERROR_SERVICE_OPTION_OUT_OF_ORDER;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_NSAPI_IN_USE] = GECKO_DATACALL_ERROR_NSAPI_IN_USE;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ONLY_IPV4_ALLOWED] = GECKO_DATACALL_ERROR_ONLY_IPV4_ALLOWED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ONLY_IPV6_ALLOWED] = GECKO_DATACALL_ERROR_ONLY_IPV6_ALLOWED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ONLY_SINGLE_BEARER_ALLOWED] = GECKO_DATACALL_ERROR_ONLY_SINGLE_BEARER_ALLOWED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_PROTOCOL_ERRORS] = GECKO_DATACALL_ERROR_PROTOCOL_ERRORS;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_VOICE_REGISTRATION_FAIL] = GECKO_DATACALL_ERROR_VOICE_REGISTRATION_FAIL;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_DATA_REGISTRATION_FAIL] = GECKO_DATACALL_ERROR_DATA_REGISTRATION_FAIL;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_SIGNAL_LOST] = GECKO_DATACALL_ERROR_SIGNAL_LOST;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_PREF_RADIO_TECH_CHANGED] = GECKO_DATACALL_ERROR_PREF_RADIO_TECH_CHANGED;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_RADIO_POWER_OFF] = GECKO_DATACALL_ERROR_RADIO_POWER_OFF;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_TETHERED_CALL_ACTIVE] = GECKO_DATACALL_ERROR_TETHERED_CALL_ACTIVE;
-RIL_DATACALL_FAILCAUSE_TO_GECKO_DATACALL_ERROR[DATACALL_FAIL_ERROR_UNSPECIFIED] = GECKO_DATACALL_ERROR_UNSPECIFIED;
-
-this.GECKO_RADIO_TECH = [
- null,
- "gprs",
- "edge",
- "umts",
- "is95a",
- "is95b",
- "1xrtt",
- "evdo0",
- "evdoa",
- "hsdpa",
- "hsupa",
- "hspa",
- "evdob",
- "ehrpd",
- "lte",
- "hspa+",
- "gsm",
- null,
- "hspa+", // DC-HSPA+
- "hspa+"
-];
-
-this.GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN = -1;
-
-// Call forwarding action. Must be in sync with nsIMobileConnectionService interface
-this.CALL_FORWARD_ACTION_DISABLE = 0;
-this.CALL_FORWARD_ACTION_ENABLE = 1;
-this.CALL_FORWARD_ACTION_QUERY_STATUS = 2;
-this.CALL_FORWARD_ACTION_REGISTRATION = 3;
-this.CALL_FORWARD_ACTION_ERASURE = 4;
-
-// Call forwarding reason. Must be in sync with nsIMobileConnectionService interface
-this.CALL_FORWARD_REASON_UNCONDITIONAL = 0;
-this.CALL_FORWARD_REASON_MOBILE_BUSY = 1;
-this.CALL_FORWARD_REASON_NO_REPLY = 2;
-this.CALL_FORWARD_REASON_NOT_REACHABLE = 3;
-this.CALL_FORWARD_REASON_ALL_CALL_FORWARDING = 4;
-this.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING = 5;
-
-// Call barring program. Must be in sync with nsIMobileConnectionService interface
-this.CALL_BARRING_PROGRAM_ALL_OUTGOING = 0;
-this.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL = 1;
-this.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME = 2;
-this.CALL_BARRING_PROGRAM_ALL_INCOMING = 3;
-this.CALL_BARRING_PROGRAM_INCOMING_ROAMING = 4;
-this.CALL_BARRING_PROGRAM_ALL_SERVICE = 5;
-this.CALL_BARRING_PROGRAM_OUTGOING_SERVICE = 6;
-this.CALL_BARRING_PROGRAM_INCOMING_SERVICE = 7;
-
-this.CALL_BARRING_PROGRAM_TO_FACILITY = {};
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_ALL_OUTGOING] = ICC_CB_FACILITY_BAOC;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL] = ICC_CB_FACILITY_BAOIC;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME] = ICC_CB_FACILITY_BAOICxH;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_ALL_INCOMING] = ICC_CB_FACILITY_BAIC;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_INCOMING_ROAMING] = ICC_CB_FACILITY_BAICr;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_ALL_SERVICE] = ICC_CB_FACILITY_BA_ALL;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_OUTGOING_SERVICE] = ICC_CB_FACILITY_BA_MO;
-CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_INCOMING_SERVICE] = ICC_CB_FACILITY_BA_MT;
-
-/**
- * CDMA PDU constants
- */
-
-// SMS Message Type, as defined in 3GPP2 C.S0015-A v2.0, Table 3.4-1
-this.PDU_CDMA_MSG_TYPE_P2P = 0x00; // Point-to-Point
-this.PDU_CDMA_MSG_TYPE_BROADCAST = 0x01; // Broadcast
-this.PDU_CDMA_MSG_TYPE_ACK = 0x02; // Acknowledge
-
-// SMS Teleservice Identitifier, as defined in 3GPP2 N.S0005, Table 175
-this.PDU_CDMA_MSG_TELESERIVCIE_ID_SMS = 0x1002; // SMS
-this.PDU_CDMA_MSG_TELESERIVCIE_ID_WAP = 0x1004; // WAP
-this.PDU_CDMA_MSG_TELESERIVCIE_ID_WEMT = 0x1005; // Wireless Enhanced Messaging Teleservice
- // required for fragmented SMS
-
-// SMS Service Category, as defined in 3GPP2 C.R1001-D, Table 9.3.1-1
-this.PDU_CDMA_MSG_CATEGORY_UNSPEC = 0x00; // Unknown/Unspecified
-
-// Address Information, Digit Mode, as defined in 3GPP2 C.S0015-A v2.0, sec 3.4.3.3
-this.PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF = 0x00; // Digit Mode : DTMF
-this.PDU_CDMA_MSG_ADDR_DIGIT_MODE_ASCII = 0x01; // Digit Mode : 8-bit ASCII with MSB = 0
-
-// Address Information, Number Mode, as defined in 3GPP2 C.S0015-A v2.0, sec 3.4.3.3
-this.PDU_CDMA_MSG_ADDR_NUMBER_MODE_ANSI = 0x00; // Number Mode : ANSI T1.607-2000(R2004)
-this.PDU_CDMA_MSG_ADDR_NUMBER_MODE_ASCII = 0x01; // Number Mode : Data network address format
-
-// Address Information, Number Type, as defined in 3GPP2 C.S0015-A v2.0, Table 3.4.3.3-1
-this.PDU_CDMA_MSG_ADDR_NUMBER_TYPE_UNKNOWN = 0x00; // Number Type : Unknown
-this.PDU_CDMA_MSG_ADDR_NUMBER_TYPE_INTERNATIONAL = 0x01; // Number Type : Internaltional number(+XXXXX)
-this.PDU_CDMA_MSG_ADDR_NUMBER_TYPE_NATIONAL = 0x02; // Number Type : National number
-
-// Address Information, Number Plan, as defined in 3GPP2 C.S0005-D v2.0, Table 2.7.1.3.2.4-3
-this.PDU_CDMA_MSG_ADDR_NUMBER_PLAN_UNKNOWN = 0x00; // Number Plan : Unknown
-this.PDU_CDMA_MSG_ADDR_NUMBER_PLAN_ISDN = 0x01; // Number Plan : ISDN/Telephony numbering plan
-
-// SMS Encoding, as defined in 3GPP2 C.R1001-D, Table 9.1-1
-this.PDU_CDMA_MSG_CODING_OCTET = 0x00; // octet(8-bit), Not tested
-this.PDU_CDMA_MSG_CODING_IS_91 = 0x01; // IS-91 Extended Protocol Message(variable), Not tested
-this.PDU_CDMA_MSG_CODING_7BITS_ASCII = 0x02; // 7-bit ASCII(7-bit)
-this.PDU_CDMA_MSG_CODING_IA5 = 0x03; // IA5(7-bit), Not tested
-this.PDU_CDMA_MSG_CODING_UNICODE = 0x04; // Unicode(16-bit)
-this.PDU_CDMA_MSG_CODING_SHIFT_JIS = 0x05; // Shift-6 JIS(8/16-bit variable), Not supported
-this.PDU_CDMA_MSG_CODING_KOREAN = 0x06; // Korean(8/16-bit variable), Not supported
-this.PDU_CDMA_MSG_CODING_LATIN_HEBREW = 0x07; // Latin/ Hebrew(8-bit), ISO/IEC 8859-8, Not supported
-this.PDU_CDMA_MSG_CODING_LATIN = 0x08; // Latin(8-bit), ISO/IEC 8859-1, Not tested
-this.PDU_CDMA_MSG_CODING_7BITS_GSM = 0x09; // GSM 7-bit default alphabet(7-bit), Not tested
-this.PDU_CDMA_MSG_CODING_GSM_DCS = 0x0A; // GSM Data-Coding-Scheme, Not supported
-
-// SMS Message Type, as defined in 3GPP2 C.S0015-A v2.0, Table 4.5.1-1
-this.PDU_CDMA_MSG_TYPE_DELIVER = 0x01; // Deliver
-this.PDU_CDMA_MSG_TYPE_SUBMIT = 0x02; // Submit
-this.PDU_CDMA_MSG_TYPE_DELIVER_ACK = 0x04; // Delivery Acknowledgment
-
-// SMS User Data Subparameters, as defined in 3GPP2 C.S0015-A v2.0, Table 4.5-1
-this.PDU_CDMA_MSG_USERDATA_MSG_ID = 0x00; // Message Identifier
-this.PDU_CDMA_MSG_USERDATA_BODY = 0x01; // User Data Body
-this.PDU_CDMA_MSG_USERDATA_TIMESTAMP = 0x03; // Message Center Time Stamp
-this.PDU_CDMA_MSG_USERDATA_REPLY_OPTION = 0x0A; // Reply Option
-this.PDU_CDMA_LANGUAGE_INDICATOR = 0x0D; // Language Indicator
-this.PDU_CDMA_MSG_USERDATA_CALLBACK_NUMBER = 0x0E; // Callback Number
-this.PDU_CDMA_MSG_USER_DATA_MSG_STATUS = 0x14; // Message Status
-
-// CDMA Language Indicator: Language groups
-// see 3GPP2 C.R1001-F table 9.2-1
-this.CB_CDMA_LANG_GROUP = [
- null, "en", "fr", "es", "ja", "ko", "zh", "he"
-];
-
-// IS-91 Message Type, as defined in TIA/EIA/IS-91-A, Table 9
-this.PDU_CDMA_MSG_CODING_IS_91_TYPE_VOICEMAIL_STATUS = 0x82;
-this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS_FULL = 0x83;
-this.PDU_CDMA_MSG_CODING_IS_91_TYPE_CLI = 0x84;
-this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS = 0x85;
-
-// Information Record Type, reference from ril.h
-this.PDU_CDMA_INFO_REC_TYPE_DISPLAY = 0;
-this.PDU_CDMA_INFO_REC_TYPE_CALLED_PARTY_NUMBER = 1;
-this.PDU_CDMA_INFO_REC_TYPE_CALLING_PARTY_NUMBER = 2;
-this.PDU_CDMA_INFO_REC_TYPE_CONNECTED_NUMBER =3;
-this.PDU_CDMA_INFO_REC_TYPE_SIGNAL = 4;
-this.PDU_CDMA_INFO_REC_TYPE_REDIRECTING_NUMBER = 5;
-this.PDU_CDMA_INFO_REC_TYPE_LINE_CONTROL = 6;
-this.PDU_CDMA_INFO_REC_TYPE_EXTENDED_DISPLAY = 7;
-this.PDU_CDMA_INFO_REC_TYPE_T53_CLIR = 8;
-this.PDU_CDMA_INFO_REC_TYPE_T53_RELEASE = 9;
-this.PDU_CDMA_INFO_REC_TYPE_T53_AUDIO_CONTROL = 10;
-
-// Display type of extended display of information record,
-// as defined in C.S0005-F v1.0, Table 3.7.5.16-2
-this.INFO_REC_EXTENDED_DISPLAY_BLANK = 0x80;
-this.INFO_REC_EXTENDED_DISPLAY_SKIP = 0x81;
-this.INFO_REC_EXTENDED_DISPLAY_CONTINATION = 0x82;
-this.INFO_REC_EXTENDED_DISPLAY_CALLED_ADDRESS = 0x83;
-this.INFO_REC_EXTENDED_DISPLAY_CAUSE = 0x84;
-this.INFO_REC_EXTENDED_DISPLAY_PROGRESS_INDICATOR = 0x85;
-this.INFO_REC_EXTENDED_DISPLAY_NOTIFICATION_INDICATOR = 0x86;
-this.INFO_REC_EXTENDED_DISPLAY_PROMPT = 0x87;
-this.INFO_REC_EXTENDED_DISPLAY_ACCUMULATED_DIGITS = 0x88;
-this.INFO_REC_EXTENDED_DISPLAY_STATUS = 0x89;
-this.INFO_REC_EXTENDED_DISPLAY_INBAND = 0x8A;
-this.INFO_REC_EXTENDED_DISPLAY_CALLING_ADDRESS = 0x8B;
-this.INFO_REC_EXTENDED_DISPLAY_REASON = 0x8C;
-this.INFO_REC_EXTENDED_DISPLAY_CALLING_PARTY_NAME = 0x8D;
-this.INFO_REC_EXTENDED_DISPLAY_CALLED_PARTY_NAME = 0x8E;
-this.INFO_REC_EXTENDED_DISPLAY_ORIGINAL_CALLED_NAME = 0x8F;
-this.INFO_REC_EXTENDED_DISPLAY_REDIRECT_NAME = 0x90;
-this.INFO_REC_EXTENDED_DISPLAY_CONNECTED_NAME = 0x91;
-this.INFO_REC_EXTENDED_DISPLAY_ORIGINATING_RESTRICTIONS = 0x92;
-this.INFO_REC_EXTENDED_DISPLAY_DATE_TIME_OF_DAY = 0x93;
-this.INFO_REC_EXTENDED_DISPLAY_CALL_APPEARANCE_ID = 0x94;
-this.INFO_REC_EXTENDED_DISPLAY_FEATURE_ADDRESS = 0x95;
-this.INFO_REC_EXTENDED_DISPLAY_REDIRECTION_NAME = 0x96;
-this.INFO_REC_EXTENDED_DISPLAY_REDIRECTION_NUMBER = 0x97;
-this.INFO_REC_EXTENDED_DISPLAY_REDIRECTING_NUMBER = 0x98;
-this.INFO_REC_EXTENDED_DISPLAY_ORIGINAL_CALLED_NUMBER = 0x99;
-this.INFO_REC_EXTENDED_DISPLAY_CONNECTED_NUMBER = 0x9A;
-this.INFO_REC_EXTENDED_DISPLAY_TEXT = 0x9B;
-
-/**
- * The table for MCC/MNC which the length of MNC is 3.
- *
- * This table is built from below links.
- * - http://www.itu.int/pub/T-SP-E.212B-2013
- * - http://en.wikipedia.org/wiki/Mobile_Network_Code
- */
-this.PLMN_HAVING_3DIGITS_MNC = {
- // Puerto Rico.
- "330":
- ["110", // América Móvil
- "120" // PR Wireless
- ],
- // Trinidad and Tobago.
- "374":
- ["130", // Digicel Trinidad and Tobago Ltd.
- "140" // LaqTel Ltd.
- ],
- // India.
- "405":
- ["000", // Shyam Telelink Ltd.
- "005", // Reliance, Delhi
- "006", // Reliance, Gujarat
- "007", // Reliance, Haryana
- "009", // Reliance, J&K
- "010", // Reliance, Karnataka
- "011", // Reliance, Kerala
- "012", // Reliance, Andhra Pradesh
- "013", // Reliance, Maharashtr
- "014", // Reliance, Madhya Pradesh
- "018", // Reliance, Punjab
- "020", // Reliance, Tamilnadu
- "021", // Reliance, UP (East)
- "022", // Reliance, UP (West)
- "025", // TATA DOCOMO, Andhra Pradesh
- "026", // TATA DOCOMO, Assam
- "027", // TATA DOCOMO, Bihar
- "028", // TATA DOCOMO, Chennai
- "029", // TATA DOCOMO, Delhi
- "030", // TATA DOCOMO, Gujarat
- "031", // TATA DOCOMO, Haryana
- "032", // TATA DOCOMO, Himachal Pradesh
- "033", // Reliance, Bihar
- "034", // TATA DOCOMO, Kamataka
- "035", // TATA DOCOMO, Kerala
- "036", // TATA DOCOMO, Kolkata
- "037", // TATA DOCOMO, Maharashtra
- "038", // TATA DOCOMO, Madhya Pradesh
- "039", // TATA DOCOMO, Mumbai
- "040", // Reliance, Chennai
- "041", // TATA DOCOMO, Orissa
- "042", // TATA DOCOMO, Punjab
- "043", // TATA DOCOMO, Rajasthan
- "044", // TATA DOCOMO, Tamilnadu
- "045", // TATA DOCOMO, UP (East)
- "046", // TATA DOCOMO, UP (West)
- "047", // TATA DOCOMO, West Bengal
- "750", // Vodafone IN, J&K
- "751", // Vodafone IN, Assam
- "752", // Vodafone IN, Bihar
- "753", // Vodafone IN, Orissa
- "754", // Vodafone IN, Himachal Pradesh
- "755", // Vodafone IN, North East
- "756", // Vodafone IN, Madhya Pradesh & Chhattisgarh
- "799", // Idea, MUMBAI
- "800", // Aircell, Delhi
- "801", // Aircell, Andhra Pradesh
- "802", // Aircell, Gujarat
- "803", // Aircell, Kamataka
- "804", // Aircell, Maharashtra
- "805", // Aircell, Mumbai
- "806", // Aircell, Rajasthan
- "807", // Aircell, Haryana
- "808", // Aircell, Madhya Pradesh
- "809", // Aircell, Kerala
- "810", // Aircell, Uttar Pradesh (East)
- "811", // Aircell, Uttar Pradesh (West)
- "812", // Aircell, Punjab
- "818", // Uninor, Uttar Pradesh (West)
- "819", // Uninor, Andhra Pradesh
- "820", // Uninor, Karnataka
- "821", // Uninor, Kerala
- "822", // Uninor, Kolkata
- "824", // Videocon, Assam
- "827", // Videocon, Gujarat
- "834", // Videocon, Madhya Pradesh
- "840", // Jio, West Bengal
- "844", // Uninor, Delhi & NCR
- "845", // IDEA, Assam
- "846", // IDEA, Jammu & Kashmir
- "847", // IDEA, Karnataka
- "848", // IDEA, Kolkata
- "849", // IDEA, North East
- "850", // IDEA, Orissa
- "851", // IDEA, Punjab
- "852", // IDEA, Tamil Nadu
- "853", // IDEA, West Bengal
- "854", // Jio, Andra Pradesh
- "855", // Jio, Assam
- "856", // Jio, Bihar
- "857", // Jio, Gujarat
- "858", // Jio, Haryana
- "859", // Jio, Himachal Pradesh
- "860", // Jio, Jammu Kashmir
- "861", // Jio, Karnataka
- "862", // Jio, Kerala
- "863", // Jio, Madhyya Pradesh
- "864", // Jio, Maharashtra
- "865", // Jio, North East
- "866", // Jio, Orissa
- "867", // Jio, Punjab
- "868", // Jio, Rajasthan
- "869", // Jio, Tamil Nadu Chennai
- "870", // Jio, Uttar Pradesh West
- "871", // Jio, Uttar Pradesh East
- "872", // Jio, Delhi
- "873", // Jio, Kolkatta
- "874", // Jio, Mumbai
- "875", // Uninor, Assam
- "880", // Uninor, West Bengal
- "881", // S Tel, Assam
- "908", // IDEA, Andhra Pradesh
- "909", // IDEA, Delhi
- "910", // IDEA, Haryana
- "911", // Etisalat, Maharashtra
- "912", // Etisalat, Andhra Pradesh
- "913", // Etisalat, Delhi & NCR
- "914", // Etisalat, Gujarat
- "917", // Etisalat, Kerala
- "927", // Uninor, Gujarat
- "929" // Uninor, Maharashtra
- ],
- // Malaysia.
- "502":
- ["150", // Tune Talk Sdn Bhd
- "151", // Baraka Telecom Sdn Bhd (MVNE)
- "152", // YTL Communications Sdn Bhd
- "156" // Altel Communications Sdn Bhd
- ],
- // Brazil.
- "724":
- ["055" // Sercomtel
- ]
-};
-
-/**
- * The table for MCC which the length of MNC is 3
- *
- * This table is built from below links.
- * - http://www.itu.int/pub/T-SP-E.212B-2013
- * - http://en.wikipedia.org/wiki/Mobile_Network_Code
- */
-this.MCC_TABLE_FOR_MNC_LENGTH_IS_3 = [
- "302", // Canada
- "310", // United States of America
- "311", // United States of America
- "312", // United States of America
- "313", // United States of America
- "316", // United States of America
- "330", // Puerto Rico
- "334", // Mexico
- "338", // Jamaica
- "342", // Barbados
- "344", // Antigua and Barbuda
- "346", // Cayman Islands
- "348", // British Virgin Islands
- "350", // Bermuda
- "352", // Grenada
- "354", // Montserrat
- "356", // Saint Kitts and Nevis
- "358", // Saint Lucia
- "360", // Saint Vincent and the Grenadines
- "365", // Anguilla
- "366", // Dominica
- "376", // Turks and Caicos Islands
- "708", // Honduras
- "722", // Argentina
- "732", // Colombia
- "750" // Falkland Islands (Malvinas)
-];
-
-// Supplementary service notifications, code2, as defined in 3GPP 27.007 7.17
-this.SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD = 2;
-this.SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED = 3;
-
-this.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD = "RemoteHeld";
-this.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED = "RemoteResumed";
-
-this.GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2 = {};
-GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2[SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD] = GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD;
-GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2[SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED] = GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED;
-
-/**
- * The status for an Over-the-Air Service Provisioning / Over-the-Air
- * Parameter Administration (OTASP/OTAPA) session.
- *
- * @see 3GPP2 C.S0016
- */
-this.GECKO_OTA_STATUS_SPL_UNLOCKED = "spl_unlocked";
-this.GECKO_OTA_STATUS_SPC_RETRIES_EXCEEDED = "spc_retries_exceeded";
-this.GECKO_OTA_STATUS_A_KEY_EXCHANGED = "a_key_exchanged";
-this.GECKO_OTA_STATUS_SSD_UPDATED = "ssd_updated";
-this.GECKO_OTA_STATUS_NAM_DOWNLOADED = "nam_downloaded";
-this.GECKO_OTA_STATUS_MDN_DOWNLOADED = "mdn_downloaded";
-this.GECKO_OTA_STATUS_IMSI_DOWNLOADED = "imsi_downloaded";
-this.GECKO_OTA_STATUS_PRL_DOWNLOADED = "prl_downloaded";
-this.GECKO_OTA_STATUS_COMMITTED = "committed";
-this.GECKO_OTA_STATUS_OTAPA_STARTED = "otapa_started";
-this.GECKO_OTA_STATUS_OTAPA_STOPPED = "otapa_stopped";
-this.GECKO_OTA_STATUS_OTAPA_ABORTED = "otapa_aborted";
-this.CDMA_OTA_PROVISION_STATUS_TO_GECKO = [
- GECKO_OTA_STATUS_SPL_UNLOCKED,
- GECKO_OTA_STATUS_SPC_RETRIES_EXCEEDED,
- GECKO_OTA_STATUS_A_KEY_EXCHANGED,
- GECKO_OTA_STATUS_SSD_UPDATED,
- GECKO_OTA_STATUS_NAM_DOWNLOADED,
- GECKO_OTA_STATUS_MDN_DOWNLOADED,
- GECKO_OTA_STATUS_IMSI_DOWNLOADED,
- GECKO_OTA_STATUS_PRL_DOWNLOADED,
- GECKO_OTA_STATUS_COMMITTED,
- GECKO_OTA_STATUS_OTAPA_STARTED,
- GECKO_OTA_STATUS_OTAPA_STOPPED,
- GECKO_OTA_STATUS_OTAPA_ABORTED
-];
-
-// Allow this file to be imported via Components.utils.import().
-this.EXPORTED_SYMBOLS = Object.keys(this);
diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js
deleted file mode 100644
index 0608a5be3..000000000
--- a/dom/system/gonk/ril_worker.js
+++ /dev/null
@@ -1,15206 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * This file implements the RIL worker thread. It communicates with
- * the main thread to provide a high-level API to the phone's RIL
- * stack, and with the RIL IPC thread to communicate with the RIL
- * device itself. These communication channels use message events as
- * known from Web Workers:
- *
- * - postMessage()/"message" events for main thread communication
- *
- * - postRILMessage()/"RILMessageEvent" events for RIL IPC thread
- * communication.
- *
- * The two main objects in this file represent individual parts of this
- * communication chain:
- *
- * - RILMessageEvent -> Buf -> RIL -> postMessage() -> nsIRadioInterfaceLayer
- * - nsIRadioInterfaceLayer -> postMessage() -> RIL -> Buf -> postRILMessage()
- *
- * Note: The code below is purposely lean on abstractions to be as lean in
- * terms of object allocations. As a result, it may look more like C than
- * JavaScript, and that's intended.
- */
-
-/* global BufObject */
-/* global TelephonyRequestQueue */
-
-"use strict";
-
-importScripts("ril_consts.js");
-importScripts("resource://gre/modules/workers/require.js");
-importScripts("ril_worker_buf_object.js");
-importScripts("ril_worker_telephony_request_queue.js");
-
-// set to true in ril_consts.js to see debug messages
-var DEBUG = DEBUG_WORKER;
-var GLOBAL = this;
-
-if (!this.debug) {
- // Debugging stub that goes nowhere.
- this.debug = function debug(message) {
- dump("RIL Worker: " + message + "\n");
- };
-}
-
-// Timeout value for emergency callback mode.
-const EMERGENCY_CB_MODE_TIMEOUT_MS = 300000; // 5 mins = 300000 ms.
-
-const ICC_MAX_LINEAR_FIXED_RECORDS = 0xfe;
-
-const GET_CURRENT_CALLS_RETRY_MAX = 3;
-
-var RILQUIRKS_CALLSTATE_EXTRA_UINT32;
-var RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL;
-var RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS;
-var RILQUIRKS_SIGNAL_EXTRA_INT32;
-var RILQUIRKS_AVAILABLE_NETWORKS_EXTRA_STRING;
-// Needed for call-waiting on Peak device
-var RILQUIRKS_EXTRA_UINT32_2ND_CALL;
-// On the emulator we support querying the number of lock retries
-var RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT;
-// Ril quirk to Send STK Profile Download
-var RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD;
-// Ril quirk to attach data registration on demand.
-var RILQUIRKS_DATA_REGISTRATION_ON_DEMAND;
-// Ril quirk to control the uicc/data subscription.
-var RILQUIRKS_SUBSCRIPTION_CONTROL;
-// Ril quirk to describe the SMSC address format.
-var RILQUIRKS_SMSC_ADDRESS_FORMAT;
-
-/**
- * The RIL state machine.
- *
- * This object communicates with rild via parcels and with the main thread
- * via post messages. It maintains state about the radio, ICC, calls, etc.
- * and acts upon state changes accordingly.
- */
-function RilObject(aContext) {
- this.context = aContext;
-
- this.telephonyRequestQueue = new TelephonyRequestQueue(this);
- this.currentConferenceState = CALL_STATE_UNKNOWN;
- this._pendingSentSmsMap = {};
- this.pendingNetworkType = {};
- this._receivedSmsCbPagesMap = {};
- this._getCurrentCallsRetryCount = 0;
-}
-RilObject.prototype = {
- context: null,
-
- /**
- * RIL version.
- */
- version: null,
-
- /**
- * Call state of current conference group.
- */
- currentConferenceState: null,
-
- /**
- * Outgoing messages waiting for SMS-STATUS-REPORT.
- */
- _pendingSentSmsMap: null,
-
- /**
- * Marker object.
- */
- pendingNetworkType: null,
-
- /**
- * Global Cell Broadcast switch.
- */
- cellBroadcastDisabled: false,
-
- /**
- * Parsed Cell Broadcast search lists.
- * cellBroadcastConfigs.MMI should be preserved over rild reset.
- */
- cellBroadcastConfigs: null,
- mergedCellBroadcastConfig: null,
-
- _receivedSmsCbPagesMap: null,
-
- initRILState: function() {
- /**
- * One of the RADIO_STATE_* constants.
- */
- this.radioState = GECKO_RADIOSTATE_UNKNOWN;
-
- /**
- * True if we are on a CDMA phone.
- */
- this._isCdma = false;
-
- /**
- * True if we are in emergency callback mode.
- */
- this._isInEmergencyCbMode = false;
-
- /**
- * Set when radio is ready but radio tech is unknown. That is, we are
- * waiting for REQUEST_VOICE_RADIO_TECH
- */
- this._waitingRadioTech = false;
-
- /**
- * Card state
- */
- this.cardState = GECKO_CARDSTATE_UNINITIALIZED;
-
- /**
- * Device Identities including IMEI, IMEISV, ESN and MEID.
- */
- this.deviceIdentities = null;
-
- /**
- * ICC information that is not exposed to Gaia.
- */
- this.iccInfoPrivate = {};
-
- /**
- * ICC information, such as MSISDN, MCC, MNC, SPN...etc.
- */
- this.iccInfo = {};
-
- /**
- * CDMA specific information. ex. CDMA Network ID, CDMA System ID... etc.
- */
- this.cdmaHome = null;
-
- /**
- * Application identification for apps in ICC.
- */
- this.aid = null;
-
- /**
- * Application type for apps in ICC.
- */
- this.appType = null;
-
- this.networkSelectionMode = GECKO_NETWORK_SELECTION_UNKNOWN;
-
- this.voiceRegistrationState = {};
- this.dataRegistrationState = {};
-
- /**
- * List of strings identifying the network operator.
- */
- this.operator = null;
-
- /**
- * String containing the baseband version.
- */
- this.basebandVersion = null;
-
- // Clean up currentCalls: rild might have restarted.
- this.sendChromeMessage({
- rilMessageType: "currentCalls",
- calls: {}
- });
-
- // Don't clean up this._pendingSentSmsMap
- // because on rild restart: we may continue with the pending segments.
-
- /**
- * Whether or not the multiple requests in requestNetworkInfo() are currently
- * being processed
- */
- this._processingNetworkInfo = false;
-
- /**
- * Multiple requestNetworkInfo() in a row before finishing the first
- * request, hence we need to fire requestNetworkInfo() again after
- * gathering all necessary stuffs. This is to make sure that ril_worker
- * gets precise network information.
- */
- this._needRepollNetworkInfo = false;
-
- /**
- * Pending messages to be send in batch from requestNetworkInfo()
- */
- this._pendingNetworkInfo = {rilMessageType: "networkinfochanged"};
-
- /**
- * Cell Broadcast Search Lists.
- */
- let cbmmi = this.cellBroadcastConfigs && this.cellBroadcastConfigs.MMI;
- this.cellBroadcastConfigs = {
- MMI: cbmmi || null
- };
- this.mergedCellBroadcastConfig = null;
-
- /**
- * True when the request to report SMS Memory Status is pending.
- */
- this.pendingToReportSmsMemoryStatus = false;
- this.smsStorageAvailable = true;
- },
-
- /**
- * Parse an integer from a string, falling back to a default value
- * if the the provided value is not a string or does not contain a valid
- * number.
- *
- * @param string
- * String to be parsed.
- * @param defaultValue [optional]
- * Default value to be used.
- * @param radix [optional]
- * A number that represents the numeral system to be used. Default 10.
- */
- parseInt: function(string, defaultValue, radix) {
- let number = parseInt(string, radix || 10);
- if (!isNaN(number)) {
- return number;
- }
- if (defaultValue === undefined) {
- defaultValue = null;
- }
- return defaultValue;
- },
-
-
- /**
- * Outgoing requests to the RIL. These can be triggered from the
- * main thread via messages that look like this:
- *
- * {rilMessageType: "methodName",
- * extra: "parameters",
- * go: "here"}
- *
- * So if one of the following methods takes arguments, it takes only one,
- * an object, which then contains all of the parameters as attributes.
- * The "@param" documentation is to be interpreted accordingly.
- */
-
- /**
- * Retrieve the ICC's status.
- */
- getICCStatus: function() {
- this.context.Buf.simpleRequest(REQUEST_GET_SIM_STATUS);
- },
-
- /**
- * Helper function for unlocking ICC locks.
- */
- iccUnlockCardLock: function(options) {
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN:
- this.enterICCPIN(options);
- break;
- case GECKO_CARDLOCK_PIN2:
- this.enterICCPIN2(options);
- break;
- case GECKO_CARDLOCK_PUK:
- this.enterICCPUK(options);
- break;
- case GECKO_CARDLOCK_PUK2:
- this.enterICCPUK2(options);
- break;
- case GECKO_CARDLOCK_NCK:
- case GECKO_CARDLOCK_NSCK:
- case GECKO_CARDLOCK_NCK1:
- case GECKO_CARDLOCK_NCK2:
- case GECKO_CARDLOCK_HNCK:
- case GECKO_CARDLOCK_CCK:
- case GECKO_CARDLOCK_SPCK:
- case GECKO_CARDLOCK_PCK:
- case GECKO_CARDLOCK_RCCK:
- case GECKO_CARDLOCK_RSPCK:
- case GECKO_CARDLOCK_NCK_PUK:
- case GECKO_CARDLOCK_NSCK_PUK:
- case GECKO_CARDLOCK_NCK1_PUK:
- case GECKO_CARDLOCK_NCK2_PUK:
- case GECKO_CARDLOCK_HNCK_PUK:
- case GECKO_CARDLOCK_CCK_PUK:
- case GECKO_CARDLOCK_SPCK_PUK:
- case GECKO_CARDLOCK_PCK_PUK:
- case GECKO_CARDLOCK_RCCK_PUK: // Fall through.
- case GECKO_CARDLOCK_RSPCK_PUK:
- this.enterDepersonalization(options);
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- }
- },
-
- /**
- * Enter a PIN to unlock the ICC.
- *
- * @param password
- * String containing the PIN.
- * @param [optional] aid
- * AID value.
- */
- enterICCPIN: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_SIM_PIN, options);
- Buf.writeInt32(2);
- Buf.writeString(options.password);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Enter a PIN2 to unlock the ICC.
- *
- * @param password
- * String containing the PIN2.
- * @param [optional] aid
- * AID value.
- */
- enterICCPIN2: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_SIM_PIN2, options);
- Buf.writeInt32(2);
- Buf.writeString(options.password);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Requests a network personalization be deactivated.
- *
- * @param personlization
- * One of CARD_PERSOSUBSTATE_*
- * @param password
- * String containing the password.
- */
- enterDepersonalization: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE, options);
- Buf.writeInt32(1);
- Buf.writeString(options.password);
- Buf.sendParcel();
- },
-
- /**
- * Change the current ICC PIN number.
- *
- * @param password
- * String containing the old PIN value
- * @param newPassword
- * String containing the new PIN value
- * @param [optional] aid
- * AID value.
- */
- changeICCPIN: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CHANGE_SIM_PIN, options);
- Buf.writeInt32(3);
- Buf.writeString(options.password);
- Buf.writeString(options.newPassword);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Change the current ICC PIN2 number.
- *
- * @param password
- * String containing the old PIN2 value
- * @param newPassword
- * String containing the new PIN2 value
- * @param [optional] aid
- * AID value.
- */
- changeICCPIN2: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CHANGE_SIM_PIN2, options);
- Buf.writeInt32(3);
- Buf.writeString(options.password);
- Buf.writeString(options.newPassword);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Supplies ICC PUK and a new PIN to unlock the ICC.
- *
- * @param password
- * String containing the PUK value.
- * @param newPassword
- * String containing the new PIN value.
- * @param [optional] aid
- * AID value.
- */
- enterICCPUK: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_SIM_PUK, options);
- Buf.writeInt32(3);
- Buf.writeString(options.password);
- Buf.writeString(options.newPin);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Supplies ICC PUK2 and a new PIN2 to unlock the ICC.
- *
- * @param password
- * String containing the PUK2 value.
- * @param newPassword
- * String containing the new PIN2 value.
- * @param [optional] aid
- * AID value.
- */
- enterICCPUK2: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_ENTER_SIM_PUK2, options);
- Buf.writeInt32(3);
- Buf.writeString(options.password);
- Buf.writeString(options.newPin);
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Helper function for changing ICC locks.
- */
- iccChangeCardLockPassword: function(options) {
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN:
- this.changeICCPIN(options);
- break;
- case GECKO_CARDLOCK_PIN2:
- this.changeICCPIN2(options);
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- }
- },
-
- /**
- * Helper function for setting the state of ICC locks.
- */
- iccSetCardLockEnabled: function(options) {
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN: // Fall through.
- case GECKO_CARDLOCK_FDN:
- options.facility = GECKO_CARDLOCK_TO_FACILITY[options.lockType];
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- options.serviceClass = ICC_SERVICE_CLASS_VOICE |
- ICC_SERVICE_CLASS_DATA |
- ICC_SERVICE_CLASS_FAX;
- this.setICCFacilityLock(options);
- },
-
- /**
- * Helper function for fetching the state of ICC locks.
- */
- iccGetCardLockEnabled: function(options) {
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN: // Fall through.
- case GECKO_CARDLOCK_FDN:
- options.facility = GECKO_CARDLOCK_TO_FACILITY[options.lockType];
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- options.password = ""; // For query no need to provide pin.
- options.serviceClass = ICC_SERVICE_CLASS_VOICE |
- ICC_SERVICE_CLASS_DATA |
- ICC_SERVICE_CLASS_FAX;
- this.queryICCFacilityLock(options);
- },
-
- /**
- * Helper function for fetching the number of unlock retries of ICC locks.
- *
- * We only query the retry count when we're on the emulator. The phones do
- * not support the request id and their rild doesn't return an error.
- */
- iccGetCardLockRetryCount: function(options) {
- if (!RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT) {
- // Only the emulator supports this request.
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- switch (options.lockType) {
- case GECKO_CARDLOCK_PIN:
- case GECKO_CARDLOCK_PIN2:
- case GECKO_CARDLOCK_PUK:
- case GECKO_CARDLOCK_PUK2:
- case GECKO_CARDLOCK_NCK:
- case GECKO_CARDLOCK_NSCK:
- case GECKO_CARDLOCK_CCK: // Fall through.
- case GECKO_CARDLOCK_SPCK:
- // TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM
- // @ ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_SPCK.
- options.selCode = GECKO_CARDLOCK_TO_SEL_CODE[options.lockType];
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- this.queryICCLockRetryCount(options);
- },
-
- /**
- * Query ICC lock retry count.
- *
- * @param selCode
- * One of ICC_SEL_CODE_*.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_*.
- */
- queryICCLockRetryCount: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_GET_UNLOCK_RETRY_COUNT, options);
- Buf.writeInt32(1);
- Buf.writeString(options.selCode);
- Buf.sendParcel();
- },
-
- /**
- * Query ICC facility lock.
- *
- * @param facility
- * One of ICC_CB_FACILITY_*.
- * @param password
- * Password for the facility, or "" if not required.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_*.
- * @param [optional] aid
- * AID value.
- */
- queryICCFacilityLock: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_QUERY_FACILITY_LOCK, options);
- Buf.writeInt32(4);
- Buf.writeString(options.facility);
- Buf.writeString(options.password);
- Buf.writeString(options.serviceClass.toString());
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Set ICC facility lock.
- *
- * @param facility
- * One of ICC_CB_FACILITY_*.
- * @param enabled
- * true to enable, false to disable.
- * @param password
- * Password for the facility, or "" if not required.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_*.
- * @param [optional] aid
- * AID value.
- */
- setICCFacilityLock: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_FACILITY_LOCK, options);
- Buf.writeInt32(5);
- Buf.writeString(options.facility);
- Buf.writeString(options.enabled ? "1" : "0");
- Buf.writeString(options.password);
- Buf.writeString(options.serviceClass.toString());
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Request an ICC I/O operation.
- *
- * See TS 27.007 "restricted SIM" operation, "AT Command +CRSM".
- * The sequence is in the same order as how libril reads this parcel,
- * see the struct RIL_SIM_IO_v5 or RIL_SIM_IO_v6 defined in ril.h
- *
- * @param command
- * The I/O command, one of the ICC_COMMAND_* constants.
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- * @param pathId
- * String type, check the 'pathid' parameter from TS 27.007 +CRSM.
- * @param p1, p2, p3
- * Arbitrary integer parameters for the command.
- * @param [optional] dataWriter
- * The function for writing string parameter for the ICC_COMMAND_UPDATE_RECORD.
- * @param [optional] pin2
- * String containing the PIN2.
- * @param [optional] aid
- * AID value.
- */
- iccIO: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SIM_IO, options);
- Buf.writeInt32(options.command);
- Buf.writeInt32(options.fileId);
- Buf.writeString(options.pathId);
- Buf.writeInt32(options.p1);
- Buf.writeInt32(options.p2);
- Buf.writeInt32(options.p3);
-
- // Write data.
- if (options.command == ICC_COMMAND_UPDATE_RECORD &&
- options.dataWriter) {
- options.dataWriter(options.p3);
- } else {
- Buf.writeString(null);
- }
-
- // Write pin2.
- if (options.command == ICC_COMMAND_UPDATE_RECORD &&
- options.pin2) {
- Buf.writeString(options.pin2);
- } else {
- Buf.writeString(null);
- }
-
- Buf.writeString(options.aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Get IMSI.
- *
- * @param [optional] aid
- * AID value.
- */
- getIMSI: function(aid) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_GET_IMSI);
- Buf.writeInt32(1);
- Buf.writeString(aid || this.aid);
- Buf.sendParcel();
- },
-
- /**
- * Retrieve ICC's GID1 field.
- */
- getGID1: function(options) {
- options.gid1 = this.iccInfoPrivate.gid1;
- this.sendChromeMessage(options);
- },
-
- /**
- * Read UICC Phonebook contacts.
- *
- * @param contactType
- * One of GECKO_CARDCONTACT_TYPE_*.
- * @param requestId
- * Request id from RadioInterfaceLayer.
- */
- readICCContacts: function(options) {
- if (!this.appType) {
- options.errorMsg = CONTACT_ERR_REQUEST_NOT_SUPPORTED;
- this.sendChromeMessage(options);
- return;
- }
-
- this.context.ICCContactHelper.readICCContacts(
- this.appType,
- options.contactType,
- function onsuccess(contacts) {
- for (let i = 0; i < contacts.length; i++) {
- let contact = contacts[i];
- let pbrIndex = contact.pbrIndex || 0;
- let recordIndex = pbrIndex * ICC_MAX_LINEAR_FIXED_RECORDS + contact.recordId;
- contact.contactId = this.iccInfo.iccid + recordIndex;
- }
- // Reuse 'options' to get 'requestId' and 'contactType'.
- options.contacts = contacts;
- this.sendChromeMessage(options);
- }.bind(this),
- function onerror(errorMsg) {
- options.errorMsg = errorMsg;
- this.sendChromeMessage(options);
- }.bind(this));
- },
-
- /**
- * Update UICC Phonebook.
- *
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param contact The contact will be updated.
- * @param pin2 PIN2 is required for updating FDN.
- * @param requestId Request id from RadioInterfaceLayer.
- */
- updateICCContact: function(options) {
- let onsuccess = function onsuccess(updatedContact) {
- let recordIndex =
- updatedContact.pbrIndex * ICC_MAX_LINEAR_FIXED_RECORDS + updatedContact.recordId;
- updatedContact.contactId = this.iccInfo.iccid + recordIndex;
- options.contact = updatedContact;
- // Reuse 'options' to get 'requestId' and 'contactType'.
- this.sendChromeMessage(options);
- }.bind(this);
-
- let onerror = function onerror(errorMsg) {
- options.errorMsg = errorMsg;
- this.sendChromeMessage(options);
- }.bind(this);
-
- if (!this.appType || !options.contact) {
- onerror(CONTACT_ERR_REQUEST_NOT_SUPPORTED );
- return;
- }
-
- let contact = options.contact;
- let iccid = this.iccInfo.iccid;
- let isValidRecordId = false;
- if (typeof contact.contactId === "string" &&
- contact.contactId.startsWith(iccid)) {
- let recordIndex = contact.contactId.substring(iccid.length);
- contact.pbrIndex = Math.floor(recordIndex / ICC_MAX_LINEAR_FIXED_RECORDS);
- contact.recordId = recordIndex % ICC_MAX_LINEAR_FIXED_RECORDS;
- isValidRecordId = contact.recordId > 0 && contact.recordId < 0xff;
- }
-
- if (DEBUG) {
- this.context.debug("Update ICC Contact " + JSON.stringify(contact));
- }
-
- let ICCContactHelper = this.context.ICCContactHelper;
- // If contact has 'recordId' property, updates corresponding record.
- // If not, inserts the contact into a free record.
- if (isValidRecordId) {
- ICCContactHelper.updateICCContact(
- this.appType, options.contactType, contact, options.pin2, onsuccess, onerror);
- } else {
- ICCContactHelper.addICCContact(
- this.appType, options.contactType, contact, options.pin2, onsuccess, onerror);
- }
- },
-
- /**
- * Check if operator name needs to be overriden by current voiceRegistrationState
- * , EFOPL and EFPNN. See 3GPP TS 31.102 clause 4.2.58 EFPNN and 4.2.59 EFOPL
- * for detail.
- *
- * @return true if operator name is overridden, false otherwise.
- */
- overrideICCNetworkName: function() {
- if (!this.operator) {
- return false;
- }
-
- // We won't get network name using PNN and OPL if voice registration isn't
- // ready.
- if (!this.voiceRegistrationState.cell ||
- this.voiceRegistrationState.cell.gsmLocationAreaCode == -1) {
- return false;
- }
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- let networkName = ICCUtilsHelper.getNetworkNameFromICC(
- this.operator.mcc,
- this.operator.mnc,
- this.voiceRegistrationState.cell.gsmLocationAreaCode);
-
- if (!networkName) {
- return false;
- }
-
- if (DEBUG) {
- this.context.debug("Operator names will be overriden: " +
- "longName = " + networkName.fullName + ", " +
- "shortName = " + networkName.shortName);
- }
-
- this.operator.longName = networkName.fullName;
- this.operator.shortName = networkName.shortName;
-
- this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator);
- return true;
- },
-
- /**
- * Request the phone's radio to be enabled or disabled.
- *
- * @param enabled
- * Boolean indicating the desired state.
- */
- setRadioEnabled: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_RADIO_POWER, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.enabled ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Query call waiting status.
- *
- */
- queryCallWaiting: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_QUERY_CALL_WAITING, options);
- Buf.writeInt32(1);
- // As per 3GPP TS 24.083, section 1.6 UE doesn't need to send service
- // class parameter in call waiting interrogation to network.
- Buf.writeInt32(ICC_SERVICE_CLASS_NONE);
- Buf.sendParcel();
- },
-
- /**
- * Set call waiting status.
- *
- * @param enabled
- * Boolean indicating the desired waiting status.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- */
- setCallWaiting: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_CALL_WAITING, options);
- Buf.writeInt32(2);
- Buf.writeInt32(options.enabled ? 1 : 0);
- Buf.writeInt32(options.serviceClass);
- Buf.sendParcel();
- },
-
- /**
- * Queries current CLIP status.
- */
- queryCLIP: function(options) {
- this.context.Buf.simpleRequest(REQUEST_QUERY_CLIP, options);
- },
-
- /**
- * Queries current CLIR status.
- *
- */
- getCLIR: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_CLIR, options);
- },
-
- /**
- * Enables or disables the presentation of the calling line identity (CLI) to
- * the called party when originating a call.
- *
- * @param options.clirMode
- * One of the CLIR_* constants.
- */
- setCLIR: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_CLIR, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.clirMode);
- Buf.sendParcel();
- },
-
- /**
- * Set screen state.
- *
- * @param on
- * Boolean indicating whether the screen should be on or off.
- */
- setScreenState: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SCREEN_STATE);
- Buf.writeInt32(1);
- Buf.writeInt32(options.on ? 1 : 0);
- Buf.sendParcel();
- },
-
- getVoiceRegistrationState: function() {
- this.context.Buf.simpleRequest(REQUEST_VOICE_REGISTRATION_STATE);
- },
-
- getVoiceRadioTechnology: function() {
- this.context.Buf.simpleRequest(REQUEST_VOICE_RADIO_TECH);
- },
-
- getDataRegistrationState: function() {
- this.context.Buf.simpleRequest(REQUEST_DATA_REGISTRATION_STATE);
- },
-
- getOperator: function() {
- this.context.Buf.simpleRequest(REQUEST_OPERATOR);
- },
-
- /**
- * Set the preferred network type.
- *
- * @param options An object contains a valid value of
- * RIL_PREFERRED_NETWORK_TYPE_TO_GECKO as its `type` attribute.
- */
- setPreferredNetworkType: function(options) {
- let networkType = options.type;
- if (networkType < 0 || networkType >= RIL_PREFERRED_NETWORK_TYPE_TO_GECKO.length) {
- options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_PREFERRED_NETWORK_TYPE, options);
- Buf.writeInt32(1);
- Buf.writeInt32(networkType);
- Buf.sendParcel();
- },
-
- /**
- * Get the preferred network type.
- */
- getPreferredNetworkType: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_PREFERRED_NETWORK_TYPE, options);
- },
-
- /**
- * Request neighboring cell ids in GSM network.
- */
- getNeighboringCellIds: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_NEIGHBORING_CELL_IDS, options);
- },
-
- /**
- * Request all of the current cell information known to the radio.
- */
- getCellInfoList: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_CELL_INFO_LIST, options);
- },
-
- /**
- * Request various states about the network.
- */
- requestNetworkInfo: function() {
- if (this._processingNetworkInfo) {
- if (DEBUG) {
- this.context.debug("Network info requested, but we're already " +
- "requesting network info.");
- }
- this._needRepollNetworkInfo = true;
- return;
- }
-
- if (DEBUG) this.context.debug("Requesting network info");
-
- this._processingNetworkInfo = true;
- this.getVoiceRegistrationState();
- this.getDataRegistrationState(); //TODO only GSM
- this.getOperator();
- this.getNetworkSelectionMode();
- this.getSignalStrength();
- },
-
- /**
- * Get the available networks
- */
- getAvailableNetworks: function(options) {
- if (DEBUG) this.context.debug("Getting available networks");
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_QUERY_AVAILABLE_NETWORKS, options);
- Buf.sendParcel();
- },
-
- /**
- * Request the radio's network selection mode
- */
- getNetworkSelectionMode: function() {
- if (DEBUG) this.context.debug("Getting network selection mode");
- this.context.Buf.simpleRequest(REQUEST_QUERY_NETWORK_SELECTION_MODE);
- },
-
- /**
- * Tell the radio to automatically choose a voice/data network
- */
- selectNetworkAuto: function(options) {
- if (DEBUG) this.context.debug("Setting automatic network selection");
- this.context.Buf.simpleRequest(REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, options);
- },
-
- /**
- * Set the roaming preference mode
- */
- setRoamingPreference: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CDMA_SET_ROAMING_PREFERENCE, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.mode);
- Buf.sendParcel();
- },
-
- /**
- * Get the roaming preference mode
- */
- queryRoamingPreference: function(options) {
- this.context.Buf.simpleRequest(REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, options);
- },
-
- /**
- * Set the voice privacy mode
- */
- setVoicePrivacyMode: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.enabled ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Get the voice privacy mode
- */
- queryVoicePrivacyMode: function(options) {
- this.context.Buf.simpleRequest(REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, options);
- },
-
- /**
- * Open Logical UICC channel (aid) for Secure Element access
- */
- iccOpenChannel: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SIM_OPEN_CHANNEL, options);
- Buf.writeString(options.aid);
- Buf.sendParcel();
- },
-
- /**
- * Exchange APDU data on an open Logical UICC channel
- */
- iccExchangeAPDU: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SIM_TRANSMIT_APDU_CHANNEL, options);
- Buf.writeInt32(options.channel);
- Buf.writeInt32(options.apdu.cla);
- Buf.writeInt32(options.apdu.command);
- Buf.writeInt32(options.apdu.p1);
- Buf.writeInt32(options.apdu.p2);
- Buf.writeInt32(options.apdu.p3);
- Buf.writeString(options.apdu.data);
- Buf.sendParcel();
- },
-
- /**
- * Close Logical UICC channel
- */
- iccCloseChannel: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SIM_CLOSE_CHANNEL, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.channel);
- Buf.sendParcel();
- },
-
- /**
- * Get UICC service state
- */
- getIccServiceState: function(options) {
- switch (options.service) {
- case GECKO_CARDSERVICE_FDN:
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- options.result = ICCUtilsHelper.isICCServiceAvailable("FDN");
- break;
- default:
- options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
- break;
- }
- this.sendChromeMessage(options);
- },
-
- /**
- * Enable/Disable UICC subscription
- */
- setUiccSubscription: function(options) {
- if (DEBUG) {
- this.context.debug("setUiccSubscription: " + JSON.stringify(options));
- }
-
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_UICC_SUBSCRIPTION, options);
- Buf.writeInt32(this.context.clientId);
- Buf.writeInt32(options.appIndex);
- Buf.writeInt32(this.context.clientId);
- Buf.writeInt32(options.enabled ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Tell the radio to choose a specific voice/data network
- */
- selectNetwork: function(options) {
- if (DEBUG) {
- this.context.debug("Setting manual network selection: " +
- options.mcc + ", " + options.mnc);
- }
-
- let numeric = (options.mcc && options.mnc) ? options.mcc + options.mnc : null;
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_NETWORK_SELECTION_MANUAL, options);
- Buf.writeString(numeric);
- Buf.sendParcel();
- },
-
- /**
- * Get the signal strength.
- */
- getSignalStrength: function() {
- this.context.Buf.simpleRequest(REQUEST_SIGNAL_STRENGTH);
- },
-
- getDeviceIdentity: function() {
- this.deviceIdentities || this.context.Buf.simpleRequest(REQUEST_DEVICE_IDENTITY);
- },
-
- getBasebandVersion: function() {
- this.context.Buf.simpleRequest(REQUEST_BASEBAND_VERSION);
- },
-
- sendExitEmergencyCbModeRequest: function(options) {
- this.context.Buf.simpleRequest(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, options);
- },
-
- getCdmaSubscription: function() {
- this.context.Buf.simpleRequest(REQUEST_CDMA_SUBSCRIPTION);
- },
-
- exitEmergencyCbMode: function(options) {
- // The function could be called by an API from RadioInterfaceLayer or by
- // ril_worker itself. From ril_worker, we won't pass the parameter
- // 'options'. In this case, it is marked as internal.
- if (!options) {
- options = {internal: true};
- }
- this._cancelEmergencyCbModeTimeout();
- this.sendExitEmergencyCbModeRequest(options);
- },
-
- /**
- * Dial a non-emergency number.
- *
- * @param isEmergency
- * Whether the number is an emergency number.
- * @param number
- * String containing the number to dial.
- * @param clirMode
- * Integer for showing/hidding the caller Id to the called party.
- * @param uusInfo
- * Integer doing something XXX TODO
- */
- dial: function(options) {
- if (options.isEmergency) {
- options.request = RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL ?
- REQUEST_DIAL_EMERGENCY_CALL : REQUEST_DIAL;
-
- } else {
- options.request = REQUEST_DIAL;
-
- // Exit emergency callback mode when user dial a non-emergency call.
- if (this._isInEmergencyCbMode) {
- this.exitEmergencyCbMode();
- }
- }
-
- this.telephonyRequestQueue.push(options.request, () => {
- let Buf = this.context.Buf;
- Buf.newParcel(options.request, options);
- Buf.writeString(options.number);
- Buf.writeInt32(options.clirMode || 0);
- Buf.writeInt32(options.uusInfo || 0);
- // TODO Why do we need this extra 0? It was put it in to make this
- // match the format of the binary message.
- Buf.writeInt32(0);
- Buf.sendParcel();
- });
- },
-
- /**
- * CDMA flash.
- *
- * @param featureStr (optional)
- * Dialing number when the command is used for three-way-calling
- */
- cdmaFlash: function(options) {
- let Buf = this.context.Buf;
- options.request = REQUEST_CDMA_FLASH;
- Buf.newParcel(options.request, options);
- Buf.writeString(options.featureStr || "");
- Buf.sendParcel();
- },
-
- /**
- * Hang up the phone.
- *
- * @param callIndex
- * Call index (1-based) as reported by REQUEST_GET_CURRENT_CALLS.
- */
- hangUpCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_HANGUP, () => {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_HANGUP, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.callIndex);
- Buf.sendParcel();
- });
- },
-
- hangUpForeground: function(options) {
- this.telephonyRequestQueue.push(REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, () => {
- this.context.Buf.simpleRequest(REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
- options);
- });
- },
-
- hangUpBackground: function(options) {
- this.telephonyRequestQueue.push(REQUEST_HANGUP_WAITING_OR_BACKGROUND, () => {
- this.context.Buf.simpleRequest(REQUEST_HANGUP_WAITING_OR_BACKGROUND,
- options);
- });
- },
-
- switchActiveCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, () => {
- this.context.Buf.simpleRequest(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
- options);
- });
- },
-
- udub: function(options) {
- this.telephonyRequestQueue.push(REQUEST_UDUB, () => {
- this.context.Buf.simpleRequest(REQUEST_UDUB, options);
- });
- },
-
- answerCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_ANSWER, () => {
- this.context.Buf.simpleRequest(REQUEST_ANSWER, options);
- });
- },
-
- conferenceCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_CONFERENCE, () => {
- this.context.Buf.simpleRequest(REQUEST_CONFERENCE, options);
- });
- },
-
- separateCall: function(options) {
- this.telephonyRequestQueue.push(REQUEST_SEPARATE_CONNECTION, () => {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SEPARATE_CONNECTION, options);
- Buf.writeInt32(1);
- Buf.writeInt32(options.callIndex);
- Buf.sendParcel();
- });
- },
-
- /**
- * Get current calls.
- */
- getCurrentCalls: function(options) {
- this.telephonyRequestQueue.push(REQUEST_GET_CURRENT_CALLS, () => {
- this.context.Buf.simpleRequest(REQUEST_GET_CURRENT_CALLS, options);
- });
- },
-
- /**
- * Mute or unmute the radio.
- *
- * @param mute
- * Boolean to indicate whether to mute or unmute the radio.
- */
- setMute: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_MUTE);
- Buf.writeInt32(1);
- Buf.writeInt32(options.muted ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Send an SMS.
- *
- * The `options` parameter object should contain the following attributes:
- *
- * @param number
- * String containing the recipient number.
- * @param body
- * String containing the message text.
- * @param envelopeId
- * Numeric value identifying the sms request.
- */
- sendSMS: function(options) {
- options.langIndex = options.langIndex || PDU_NL_IDENTIFIER_DEFAULT;
- options.langShiftIndex = options.langShiftIndex || PDU_NL_IDENTIFIER_DEFAULT;
-
- if (!options.segmentSeq) {
- // Fist segment to send
- options.segmentSeq = 1;
- options.body = options.segments[0].body;
- options.encodedBodyLength = options.segments[0].encodedBodyLength;
- }
-
- let Buf = this.context.Buf;
- if (this._isCdma) {
- Buf.newParcel(REQUEST_CDMA_SEND_SMS, options);
- this.context.CdmaPDUHelper.writeMessage(options);
- } else {
- Buf.newParcel(REQUEST_SEND_SMS, options);
- Buf.writeInt32(2);
- Buf.writeString(options.SMSC);
- this.context.GsmPDUHelper.writeMessage(options);
- }
- Buf.sendParcel();
- },
-
- /**
- * Acknowledge the receipt and handling of an SMS.
- *
- * @param success
- * Boolean indicating whether the message was successfuly handled.
- * @param cause
- * SMS_* constant indicating the reason for unsuccessful handling.
- */
- acknowledgeGsmSms: function(success, cause) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SMS_ACKNOWLEDGE);
- Buf.writeInt32(2);
- Buf.writeInt32(success ? 1 : 0);
- Buf.writeInt32(cause);
- Buf.sendParcel();
- },
-
- /**
- * Acknowledge the receipt and handling of an SMS.
- *
- * @param success
- * Boolean indicating whether the message was successfuly handled.
- */
- ackSMS: function(options) {
- if (options.result == PDU_FCS_RESERVED) {
- return;
- }
- if (this._isCdma) {
- this.acknowledgeCdmaSms(options.result == PDU_FCS_OK, options.result);
- } else {
- this.acknowledgeGsmSms(options.result == PDU_FCS_OK, options.result);
- }
- },
-
- /**
- * Acknowledge the receipt and handling of a CDMA SMS.
- *
- * @param success
- * Boolean indicating whether the message was successfuly handled.
- * @param cause
- * SMS_* constant indicating the reason for unsuccessful handling.
- */
- acknowledgeCdmaSms: function(success, cause) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CDMA_SMS_ACKNOWLEDGE);
- Buf.writeInt32(success ? 0 : 1);
- Buf.writeInt32(cause);
- Buf.sendParcel();
- },
-
- /**
- * Update received MWI into EF_MWIS.
- */
- updateMwis: function(options) {
- if (this.context.ICCUtilsHelper.isICCServiceAvailable("MWIS")) {
- this.context.SimRecordHelper.updateMWIS(options.mwi);
- }
- },
-
- /**
- * Report SMS storage status to modem.
- */
- _updateSmsMemoryStatus: function() {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_REPORT_SMS_MEMORY_STATUS);
- Buf.writeInt32(1);
- Buf.writeInt32(this.smsStorageAvailable ? 1 : 0);
- Buf.sendParcel();
- },
-
- reportSmsMemoryStatus: function(options) {
- this.pendingToReportSmsMemoryStatus = true;
- this.smsStorageAvailable = options.isAvailable;
- this._updateSmsMemoryStatus();
- },
-
- setCellBroadcastDisabled: function(options) {
- this.cellBroadcastDisabled = options.disabled;
-
- // If |this.mergedCellBroadcastConfig| is null, either we haven't finished
- // reading required SIM files, or no any channel is ever configured. In
- // the former case, we'll call |this.updateCellBroadcastConfig()| later
- // with correct configs; in the latter case, we don't bother resetting CB
- // to disabled again.
- if (this.mergedCellBroadcastConfig) {
- this.updateCellBroadcastConfig();
- }
- },
-
- setCellBroadcastSearchList: function(options) {
- let getSearchListStr = function(aSearchList) {
- if (typeof aSearchList === "string" || aSearchList instanceof String) {
- return aSearchList;
- }
-
- // TODO: Set search list for CDMA/GSM individually. Bug 990926
- let prop = this._isCdma ? "cdma" : "gsm";
-
- return aSearchList && aSearchList[prop];
- }.bind(this);
-
- try {
- let str = getSearchListStr(options.searchList);
- this.cellBroadcastConfigs.MMI = this._convertCellBroadcastSearchList(str);
- } catch (e) {
- if (DEBUG) {
- this.context.debug("Invalid Cell Broadcast search list: " + e);
- }
- options.errorMsg = GECKO_ERROR_UNSPECIFIED_ERROR;
- }
-
- this.sendChromeMessage(options);
- if (options.errorMsg) {
- return;
- }
-
- this._mergeAllCellBroadcastConfigs();
- },
-
- updateCellBroadcastConfig: function() {
- let activate = !this.cellBroadcastDisabled &&
- (this.mergedCellBroadcastConfig != null) &&
- (this.mergedCellBroadcastConfig.length > 0);
- if (activate) {
- this.setSmsBroadcastConfig(this.mergedCellBroadcastConfig);
- } else {
- // It's unnecessary to set config first if we're deactivating.
- this.setSmsBroadcastActivation(false);
- }
- },
-
- setGsmSmsBroadcastConfig: function(config) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_GSM_SET_BROADCAST_SMS_CONFIG);
-
- let numConfigs = config ? config.length / 2 : 0;
- Buf.writeInt32(numConfigs);
- for (let i = 0; i < config.length;) {
- // convert [from, to) to [from, to - 1]
- Buf.writeInt32(config[i++]);
- Buf.writeInt32(config[i++] - 1);
- Buf.writeInt32(0x00);
- Buf.writeInt32(0xFF);
- Buf.writeInt32(1);
- }
-
- Buf.sendParcel();
- },
-
- /**
- * Send CDMA SMS broadcast config.
- *
- * @see 3GPP2 C.R1001 Sec. 9.2 and 9.3
- */
- setCdmaSmsBroadcastConfig: function(config) {
- let Buf = this.context.Buf;
- // |config| is an array of half-closed range: [[from, to), [from, to), ...].
- // It will be further decomposed, ex: [1, 4) => 1, 2, 3.
- Buf.newParcel(REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG);
-
- let numConfigs = 0;
- for (let i = 0; i < config.length; i += 2) {
- numConfigs += (config[i+1] - config[i]);
- }
-
- Buf.writeInt32(numConfigs);
- for (let i = 0; i < config.length;) {
- let begin = config[i++];
- let end = config[i++];
-
- for (let j = begin; j < end; ++j) {
- Buf.writeInt32(j);
- Buf.writeInt32(0); // Language Indicator: Unknown or unspecified.
- Buf.writeInt32(1);
- }
- }
-
- Buf.sendParcel();
- },
-
- setSmsBroadcastConfig: function(config) {
- if (this._isCdma) {
- this.setCdmaSmsBroadcastConfig(config);
- } else {
- this.setGsmSmsBroadcastConfig(config);
- }
- },
-
- setSmsBroadcastActivation: function(activate) {
- let parcelType = this._isCdma ? REQUEST_CDMA_SMS_BROADCAST_ACTIVATION :
- REQUEST_GSM_SMS_BROADCAST_ACTIVATION;
- let Buf = this.context.Buf;
- Buf.newParcel(parcelType);
- Buf.writeInt32(1);
- // See hardware/ril/include/telephony/ril.h, 0 - Activate, 1 - Turn off.
- Buf.writeInt32(activate ? 0 : 1);
- Buf.sendParcel();
- },
-
- /**
- * Start a DTMF Tone.
- *
- * @param dtmfChar
- * DTMF signal to send, 0-9, *, +
- */
- startTone: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_DTMF_START, options);
- Buf.writeString(options.dtmfChar);
- Buf.sendParcel();
- },
-
- stopTone: function() {
- this.context.Buf.simpleRequest(REQUEST_DTMF_STOP);
- },
-
- /**
- * Send a DTMF tone.
- *
- * @param dtmfChar
- * DTMF signal to send, 0-9, *, +
- */
- sendTone: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_DTMF);
- Buf.writeString(options.dtmfChar);
- Buf.sendParcel();
- },
-
- /**
- * Get the Short Message Service Center address.
- */
- getSmscAddress: function(options) {
- this.context.Buf.simpleRequest(REQUEST_GET_SMSC_ADDRESS, options);
- },
-
- /**
- * Set the Short Message Service Center address.
- *
- * @param smscAddress
- * Number part of the SMSC address.
- * @param typeOfNumber
- * Type of number in integer, as defined in
- * |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
- * @param numberPlanIdentification
- * The index of number plan identification value in
- * CALLED_PARTY_BCD_NPI array.
- */
- setSmscAddress: function(options) {
- let ton = options.typeOfNumber;
- let npi = CALLED_PARTY_BCD_NPI[options.numberPlanIdentification];
-
- // If any of the mandatory arguments is not available, return an error
- // immediately.
- if (ton === undefined || npi === undefined || !options.smscAddress) {
- options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
- this.sendChromeMessage(options);
- return;
- }
-
- // Remove all illegal characters in the number string for user-input fault
- // tolerance.
- let numStart = options.smscAddress[0] === "+" ? 1 : 0;
- let number = options.smscAddress.substring(0, numStart) +
- options.smscAddress.substring(numStart)
- .replace(/[^0-9*#abc]/ig, "");
-
- // If the filtered number is an empty string, return an error immediately.
- if (number.length === 0) {
- options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
- this.sendChromeMessage(options);
- return;
- }
-
- // Init parcel.
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_SMSC_ADDRESS, options);
-
- // +---+-----------+---------------+
- // | 1 | TON | NPI |
- // +---+-----------+---------------+
- let tosca = (0x1 << 7) + (ton << 4) + npi;
- if (RILQUIRKS_SMSC_ADDRESS_FORMAT === "pdu") {
- let pduHelper = this.context.GsmPDUHelper;
-
- // Remove the preceding '+', and covert the special BCD digits defined in
- // |Called party BCD number| of 3GPP TS 24.008 to corresponding
- // hexadecimal values (refer the following table).
- //
- // +=========+=======+=====+
- // | value | digit | hex |
- // +========================
- // | 1 0 1 0 | * | 0xA |
- // | 1 0 1 1 | # | 0xB |
- // | 1 1 0 0 | a | 0xC |
- // | 1 1 0 1 | b | 0xD |
- // | 1 1 1 0 | c | 0xE |
- // +=========+=======+=====+
- //
- // The replace order is reversed intentionally, because if the digits are
- // replaced in ascending order, "#" will be converted to "b" and then be
- // converted again to "d", which generates incorrect result.
- let pureNumber = number.substring(numStart)
- .replace(/c/ig, "e")
- .replace(/b/ig, "d")
- .replace(/a/ig, "c")
- .replace(/\#/g, "b")
- .replace(/\*/g, "a");
-
- // address length and string length
- let length = Math.ceil(pureNumber.length / 2) + 1; // +1 octet for TOA
- let strlen = length * 2 + 2; // +2 semi-octets for length octet
-
- Buf.writeInt32(strlen);
- pduHelper.writeHexOctet(length);
- pduHelper.writeHexOctet(tosca);
- pduHelper.writeSwappedNibbleBCD(pureNumber);
- Buf.writeStringDelimiter(strlen);
- } else /* RILQUIRKS_SMSC_ADDRESS_FORMAT === "text" */ {
- let sca;
- sca = '"' + number + '"' + ',' + tosca;
- Buf.writeString(sca);
- }
-
- Buf.sendParcel();
- },
-
- /**
- * Setup a data call.
- *
- * @param radioTech
- * Integer to indicate radio technology.
- * DATACALL_RADIOTECHNOLOGY_CDMA => CDMA.
- * DATACALL_RADIOTECHNOLOGY_GSM => GSM.
- * @param apn
- * String containing the name of the APN to connect to.
- * @param user
- * String containing the username for the APN.
- * @param passwd
- * String containing the password for the APN.
- * @param chappap
- * Integer containing CHAP/PAP auth type.
- * DATACALL_AUTH_NONE => PAP and CHAP is never performed.
- * DATACALL_AUTH_PAP => PAP may be performed.
- * DATACALL_AUTH_CHAP => CHAP may be performed.
- * DATACALL_AUTH_PAP_OR_CHAP => PAP / CHAP may be performed.
- * @param pdptype
- * String containing PDP type to request. ("IP", "IPV6", ...)
- */
- setupDataCall: function(options) {
- // From ./hardware/ril/include/telephony/ril.h:
- // ((const char **)data)[0] Radio technology to use: 0-CDMA, 1-GSM/UMTS, 2...
- // for values above 2 this is RIL_RadioTechnology + 2.
- //
- // From frameworks/base/telephony/java/com/android/internal/telephony/DataConnection.java:
- // if the mRilVersion < 6, radio technology must be GSM/UMTS or CDMA.
- // Otherwise, it must be + 2
- //
- // See also bug 901232 and 867873
- let radioTech = options.radioTech + 2;
- let Buf = this.context.Buf;
- let token = Buf.newParcel(REQUEST_SETUP_DATA_CALL, options);
- Buf.writeInt32(7);
- Buf.writeString(radioTech.toString());
- Buf.writeString(DATACALL_PROFILE_DEFAULT.toString());
- Buf.writeString(options.apn);
- Buf.writeString(options.user);
- Buf.writeString(options.passwd);
- Buf.writeString(options.chappap.toString());
- Buf.writeString(options.pdptype);
- Buf.sendParcel();
- return token;
- },
-
- /**
- * Deactivate a data call.
- *
- * @param cid
- * String containing CID.
- * @param reason
- * One of DATACALL_DEACTIVATE_* constants.
- */
- deactivateDataCall: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_DEACTIVATE_DATA_CALL, options);
- Buf.writeInt32(2);
- Buf.writeString(options.cid.toString());
- Buf.writeString(options.reason !== undefined ?
- options.reason.toString() :
- DATACALL_DEACTIVATE_NO_REASON.toString());
- Buf.sendParcel();
- },
-
- /**
- * Get a list of data calls.
- */
- getDataCallList: function(options) {
- this.context.Buf.simpleRequest(REQUEST_DATA_CALL_LIST, options);
- },
-
- _attachDataRegistration: false,
- /**
- * Manually attach/detach data registration.
- *
- * @param attach
- * Boolean value indicating attach or detach.
- */
- setDataRegistration: function(options) {
- this._attachDataRegistration = options.attach;
-
- if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
- let request = options.attach ? RIL_REQUEST_GPRS_ATTACH :
- RIL_REQUEST_GPRS_DETACH;
- this.context.Buf.simpleRequest(request, options);
- return;
- } else if (RILQUIRKS_SUBSCRIPTION_CONTROL && options.attach) {
- this.context.Buf.simpleRequest(REQUEST_SET_DATA_SUBSCRIPTION, options);
- return;
- }
-
- // We don't really send a request to rild, so instantly reply success to
- // RadioInterfaceLayer.
- this.sendChromeMessage(options);
- },
-
- /**
- * Get failure casue code for the most recently failed PDP context.
- */
- getFailCause: function(options) {
- this.context.Buf.simpleRequest(REQUEST_LAST_CALL_FAIL_CAUSE, options);
- },
-
- /**
- * Send USSD.
- *
- * @param ussd
- * String containing the USSD code.
- */
- sendUSSD: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SEND_USSD, options);
- Buf.writeString(options.ussd);
- Buf.sendParcel();
- },
-
- /**
- * Cancel pending USSD.
- */
- cancelUSSD: function(options) {
- this.context.Buf.simpleRequest(REQUEST_CANCEL_USSD, options);
- },
-
- /**
- * Queries current call forward rules.
- *
- * @param reason
- * One of CALL_FORWARD_REASON_* constants.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- * @param number
- * Phone number of forwarding address.
- */
- queryCallForwardStatus: function(options) {
- let Buf = this.context.Buf;
- let number = options.number || "";
- Buf.newParcel(REQUEST_QUERY_CALL_FORWARD_STATUS, options);
- Buf.writeInt32(CALL_FORWARD_ACTION_QUERY_STATUS);
- Buf.writeInt32(options.reason);
- Buf.writeInt32(options.serviceClass || ICC_SERVICE_CLASS_NONE);
- Buf.writeInt32(this._toaFromString(number));
- Buf.writeString(number);
- Buf.writeInt32(0);
- Buf.sendParcel();
- },
-
- /**
- * Configures call forward rule.
- *
- * @param action
- * One of CALL_FORWARD_ACTION_* constants.
- * @param reason
- * One of CALL_FORWARD_REASON_* constants.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- * @param number
- * Phone number of forwarding address.
- * @param timeSeconds
- * Time in seconds to wait beforec all is forwarded.
- */
- setCallForward: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_SET_CALL_FORWARD, options);
- Buf.writeInt32(options.action);
- Buf.writeInt32(options.reason);
- Buf.writeInt32(options.serviceClass);
- Buf.writeInt32(this._toaFromString(options.number));
- Buf.writeString(options.number);
- Buf.writeInt32(options.timeSeconds);
- Buf.sendParcel();
- },
-
- /**
- * Queries current call barring rules.
- *
- * @param program
- * One of CALL_BARRING_PROGRAM_* constants.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- */
- queryCallBarringStatus: function(options) {
- options.facility = CALL_BARRING_PROGRAM_TO_FACILITY[options.program];
- options.password = ""; // For query no need to provide it.
-
- // For some operators, querying specific serviceClass doesn't work. We use
- // serviceClass 0 instead, and then process the response to extract the
- // answer for queryServiceClass.
- options.queryServiceClass = options.serviceClass;
- options.serviceClass = 0;
-
- this.queryICCFacilityLock(options);
- },
-
- /**
- * Configures call barring rule.
- *
- * @param program
- * One of CALL_BARRING_PROGRAM_* constants.
- * @param enabled
- * Enable or disable the call barring.
- * @param password
- * Barring password.
- * @param serviceClass
- * One of ICC_SERVICE_CLASS_* constants.
- */
- setCallBarring: function(options) {
- options.facility = CALL_BARRING_PROGRAM_TO_FACILITY[options.program];
- this.setICCFacilityLock(options);
- },
-
- /**
- * Change call barring facility password.
- *
- * @param pin
- * Old password.
- * @param newPin
- * New password.
- */
- changeCallBarringPassword: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_CHANGE_BARRING_PASSWORD, options);
- Buf.writeInt32(3);
- // Set facility to ICC_CB_FACILITY_BA_ALL by following TS.22.030 clause
- // 6.5.4 and Table B.1.
- Buf.writeString(ICC_CB_FACILITY_BA_ALL);
- Buf.writeString(options.pin);
- Buf.writeString(options.newPin);
- Buf.sendParcel();
- },
-
- /**
- * Handle STK CALL_SET_UP request.
- *
- * @param hasConfirmed
- * Does use have confirmed the call requested from ICC?
- */
- stkHandleCallSetup: function(options) {
- let Buf = this.context.Buf;
- Buf.newParcel(REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM);
- Buf.writeInt32(1);
- Buf.writeInt32(options.hasConfirmed ? 1 : 0);
- Buf.sendParcel();
- },
-
- /**
- * Send STK Profile Download.
- *
- * @param profile Profile supported by ME.
- */
- sendStkTerminalProfile: function(profile) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- Buf.newParcel(REQUEST_STK_SET_PROFILE);
- Buf.writeInt32(profile.length * 2);
- for (let i = 0; i < profile.length; i++) {
- GsmPDUHelper.writeHexOctet(profile[i]);
- }
- Buf.writeInt32(0);
- Buf.sendParcel();
- },
-
- /**
- * Send STK terminal response.
- *
- * @param command
- * @param deviceIdentities
- * @param resultCode
- * @param [optional] additionalInformation
- * @param [optional] itemIdentifier
- * @param [optional] input
- * @param [optional] isYesNo
- * @param [optional] hasConfirmed
- * @param [optional] localInfo
- * @param [optional] timer
- */
- sendStkTerminalResponse: function(response) {
- if (response.hasConfirmed !== undefined) {
- this.stkHandleCallSetup(response);
- return;
- }
-
- let Buf = this.context.Buf;
- let ComprehensionTlvHelper = this.context.ComprehensionTlvHelper;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let command = response.command;
- Buf.newParcel(REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // 1st mark for Parcel size
- Buf.startCalOutgoingSize(function(size) {
- // Parcel size is in string length, which costs 2 uint8 per char.
- Buf.writeInt32(size / 2);
- });
-
- // Command Details
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(3);
- if (command) {
- GsmPDUHelper.writeHexOctet(command.commandNumber);
- GsmPDUHelper.writeHexOctet(command.typeOfCommand);
- GsmPDUHelper.writeHexOctet(command.commandQualifier);
- } else {
- GsmPDUHelper.writeHexOctet(0x00);
- GsmPDUHelper.writeHexOctet(0x00);
- GsmPDUHelper.writeHexOctet(0x00);
- }
-
- // Device Identifier
- // According to TS102.223/TS31.111 section 6.8 Structure of
- // TERMINAL RESPONSE, "For all SIMPLE-TLV objects with Min=N,
- // the ME should set the CR(comprehension required) flag to
- // comprehension not required.(CR=0)"
- // Since DEVICE_IDENTITIES and DURATION TLVs have Min=N,
- // the CR flag is not set.
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DEVICE_ID);
- GsmPDUHelper.writeHexOctet(2);
- GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_ME);
- GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_SIM);
-
- // Result
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- if ("additionalInformation" in response) {
- // In |12.12 Result| TS 11.14, the length of additional information is
- // varied and all possible values are addressed in 12.12.1-11 of TS 11.14
- // and 8.12.1-13 in TS 31.111.
- // However,
- // 1. Only SEND SS requires info with more than 1 octet.
- // 2. In rild design, SEND SS is expected to be handled by modem and
- // UNSOLICITED_STK_EVENT_NOTIFY will be sent to application layer to
- // indicate appropriate messages to users. TR is not required in this
- // case.
- // Hence, we simplify the structure of |additionalInformation| to a
- // numeric value instead of a octet array.
- GsmPDUHelper.writeHexOctet(2);
- GsmPDUHelper.writeHexOctet(response.resultCode);
- GsmPDUHelper.writeHexOctet(response.additionalInformation);
- } else {
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(response.resultCode);
- }
-
- // Item Identifier
- if (response.itemIdentifier != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ITEM_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(response.itemIdentifier);
- }
-
- // No need to process Text data if user requests help information.
- if (response.resultCode != STK_RESULT_HELP_INFO_REQUIRED) {
- let text;
- let coding = command.options.isUCS2 ?
- STK_TEXT_CODING_UCS2 :
- (command.options.isPacked ?
- STK_TEXT_CODING_GSM_7BIT_PACKED :
- STK_TEXT_CODING_GSM_8BIT);
- if (response.isYesNo !== undefined) {
- // Tag: GET_INKEY
- // When the ME issues a successful TERMINAL RESPONSE for a GET INKEY
- // ("Yes/No") command with command qualifier set to "Yes/No", it shall
- // supply the value '01' when the answer is "positive" and the value
- // '00' when the answer is "negative" in the Text string data object.
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- // Length: 2
- GsmPDUHelper.writeHexOctet(2);
- // Value: Coding, Yes/No.
- GsmPDUHelper.writeHexOctet(coding);
- GsmPDUHelper.writeHexOctet(response.isYesNo ? 0x01 : 0x00);
- } else {
- if (response.input !== undefined) {
- ComprehensionTlvHelper.writeTextStringTlv(response.input, coding);
- }
- }
- }
-
- // Duration
- if (response.resultCode === STK_RESULT_NO_RESPONSE_FROM_USER) {
- // In TS102 223, 6.4.2 GET INKEY, "if the UICC requests a variable timeout,
- // the terminal shall wait until either the user enters a single character
- // or the timeout expires. The timer starts when the text is displayed on
- // the screen and stops when the TERMINAL RESPONSE is sent. The terminal
- // shall pass the total display text duration (command execution duration)
- // to the UICC using the TERMINAL RESPONSE. The time unit of the response
- // is identical to the time unit of the requested variable timeout."
- let duration = command && command.options && command.options.duration;
- if (duration) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DURATION);
- GsmPDUHelper.writeHexOctet(2);
- GsmPDUHelper.writeHexOctet(duration.timeUnit);
- GsmPDUHelper.writeHexOctet(duration.timeInterval);
- }
- }
-
- // Local Information
- if (response.localInfo) {
- let localInfo = response.localInfo;
-
- // Location Infomation
- if (localInfo.locationInfo) {
- ComprehensionTlvHelper.writeLocationInfoTlv(localInfo.locationInfo);
- }
-
- // IMEI
- if (localInfo.imei != null) {
- let imei = localInfo.imei;
- if (imei.length == 15) {
- imei = imei + "0";
- }
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_IMEI);
- GsmPDUHelper.writeHexOctet(8);
- for (let i = 0; i < imei.length / 2; i++) {
- GsmPDUHelper.writeHexOctet(parseInt(imei.substr(i * 2, 2), 16));
- }
- }
-
- // Date and Time Zone
- if (localInfo.date != null) {
- ComprehensionTlvHelper.writeDateTimeZoneTlv(localInfo.date);
- }
-
- // Language
- if (localInfo.language) {
- ComprehensionTlvHelper.writeLanguageTlv(localInfo.language);
- }
- }
-
- // Timer
- if (response.timer) {
- let timer = response.timer;
-
- if (timer.timerId) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(timer.timerId);
- }
-
- if (timer.timerValue) {
- ComprehensionTlvHelper.writeTimerValueTlv(timer.timerValue, false);
- }
- }
-
- // Calculate and write Parcel size to 1st mark
- Buf.stopCalOutgoingSize();
-
- Buf.writeInt32(0);
- Buf.sendParcel();
- },
-
- /**
- * Send STK Envelope(Menu Selection) command.
- *
- * @param itemIdentifier
- * @param helpRequested
- */
- sendStkMenuSelection: function(command) {
- command.tag = BER_MENU_SELECTION_TAG;
- command.deviceId = {
- sourceId :STK_DEVICE_ID_KEYPAD,
- destinationId: STK_DEVICE_ID_SIM
- };
- this.sendICCEnvelopeCommand(command);
- },
-
- /**
- * Send STK Envelope(Timer Expiration) command.
- *
- * @param timer
- */
- sendStkTimerExpiration: function(command) {
- command.tag = BER_TIMER_EXPIRATION_TAG;
- command.deviceId = {
- sourceId: STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.timerId = command.timer.timerId;
- command.timerValue = command.timer.timerValue;
- this.sendICCEnvelopeCommand(command);
- },
-
- /**
- * Send STK Envelope(Event Download) command.
- * @param event
- */
- sendStkEventDownload: function(command) {
- command.tag = BER_EVENT_DOWNLOAD_TAG;
- command.eventList = command.event.eventType;
- switch (command.eventList) {
- case STK_EVENT_TYPE_LOCATION_STATUS:
- command.deviceId = {
- sourceId :STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.locationStatus = command.event.locationStatus;
- // Location info should only be provided when locationStatus is normal.
- if (command.locationStatus == STK_SERVICE_STATE_NORMAL) {
- command.locationInfo = command.event.locationInfo;
- }
- break;
- case STK_EVENT_TYPE_MT_CALL:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_NETWORK,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.transactionId = 0;
- command.address = command.event.number;
- break;
- case STK_EVENT_TYPE_CALL_DISCONNECTED:
- command.cause = command.event.error;
- // Fall through.
- case STK_EVENT_TYPE_CALL_CONNECTED:
- command.deviceId = {
- sourceId: (command.event.isIssuedByRemote ?
- STK_DEVICE_ID_NETWORK : STK_DEVICE_ID_ME),
- destinationId: STK_DEVICE_ID_SIM
- };
- command.transactionId = 0;
- break;
- case STK_EVENT_TYPE_USER_ACTIVITY:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- break;
- case STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_DISPLAY,
- destinationId: STK_DEVICE_ID_SIM
- };
- break;
- case STK_EVENT_TYPE_LANGUAGE_SELECTION:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.language = command.event.language;
- break;
- case STK_EVENT_TYPE_BROWSER_TERMINATION:
- command.deviceId = {
- sourceId: STK_DEVICE_ID_ME,
- destinationId: STK_DEVICE_ID_SIM
- };
- command.terminationCause = command.event.terminationCause;
- break;
- }
- this.sendICCEnvelopeCommand(command);
- },
-
- /**
- * Send REQUEST_STK_SEND_ENVELOPE_COMMAND to ICC.
- *
- * @param tag
- * @patam deviceId
- * @param [optioanl] itemIdentifier
- * @param [optional] helpRequested
- * @param [optional] eventList
- * @param [optional] locationStatus
- * @param [optional] locationInfo
- * @param [optional] address
- * @param [optional] transactionId
- * @param [optional] cause
- * @param [optional] timerId
- * @param [optional] timerValue
- * @param [optional] terminationCause
- */
- sendICCEnvelopeCommand: function(options) {
- if (DEBUG) {
- this.context.debug("Stk Envelope " + JSON.stringify(options));
- }
-
- let Buf = this.context.Buf;
- let ComprehensionTlvHelper = this.context.ComprehensionTlvHelper;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- Buf.newParcel(REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // 1st mark for Parcel size
- Buf.startCalOutgoingSize(function(size) {
- // Parcel size is in string length, which costs 2 uint8 per char.
- Buf.writeInt32(size / 2);
- });
-
- // Write a BER-TLV
- GsmPDUHelper.writeHexOctet(options.tag);
- // 2nd mark for BER length
- Buf.startCalOutgoingSize(function(size) {
- // BER length is in number of hexOctets, which costs 4 uint8 per hexOctet.
- GsmPDUHelper.writeHexOctet(size / 4);
- });
-
- // Event List
- if (options.eventList != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.eventList);
- }
-
- // Device Identifies
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(2);
- GsmPDUHelper.writeHexOctet(options.deviceId.sourceId);
- GsmPDUHelper.writeHexOctet(options.deviceId.destinationId);
-
- // Item Identifier
- if (options.itemIdentifier != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ITEM_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.itemIdentifier);
- }
-
- // Help Request
- if (options.helpRequested) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_HELP_REQUEST |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(0);
- // Help Request doesn't have value
- }
-
- // Location Status
- if (options.locationStatus != null) {
- let len = options.locationStatus.length;
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LOCATION_STATUS |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.locationStatus);
- }
-
- // Location Info
- if (options.locationInfo) {
- ComprehensionTlvHelper.writeLocationInfoTlv(options.locationInfo);
- }
-
- // Transaction Id
- if (options.transactionId != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TRANSACTION_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.transactionId);
- }
-
- // Address
- if (options.address) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ADDRESS |
- COMPREHENSIONTLV_FLAG_CR);
- let addressLength = options.address[0] == '+' ? options.address.length - 1
- : options.address.length;
- ComprehensionTlvHelper.writeLength(
- Math.ceil(addressLength / 2) + 1 // address BCD + TON
- );
- this.context.ICCPDUHelper.writeDiallingNumber(options.address);
- }
-
- // Cause of disconnection.
- if (options.cause != null) {
- ComprehensionTlvHelper.writeCauseTlv(options.cause);
- }
-
- // Timer Identifier
- if (options.timerId != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.timerId);
- }
-
- // Timer Value
- if (options.timerValue != null) {
- ComprehensionTlvHelper.writeTimerValueTlv(options.timerValue, true);
- }
-
- // Language
- if (options.language) {
- ComprehensionTlvHelper.writeLanguageTlv(options.language);
- }
-
- // Browser Termination
- if (options.terminationCause != null) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_BROWSER_TERMINATION_CAUSE |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(1);
- GsmPDUHelper.writeHexOctet(options.terminationCause);
- }
-
- // Calculate and write BER length to 2nd mark
- Buf.stopCalOutgoingSize();
-
- // Calculate and write Parcel size to 1st mark
- Buf.stopCalOutgoingSize();
-
- Buf.writeInt32(0);
- Buf.sendParcel();
- },
-
- /**
- * Report STK Service is running.
- */
- reportStkServiceIsRunning: function() {
- this.context.Buf.simpleRequest(REQUEST_REPORT_STK_SERVICE_IS_RUNNING);
- },
-
- /**
- * Process ICC status.
- */
- _processICCStatus: function(iccStatus) {
- // If |_waitingRadioTech| is true, we should not get app information because
- // the |_isCdma| flag is not ready yet. Otherwise we may use wrong index to
- // get app information, especially for the case that icc card has both cdma
- // and gsm subscription.
- if (this._waitingRadioTech) {
- return;
- }
-
- // When |iccStatus.cardState| is not CARD_STATE_PRESENT, set cardState to
- // undetected.
- if (iccStatus.cardState !== CARD_STATE_PRESENT) {
- if (this.cardState !== GECKO_CARDSTATE_UNDETECTED) {
- this.operator = null;
- // We should send |cardstatechange| before |iccinfochange|, otherwise we
- // may lost cardstatechange event when icc card becomes undetected.
- this.cardState = GECKO_CARDSTATE_UNDETECTED;
- this.sendChromeMessage({rilMessageType: "cardstatechange",
- cardState: this.cardState});
-
- this.iccInfo = {iccType: null};
- this.context.ICCUtilsHelper.handleICCInfoChange();
- }
- return;
- }
-
- if (RILQUIRKS_SUBSCRIPTION_CONTROL) {
- // All appIndex is -1 means the subscription is not activated yet.
- // Note that we don't support "ims" for now, so we don't take it into
- // account.
- let neetToActivate = iccStatus.cdmaSubscriptionAppIndex === -1 &&
- iccStatus.gsmUmtsSubscriptionAppIndex === -1;
- if (neetToActivate &&
- // Note: setUiccSubscription works abnormally when RADIO is OFF,
- // which causes SMS function broken in Flame.
- // See bug 1008557 for detailed info.
- this.radioState === GECKO_RADIOSTATE_ENABLED) {
- for (let i = 0; i < iccStatus.apps.length; i++) {
- this.setUiccSubscription({appIndex: i, enabled: true});
- }
- }
- }
-
- let newCardState;
- let index = this._isCdma ? iccStatus.cdmaSubscriptionAppIndex
- : iccStatus.gsmUmtsSubscriptionAppIndex;
- let app = iccStatus.apps[index];
- if (app) {
- // fetchICCRecords will need to read aid, so read aid here.
- this.aid = app.aid;
- this.appType = app.app_type;
- this.iccInfo.iccType = GECKO_CARD_TYPE[this.appType];
-
- switch (app.app_state) {
- case CARD_APPSTATE_ILLEGAL:
- newCardState = GECKO_CARDSTATE_ILLEGAL;
- break;
- case CARD_APPSTATE_PIN:
- newCardState = GECKO_CARDSTATE_PIN_REQUIRED;
- break;
- case CARD_APPSTATE_PUK:
- newCardState = GECKO_CARDSTATE_PUK_REQUIRED;
- break;
- case CARD_APPSTATE_SUBSCRIPTION_PERSO:
- newCardState = PERSONSUBSTATE[app.perso_substate];
- break;
- case CARD_APPSTATE_READY:
- newCardState = GECKO_CARDSTATE_READY;
- break;
- case CARD_APPSTATE_UNKNOWN:
- case CARD_APPSTATE_DETECTED:
- // Fall through.
- default:
- newCardState = GECKO_CARDSTATE_UNKNOWN;
- }
-
- let pin1State = app.pin1_replaced ? iccStatus.universalPINState :
- app.pin1;
- if (pin1State === CARD_PINSTATE_ENABLED_PERM_BLOCKED) {
- newCardState = GECKO_CARDSTATE_PERMANENT_BLOCKED;
- }
- } else {
- // Having incorrect app information, set card state to unknown.
- newCardState = GECKO_CARDSTATE_UNKNOWN;
- }
-
- let ICCRecordHelper = this.context.ICCRecordHelper;
- // Try to get iccId only when cardState left GECKO_CARDSTATE_UNDETECTED.
- if (iccStatus.cardState === CARD_STATE_PRESENT &&
- (this.cardState === GECKO_CARDSTATE_UNINITIALIZED ||
- this.cardState === GECKO_CARDSTATE_UNDETECTED)) {
- ICCRecordHelper.readICCID();
- }
-
- if (this.cardState == newCardState) {
- return;
- }
-
- // This was moved down from CARD_APPSTATE_READY
- this.requestNetworkInfo();
- if (newCardState == GECKO_CARDSTATE_READY) {
- // For type SIM, we need to check EF_phase first.
- // Other types of ICC we can send Terminal_Profile immediately.
- if (this.appType == CARD_APPTYPE_SIM) {
- this.context.SimRecordHelper.readSimPhase();
- } else if (RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD) {
- this.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
- }
-
- ICCRecordHelper.fetchICCRecords();
- }
-
- this.cardState = newCardState;
- this.sendChromeMessage({rilMessageType: "cardstatechange",
- cardState: this.cardState});
- },
-
- /**
- * Helper for processing responses of functions such as enterICC* and changeICC*.
- */
- _processEnterAndChangeICCResponses: function(length, options) {
- options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
- this.sendChromeMessage(options);
- },
-
- // We combine all of the NETWORK_INFO_MESSAGE_TYPES into one "networkinfochange"
- // message to the RadioInterfaceLayer, so we can avoid sending multiple
- // VoiceInfoChanged events for both operator / voice_data_registration
- //
- // State management here is a little tricky. We need to know both:
- // 1. Whether or not a response was received for each of the
- // NETWORK_INFO_MESSAGE_TYPES
- // 2. The outbound message that corresponds with that response -- but this
- // only happens when internal state changes (i.e. it isn't guaranteed)
- //
- // To collect this state, each message response function first calls
- // _receivedNetworkInfo, to mark the response as received. When the
- // final response is received, a call to _sendPendingNetworkInfo is placed
- // on the next tick of the worker thread.
- //
- // Since the original call to _receivedNetworkInfo happens at the top
- // of the response handler, this gives the final handler a chance to
- // queue up it's "changed" message by calling _sendNetworkInfoMessage if/when
- // the internal state has actually changed.
- _sendNetworkInfoMessage: function(type, message) {
- if (!this._processingNetworkInfo) {
- // We only combine these messages in the case of the combined request
- // in requestNetworkInfo()
- this.sendChromeMessage(message);
- return;
- }
-
- if (DEBUG) {
- this.context.debug("Queuing " + type + " network info message: " +
- JSON.stringify(message));
- }
- this._pendingNetworkInfo[type] = message;
- },
-
- _receivedNetworkInfo: function(type) {
- if (DEBUG) this.context.debug("Received " + type + " network info.");
- if (!this._processingNetworkInfo) {
- return;
- }
-
- let pending = this._pendingNetworkInfo;
-
- // We still need to track states for events that aren't fired.
- if (!(type in pending)) {
- pending[type] = this.pendingNetworkType;
- }
-
- // Pending network info is ready to be sent when no more messages
- // are waiting for responses, but the combined payload hasn't been sent.
- for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
- let msgType = NETWORK_INFO_MESSAGE_TYPES[i];
- if (!(msgType in pending)) {
- if (DEBUG) {
- this.context.debug("Still missing some more network info, not " +
- "notifying main thread.");
- }
- return;
- }
- }
-
- // Do a pass to clean up the processed messages that didn't create
- // a response message, so we don't have unused keys in the outbound
- // networkinfochanged message.
- for (let key in pending) {
- if (pending[key] == this.pendingNetworkType) {
- delete pending[key];
- }
- }
-
- if (DEBUG) {
- this.context.debug("All pending network info has been received: " +
- JSON.stringify(pending));
- }
-
- // Send the message on the next tick of the worker's loop, so we give the
- // last message a chance to call _sendNetworkInfoMessage first.
- setTimeout(this._sendPendingNetworkInfo.bind(this), 0);
- },
-
- _sendPendingNetworkInfo: function() {
- this.sendChromeMessage(this._pendingNetworkInfo);
-
- this._processingNetworkInfo = false;
- for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
- delete this._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]];
- }
-
- if (this._needRepollNetworkInfo) {
- this._needRepollNetworkInfo = false;
- this.requestNetworkInfo();
- }
- },
-
- /**
- * Normalize the signal strength in dBm to the signal level from 0 to 100.
- *
- * @param signal
- * The signal strength in dBm to normalize.
- * @param min
- * The signal strength in dBm maps to level 0.
- * @param max
- * The signal strength in dBm maps to level 100.
- *
- * @return level
- * The signal level from 0 to 100.
- */
- _processSignalLevel: function(signal, min, max) {
- if (signal <= min) {
- return 0;
- }
-
- if (signal >= max) {
- return 100;
- }
-
- return Math.floor((signal - min) * 100 / (max - min));
- },
-
- /**
- * Process LTE signal strength to the signal info object.
- *
- * @param signal
- * The signal object reported from RIL/modem.
- *
- * @return The object of signal strength info.
- * Or null if invalid signal input.
- *
- * TODO: Bug 982013: reconsider the format of signal strength APIs for
- * GSM/CDMA/LTE to expose details, such as rsrp and rsnnr,
- * individually.
- */
- _processLteSignal: function(signal) {
- let info = {
- voice: {
- signalStrength: null,
- relSignalStrength: null
- },
- data: {
- signalStrength: null,
- relSignalStrength: null
- }
- };
-
- // Referring to AOSP, use lteRSRP for signalStrength in dBm.
- let signalStrength = (signal.lteRSRP === undefined || signal.lteRSRP === 0x7FFFFFFF) ?
- null : signal.lteRSRP;
- info.voice.signalStrength = info.data.signalStrength = signalStrength;
-
- // Referring to AOSP, first determine signalLevel based on RSRP and RSSNR,
- // then on lteSignalStrength if RSRP and RSSNR are invalid.
- let rsrpLevel = -1;
- let rssnrLevel = -1;
- if (signal.lteRSRP !== undefined &&
- signal.lteRSRP !== 0x7FFFFFFF &&
- signal.lteRSRP >= 44 &&
- signal.lteRSRP <= 140) {
- rsrpLevel = this._processSignalLevel(signal.lteRSRP * -1, -115, -85);
- }
-
- if (signal.lteRSSNR !== undefined &&
- signal.lteRSSNR !== 0x7FFFFFFF &&
- signal.lteRSSNR >= -200 &&
- signal.lteRSSNR <= 300) {
- rssnrLevel = this._processSignalLevel(signal.lteRSSNR, -30, 130);
- }
-
- if (rsrpLevel !== -1 && rssnrLevel !== -1) {
- info.voice.relSignalStrength = info.data.relSignalStrength =
- Math.min(rsrpLevel, rssnrLevel);
- return info;
- }
-
- let level = Math.max(rsrpLevel, rssnrLevel);
- if (level !== -1) {
- info.voice.relSignalStrength = info.data.relSignalStrength = level;
- return info;
- }
-
- // Valid values are 0-63 as defined in TS 27.007 clause 8.69.
- if (signal.lteSignalStrength !== undefined &&
- signal.lteSignalStrength >= 0 &&
- signal.lteSignalStrength <= 63) {
- level = this._processSignalLevel(signal.lteSignalStrength, 0, 12);
- info.voice.relSignalStrength = info.data.relSignalStrength = level;
- return info;
- }
-
- return null;
- },
-
- _processSignalStrength: function(signal) {
- let info = {
- voice: {
- signalStrength: null,
- relSignalStrength: null
- },
- data: {
- signalStrength: null,
- relSignalStrength: null
- }
- };
-
- // During startup, |radioTech| is not yet defined, so we need to
- // check it separately.
- if (("radioTech" in this.voiceRegistrationState) &&
- !this._isGsmTechGroup(this.voiceRegistrationState.radioTech)) {
- // CDMA RSSI.
- // Valid values are positive integers. This value is the actual RSSI value
- // multiplied by -1. Example: If the actual RSSI is -75, then this
- // response value will be 75.
- if (signal.cdmaDBM && signal.cdmaDBM > 0) {
- let signalStrength = -1 * signal.cdmaDBM;
- info.voice.signalStrength = signalStrength;
-
- // -105 and -70 are referred to AOSP's implementation. These values are
- // not constants and can be customized based on different requirement.
- let signalLevel = this._processSignalLevel(signalStrength, -105, -70);
- info.voice.relSignalStrength = signalLevel;
- }
-
- // EVDO RSSI.
- // Valid values are positive integers. This value is the actual RSSI value
- // multiplied by -1. Example: If the actual RSSI is -75, then this
- // response value will be 75.
- if (signal.evdoDBM && signal.evdoDBM > 0) {
- let signalStrength = -1 * signal.evdoDBM;
- info.data.signalStrength = signalStrength;
-
- // -105 and -70 are referred to AOSP's implementation. These values are
- // not constants and can be customized based on different requirement.
- let signalLevel = this._processSignalLevel(signalStrength, -105, -70);
- info.data.relSignalStrength = signalLevel;
- }
- } else {
- // Check LTE level first, and check GSM/UMTS level next if LTE one is not
- // valid.
- let lteInfo = this._processLteSignal(signal);
- if (lteInfo) {
- info = lteInfo;
- } else {
- // GSM signal strength.
- // Valid values are 0-31 as defined in TS 27.007 8.5.
- // 0 : -113 dBm or less
- // 1 : -111 dBm
- // 2...30: -109...-53 dBm
- // 31 : -51 dBm
- if (signal.gsmSignalStrength &&
- signal.gsmSignalStrength >= 0 &&
- signal.gsmSignalStrength <= 31) {
- let signalStrength = -113 + 2 * signal.gsmSignalStrength;
- info.voice.signalStrength = info.data.signalStrength = signalStrength;
-
- // -115 and -85 are referred to AOSP's implementation. These values are
- // not constants and can be customized based on different requirement.
- let signalLevel = this._processSignalLevel(signalStrength, -110, -85);
- info.voice.relSignalStrength = info.data.relSignalStrength = signalLevel;
- }
- }
- }
-
- info.rilMessageType = "signalstrengthchange";
- this._sendNetworkInfoMessage(NETWORK_INFO_SIGNAL, info);
- },
-
- /**
- * Process the network registration flags.
- *
- * @return true if the state changed, false otherwise.
- */
- _processCREG: function(curState, newState) {
- let changed = false;
-
- let regState = this.parseInt(newState[0], NETWORK_CREG_STATE_UNKNOWN);
- if (curState.regState === undefined || curState.regState !== regState) {
- changed = true;
- curState.regState = regState;
-
- curState.state = NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[regState];
- curState.connected = regState == NETWORK_CREG_STATE_REGISTERED_HOME ||
- regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
- curState.roaming = regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
- curState.emergencyCallsOnly = !curState.connected;
- }
-
- if (!curState.cell) {
- curState.cell = {};
- }
-
- // From TS 23.003, 0000 and 0xfffe are indicated that no valid LAI exists
- // in MS. So we still need to report the '0000' as well.
- let lac = this.parseInt(newState[1], -1, 16);
- if (curState.cell.gsmLocationAreaCode === undefined ||
- curState.cell.gsmLocationAreaCode !== lac) {
- curState.cell.gsmLocationAreaCode = lac;
- changed = true;
- }
-
- let cid = this.parseInt(newState[2], -1, 16);
- if (curState.cell.gsmCellId === undefined ||
- curState.cell.gsmCellId !== cid) {
- curState.cell.gsmCellId = cid;
- changed = true;
- }
-
- let radioTech = (newState[3] === undefined ?
- NETWORK_CREG_TECH_UNKNOWN :
- this.parseInt(newState[3], NETWORK_CREG_TECH_UNKNOWN));
- if (curState.radioTech === undefined || curState.radioTech !== radioTech) {
- changed = true;
- curState.radioTech = radioTech;
- curState.type = GECKO_RADIO_TECH[radioTech] || null;
- }
- return changed;
- },
-
- _processVoiceRegistrationState: function(state) {
- let rs = this.voiceRegistrationState;
- let stateChanged = this._processCREG(rs, state);
- if (stateChanged && rs.connected) {
- this.getSmscAddress();
- }
-
- let cell = rs.cell;
- if (this._isCdma) {
- // Some variables below are not used. Comment them instead of removing to
- // keep the information about state[x].
- let cdmaBaseStationId = this.parseInt(state[4], -1);
- let cdmaBaseStationLatitude = this.parseInt(state[5], -2147483648);
- let cdmaBaseStationLongitude = this.parseInt(state[6], -2147483648);
- // let cssIndicator = this.parseInt(state[7]);
- let cdmaSystemId = this.parseInt(state[8], -1);
- let cdmaNetworkId = this.parseInt(state[9], -1);
- // let roamingIndicator = this.parseInt(state[10]);
- // let systemIsInPRL = this.parseInt(state[11]);
- // let defaultRoamingIndicator = this.parseInt(state[12]);
- // let reasonForDenial = this.parseInt(state[13]);
-
- if (cell.cdmaBaseStationId !== cdmaBaseStationId ||
- cell.cdmaBaseStationLatitude !== cdmaBaseStationLatitude ||
- cell.cdmaBaseStationLongitude !== cdmaBaseStationLongitude ||
- cell.cdmaSystemId !== cdmaSystemId ||
- cell.cdmaNetworkId !== cdmaNetworkId) {
- stateChanged = true;
- cell.cdmaBaseStationId = cdmaBaseStationId;
- cell.cdmaBaseStationLatitude = cdmaBaseStationLatitude;
- cell.cdmaBaseStationLongitude = cdmaBaseStationLongitude;
- cell.cdmaSystemId = cdmaSystemId;
- cell.cdmaNetworkId = cdmaNetworkId;
- }
- }
-
- if (stateChanged) {
- rs.rilMessageType = "voiceregistrationstatechange";
- this._sendNetworkInfoMessage(NETWORK_INFO_VOICE_REGISTRATION_STATE, rs);
- }
- },
-
- _processDataRegistrationState: function(state) {
- let rs = this.dataRegistrationState;
- let stateChanged = this._processCREG(rs, state);
- if (stateChanged) {
- rs.rilMessageType = "dataregistrationstatechange";
- this._sendNetworkInfoMessage(NETWORK_INFO_DATA_REGISTRATION_STATE, rs);
- }
- },
-
- _processOperator: function(operatorData) {
- if (operatorData.length < 3) {
- if (DEBUG) {
- this.context.debug("Expected at least 3 strings for operator.");
- }
- }
-
- if (!this.operator) {
- this.operator = {
- rilMessageType: "operatorchange",
- longName: null,
- shortName: null
- };
- }
-
- let [longName, shortName, networkTuple] = operatorData;
- let thisTuple = (this.operator.mcc || "") + (this.operator.mnc || "");
-
- if (this.operator.longName !== longName ||
- this.operator.shortName !== shortName ||
- thisTuple !== networkTuple) {
-
- this.operator.mcc = null;
- this.operator.mnc = null;
-
- if (networkTuple) {
- try {
- this._processNetworkTuple(networkTuple, this.operator);
- } catch (e) {
- if (DEBUG) this.context.debug("Error processing operator tuple: " + e);
- }
- } else {
- // According to ril.h, the operator fields will be NULL when the operator
- // is not currently registered. We can avoid trying to parse the numeric
- // tuple in that case.
- if (DEBUG) {
- this.context.debug("Operator is currently unregistered");
- }
- }
-
- this.operator.longName = longName;
- this.operator.shortName = shortName;
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- if (ICCUtilsHelper.updateDisplayCondition()) {
- ICCUtilsHelper.handleICCInfoChange();
- }
-
- // NETWORK_INFO_OPERATOR message will be sent out by overrideICCNetworkName
- // itself if operator name is overridden after checking, or we have to
- // do it by ourself.
- if (!this.overrideICCNetworkName()) {
- this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator);
- }
- }
- },
-
- _processSuppSvcNotification: function(info) {
- if (DEBUG) {
- this.context.debug("handle supp svc notification: " + JSON.stringify(info));
- }
-
- if (info.notificationType !== 1) {
- // We haven't supported MO intermediate result code, i.e.
- // info.notificationType === 0, which refers to code1 defined in 3GPP
- // 27.007 7.17. We only support partial MT unsolicited result code,
- // referring to code2, for now.
- return;
- }
-
- let notification = null;
-
- switch (info.code) {
- case SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD:
- case SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED:
- notification = GECKO_SUPP_SVC_NOTIFICATION_FROM_CODE2[info.code];
- break;
- default:
- // Notification type not supported.
- return;
- }
-
- let message = {rilMessageType: "suppSvcNotification",
- number: info.number, // could be empty.
- notification: notification};
- this.sendChromeMessage(message);
- },
-
- _cancelEmergencyCbModeTimeout: function() {
- if (this._exitEmergencyCbModeTimeoutID) {
- clearTimeout(this._exitEmergencyCbModeTimeoutID);
- this._exitEmergencyCbModeTimeoutID = null;
- }
- },
-
- _handleChangedEmergencyCbMode: function(active) {
- this._isInEmergencyCbMode = active;
-
- // Clear the existed timeout event.
- this._cancelEmergencyCbModeTimeout();
-
- // Start a new timeout event when entering the mode.
- if (active) {
- this._exitEmergencyCbModeTimeoutID = setTimeout(
- this.exitEmergencyCbMode.bind(this), EMERGENCY_CB_MODE_TIMEOUT_MS);
- }
-
- let message = {rilMessageType: "emergencyCbModeChange",
- active: active,
- timeoutMs: EMERGENCY_CB_MODE_TIMEOUT_MS};
- this.sendChromeMessage(message);
- },
-
- _updateNetworkSelectionMode: function(mode) {
- if (this.networkSelectionMode === mode) {
- return;
- }
-
- let options = {
- rilMessageType: "networkselectionmodechange",
- mode: mode
- };
- this.networkSelectionMode = mode;
- this._sendNetworkInfoMessage(NETWORK_INFO_NETWORK_SELECTION_MODE, options);
- },
-
- _processNetworks: function() {
- let strings = this.context.Buf.readStringList();
- let networks = [];
-
- for (let i = 0; i < strings.length;
- i += RILQUIRKS_AVAILABLE_NETWORKS_EXTRA_STRING ? 5 : 4) {
- let network = {
- longName: strings[i],
- shortName: strings[i + 1],
- mcc: null,
- mnc: null,
- state: null
- };
-
- let networkTuple = strings[i + 2];
- try {
- this._processNetworkTuple(networkTuple, network);
- } catch (e) {
- if (DEBUG) this.context.debug("Error processing operator tuple: " + e);
- }
-
- let state = strings[i + 3];
- network.state = RIL_QAN_STATE_TO_GECKO_STATE[state];
-
- networks.push(network);
- }
- return networks;
- },
-
- /**
- * The "numeric" portion of the operator info is a tuple
- * containing MCC (country code) and MNC (network code).
- * AFAICT, MCC should always be 3 digits, making the remaining
- * portion the MNC.
- */
- _processNetworkTuple: function(networkTuple, network) {
- let tupleLen = networkTuple.length;
-
- if (tupleLen == 5 || tupleLen == 6) {
- network.mcc = networkTuple.substr(0, 3);
- network.mnc = networkTuple.substr(3);
- } else {
- network.mcc = null;
- network.mnc = null;
-
- throw new Error("Invalid network tuple (should be 5 or 6 digits): " + networkTuple);
- }
- },
-
- /**
- * Check if GSM radio access technology group.
- */
- _isGsmTechGroup: function(radioTech) {
- if (!radioTech) {
- return true;
- }
-
- switch(radioTech) {
- case NETWORK_CREG_TECH_GPRS:
- case NETWORK_CREG_TECH_EDGE:
- case NETWORK_CREG_TECH_UMTS:
- case NETWORK_CREG_TECH_HSDPA:
- case NETWORK_CREG_TECH_HSUPA:
- case NETWORK_CREG_TECH_HSPA:
- case NETWORK_CREG_TECH_LTE:
- case NETWORK_CREG_TECH_HSPAP:
- case NETWORK_CREG_TECH_GSM:
- case NETWORK_CREG_TECH_DCHSPAP_1:
- case NETWORK_CREG_TECH_DCHSPAP_2:
- return true;
- }
-
- return false;
- },
-
- /**
- * Process radio technology change.
- */
- _processRadioTech: function(radioTech) {
- let isCdma = !this._isGsmTechGroup(radioTech);
- this.radioTech = radioTech;
-
- if (DEBUG) {
- this.context.debug("Radio tech is set to: " + GECKO_RADIO_TECH[radioTech] +
- ", it is a " + (isCdma?"cdma":"gsm") + " technology");
- }
-
- // We should request SIM information when
- // 1. Radio state has been changed, so we are waiting for radioTech or
- // 2. isCdma is different from this._isCdma.
- if (this._waitingRadioTech || isCdma != this._isCdma) {
- this._isCdma = isCdma;
- this._waitingRadioTech = false;
- this.getICCStatus();
- }
- },
-
- /**
- * Helper for returning the TOA for the given dial string.
- */
- _toaFromString: function(number) {
- let toa = TOA_UNKNOWN;
- if (number && number.length > 0 && number[0] == '+') {
- toa = TOA_INTERNATIONAL;
- }
- return toa;
- },
-
- /**
- * @param message A decoded SMS-DELIVER message.
- *
- * @see 3GPP TS 31.111 section 7.1.1
- */
- dataDownloadViaSMSPP: function(message) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let options = {
- pid: message.pid,
- dcs: message.dcs,
- encoding: message.encoding,
- };
- Buf.newParcel(REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, options);
-
- Buf.seekIncoming(-1 * (Buf.getCurrentParcelSize() - Buf.getReadAvailable()
- - 2 * Buf.UINT32_SIZE)); // Skip response_type & request_type.
- let messageStringLength = Buf.readInt32(); // In semi-octets
- let smscLength = GsmPDUHelper.readHexOctet(); // In octets, inclusive of TOA
- let tpduLength = (messageStringLength / 2) - (smscLength + 1); // In octets
-
- // Device identities: 4 bytes
- // Address: 0 or (2 + smscLength)
- // SMS TPDU: (2 or 3) + tpduLength
- let berLen = 4 +
- (smscLength ? (2 + smscLength) : 0) +
- (tpduLength <= 127 ? 2 : 3) + tpduLength; // In octets
-
- let parcelLength = (berLen <= 127 ? 2 : 3) + berLen; // In octets
- Buf.writeInt32(parcelLength * 2); // In semi-octets
-
- // Write a BER-TLV
- GsmPDUHelper.writeHexOctet(BER_SMS_PP_DOWNLOAD_TAG);
- if (berLen > 127) {
- GsmPDUHelper.writeHexOctet(0x81);
- }
- GsmPDUHelper.writeHexOctet(berLen);
-
- // Device Identifies-TLV
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(0x02);
- GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_NETWORK);
- GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_SIM);
-
- // Address-TLV
- if (smscLength) {
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ADDRESS);
- GsmPDUHelper.writeHexOctet(smscLength);
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * smscLength);
- }
-
- // SMS TPDU-TLV
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_SMS_TPDU |
- COMPREHENSIONTLV_FLAG_CR);
- if (tpduLength > 127) {
- GsmPDUHelper.writeHexOctet(0x81);
- }
- GsmPDUHelper.writeHexOctet(tpduLength);
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * tpduLength);
-
- // Write 2 string delimitors for the total string length must be even.
- Buf.writeStringDelimiter(0);
-
- Buf.sendParcel();
- },
-
- /**
- * @param success A boolean value indicating the result of previous
- * SMS-DELIVER message handling.
- * @param responsePduLen ICC IO response PDU length in octets.
- * @param options An object that contains four attributes: `pid`, `dcs`,
- * `encoding` and `responsePduLen`.
- *
- * @see 3GPP TS 23.040 section 9.2.2.1a
- */
- acknowledgeIncomingGsmSmsWithPDU: function(success, responsePduLen, options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- Buf.newParcel(REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU);
-
- // Two strings.
- Buf.writeInt32(2);
-
- // String 1: Success
- Buf.writeString(success ? "1" : "0");
-
- // String 2: RP-ACK/RP-ERROR PDU
- Buf.writeInt32(2 * (responsePduLen + (success ? 5 : 6))); // In semi-octet
- // 1. TP-MTI & TP-UDHI
- GsmPDUHelper.writeHexOctet(PDU_MTI_SMS_DELIVER);
- if (!success) {
- // 2. TP-FCS
- GsmPDUHelper.writeHexOctet(PDU_FCS_USIM_DATA_DOWNLOAD_ERROR);
- }
- // 3. TP-PI
- GsmPDUHelper.writeHexOctet(PDU_PI_USER_DATA_LENGTH |
- PDU_PI_DATA_CODING_SCHEME |
- PDU_PI_PROTOCOL_IDENTIFIER);
- // 4. TP-PID
- GsmPDUHelper.writeHexOctet(options.pid);
- // 5. TP-DCS
- GsmPDUHelper.writeHexOctet(options.dcs);
- // 6. TP-UDL
- if (options.encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- GsmPDUHelper.writeHexOctet(Math.floor(responsePduLen * 8 / 7));
- } else {
- GsmPDUHelper.writeHexOctet(responsePduLen);
- }
- // TP-UD
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * responsePduLen);
- // Write 2 string delimitors for the total string length must be even.
- Buf.writeStringDelimiter(0);
-
- Buf.sendParcel();
- },
-
- /**
- * @param message A decoded SMS-DELIVER message.
- */
- writeSmsToSIM: function(message) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- Buf.newParcel(REQUEST_WRITE_SMS_TO_SIM);
-
- // Write EFsms Status
- Buf.writeInt32(EFSMS_STATUS_FREE);
-
- Buf.seekIncoming(-1 * (Buf.getCurrentParcelSize() - Buf.getReadAvailable()
- - 2 * Buf.UINT32_SIZE)); // Skip response_type & request_type.
- let messageStringLength = Buf.readInt32(); // In semi-octets
- let smscLength = GsmPDUHelper.readHexOctet(); // In octets, inclusive of TOA
- let pduLength = (messageStringLength / 2) - (smscLength + 1); // In octets
-
- // 1. Write PDU first.
- if (smscLength > 0) {
- Buf.seekIncoming(smscLength * Buf.PDU_HEX_OCTET_SIZE);
- }
- // Write EFsms PDU string length
- Buf.writeInt32(2 * pduLength); // In semi-octets
- if (pduLength) {
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * pduLength);
- }
- // Write 2 string delimitors for the total string length must be even.
- Buf.writeStringDelimiter(0);
-
- // 2. Write SMSC
- // Write EFsms SMSC string length
- Buf.writeInt32(2 * (smscLength + 1)); // Plus smscLength itself, in semi-octets
- // Write smscLength
- GsmPDUHelper.writeHexOctet(smscLength);
- // Write TOA & SMSC Address
- if (smscLength) {
- Buf.seekIncoming(-1 * (Buf.getCurrentParcelSize() - Buf.getReadAvailable()
- - 2 * Buf.UINT32_SIZE // Skip response_type, request_type.
- - 2 * Buf.PDU_HEX_OCTET_SIZE)); // Skip messageStringLength & smscLength.
- Buf.copyIncomingToOutgoing(Buf.PDU_HEX_OCTET_SIZE * smscLength);
- }
- // Write 2 string delimitors for the total string length must be even.
- Buf.writeStringDelimiter(0);
-
- Buf.sendParcel();
- },
-
- /**
- * Helper to delegate the received sms segment to RadioInterface to process.
- *
- * @param message
- * Received sms message.
- *
- * @return MOZ_FCS_WAIT_FOR_EXPLICIT_ACK
- */
- _processSmsMultipart: function(message) {
- message.rilMessageType = "sms-received";
-
- this.sendChromeMessage(message);
-
- return MOZ_FCS_WAIT_FOR_EXPLICIT_ACK;
- },
-
- /**
- * Helper for processing SMS-STATUS-REPORT PDUs.
- *
- * @param length
- * Length of SMS string in the incoming parcel.
- *
- * @return A failure cause defined in 3GPP 23.040 clause 9.2.3.22.
- */
- _processSmsStatusReport: function(length) {
- let [message, result] = this.context.GsmPDUHelper.processReceivedSms(length);
- if (!message) {
- if (DEBUG) this.context.debug("invalid SMS-STATUS-REPORT");
- return PDU_FCS_UNSPECIFIED;
- }
-
- let options = this._pendingSentSmsMap[message.messageRef];
- if (!options) {
- if (DEBUG) this.context.debug("no pending SMS-SUBMIT message");
- return PDU_FCS_OK;
- }
-
- let status = message.status;
-
- // 3GPP TS 23.040 9.2.3.15 `The MS shall interpret any reserved values as
- // "Service Rejected"(01100011) but shall store them exactly as received.`
- if ((status >= 0x80)
- || ((status >= PDU_ST_0_RESERVED_BEGIN)
- && (status < PDU_ST_0_SC_SPECIFIC_BEGIN))
- || ((status >= PDU_ST_1_RESERVED_BEGIN)
- && (status < PDU_ST_1_SC_SPECIFIC_BEGIN))
- || ((status >= PDU_ST_2_RESERVED_BEGIN)
- && (status < PDU_ST_2_SC_SPECIFIC_BEGIN))
- || ((status >= PDU_ST_3_RESERVED_BEGIN)
- && (status < PDU_ST_3_SC_SPECIFIC_BEGIN))
- ) {
- status = PDU_ST_3_SERVICE_REJECTED;
- }
-
- // Pending. Waiting for next status report.
- if ((status >>> 5) == 0x01) {
- if (DEBUG) this.context.debug("SMS-STATUS-REPORT: delivery still pending");
- return PDU_FCS_OK;
- }
-
- delete this._pendingSentSmsMap[message.messageRef];
-
- let deliveryStatus = ((status >>> 5) === 0x00)
- ? GECKO_SMS_DELIVERY_STATUS_SUCCESS
- : GECKO_SMS_DELIVERY_STATUS_ERROR;
- this.sendChromeMessage({
- rilMessageType: options.rilMessageType,
- rilMessageToken: options.rilMessageToken,
- deliveryStatus: deliveryStatus
- });
-
- return PDU_FCS_OK;
- },
-
- /**
- * Helper for processing CDMA SMS Delivery Acknowledgment Message
- *
- * @param message
- * decoded SMS Delivery ACK message from CdmaPDUHelper.
- *
- * @return A failure cause defined in 3GPP 23.040 clause 9.2.3.22.
- */
- _processCdmaSmsStatusReport: function(message) {
- let options = this._pendingSentSmsMap[message.msgId];
- if (!options) {
- if (DEBUG) this.context.debug("no pending SMS-SUBMIT message");
- return PDU_FCS_OK;
- }
-
- if (message.errorClass === 2) {
- if (DEBUG) {
- this.context.debug("SMS-STATUS-REPORT: delivery still pending, " +
- "msgStatus: " + message.msgStatus);
- }
- return PDU_FCS_OK;
- }
-
- delete this._pendingSentSmsMap[message.msgId];
-
- if (message.errorClass === -1 && message.body) {
- // Process as normal incoming SMS, if errorClass is invalid
- // but message body is available.
- return this._processSmsMultipart(message);
- }
-
- let deliveryStatus = (message.errorClass === 0)
- ? GECKO_SMS_DELIVERY_STATUS_SUCCESS
- : GECKO_SMS_DELIVERY_STATUS_ERROR;
- this.sendChromeMessage({
- rilMessageType: options.rilMessageType,
- rilMessageToken: options.rilMessageToken,
- deliveryStatus: deliveryStatus
- });
-
- return PDU_FCS_OK;
- },
-
- /**
- * Helper for processing CDMA SMS WAP Push Message
- *
- * @param message
- * decoded WAP message from CdmaPDUHelper.
- *
- * @return A failure cause defined in 3GPP 23.040 clause 9.2.3.22.
- */
- _processCdmaSmsWapPush: function(message) {
- if (!message.data) {
- if (DEBUG) this.context.debug("no data inside WAP Push message.");
- return PDU_FCS_OK;
- }
-
- // See 6.5. MAPPING OF WDP TO CDMA SMS in WAP-295-WDP.
- //
- // Field | Length (bits)
- // -----------------------------------------
- // MSG_TYPE | 8
- // TOTAL_SEGMENTS | 8
- // SEGMENT_NUMBER | 8
- // DATAGRAM | (NUM_FIELDS - 3) * 8
- let index = 0;
- if (message.data[index++] !== 0) {
- if (DEBUG) this.context.debug("Ignore a WAP Message which is not WDP.");
- return PDU_FCS_OK;
- }
-
- // 1. Originator Address in SMS-TL + Message_Id in SMS-TS are used to identify a unique WDP datagram.
- // 2. TOTAL_SEGMENTS, SEGMENT_NUMBER are used to verify that a complete
- // datagram has been received and is ready to be passed to a higher layer.
- message.header = {
- segmentRef: message.msgId,
- segmentMaxSeq: message.data[index++],
- segmentSeq: message.data[index++] + 1 // It's zero-based in CDMA WAP Push.
- };
-
- if (message.header.segmentSeq > message.header.segmentMaxSeq) {
- if (DEBUG) this.context.debug("Wrong WDP segment info.");
- return PDU_FCS_OK;
- }
-
- // Ports are only specified in 1st segment.
- if (message.header.segmentSeq == 1) {
- message.header.originatorPort = message.data[index++] << 8;
- message.header.originatorPort |= message.data[index++];
- message.header.destinationPort = message.data[index++] << 8;
- message.header.destinationPort |= message.data[index++];
- }
-
- message.data = message.data.subarray(index);
-
- return this._processSmsMultipart(message);
- },
-
- /**
- * Helper for processing sent multipart SMS.
- */
- _processSentSmsSegment: function(options) {
- // Setup attributes for sending next segment
- let next = options.segmentSeq;
- options.body = options.segments[next].body;
- options.encodedBodyLength = options.segments[next].encodedBodyLength;
- options.segmentSeq = next + 1;
-
- this.sendSMS(options);
- },
-
- /**
- * Helper for processing result of send SMS.
- *
- * @param length
- * Length of SMS string in the incoming parcel.
- * @param options
- * Sms information.
- */
- _processSmsSendResult: function(length, options) {
- if (options.errorMsg) {
- if (DEBUG) {
- this.context.debug("_processSmsSendResult: errorMsg = " +
- options.errorMsg);
- }
-
- this.sendChromeMessage({
- rilMessageType: options.rilMessageType,
- rilMessageToken: options.rilMessageToken,
- errorMsg: options.errorMsg,
- });
- return;
- }
-
- let Buf = this.context.Buf;
- options.messageRef = Buf.readInt32();
- options.ackPDU = Buf.readString();
- options.errorCode = Buf.readInt32();
-
- if ((options.segmentMaxSeq > 1)
- && (options.segmentSeq < options.segmentMaxSeq)) {
- // Not last segment
- this._processSentSmsSegment(options);
- } else {
- // Last segment sent with success.
- if (options.requestStatusReport) {
- if (DEBUG) {
- this.context.debug("waiting SMS-STATUS-REPORT for messageRef " +
- options.messageRef);
- }
- this._pendingSentSmsMap[options.messageRef] = options;
- }
-
- this.sendChromeMessage({
- rilMessageType: options.rilMessageType,
- rilMessageToken: options.rilMessageToken,
- });
- }
- },
-
- _processReceivedSmsCbPage: function(original) {
- if (original.numPages <= 1) {
- if (original.body) {
- original.fullBody = original.body;
- delete original.body;
- } else if (original.data) {
- original.fullData = original.data;
- delete original.data;
- }
- return original;
- }
-
- // Hash = <serial>:<mcc>:<mnc>:<lac>:<cid>
- let hash = original.serial + ":" + this.iccInfo.mcc + ":"
- + this.iccInfo.mnc + ":";
- switch (original.geographicalScope) {
- case CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE:
- case CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE:
- hash += this.voiceRegistrationState.cell.gsmLocationAreaCode + ":"
- + this.voiceRegistrationState.cell.gsmCellId;
- break;
- case CB_GSM_GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE:
- hash += this.voiceRegistrationState.cell.gsmLocationAreaCode + ":";
- break;
- default:
- hash += ":";
- break;
- }
-
- let index = original.pageIndex;
-
- let options = this._receivedSmsCbPagesMap[hash];
- if (!options) {
- options = original;
- this._receivedSmsCbPagesMap[hash] = options;
-
- options.receivedPages = 0;
- options.pages = [];
- } else if (options.pages[index]) {
- // Duplicated page?
- if (DEBUG) {
- this.context.debug("Got duplicated page no." + index +
- " of a multipage SMSCB: " + JSON.stringify(original));
- }
- return null;
- }
-
- if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
- options.pages[index] = original.data;
- delete original.data;
- } else {
- options.pages[index] = original.body;
- delete original.body;
- }
- options.receivedPages++;
- if (options.receivedPages < options.numPages) {
- if (DEBUG) {
- this.context.debug("Got page no." + index + " of a multipage SMSCB: " +
- JSON.stringify(options));
- }
- return null;
- }
-
- // Remove from map
- delete this._receivedSmsCbPagesMap[hash];
-
- // Rebuild full body
- if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
- // Uint8Array doesn't have `concat`, so we have to merge all pages by hand.
- let fullDataLen = 0;
- for (let i = 1; i <= options.numPages; i++) {
- fullDataLen += options.pages[i].length;
- }
-
- options.fullData = new Uint8Array(fullDataLen);
- for (let d= 0, i = 1; i <= options.numPages; i++) {
- let data = options.pages[i];
- for (let j = 0; j < data.length; j++) {
- options.fullData[d++] = data[j];
- }
- }
- } else {
- options.fullBody = options.pages.join("");
- }
-
- if (DEBUG) {
- this.context.debug("Got full multipage SMSCB: " + JSON.stringify(options));
- }
-
- return options;
- },
-
- _mergeCellBroadcastConfigs: function(list, from, to) {
- if (!list) {
- return [from, to];
- }
-
- for (let i = 0, f1, t1; i < list.length;) {
- f1 = list[i++];
- t1 = list[i++];
- if (to == f1) {
- // ...[from]...[to|f1]...(t1)
- list[i - 2] = from;
- return list;
- }
-
- if (to < f1) {
- // ...[from]...(to)...[f1] or ...[from]...(to)[f1]
- if (i > 2) {
- // Not the first range pair, merge three arrays.
- return list.slice(0, i - 2).concat([from, to]).concat(list.slice(i - 2));
- } else {
- return [from, to].concat(list);
- }
- }
-
- if (from > t1) {
- // ...[f1]...(t1)[from] or ...[f1]...(t1)...[from]
- continue;
- }
-
- // Have overlap or merge-able adjacency with [f1]...(t1). Replace it
- // with [min(from, f1)]...(max(to, t1)).
-
- let changed = false;
- if (from < f1) {
- // [from]...[f1]...(t1) or [from][f1]...(t1)
- // Save minimum from value.
- list[i - 2] = from;
- changed = true;
- }
-
- if (to <= t1) {
- // [from]...[to](t1) or [from]...(to|t1)
- // Can't have further merge-able adjacency. Return.
- return list;
- }
-
- // Try merging possible next adjacent range.
- let j = i;
- for (let f2, t2; j < list.length;) {
- f2 = list[j++];
- t2 = list[j++];
- if (to > t2) {
- // [from]...[f2]...[t2]...(to) or [from]...[f2]...[t2](to)
- // Merge next adjacent range again.
- continue;
- }
-
- if (to < t2) {
- if (to < f2) {
- // [from]...(to)[f2] or [from]...(to)...[f2]
- // Roll back and give up.
- j -= 2;
- } else if (to < t2) {
- // [from]...[to|f2]...(t2), or [from]...[f2]...[to](t2)
- // Merge to [from]...(t2) and give up.
- to = t2;
- }
- }
-
- break;
- }
-
- // Save maximum to value.
- list[i - 1] = to;
-
- if (j != i) {
- // Remove merged adjacent ranges.
- let ret = list.slice(0, i);
- if (j < list.length) {
- ret = ret.concat(list.slice(j));
- }
- return ret;
- }
-
- return list;
- }
-
- // Append to the end.
- list.push(from);
- list.push(to);
-
- return list;
- },
-
- _isCellBroadcastConfigReady: function() {
- if (!("MMI" in this.cellBroadcastConfigs)) {
- return false;
- }
-
- // CBMI should be ready in GSM.
- if (!this._isCdma &&
- (!("CBMI" in this.cellBroadcastConfigs) ||
- !("CBMID" in this.cellBroadcastConfigs) ||
- !("CBMIR" in this.cellBroadcastConfigs))) {
- return false;
- }
-
- return true;
- },
-
- /**
- * Merge all members of cellBroadcastConfigs into mergedCellBroadcastConfig.
- */
- _mergeAllCellBroadcastConfigs: function() {
- if (!this._isCellBroadcastConfigReady()) {
- if (DEBUG) {
- this.context.debug("cell broadcast configs not ready, waiting ...");
- }
- return;
- }
-
- // Prepare cell broadcast config. CBMI* are only used in GSM.
- let usedCellBroadcastConfigs = {MMI: this.cellBroadcastConfigs.MMI};
- if (!this._isCdma) {
- usedCellBroadcastConfigs.CBMI = this.cellBroadcastConfigs.CBMI;
- usedCellBroadcastConfigs.CBMID = this.cellBroadcastConfigs.CBMID;
- usedCellBroadcastConfigs.CBMIR = this.cellBroadcastConfigs.CBMIR;
- }
-
- if (DEBUG) {
- this.context.debug("Cell Broadcast search lists: " +
- JSON.stringify(usedCellBroadcastConfigs));
- }
-
- let list = null;
- for (let key in usedCellBroadcastConfigs) {
- let ll = usedCellBroadcastConfigs[key];
- if (ll == null) {
- continue;
- }
-
- for (let i = 0; i < ll.length; i += 2) {
- list = this._mergeCellBroadcastConfigs(list, ll[i], ll[i + 1]);
- }
- }
-
- if (DEBUG) {
- this.context.debug("Cell Broadcast search lists(merged): " +
- JSON.stringify(list));
- }
- this.mergedCellBroadcastConfig = list;
- this.updateCellBroadcastConfig();
- },
-
- /**
- * Check whether search list from settings is settable by MMI, that is,
- * whether the range is bounded in any entries of CB_NON_MMI_SETTABLE_RANGES.
- */
- _checkCellBroadcastMMISettable: function(from, to) {
- if ((to <= from) || (from >= 65536) || (from < 0)) {
- return false;
- }
-
- if (!this._isCdma) {
- // GSM not settable ranges.
- for (let i = 0, f, t; i < CB_NON_MMI_SETTABLE_RANGES.length;) {
- f = CB_NON_MMI_SETTABLE_RANGES[i++];
- t = CB_NON_MMI_SETTABLE_RANGES[i++];
- if ((from < t) && (to > f)) {
- // Have overlap.
- return false;
- }
- }
- }
-
- return true;
- },
-
- /**
- * Convert Cell Broadcast settings string into search list.
- */
- _convertCellBroadcastSearchList: function(searchListStr) {
- let parts = searchListStr && searchListStr.split(",");
- if (!parts) {
- return null;
- }
-
- let list = null;
- let result, from, to;
- for (let range of parts) {
- // Match "12" or "12-34". The result will be ["12", "12", null] or
- // ["12-34", "12", "34"].
- result = range.match(/^(\d+)(?:-(\d+))?$/);
- if (!result) {
- throw "Invalid format";
- }
-
- from = parseInt(result[1], 10);
- to = (result[2]) ? parseInt(result[2], 10) + 1 : from + 1;
- if (!this._checkCellBroadcastMMISettable(from, to)) {
- throw "Invalid range";
- }
-
- if (list == null) {
- list = [];
- }
- list.push(from);
- list.push(to);
- }
-
- return list;
- },
-
- /**
- * Handle incoming messages from the main UI thread.
- *
- * @param message
- * Object containing the message. Messages are supposed
- */
- handleChromeMessage: function(message) {
- if (DEBUG) {
- this.context.debug("Received chrome message " + JSON.stringify(message));
- }
- let method = this[message.rilMessageType];
- if (typeof method != "function") {
- if (DEBUG) {
- this.context.debug("Don't know what to do with message " +
- JSON.stringify(message));
- }
- return;
- }
- method.call(this, message);
- },
-
- /**
- * Process STK Proactive Command.
- */
- processStkProactiveCommand: function() {
- let Buf = this.context.Buf;
- let length = Buf.readInt32();
- let berTlv;
- try {
- berTlv = this.context.BerTlvHelper.decode(length / 2);
- } catch (e) {
- if (DEBUG) this.context.debug("processStkProactiveCommand : " + e);
- this.sendStkTerminalResponse({
- resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
- return;
- }
-
- Buf.readStringDelimiter(length);
-
- let ctlvs = berTlv.value;
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
- if (!ctlv) {
- this.sendStkTerminalResponse({
- resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
- throw new Error("Can't find COMMAND_DETAILS ComprehensionTlv");
- }
-
- let cmdDetails = ctlv.value;
- if (DEBUG) {
- this.context.debug("commandNumber = " + cmdDetails.commandNumber +
- " typeOfCommand = " + cmdDetails.typeOfCommand.toString(16) +
- " commandQualifier = " + cmdDetails.commandQualifier);
- }
-
- // STK_CMD_MORE_TIME need not to propagate event to chrome.
- if (cmdDetails.typeOfCommand == STK_CMD_MORE_TIME) {
- this.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_OK});
- return;
- }
-
- this.context.StkCommandParamsFactory.createParam(cmdDetails,
- ctlvs,
- (aResult) => {
- cmdDetails.options = aResult;
- cmdDetails.rilMessageType = "stkcommand";
- this.sendChromeMessage(cmdDetails);
- });
- },
-
- sendDefaultResponse: function(options) {
- if (!options.rilMessageType) {
- return;
- }
-
- this.sendChromeMessage(options);
- },
-
- /**
- * Send messages to the main thread.
- */
- sendChromeMessage: function(message) {
- message.rilMessageClientId = this.context.clientId;
- postMessage(message);
- },
-
- /**
- * Handle incoming requests from the RIL. We find the method that
- * corresponds to the request type. Incidentally, the request type
- * _is_ the method name, so that's easy.
- */
-
- handleParcel: function(request_type, length, options) {
- let method = this[request_type];
- if (typeof method == "function") {
- if (DEBUG) this.context.debug("Handling parcel as " + method.name);
- method.call(this, length, options);
- }
-
- if (this.telephonyRequestQueue.isValidRequest(request_type)) {
- this.telephonyRequestQueue.pop(request_type);
- }
- }
-};
-
-RilObject.prototype[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) {
- if (options.errorMsg) {
- return;
- }
-
- let iccStatus = {};
- let Buf = this.context.Buf;
- iccStatus.cardState = Buf.readInt32(); // CARD_STATE_*
- iccStatus.universalPINState = Buf.readInt32(); // CARD_PINSTATE_*
- iccStatus.gsmUmtsSubscriptionAppIndex = Buf.readInt32();
- iccStatus.cdmaSubscriptionAppIndex = Buf.readInt32();
- iccStatus.imsSubscriptionAppIndex = Buf.readInt32();
-
- let apps_length = Buf.readInt32();
- if (apps_length > CARD_MAX_APPS) {
- apps_length = CARD_MAX_APPS;
- }
-
- iccStatus.apps = [];
- for (let i = 0 ; i < apps_length ; i++) {
- iccStatus.apps.push({
- app_type: Buf.readInt32(), // CARD_APPTYPE_*
- app_state: Buf.readInt32(), // CARD_APPSTATE_*
- perso_substate: Buf.readInt32(), // CARD_PERSOSUBSTATE_*
- aid: Buf.readString(),
- app_label: Buf.readString(),
- pin1_replaced: Buf.readInt32(),
- pin1: Buf.readInt32(),
- pin2: Buf.readInt32()
- });
- if (RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS) {
- Buf.readInt32();
- Buf.readInt32();
- Buf.readInt32();
- Buf.readInt32();
- }
- }
-
- if (DEBUG) this.context.debug("iccStatus: " + JSON.stringify(iccStatus));
- this._processICCStatus(iccStatus);
-};
-RilObject.prototype[REQUEST_ENTER_SIM_PIN] = function REQUEST_ENTER_SIM_PIN(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_ENTER_SIM_PUK] = function REQUEST_ENTER_SIM_PUK(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_ENTER_SIM_PIN2] = function REQUEST_ENTER_SIM_PIN2(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_ENTER_SIM_PUK2] = function REQUEST_ENTER_SIM_PUK(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_CHANGE_SIM_PIN] = function REQUEST_CHANGE_SIM_PIN(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_CHANGE_SIM_PIN2] = function REQUEST_CHANGE_SIM_PIN2(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE] =
- function REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE(length, options) {
- this._processEnterAndChangeICCResponses(length, options);
-};
-RilObject.prototype[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, options) {
- // Retry getCurrentCalls several times when error occurs.
- if (options.errorMsg) {
- if (this._getCurrentCallsRetryCount < GET_CURRENT_CALLS_RETRY_MAX) {
- this._getCurrentCallsRetryCount++;
- this.getCurrentCalls(options);
- } else {
- this.sendDefaultResponse(options);
- }
- return;
- }
-
- this._getCurrentCallsRetryCount = 0;
-
- let Buf = this.context.Buf;
- let calls_length = 0;
- // The RIL won't even send us the length integer if there are no active calls.
- // So only read this integer if the parcel actually has it.
- if (length) {
- calls_length = Buf.readInt32();
- }
-
- let calls = {};
- for (let i = 0; i < calls_length; i++) {
- let call = {};
-
- // Extra uint32 field to get correct callIndex and rest of call data for
- // call waiting feature.
- if (RILQUIRKS_EXTRA_UINT32_2ND_CALL && i > 0) {
- Buf.readInt32();
- }
-
- call.state = Buf.readInt32(); // CALL_STATE_*
- call.callIndex = Buf.readInt32(); // GSM index (1-based)
- call.toa = Buf.readInt32();
- call.isMpty = Boolean(Buf.readInt32());
- call.isMT = Boolean(Buf.readInt32());
- call.als = Buf.readInt32();
- call.isVoice = Boolean(Buf.readInt32());
- call.isVoicePrivacy = Boolean(Buf.readInt32());
- if (RILQUIRKS_CALLSTATE_EXTRA_UINT32) {
- Buf.readInt32();
- }
- call.number = Buf.readString();
- call.numberPresentation = Buf.readInt32(); // CALL_PRESENTATION_*
- call.name = Buf.readString();
- call.namePresentation = Buf.readInt32();
-
- call.uusInfo = null;
- let uusInfoPresent = Buf.readInt32();
- if (uusInfoPresent == 1) {
- call.uusInfo = {
- type: Buf.readInt32(),
- dcs: Buf.readInt32(),
- userData: null //XXX TODO byte array?!?
- };
- }
-
- if (call.isVoice) {
- calls[call.callIndex] = call;
- }
- }
-
- options.calls = calls;
- options.rilMessageType = options.rilMessageType || "currentCalls";
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_DIAL] = function REQUEST_DIAL(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_DIAL_EMERGENCY_CALL] = function REQUEST_DIAL_EMERGENCY_CALL(length, options) {
- RilObject.prototype[REQUEST_DIAL].call(this, length, options);
-};
-RilObject.prototype[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, options) {
- if (options.errorMsg) {
- return;
- }
-
- this.iccInfoPrivate.imsi = this.context.Buf.readString();
- if (DEBUG) {
- this.context.debug("IMSI: " + this.iccInfoPrivate.imsi);
- }
-
- options.rilMessageType = "iccimsi";
- options.imsi = this.iccInfoPrivate.imsi;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_HANGUP] = function REQUEST_HANGUP(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_HANGUP_WAITING_OR_BACKGROUND] = function REQUEST_HANGUP_WAITING_OR_BACKGROUND(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = function REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_CONFERENCE] = function REQUEST_CONFERENCE(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_UDUB] = function REQUEST_UDUB(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length, options) {
- // Treat it as CALL_FAIL_ERROR_UNSPECIFIED if the request failed.
- let failCause = CALL_FAIL_ERROR_UNSPECIFIED;
-
- if (!options.errorMsg) {
- let Buf = this.context.Buf;
- let num = length ? Buf.readInt32() : 0;
-
- if (num) {
- let causeNum = Buf.readInt32();
- failCause = RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[causeNum] || failCause;
- }
- if (DEBUG) this.context.debug("Last call fail cause: " + failCause);
- }
-
- options.failCause = failCause;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_SIGNAL);
-
- if (options.errorMsg) {
- return;
- }
-
- let Buf = this.context.Buf;
- let signal = {};
-
- signal.gsmSignalStrength = Buf.readInt32();
- signal.gsmBitErrorRate = Buf.readInt32();
- if (RILQUIRKS_SIGNAL_EXTRA_INT32) {
- Buf.readInt32();
- }
- signal.cdmaDBM = Buf.readInt32();
- signal.cdmaECIO = Buf.readInt32();
- signal.evdoDBM = Buf.readInt32();
- signal.evdoECIO = Buf.readInt32();
- signal.evdoSNR = Buf.readInt32();
-
- signal.lteSignalStrength = Buf.readInt32();
- signal.lteRSRP = Buf.readInt32();
- signal.lteRSRQ = Buf.readInt32();
- signal.lteRSSNR = Buf.readInt32();
- signal.lteCQI = Buf.readInt32();
-
- if (DEBUG) this.context.debug("signal strength: " + JSON.stringify(signal));
-
- this._processSignalStrength(signal);
-};
-RilObject.prototype[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_VOICE_REGISTRATION_STATE);
-
- if (options.errorMsg) {
- return;
- }
-
- let state = this.context.Buf.readStringList();
- if (DEBUG) this.context.debug("voice registration state: " + state);
-
- this._processVoiceRegistrationState(state);
-};
-RilObject.prototype[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_DATA_REGISTRATION_STATE);
-
- if (options.errorMsg) {
- return;
- }
-
- let state = this.context.Buf.readStringList();
- this._processDataRegistrationState(state);
-};
-RilObject.prototype[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_OPERATOR);
-
- if (options.errorMsg) {
- return;
- }
-
- let operatorData = this.context.Buf.readStringList();
- if (DEBUG) this.context.debug("Operator: " + operatorData);
- this._processOperator(operatorData);
-};
-RilObject.prototype[REQUEST_RADIO_POWER] = function REQUEST_RADIO_POWER(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_DTMF] = null;
-RilObject.prototype[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) {
- this._processSmsSendResult(length, options);
-};
-RilObject.prototype[REQUEST_SEND_SMS_EXPECT_MORE] = null;
-
-RilObject.prototype[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let version = Buf.readInt32();
- // Skip number of data calls.
- Buf.readInt32();
-
- this.readDataCall(options, version);
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
- if (options.errorMsg) {
- if (options.onerror) {
- options.onerror(options.errorMsg);
- }
- return;
- }
-
- let Buf = this.context.Buf;
- options.sw1 = Buf.readInt32();
- options.sw2 = Buf.readInt32();
-
- // See 3GPP TS 11.11, clause 9.4.1 for operation success results.
- if (options.sw1 !== ICC_STATUS_NORMAL_ENDING &&
- options.sw1 !== ICC_STATUS_NORMAL_ENDING_WITH_EXTRA &&
- options.sw1 !== ICC_STATUS_WITH_SIM_DATA &&
- options.sw1 !== ICC_STATUS_WITH_RESPONSE_DATA) {
- if (DEBUG) {
- this.context.debug("ICC I/O Error EF id = 0x" + options.fileId.toString(16) +
- ", command = 0x" + options.command.toString(16) +
- ", sw1 = 0x" + options.sw1.toString(16) +
- ", sw2 = 0x" + options.sw2.toString(16));
- }
- if (options.onerror) {
- // We can get fail cause from sw1/sw2 (See TS 11.11 clause 9.4.1 and
- // ISO 7816-4 clause 6). But currently no one needs this information,
- // so simply reports "GenericFailure" for now.
- options.onerror(GECKO_ERROR_GENERIC_FAILURE);
- }
- return;
- }
- this.context.ICCIOHelper.processICCIO(options);
-};
-RilObject.prototype[REQUEST_SEND_USSD] = function REQUEST_SEND_USSD(length, options) {
- if (DEBUG) {
- this.context.debug("REQUEST_SEND_USSD " + JSON.stringify(options));
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CANCEL_USSD] = function REQUEST_CANCEL_USSD(length, options) {
- if (DEBUG) {
- this.context.debug("REQUEST_CANCEL_USSD" + JSON.stringify(options));
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_CLIR] = function REQUEST_GET_CLIR(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let bufLength = Buf.readInt32();
- if (!bufLength || bufLength < 2) {
- options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
- this.sendChromeMessage(options);
- return;
- }
-
- options.n = Buf.readInt32(); // Will be TS 27.007 +CLIR parameter 'n'.
- options.m = Buf.readInt32(); // Will be TS 27.007 +CLIR parameter 'm'.
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_CLIR] = function REQUEST_SET_CLIR(length, options) {
- if (options.rilMessageType == null) {
- // The request was made by ril_worker itself automatically. Don't report.
- return;
- }
-
- this.sendChromeMessage(options);
-};
-
-RilObject.prototype[REQUEST_QUERY_CALL_FORWARD_STATUS] =
- function REQUEST_QUERY_CALL_FORWARD_STATUS(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let rulesLength = 0;
- if (length) {
- rulesLength = Buf.readInt32();
- }
- if (!rulesLength) {
- options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
- this.sendChromeMessage(options);
- return;
- }
- let rules = new Array(rulesLength);
- for (let i = 0; i < rulesLength; i++) {
- let rule = {};
- rule.active = Buf.readInt32() == 1; // CALL_FORWARD_STATUS_*
- rule.reason = Buf.readInt32(); // CALL_FORWARD_REASON_*
- rule.serviceClass = Buf.readInt32();
- rule.toa = Buf.readInt32();
- rule.number = Buf.readString();
- rule.timeSeconds = Buf.readInt32();
- rules[i] = rule;
- }
- options.rules = rules;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_CALL_FORWARD] =
- function REQUEST_SET_CALL_FORWARD(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_QUERY_CALL_WAITING] =
- function REQUEST_QUERY_CALL_WAITING(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let results = Buf.readInt32List();
- let enabled = (results[0] === 1);
- options.serviceClass = enabled ? results[1] : ICC_SERVICE_CLASS_NONE;
- this.sendChromeMessage(options);
-};
-
-RilObject.prototype[REQUEST_SET_CALL_WAITING] = function REQUEST_SET_CALL_WAITING(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SMS_ACKNOWLEDGE] = null;
-RilObject.prototype[REQUEST_GET_IMEI] = null;
-RilObject.prototype[REQUEST_GET_IMEISV] = null;
-RilObject.prototype[REQUEST_ANSWER] = function REQUEST_ANSWER(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- if (!length) {
- options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
- this.sendChromeMessage(options);
- return;
- }
-
- // Buf.readInt32List()[0] for Call Barring is a bit vector of services.
- options.serviceClass = this.context.Buf.readInt32List()[0];
- if (options.queryServiceClass) {
- options.enabled = (options.serviceClass & options.queryServiceClass) ? true : false;
- options.serviceClass = options.queryServiceClass;
- } else {
- options.enabled = options.serviceClass ? true : false;
- }
-
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_FACILITY_LOCK] = function REQUEST_SET_FACILITY_LOCK(length, options) {
- options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CHANGE_BARRING_PASSWORD] =
- function REQUEST_CHANGE_BARRING_PASSWORD(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELECTION_MODE(length, options) {
- this._receivedNetworkInfo(NETWORK_INFO_NETWORK_SELECTION_MODE);
-
- if (options.errorMsg) {
- return;
- }
-
- let mode = this.context.Buf.readInt32List();
- let selectionMode;
-
- switch (mode[0]) {
- case NETWORK_SELECTION_MODE_AUTOMATIC:
- selectionMode = GECKO_NETWORK_SELECTION_AUTOMATIC;
- break;
- case NETWORK_SELECTION_MODE_MANUAL:
- selectionMode = GECKO_NETWORK_SELECTION_MANUAL;
- break;
- default:
- selectionMode = GECKO_NETWORK_SELECTION_UNKNOWN;
- break;
- }
-
- this._updateNetworkSelectionMode(selectionMode);
-};
-RilObject.prototype[REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = function REQUEST_SET_NETWORK_SELECTION_AUTOMATIC(length, options) {
- if (!options.errorMsg) {
- this._updateNetworkSelectionMode(GECKO_NETWORK_SELECTION_AUTOMATIC);
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_NETWORK_SELECTION_MANUAL] = function REQUEST_SET_NETWORK_SELECTION_MANUAL(length, options) {
- if (!options.errorMsg) {
- this._updateNetworkSelectionMode(GECKO_NETWORK_SELECTION_MANUAL);
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_QUERY_AVAILABLE_NETWORKS] = function REQUEST_QUERY_AVAILABLE_NETWORKS(length, options) {
- if (!options.errorMsg) {
- options.networks = this._processNetworks();
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_DTMF_START] = function REQUEST_DTMF_START(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_DTMF_STOP] = null;
-RilObject.prototype[REQUEST_BASEBAND_VERSION] = function REQUEST_BASEBAND_VERSION(length, options) {
- if (options.errorMsg) {
- return;
- }
-
- this.basebandVersion = this.context.Buf.readString();
- if (DEBUG) this.context.debug("Baseband version: " + this.basebandVersion);
-};
-RilObject.prototype[REQUEST_SEPARATE_CONNECTION] = function REQUEST_SEPARATE_CONNECTION(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_SET_MUTE] = null;
-RilObject.prototype[REQUEST_GET_MUTE] = null;
-RilObject.prototype[REQUEST_QUERY_CLIP] = function REQUEST_QUERY_CLIP(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let bufLength = Buf.readInt32();
- if (!bufLength) {
- options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
- this.sendChromeMessage(options);
- return;
- }
-
- options.provisioned = Buf.readInt32();
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null;
-
-/**
- * V6:
- * # addresses - A space-delimited list of addresses with optional "/" prefix
- * length.
- * # dnses - A space-delimited list of DNS server addresses.
- * # gateways - A space-delimited list of default gateway addresses.
- *
- * V10:
- * # pcscf - A space-delimited list of Proxy Call State Control Function
- * addresses.
- */
-
-RilObject.prototype.readDataCall = function(options, version) {
- if (!options) {
- options = {};
- }
- let Buf = this.context.Buf;
- options.failCause = Buf.readInt32(); // DATACALL_FAIL_*
- options.suggestedRetryTime = Buf.readInt32();
- options.cid = Buf.readInt32().toString();
- options.active = Buf.readInt32(); // DATACALL_ACTIVE_*
- options.type = Buf.readString();
- options.ifname = Buf.readString();
- options.addresses = Buf.readString();
- options.dnses = Buf.readString();
- options.gateways = Buf.readString();
-
- if (version >= 10) {
- options.pcscf = Buf.readString();
- }
-
- if (version >= 11) {
- let mtu = Buf.readInt32();
- options.mtu = (mtu > 0) ? mtu : -1 ;
- }
-
- return options;
-};
-
-RilObject.prototype[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length, options) {
- if (options.errorMsg) {
- if (options.rilMessageType) {
- this.sendChromeMessage(options);
- }
- return;
- }
-
- if (!options.rilMessageType) {
- // This is an unsolicited data call list changed.
- options.rilMessageType = "datacalllistchanged";
- }
-
- if (!length) {
- options.datacalls = [];
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let version = Buf.readInt32();
- let num = Buf.readInt32();
- let datacalls = [];
- for (let i = 0; i < num; i++) {
- let datacall;
- datacall = this.readDataCall({}, version);
- datacalls.push(datacall);
- }
-
- options.datacalls = datacalls;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_RESET_RADIO] = null;
-RilObject.prototype[REQUEST_OEM_HOOK_RAW] = null;
-RilObject.prototype[REQUEST_OEM_HOOK_STRINGS] = null;
-RilObject.prototype[REQUEST_SCREEN_STATE] = null;
-RilObject.prototype[REQUEST_SET_SUPP_SVC_NOTIFICATION] = null;
-RilObject.prototype[REQUEST_WRITE_SMS_TO_SIM] = function REQUEST_WRITE_SMS_TO_SIM(length, options) {
- if (options.errorMsg) {
- // `The MS shall return a "protocol error, unspecified" error message if
- // the short message cannot be stored in the (U)SIM, and there is other
- // message storage available at the MS` ~ 3GPP TS 23.038 section 4. Here
- // we assume we always have indexed db as another storage.
- this.acknowledgeGsmSms(false, PDU_FCS_PROTOCOL_ERROR);
- } else {
- this.acknowledgeGsmSms(true, PDU_FCS_OK);
- }
-};
-RilObject.prototype[REQUEST_DELETE_SMS_ON_SIM] = null;
-RilObject.prototype[REQUEST_SET_BAND_MODE] = null;
-RilObject.prototype[REQUEST_QUERY_AVAILABLE_BAND_MODE] = null;
-RilObject.prototype[REQUEST_STK_GET_PROFILE] = null;
-RilObject.prototype[REQUEST_STK_SET_PROFILE] = null;
-RilObject.prototype[REQUEST_STK_SEND_ENVELOPE_COMMAND] = null;
-RilObject.prototype[REQUEST_STK_SEND_TERMINAL_RESPONSE] = null;
-RilObject.prototype[REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM] = null;
-RilObject.prototype[REQUEST_EXPLICIT_CALL_TRANSFER] = null;
-RilObject.prototype[REQUEST_SET_PREFERRED_NETWORK_TYPE] = function REQUEST_SET_PREFERRED_NETWORK_TYPE(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_PREFERRED_NETWORK_TYPE] = function REQUEST_GET_PREFERRED_NETWORK_TYPE(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- options.type = this.context.Buf.readInt32List()[0];
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_NEIGHBORING_CELL_IDS] = function REQUEST_GET_NEIGHBORING_CELL_IDS(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let radioTech = this.voiceRegistrationState.radioTech;
- if (radioTech == undefined || radioTech == NETWORK_CREG_TECH_UNKNOWN) {
- options.errorMsg = "RadioTechUnavailable";
- this.sendChromeMessage(options);
- return;
- }
- if (!this._isGsmTechGroup(radioTech) || radioTech == NETWORK_CREG_TECH_LTE) {
- options.errorMsg = "UnsupportedRadioTech";
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let neighboringCellIds = [];
- let num = Buf.readInt32();
-
- for (let i = 0; i < num; i++) {
- let cellId = {};
- cellId.networkType = GECKO_RADIO_TECH[radioTech];
- cellId.signalStrength = Buf.readInt32();
-
- let cid = Buf.readString();
- // pad cid string with leading "0"
- let length = cid.length;
- if (length > 8) {
- continue;
- }
- if (length < 8) {
- for (let j = 0; j < (8-length); j++) {
- cid = "0" + cid;
- }
- }
-
- switch (radioTech) {
- case NETWORK_CREG_TECH_GPRS:
- case NETWORK_CREG_TECH_EDGE:
- case NETWORK_CREG_TECH_GSM:
- cellId.gsmCellId = this.parseInt(cid.substring(4), -1, 16);
- cellId.gsmLocationAreaCode = this.parseInt(cid.substring(0, 4), -1, 16);
- break;
- case NETWORK_CREG_TECH_UMTS:
- case NETWORK_CREG_TECH_HSDPA:
- case NETWORK_CREG_TECH_HSUPA:
- case NETWORK_CREG_TECH_HSPA:
- case NETWORK_CREG_TECH_HSPAP:
- case NETWORK_CREG_TECH_DCHSPAP_1:
- case NETWORK_CREG_TECH_DCHSPAP_2:
- cellId.wcdmaPsc = this.parseInt(cid, -1, 16);
- break;
- }
-
- neighboringCellIds.push(cellId);
- }
-
- options.result = neighboringCellIds;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_CELL_INFO_LIST] = function REQUEST_GET_CELL_INFO_LIST(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- let cellInfoList = [];
- let num = Buf.readInt32();
- for (let i = 0; i < num; i++) {
- let cellInfo = {};
- cellInfo.type = Buf.readInt32();
- cellInfo.registered = Buf.readInt32() ? true : false;
- cellInfo.timestampType = Buf.readInt32();
- cellInfo.timestamp = Buf.readInt64();
-
- switch(cellInfo.type) {
- case CELL_INFO_TYPE_GSM:
- case CELL_INFO_TYPE_WCDMA:
- cellInfo.mcc = Buf.readInt32();
- cellInfo.mnc = Buf.readInt32();
- cellInfo.lac = Buf.readInt32();
- cellInfo.cid = Buf.readInt32();
- if (cellInfo.type == CELL_INFO_TYPE_WCDMA) {
- cellInfo.psc = Buf.readInt32();
- }
- cellInfo.signalStrength = Buf.readInt32();
- cellInfo.bitErrorRate = Buf.readInt32();
- break;
- case CELL_INFO_TYPE_CDMA:
- cellInfo.networkId = Buf.readInt32();
- cellInfo.systemId = Buf.readInt32();
- cellInfo.basestationId = Buf.readInt32();
- cellInfo.longitude = Buf.readInt32();
- cellInfo.latitude = Buf.readInt32();
- cellInfo.cdmaDbm = Buf.readInt32();
- cellInfo.cdmaEcio = Buf.readInt32();
- cellInfo.evdoDbm = Buf.readInt32();
- cellInfo.evdoEcio = Buf.readInt32();
- cellInfo.evdoSnr = Buf.readInt32();
- break;
- case CELL_INFO_TYPE_LTE:
- cellInfo.mcc = Buf.readInt32();
- cellInfo.mnc = Buf.readInt32();
- cellInfo.cid = Buf.readInt32();
- cellInfo.pcid = Buf.readInt32();
- cellInfo.tac = Buf.readInt32();
- cellInfo.signalStrength = Buf.readInt32();
- cellInfo.rsrp = Buf.readInt32();
- cellInfo.rsrq = Buf.readInt32();
- cellInfo.rssnr = Buf.readInt32();
- cellInfo.cqi = Buf.readInt32();
- break;
- }
- cellInfoList.push(cellInfo);
- }
- options.result = cellInfoList;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_LOCATION_UPDATES] = null;
-RilObject.prototype[REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE] = null;
-RilObject.prototype[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function REQUEST_CDMA_SET_ROAMING_PREFERENCE(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function REQUEST_CDMA_QUERY_ROAMING_PREFERENCE(length, options) {
- if (!options.errorMsg) {
- options.mode = this.context.Buf.readInt32List()[0];
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_TTY_MODE] = null;
-RilObject.prototype[REQUEST_QUERY_TTY_MODE] = null;
-RilObject.prototype[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let enabled = this.context.Buf.readInt32List();
- options.enabled = enabled[0] ? true : false;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_CDMA_FLASH] = function REQUEST_CDMA_FLASH(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_CDMA_BURST_DTMF] = null;
-RilObject.prototype[REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY] = null;
-RilObject.prototype[REQUEST_CDMA_SEND_SMS] = function REQUEST_CDMA_SEND_SMS(length, options) {
- this._processSmsSendResult(length, options);
-};
-RilObject.prototype[REQUEST_CDMA_SMS_ACKNOWLEDGE] = null;
-RilObject.prototype[REQUEST_GSM_GET_BROADCAST_SMS_CONFIG] = null;
-RilObject.prototype[REQUEST_GSM_SET_BROADCAST_SMS_CONFIG] = function REQUEST_GSM_SET_BROADCAST_SMS_CONFIG(length, options) {
- if (options.errorMsg) {
- return;
- }
- this.setSmsBroadcastActivation(true);
-};
-RilObject.prototype[REQUEST_GSM_SMS_BROADCAST_ACTIVATION] = null;
-RilObject.prototype[REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG] = null;
-RilObject.prototype[REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG] = function REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG(length, options) {
- if (options.errorMsg) {
- return;
- }
- this.setSmsBroadcastActivation(true);
-};
-RilObject.prototype[REQUEST_CDMA_SMS_BROADCAST_ACTIVATION] = null;
-RilObject.prototype[REQUEST_CDMA_SUBSCRIPTION] = function REQUEST_CDMA_SUBSCRIPTION(length, options) {
- if (options.errorMsg) {
- return;
- }
-
- let result = this.context.Buf.readStringList();
-
- this.iccInfo.mdn = result[0];
- // The result[1] is Home SID. (Already be handled in readCDMAHome())
- // The result[2] is Home NID. (Already be handled in readCDMAHome())
- // The result[3] is MIN.
- this.iccInfo.prlVersion = parseInt(result[4], 10);
-
- this.context.ICCUtilsHelper.handleICCInfoChange();
-};
-RilObject.prototype[REQUEST_CDMA_WRITE_SMS_TO_RUIM] = null;
-RilObject.prototype[REQUEST_CDMA_DELETE_SMS_ON_RUIM] = null;
-RilObject.prototype[REQUEST_DEVICE_IDENTITY] = function REQUEST_DEVICE_IDENTITY(length, options) {
- if (options.errorMsg) {
- this.context.debug("Failed to get device identities:" + options.errorMsg);
- return;
- }
-
- let result = this.context.Buf.readStringList();
- this.deviceIdentities = {
- imei: result[0] || null,
- imeisv: result[1] || null,
- esn: result[2] || null,
- meid: result[3] || null,
- };
-
- this.sendChromeMessage({
- rilMessageType: "deviceidentitieschange",
- deviceIdentities: this.deviceIdentities
- });
-};
-RilObject.prototype[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = function REQUEST_EXIT_EMERGENCY_CALLBACK_MODE(length, options) {
- if (options.internal) {
- return;
- }
-
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_SMSC_ADDRESS] = function REQUEST_GET_SMSC_ADDRESS(length, options) {
- if (!options.rilMessageType || options.rilMessageType !== "getSmscAddress") {
- return;
- }
-
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let tosca = TOA_UNKNOWN;
- let smsc = "";
- let Buf = this.context.Buf;
- if (RILQUIRKS_SMSC_ADDRESS_FORMAT === "pdu") {
- let pduHelper = this.context.GsmPDUHelper;
- let strlen = Buf.readInt32();
- let length = pduHelper.readHexOctet();
-
- // As defined in |8.2.5.2 Destination address element| of 3GPP TS 24.011,
- // the value of length field can not exceed 11. Since the content might be
- // filled with 12 'F' when SMSC is cleared, we don't parse the TOA and
- // address fields if reported length exceeds 11 here. Instead, keep the
- // default value (TOA_UNKNOWN with an empty address) in this case.
- const MAX_LENGTH = 11
- if (length <= MAX_LENGTH) {
- tosca = pduHelper.readHexOctet();
-
- // Read and covert the decimal values back to special BCD digits defined in
- // |Called party BCD number| of 3GPP TS 24.008 (refer the following table).
- //
- // +=========+=======+=====+
- // | value | digit | hex |
- // +========================
- // | 1 0 1 0 | * | 0xA |
- // | 1 0 1 1 | # | 0xB |
- // | 1 1 0 0 | a | 0xC |
- // | 1 1 0 1 | b | 0xD |
- // | 1 1 1 0 | c | 0xE |
- // +=========+=======+=====+
- smsc = pduHelper.readSwappedNibbleBcdString(length - 1, true)
- .replace(/a/ig, "*")
- .replace(/b/ig, "#")
- .replace(/c/ig, "a")
- .replace(/d/ig, "b")
- .replace(/e/ig, "c");
-
- Buf.readStringDelimiter(strlen);
- }
- } else /* RILQUIRKS_SMSC_ADDRESS_FORMAT === "text" */ {
- let text = Buf.readString();
- let segments = text.split(",", 2);
- // Parse TOA only if it presents since some devices might omit the TOA
- // segment in the reported SMSC address. If TOA does not present, keep the
- // default value TOA_UNKNOWN.
- if (segments.length === 2) {
- tosca = this.parseInt(segments[1], TOA_UNKNOWN, 10);
- }
-
- smsc = segments[0].replace(/\"/g, "");
- }
-
- // Convert the NPI value to the corresponding index of CALLED_PARTY_BCD_NPI
- // array. If the value does not present in the array, use
- // CALLED_PARTY_BCD_NPI_ISDN.
- let npi = CALLED_PARTY_BCD_NPI.indexOf(tosca & 0xf);
- if (npi === -1) {
- npi = CALLED_PARTY_BCD_NPI.indexOf(CALLED_PARTY_BCD_NPI_ISDN);
- }
-
- // Extract TON.
- let ton = (tosca & 0x70) >> 4;
-
- // Ensure + sign if TON is international, and vice versa.
- const TON_INTERNATIONAL = (TOA_INTERNATIONAL & 0x70) >> 4;
- if (ton === TON_INTERNATIONAL && smsc.charAt(0) !== "+") {
- smsc = "+" + smsc;
- } else if (smsc.charAt(0) === "+" && ton !== TON_INTERNATIONAL) {
- if (DEBUG) {
- this.context.debug("SMSC address number begins with '+' while the TON is not international. Change TON to international.");
- }
- ton = TON_INTERNATIONAL;
- }
-
- options.smscAddress = smsc;
- options.typeOfNumber = ton;
- options.numberPlanIdentification = npi;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SET_SMSC_ADDRESS] = function REQUEST_SET_SMSC_ADDRESS(length, options) {
- if (!options.rilMessageType || options.rilMessageType !== "setSmscAddress") {
- return;
- }
-
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_REPORT_SMS_MEMORY_STATUS] = function REQUEST_REPORT_SMS_MEMORY_STATUS(length, options) {
- this.pendingToReportSmsMemoryStatus = !!options.errorMsg;
-};
-RilObject.prototype[REQUEST_REPORT_STK_SERVICE_IS_RUNNING] = null;
-RilObject.prototype[REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE] = null;
-RilObject.prototype[REQUEST_ISIM_AUTHENTICATION] = null;
-RilObject.prototype[REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU] = null;
-RilObject.prototype[REQUEST_STK_SEND_ENVELOPE_WITH_STATUS] = function REQUEST_STK_SEND_ENVELOPE_WITH_STATUS(length, options) {
- if (options.errorMsg) {
- this.acknowledgeGsmSms(false, PDU_FCS_UNSPECIFIED);
- return;
- }
-
- let Buf = this.context.Buf;
- let sw1 = Buf.readInt32();
- let sw2 = Buf.readInt32();
- if ((sw1 == ICC_STATUS_SAT_BUSY) && (sw2 === 0x00)) {
- this.acknowledgeGsmSms(false, PDU_FCS_USAT_BUSY);
- return;
- }
-
- let success = ((sw1 == ICC_STATUS_NORMAL_ENDING) && (sw2 === 0x00))
- || (sw1 == ICC_STATUS_NORMAL_ENDING_WITH_EXTRA);
-
- let messageStringLength = Buf.readInt32(); // In semi-octets
- let responsePduLen = messageStringLength / 2; // In octets
- if (!responsePduLen) {
- this.acknowledgeGsmSms(success, success ? PDU_FCS_OK
- : PDU_FCS_USIM_DATA_DOWNLOAD_ERROR);
- return;
- }
-
- this.acknowledgeIncomingGsmSmsWithPDU(success, responsePduLen, options);
-};
-RilObject.prototype[REQUEST_VOICE_RADIO_TECH] = function REQUEST_VOICE_RADIO_TECH(length, options) {
- if (options.errorMsg) {
- if (DEBUG) {
- this.context.debug("Error when getting voice radio tech: " +
- options.errorMsg);
- }
- return;
- }
- let radioTech = this.context.Buf.readInt32List();
- this._processRadioTech(radioTech[0]);
-};
-RilObject.prototype[REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE] = null;
-RilObject.prototype[REQUEST_SET_INITIAL_ATTACH_APN] = null;
-RilObject.prototype[REQUEST_IMS_REGISTRATION_STATE] = null;
-RilObject.prototype[REQUEST_IMS_SEND_SMS] = null;
-RilObject.prototype[REQUEST_SIM_TRANSMIT_APDU_BASIC] = null;
-RilObject.prototype[REQUEST_SIM_OPEN_CHANNEL] = function REQUEST_SIM_OPEN_CHANNEL(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- options.channel = this.context.Buf.readInt32List()[0];
- // onwards may optionally contain the select response for the open channel
- // command with one byte per integer.
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_SIM_CLOSE_CHANNEL] = function REQUEST_SIM_CLOSE_CHANNEL(length, options) {
- this.sendDefaultResponse(options);
-};
-RilObject.prototype[REQUEST_SIM_TRANSMIT_APDU_CHANNEL] = function REQUEST_SIM_TRANSMIT_APDU_CHANNEL(length, options) {
- if (options.errorMsg) {
- this.sendChromeMessage(options);
- return;
- }
-
- let Buf = this.context.Buf;
- options.sw1 = Buf.readInt32();
- options.sw2 = Buf.readInt32();
- options.simResponse = Buf.readString();
- if (DEBUG) {
- this.context.debug("Setting return values for RIL[REQUEST_SIM_TRANSMIT_APDU_CHANNEL]: [" +
- options.sw1 + "," +
- options.sw2 + ", " +
- options.simResponse + "]");
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_NV_READ_ITEM] = null;
-RilObject.prototype[REQUEST_NV_WRITE_ITEM] = null;
-RilObject.prototype[REQUEST_NV_WRITE_CDMA_PRL] = null;
-RilObject.prototype[REQUEST_NV_RESET_CONFIG] = null;
-RilObject.prototype[REQUEST_SET_UICC_SUBSCRIPTION] = function REQUEST_SET_UICC_SUBSCRIPTION(length, options) {
- // Resend data subscription after uicc subscription.
- if (this._attachDataRegistration) {
- this.setDataRegistration({attach: true});
- }
-};
-RilObject.prototype[REQUEST_ALLOW_DATA] = null;
-RilObject.prototype[REQUEST_GET_HARDWARE_CONFIG] = null;
-RilObject.prototype[REQUEST_SIM_AUTHENTICATION] = null;
-RilObject.prototype[REQUEST_GET_DC_RT_INFO] = null;
-RilObject.prototype[REQUEST_SET_DC_RT_INFO_RATE] = null;
-RilObject.prototype[REQUEST_SET_DATA_PROFILE] = null;
-RilObject.prototype[REQUEST_SHUTDOWN] = null;
-RilObject.prototype[REQUEST_SET_DATA_SUBSCRIPTION] = function REQUEST_SET_DATA_SUBSCRIPTION(length, options) {
- if (!options.rilMessageType) {
- // The request was made by ril_worker itself. Don't report.
- return;
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[REQUEST_GET_UNLOCK_RETRY_COUNT] = function REQUEST_GET_UNLOCK_RETRY_COUNT(length, options) {
- options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
- this.sendChromeMessage(options);
-};
-RilObject.prototype[RIL_REQUEST_GPRS_ATTACH] = function RIL_REQUEST_GPRS_ATTACH(length, options) {
- if (!options.rilMessageType) {
- // The request was made by ril_worker itself. Don't report.
- return;
- }
- this.sendChromeMessage(options);
-};
-RilObject.prototype[RIL_REQUEST_GPRS_DETACH] = function RIL_REQUEST_GPRS_DETACH(length, options) {
- this.sendChromeMessage(options);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED() {
- let radioState = this.context.Buf.readInt32();
- let newState;
- switch (radioState) {
- case RADIO_STATE_UNAVAILABLE:
- newState = GECKO_RADIOSTATE_UNKNOWN;
- break;
- case RADIO_STATE_OFF:
- newState = GECKO_RADIOSTATE_DISABLED;
- break;
- default:
- newState = GECKO_RADIOSTATE_ENABLED;
- }
-
- if (DEBUG) {
- this.context.debug("Radio state changed from '" + this.radioState +
- "' to '" + newState + "'");
- }
- if (this.radioState == newState) {
- return;
- }
-
- if (radioState !== RADIO_STATE_UNAVAILABLE) {
- // Retrieve device identities once radio is available.
- this.getDeviceIdentity();
- }
-
- if (radioState == RADIO_STATE_ON) {
- // This value is defined in RIL v7, we will retrieve radio tech by another
- // request. We leave _isCdma untouched, and it will be set once we get the
- // radio technology.
- this._waitingRadioTech = true;
- this.getVoiceRadioTechnology();
- }
-
- if ((this.radioState == GECKO_RADIOSTATE_UNKNOWN ||
- this.radioState == GECKO_RADIOSTATE_DISABLED) &&
- newState == GECKO_RADIOSTATE_ENABLED) {
- // The radio became available, let's get its info.
- this.getBasebandVersion();
- this.updateCellBroadcastConfig();
- if ((RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
- RILQUIRKS_SUBSCRIPTION_CONTROL) &&
- this._attachDataRegistration) {
- this.setDataRegistration({attach: true});
- }
-
- if (this.pendingToReportSmsMemoryStatus) {
- this._updateSmsMemoryStatus();
- }
- }
-
- this.radioState = newState;
- this.sendChromeMessage({
- rilMessageType: "radiostatechange",
- radioState: newState
- });
-
- // If the radio is up and on, so let's query the card state.
- // On older RILs only if the card is actually ready, though.
- // If _waitingRadioTech is set, we don't need to get icc status now.
- if (radioState == RADIO_STATE_UNAVAILABLE ||
- radioState == RADIO_STATE_OFF ||
- this._waitingRadioTech) {
- return;
- }
- this.getICCStatus();
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_CALL_STATE_CHANGED] = function UNSOLICITED_RESPONSE_CALL_STATE_CHANGED() {
- this.getCurrentCalls();
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED] = function UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED() {
- if (DEBUG) {
- this.context.debug("Network state changed, re-requesting phone state and " +
- "ICC status");
- }
- this.getICCStatus();
- this.requestNetworkInfo();
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_NEW_SMS] = function UNSOLICITED_RESPONSE_NEW_SMS(length) {
- let [message, result] = this.context.GsmPDUHelper.processReceivedSms(length);
-
- if (message) {
- result = this._processSmsMultipart(message);
- }
-
- if (result == PDU_FCS_RESERVED || result == MOZ_FCS_WAIT_FOR_EXPLICIT_ACK) {
- return;
- }
-
- // Not reserved FCS values, send ACK now.
- this.acknowledgeGsmSms(result == PDU_FCS_OK, result);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT] = function UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT(length) {
- let result = this._processSmsStatusReport(length);
- this.acknowledgeGsmSms(result == PDU_FCS_OK, result);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM] = function UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM(length) {
- let recordNumber = this.context.Buf.readInt32List()[0];
-
- this.context.SimRecordHelper.readSMS(
- recordNumber,
- function onsuccess(message) {
- if (message && message.simStatus === 3) { //New Unread SMS
- this._processSmsMultipart(message);
- }
- }.bind(this),
- function onerror(errorMsg) {
- if (DEBUG) {
- this.context.debug("Failed to Read NEW SMS on SIM #" + recordNumber +
- ", errorMsg: " + errorMsg);
- }
- });
-};
-RilObject.prototype[UNSOLICITED_ON_USSD] = function UNSOLICITED_ON_USSD() {
- let [typeCode, message] = this.context.Buf.readStringList();
- if (DEBUG) {
- this.context.debug("On USSD. Type Code: " + typeCode + " Message: " + message);
- }
-
- this.sendChromeMessage({rilMessageType: "ussdreceived",
- message: message,
- // Per ril.h the USSD session is assumed to persist if
- // the type code is "1", otherwise the current session
- // (if any) is assumed to have terminated.
- sessionEnded: typeCode !== "1"});
-};
-RilObject.prototype[UNSOLICITED_ON_USSD_REQUEST] = null;
-RilObject.prototype[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() {
- let dateString = this.context.Buf.readString();
-
- // The data contained in the NITZ message is
- // in the form "yy/mm/dd,hh:mm:ss(+/-)tz,dt"
- // for example: 12/02/16,03:36:08-20,00,310410
- // See also bug 714352 - Listen for NITZ updates from rild.
-
- if (DEBUG) this.context.debug("DateTimeZone string " + dateString);
-
- let now = Date.now();
-
- let year = parseInt(dateString.substr(0, 2), 10);
- let month = parseInt(dateString.substr(3, 2), 10);
- let day = parseInt(dateString.substr(6, 2), 10);
- let hours = parseInt(dateString.substr(9, 2), 10);
- let minutes = parseInt(dateString.substr(12, 2), 10);
- let seconds = parseInt(dateString.substr(15, 2), 10);
- // Note that |tz| is in 15-min units.
- let tz = parseInt(dateString.substr(17, 3), 10);
- // Note that |dst| is in 1-hour units and is already applied in |tz|.
- let dst = parseInt(dateString.substr(21, 2), 10);
-
- let timeInMS = Date.UTC(year + PDU_TIMESTAMP_YEAR_OFFSET, month - 1, day,
- hours, minutes, seconds);
-
- if (isNaN(timeInMS)) {
- if (DEBUG) this.context.debug("NITZ failed to convert date");
- return;
- }
-
- this.sendChromeMessage({rilMessageType: "nitzTime",
- networkTimeInMS: timeInMS,
- networkTimeZoneInMinutes: -(tz * 15),
- networkDSTInMinutes: -(dst * 60),
- receiveTimeInMS: now});
-};
-
-RilObject.prototype[UNSOLICITED_SIGNAL_STRENGTH] = function UNSOLICITED_SIGNAL_STRENGTH(length) {
- this[REQUEST_SIGNAL_STRENGTH](length, {});
-};
-RilObject.prototype[UNSOLICITED_DATA_CALL_LIST_CHANGED] = function UNSOLICITED_DATA_CALL_LIST_CHANGED(length) {
- this[REQUEST_DATA_CALL_LIST](length, {});
-};
-RilObject.prototype[UNSOLICITED_SUPP_SVC_NOTIFICATION] = function UNSOLICITED_SUPP_SVC_NOTIFICATION(length) {
- let Buf = this.context.Buf;
- let info = {};
- info.notificationType = Buf.readInt32();
- info.code = Buf.readInt32();
- info.index = Buf.readInt32();
- info.type = Buf.readInt32();
- info.number = Buf.readString();
-
- this._processSuppSvcNotification(info);
-};
-
-RilObject.prototype[UNSOLICITED_STK_SESSION_END] = function UNSOLICITED_STK_SESSION_END() {
- this.sendChromeMessage({rilMessageType: "stksessionend"});
-};
-RilObject.prototype[UNSOLICITED_STK_PROACTIVE_COMMAND] = function UNSOLICITED_STK_PROACTIVE_COMMAND() {
- this.processStkProactiveCommand();
-};
-RilObject.prototype[UNSOLICITED_STK_EVENT_NOTIFY] = function UNSOLICITED_STK_EVENT_NOTIFY() {
- this.processStkProactiveCommand();
-};
-RilObject.prototype[UNSOLICITED_STK_CALL_SETUP] = null;
-RilObject.prototype[UNSOLICITED_SIM_SMS_STORAGE_FULL] = null;
-RilObject.prototype[UNSOLICITED_SIM_REFRESH] = null;
-RilObject.prototype[UNSOLICITED_CALL_RING] = function UNSOLICITED_CALL_RING() {
- let Buf = this.context.Buf;
- let info = {rilMessageType: "callRing"};
- let isCDMA = false; //XXX TODO hard-code this for now
- if (isCDMA) {
- info.isPresent = Buf.readInt32();
- info.signalType = Buf.readInt32();
- info.alertPitch = Buf.readInt32();
- info.signal = Buf.readInt32();
- }
- // At this point we don't know much other than the fact there's an incoming
- // call, but that's enough to bring up the Phone app already. We'll know
- // details once we get a call state changed notification and can then
- // dispatch DOM events etc.
- this.sendChromeMessage(info);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED] = function UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED() {
- this.getICCStatus();
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_CDMA_NEW_SMS] = function UNSOLICITED_RESPONSE_CDMA_NEW_SMS(length) {
- let [message, result] = this.context.CdmaPDUHelper.processReceivedSms(length);
-
- if (message) {
- if (message.teleservice === PDU_CDMA_MSG_TELESERIVCIE_ID_WAP) {
- result = this._processCdmaSmsWapPush(message);
- } else if (message.subMsgType === PDU_CDMA_MSG_TYPE_DELIVER_ACK) {
- result = this._processCdmaSmsStatusReport(message);
- } else {
- result = this._processSmsMultipart(message);
- }
- }
-
- if (result == PDU_FCS_RESERVED || result == MOZ_FCS_WAIT_FOR_EXPLICIT_ACK) {
- return;
- }
-
- // Not reserved FCS values, send ACK now.
- this.acknowledgeCdmaSms(result == PDU_FCS_OK, result);
-};
-RilObject.prototype[UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS] = function UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS(length) {
- let message;
- try {
- message =
- this.context.GsmPDUHelper.readCbMessage(this.context.Buf.readInt32());
-
- // "Data-Download" message is expected to be handled by the modem.
- // Ignore it here to prevent any garbage messages to be displayed.
- // See 9.4.1.2.2 Message Identifier of TS 32.041 for the range of
- // Message-identifier of the Data-Download CB messages.
- if (message.messageId >= 0x1000 && message.messageId <= 0x10FF) {
- if (DEBUG) {
- this.context.debug("Ignore a Data-Download message, messageId: " +
- message.messageId);
- }
- return;
- }
- } catch (e) {
- if (DEBUG) {
- this.context.debug("Failed to parse Cell Broadcast message: " + e);
- }
- return;
- }
-
- message = this._processReceivedSmsCbPage(message);
- if (!message) {
- return;
- }
-
- // Bug 1235697, failed to deactivate CBS in some modem.
- // Workaround it according to the settings.
- // Note: ETWS/CMAS/PWS can be received even disabled.
- // It will be displayed according to the setting in application layer.
- if (this.cellBroadcastDisabled && (
- !(message.messageId >= 0x1100 && message.messageId <= 0x1107) && // ETWS
- !(message.messageId >= 0x1112 && message.messageId <= 0x112F) && // CMAS
- !(message.messageId >= 0x1130 && message.messageId <= 0x18FF) // PWS
- )) {
- if (DEBUG) {
- this.context.debug("Ignore a CB message when disabled, messageId: " +
- message.messageId);
- }
- return;
- }
-
- message.rilMessageType = "cellbroadcast-received";
- this.sendChromeMessage(message);
-};
-RilObject.prototype[UNSOLICITED_CDMA_RUIM_SMS_STORAGE_FULL] = null;
-RilObject.prototype[UNSOLICITED_RESTRICTED_STATE_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE() {
- this._handleChangedEmergencyCbMode(true);
-};
-RilObject.prototype[UNSOLICITED_CDMA_CALL_WAITING] = function UNSOLICITED_CDMA_CALL_WAITING(length) {
- let Buf = this.context.Buf;
- let call = {};
- call.number = Buf.readString();
- call.numberPresentation = Buf.readInt32();
- call.name = Buf.readString();
- call.namePresentation = Buf.readInt32();
- call.isPresent = Buf.readInt32();
- call.signalType = Buf.readInt32();
- call.alertPitch = Buf.readInt32();
- call.signal = Buf.readInt32();
- this.sendChromeMessage({rilMessageType: "cdmaCallWaiting",
- waitingCall: call});
-};
-RilObject.prototype[UNSOLICITED_CDMA_OTA_PROVISION_STATUS] = function UNSOLICITED_CDMA_OTA_PROVISION_STATUS() {
- let status =
- CDMA_OTA_PROVISION_STATUS_TO_GECKO[this.context.Buf.readInt32List()[0]];
- if (!status) {
- return;
- }
- this.sendChromeMessage({rilMessageType: "otastatuschange",
- status: status});
-};
-RilObject.prototype[UNSOLICITED_CDMA_INFO_REC] = function UNSOLICITED_CDMA_INFO_REC(length) {
- this.sendChromeMessage({
- rilMessageType: "cdma-info-rec-received",
- records: this.context.CdmaPDUHelper.decodeInformationRecord()
- });
-};
-RilObject.prototype[UNSOLICITED_OEM_HOOK_RAW] = null;
-RilObject.prototype[UNSOLICITED_RINGBACK_TONE] = null;
-RilObject.prototype[UNSOLICITED_RESEND_INCALL_MUTE] = null;
-RilObject.prototype[UNSOLICITED_CDMA_SUBSCRIPTION_SOURCE_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_CDMA_PRL_CHANGED] = function UNSOLICITED_CDMA_PRL_CHANGED(length) {
- let version = this.context.Buf.readInt32List()[0];
- if (version !== this.iccInfo.prlVersion) {
- this.iccInfo.prlVersion = version;
- this.context.ICCUtilsHelper.handleICCInfoChange();
- }
-};
-RilObject.prototype[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE() {
- this._handleChangedEmergencyCbMode(false);
-};
-RilObject.prototype[UNSOLICITED_RIL_CONNECTED] = function UNSOLICITED_RIL_CONNECTED(length) {
- // Prevent response id collision between UNSOLICITED_RIL_CONNECTED and
- // UNSOLICITED_VOICE_RADIO_TECH_CHANGED for Akami on gingerbread branch.
- if (!length) {
- return;
- }
-
- this.version = this.context.Buf.readInt32List()[0];
- if (DEBUG) {
- this.context.debug("Detected RIL version " + this.version);
- }
-
- this.initRILState();
- // rild might have restarted, ensure data call list.
- this.getDataCallList();
- // Always ensure that we are not in emergency callback mode when init.
- this.exitEmergencyCbMode();
- // Reset radio in the case that b2g restart (or crash).
- this.setRadioEnabled({enabled: false});
-};
-RilObject.prototype[UNSOLICITED_VOICE_RADIO_TECH_CHANGED] = function UNSOLICITED_VOICE_RADIO_TECH_CHANGED(length) {
- // This unsolicited response will be sent when the technology of a multi-tech
- // modem is changed, ex. switch between gsm and cdma.
- // TODO: We may need to do more on updating data when switching between gsm
- // and cdma mode, e.g. IMEI, ESN, iccInfo, iccType ... etc.
- // See Bug 866038.
- this._processRadioTech(this.context.Buf.readInt32List()[0]);
-};
-RilObject.prototype[UNSOLICITED_CELL_INFO_LIST] = null;
-RilObject.prototype[UNSOLICITED_RESPONSE_IMS_NETWORK_STATE_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_UICC_SUBSCRIPTION_STATUS_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_SRVCC_STATE_NOTIFY] = null;
-RilObject.prototype[UNSOLICITED_HARDWARE_CONFIG_CHANGED] = null;
-RilObject.prototype[UNSOLICITED_DC_RT_INFO_CHANGED] = null;
-
-/**
- * This object exposes the functionality to parse and serialize PDU strings
- *
- * A PDU is a string containing a series of hexadecimally encoded octets
- * or nibble-swapped binary-coded decimals (BCDs). It contains not only the
- * message text but information about the sender, the SMS service center,
- * timestamp, etc.
- */
-function GsmPDUHelperObject(aContext) {
- this.context = aContext;
-}
-GsmPDUHelperObject.prototype = {
- context: null,
-
- /**
- * Read one character (2 bytes) from a RIL string and decode as hex.
- *
- * @return the nibble as a number.
- */
- readHexNibble: function() {
- let nibble = this.context.Buf.readUint16();
- if (nibble >= 48 && nibble <= 57) {
- nibble -= 48; // ASCII '0'..'9'
- } else if (nibble >= 65 && nibble <= 70) {
- nibble -= 55; // ASCII 'A'..'F'
- } else if (nibble >= 97 && nibble <= 102) {
- nibble -= 87; // ASCII 'a'..'f'
- } else {
- throw "Found invalid nibble during PDU parsing: " +
- String.fromCharCode(nibble);
- }
- return nibble;
- },
-
- /**
- * Encode a nibble as one hex character in a RIL string (2 bytes).
- *
- * @param nibble
- * The nibble to encode (represented as a number)
- */
- writeHexNibble: function(nibble) {
- nibble &= 0x0f;
- if (nibble < 10) {
- nibble += 48; // ASCII '0'
- } else {
- nibble += 55; // ASCII 'A'
- }
- this.context.Buf.writeUint16(nibble);
- },
-
- /**
- * Read a hex-encoded octet (two nibbles).
- *
- * @return the octet as a number.
- */
- readHexOctet: function() {
- return (this.readHexNibble() << 4) | this.readHexNibble();
- },
-
- /**
- * Write an octet as two hex-encoded nibbles.
- *
- * @param octet
- * The octet (represented as a number) to encode.
- */
- writeHexOctet: function(octet) {
- this.writeHexNibble(octet >> 4);
- this.writeHexNibble(octet);
- },
-
- /**
- * Read an array of hex-encoded octets.
- */
- readHexOctetArray: function(length) {
- let array = new Uint8Array(length);
- for (let i = 0; i < length; i++) {
- array[i] = this.readHexOctet();
- }
- return array;
- },
-
- /**
- * Helper to write data into a temporary buffer for easier length encoding when
- * the number of octets for the length encoding is varied.
- *
- * @param writeFunction
- * Function of how the data to be written into temporary buffer.
- *
- * @return array of written octets.
- **/
- writeWithBuffer: function(writeFunction) {
- let buf = [];
- let writeHexOctet = this.writeHexOctet;
- this.writeHexOctet = function(octet) {
- buf.push(octet);
- }
-
- try {
- writeFunction();
- } catch (e) {
- if (DEBUG) {
- debug("Error when writeWithBuffer: " + e);
- }
- buf = [];
- } finally {
- this.writeHexOctet = writeHexOctet;
- }
-
- return buf;
- },
-
- /**
- * Convert an octet (number) to a BCD number.
- *
- * Any nibbles that are not in the BCD range count as 0.
- *
- * @param octet
- * The octet (a number, as returned by getOctet())
- *
- * @return the corresponding BCD number.
- */
- octetToBCD: function(octet) {
- return ((octet & 0xf0) <= 0x90) * ((octet >> 4) & 0x0f) +
- ((octet & 0x0f) <= 0x09) * (octet & 0x0f) * 10;
- },
-
- /**
- * Convert a BCD number to an octet (number)
- *
- * Only take two digits with absolute value.
- *
- * @param bcd
- *
- * @return the corresponding octet.
- */
- BCDToOctet: function(bcd) {
- bcd = Math.abs(bcd);
- return ((bcd % 10) << 4) + (Math.floor(bcd / 10) % 10);
- },
-
- /**
- * Convert a semi-octet (number) to a GSM BCD char, or return empty
- * string if invalid semiOctet and suppressException is set to true.
- *
- * @param semiOctet
- * Nibble to be converted to.
- * @param suppressException [optional]
- * Suppress exception if invalid semiOctet and suppressException is set
- * to true.
- *
- * @return GSM BCD char, or empty string.
- */
- bcdChars: "0123456789",
- semiOctetToBcdChar: function(semiOctet, suppressException) {
- if (semiOctet >= this.bcdChars.length) {
- if (suppressException) {
- return "";
- } else {
- throw new RangeError();
- }
- }
-
- return this.bcdChars.charAt(semiOctet);
- },
-
- /**
- * Convert a semi-octet (number) to a GSM extended BCD char, or return empty
- * string if invalid semiOctet and suppressException is set to true.
- *
- * @param semiOctet
- * Nibble to be converted to.
- * @param suppressException [optional]
- * Suppress exception if invalid semiOctet and suppressException is set
- * to true.
- *
- * @return GSM extended BCD char, or empty string.
- */
- extendedBcdChars: "0123456789*#,;",
- semiOctetToExtendedBcdChar: function(semiOctet, suppressException) {
- if (semiOctet >= this.extendedBcdChars.length) {
- if (suppressException) {
- return "";
- } else {
- throw new RangeError();
- }
- }
-
- return this.extendedBcdChars.charAt(semiOctet);
- },
-
- /**
- * Convert string to a GSM extended BCD string
- */
- stringToExtendedBcd: function(string) {
- return string.replace(/[^0-9*#,]/g, "")
- .replace(/\*/g, "a")
- .replace(/\#/g, "b")
- .replace(/\,/g, "c");
- },
-
- /**
- * Read a *swapped nibble* binary coded decimal (BCD)
- *
- * @param pairs
- * Number of nibble *pairs* to read.
- *
- * @return the decimal as a number.
- */
- readSwappedNibbleBcdNum: function(pairs) {
- let number = 0;
- for (let i = 0; i < pairs; i++) {
- let octet = this.readHexOctet();
- // Ignore 'ff' octets as they're often used as filler.
- if (octet == 0xff) {
- continue;
- }
- // If the first nibble is an "F" , only the second nibble is to be taken
- // into account.
- if ((octet & 0xf0) == 0xf0) {
- number *= 10;
- number += octet & 0x0f;
- continue;
- }
- number *= 100;
- number += this.octetToBCD(octet);
- }
- return number;
- },
-
- /**
- * Read a *swapped nibble* binary coded decimal (BCD) string
- *
- * @param pairs
- * Number of nibble *pairs* to read.
- * @param suppressException [optional]
- * Suppress exception if invalid semiOctet and suppressException is set
- * to true.
- *
- * @return The BCD string.
- */
- readSwappedNibbleBcdString: function(pairs, suppressException) {
- let str = "";
- for (let i = 0; i < pairs; i++) {
- let nibbleH = this.readHexNibble();
- let nibbleL = this.readHexNibble();
- if (nibbleL == 0x0F) {
- break;
- }
-
- str += this.semiOctetToBcdChar(nibbleL, suppressException);
- if (nibbleH != 0x0F) {
- str += this.semiOctetToBcdChar(nibbleH, suppressException);
- }
- }
-
- return str;
- },
-
- /**
- * Read a *swapped nibble* extended binary coded decimal (BCD) string
- *
- * @param pairs
- * Number of nibble *pairs* to read.
- * @param suppressException [optional]
- * Suppress exception if invalid semiOctet and suppressException is set
- * to true.
- *
- * @return The BCD string.
- */
- readSwappedNibbleExtendedBcdString: function(pairs, suppressException) {
- let str = "";
- for (let i = 0; i < pairs; i++) {
- let nibbleH = this.readHexNibble();
- let nibbleL = this.readHexNibble();
- if (nibbleL == 0x0F) {
- break;
- }
-
- str += this.semiOctetToExtendedBcdChar(nibbleL, suppressException);
- if (nibbleH != 0x0F) {
- str += this.semiOctetToExtendedBcdChar(nibbleH, suppressException);
- }
- }
-
- return str;
- },
-
- /**
- * Write numerical data as swapped nibble BCD.
- *
- * @param data
- * Data to write (as a string or a number)
- */
- writeSwappedNibbleBCD: function(data) {
- data = data.toString();
- if (data.length % 2) {
- data += "F";
- }
- let Buf = this.context.Buf;
- for (let i = 0; i < data.length; i += 2) {
- Buf.writeUint16(data.charCodeAt(i + 1));
- Buf.writeUint16(data.charCodeAt(i));
- }
- },
-
- /**
- * Write numerical data as swapped nibble BCD.
- * If the number of digit of data is even, add '0' at the beginning.
- *
- * @param data
- * Data to write (as a string or a number)
- */
- writeSwappedNibbleBCDNum: function(data) {
- data = data.toString();
- if (data.length % 2) {
- data = "0" + data;
- }
- let Buf = this.context.Buf;
- for (let i = 0; i < data.length; i += 2) {
- Buf.writeUint16(data.charCodeAt(i + 1));
- Buf.writeUint16(data.charCodeAt(i));
- }
- },
-
- /**
- * Read user data, convert to septets, look up relevant characters in a
- * 7-bit alphabet, and construct string.
- *
- * @param length
- * Number of septets to read (*not* octets)
- * @param paddingBits
- * Number of padding bits in the first byte of user data.
- * @param langIndex
- * Table index used for normal 7-bit encoded character lookup.
- * @param langShiftIndex
- * Table index used for escaped 7-bit encoded character lookup.
- *
- * @return a string.
- */
- readSeptetsToString: function(length, paddingBits, langIndex, langShiftIndex) {
- let ret = "";
- let byteLength = Math.ceil((length * 7 + paddingBits) / 8);
-
- /**
- * |<- last byte in header ->|
- * |<- incompleteBits ->|<- last header septet->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- *
- * |<- 1st byte in user data ->|
- * |<- data septet 1 ->|<-paddingBits->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- *
- * |<- 2nd byte in user data ->|
- * |<- data spetet 2 ->|<-ds1->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- */
- let data = 0;
- let dataBits = 0;
- if (paddingBits) {
- data = this.readHexOctet() >> paddingBits;
- dataBits = 8 - paddingBits;
- --byteLength;
- }
-
- let escapeFound = false;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
- do {
- // Read as much as fits in 32bit word
- let bytesToRead = Math.min(byteLength, dataBits ? 3 : 4);
- for (let i = 0; i < bytesToRead; i++) {
- data |= this.readHexOctet() << dataBits;
- dataBits += 8;
- --byteLength;
- }
-
- // Consume available full septets
- for (; dataBits >= 7; dataBits -= 7) {
- let septet = data & 0x7F;
- data >>>= 7;
-
- if (escapeFound) {
- escapeFound = false;
- if (septet == PDU_NL_EXTENDED_ESCAPE) {
- // According to 3GPP TS 23.038, section 6.2.1.1, NOTE 1, "On
- // receipt of this code, a receiving entity shall display a space
- // until another extensiion table is defined."
- ret += " ";
- } else if (septet == PDU_NL_RESERVED_CONTROL) {
- // According to 3GPP TS 23.038 B.2, "This code represents a control
- // character and therefore must not be used for language specific
- // characters."
- ret += " ";
- } else {
- ret += langShiftTable[septet];
- }
- } else if (septet == PDU_NL_EXTENDED_ESCAPE) {
- escapeFound = true;
-
- // <escape> is not an effective character
- --length;
- } else {
- ret += langTable[septet];
- }
- }
- } while (byteLength);
-
- if (ret.length != length) {
- /**
- * If num of effective characters does not equal to the length of read
- * string, cut the tail off. This happens when the last octet of user
- * data has following layout:
- *
- * |<- penultimate octet in user data ->|
- * |<- data septet N ->|<- dsN-1 ->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- *
- * |<- last octet in user data ->|
- * |<- fill bits ->|<-dsN->|
- * +===7===|===6===|===5===|===4===|===3===|===2===|===1===|===0===|
- *
- * The fill bits in the last octet may happen to form a full septet and
- * be appended at the end of result string.
- */
- ret = ret.slice(0, length);
- }
- return ret;
- },
-
- writeStringAsSeptets: function(message, paddingBits, langIndex, langShiftIndex) {
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
-
- let dataBits = paddingBits;
- let data = 0;
- for (let i = 0; i < message.length; i++) {
- let c = message.charAt(i);
- let septet = langTable.indexOf(c);
- if (septet == PDU_NL_EXTENDED_ESCAPE) {
- continue;
- }
-
- if (septet >= 0) {
- data |= septet << dataBits;
- dataBits += 7;
- } else {
- septet = langShiftTable.indexOf(c);
- if (septet == -1) {
- throw new Error("'" + c + "' is not in 7 bit alphabet "
- + langIndex + ":" + langShiftIndex + "!");
- }
-
- if (septet == PDU_NL_RESERVED_CONTROL) {
- continue;
- }
-
- data |= PDU_NL_EXTENDED_ESCAPE << dataBits;
- dataBits += 7;
- data |= septet << dataBits;
- dataBits += 7;
- }
-
- for (; dataBits >= 8; dataBits -= 8) {
- this.writeHexOctet(data & 0xFF);
- data >>>= 8;
- }
- }
-
- if (dataBits !== 0) {
- this.writeHexOctet(data & 0xFF);
- }
- },
-
- writeStringAs8BitUnpacked: function(text) {
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- let len = text ? text.length : 0;
- for (let i = 0; i < len; i++) {
- let c = text.charAt(i);
- let octet = langTable.indexOf(c);
-
- if (octet == -1) {
- octet = langShiftTable.indexOf(c);
- if (octet == -1) {
- // Fallback to ASCII space.
- octet = langTable.indexOf(' ');
- } else {
- this.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
- }
- }
- this.writeHexOctet(octet);
- }
- },
-
- /**
- * Read user data and decode as a UCS2 string.
- *
- * @param numOctets
- * Number of octets to be read as UCS2 string.
- *
- * @return a string.
- */
- readUCS2String: function(numOctets) {
- let str = "";
- let length = numOctets / 2;
- for (let i = 0; i < length; ++i) {
- let code = (this.readHexOctet() << 8) | this.readHexOctet();
- str += String.fromCharCode(code);
- }
-
- if (DEBUG) this.context.debug("Read UCS2 string: " + str);
-
- return str;
- },
-
- /**
- * Write user data as a UCS2 string.
- *
- * @param message
- * Message string to encode as UCS2 in hex-encoded octets.
- */
- writeUCS2String: function(message) {
- for (let i = 0; i < message.length; ++i) {
- let code = message.charCodeAt(i);
- this.writeHexOctet((code >> 8) & 0xFF);
- this.writeHexOctet(code & 0xFF);
- }
- },
-
- /**
- * Read 1 + UDHL octets and construct user data header.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.040 9.2.3.24
- */
- readUserDataHeader: function(msg) {
- /**
- * A header object with properties contained in received message.
- * The properties set include:
- *
- * length: totoal length of the header, default 0.
- * langIndex: used locking shift table index, default
- * PDU_NL_IDENTIFIER_DEFAULT.
- * langShiftIndex: used locking shift table index, default
- * PDU_NL_IDENTIFIER_DEFAULT.
- *
- */
- let header = {
- length: 0,
- langIndex: PDU_NL_IDENTIFIER_DEFAULT,
- langShiftIndex: PDU_NL_IDENTIFIER_DEFAULT
- };
-
- header.length = this.readHexOctet();
- if (DEBUG) this.context.debug("Read UDH length: " + header.length);
-
- let dataAvailable = header.length;
- while (dataAvailable >= 2) {
- let id = this.readHexOctet();
- let length = this.readHexOctet();
- if (DEBUG) this.context.debug("Read UDH id: " + id + ", length: " + length);
-
- dataAvailable -= 2;
-
- switch (id) {
- case PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT: {
- let ref = this.readHexOctet();
- let max = this.readHexOctet();
- let seq = this.readHexOctet();
- dataAvailable -= 3;
- if (max && seq && (seq <= max)) {
- header.segmentRef = ref;
- header.segmentMaxSeq = max;
- header.segmentSeq = seq;
- }
- break;
- }
- case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_8BIT: {
- let dstp = this.readHexOctet();
- let orip = this.readHexOctet();
- dataAvailable -= 2;
- if ((dstp < PDU_APA_RESERVED_8BIT_PORTS)
- || (orip < PDU_APA_RESERVED_8BIT_PORTS)) {
- // 3GPP TS 23.040 clause 9.2.3.24.3: "A receiving entity shall
- // ignore any information element where the value of the
- // Information-Element-Data is Reserved or not supported"
- break;
- }
- header.destinationPort = dstp;
- header.originatorPort = orip;
- break;
- }
- case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_16BIT: {
- let dstp = (this.readHexOctet() << 8) | this.readHexOctet();
- let orip = (this.readHexOctet() << 8) | this.readHexOctet();
- dataAvailable -= 4;
- if ((dstp >= PDU_APA_VALID_16BIT_PORTS) ||
- (orip >= PDU_APA_VALID_16BIT_PORTS)) {
- // 3GPP TS 23.040 clause 9.2.3.24.4: "A receiving entity shall
- // ignore any information element where the value of the
- // Information-Element-Data is Reserved or not supported"
- // Bug 1130292, some carriers set originatorPort to reserved port
- // numbers for wap push. We rise this as a warning in debug message
- // instead of ingoring this IEI to allow user to receive Wap Push
- // under these carriers.
- this.context.debug("Warning: Invalid port numbers [dstp, orip]: " +
- JSON.stringify([dstp, orip]));
- }
- header.destinationPort = dstp;
- header.originatorPort = orip;
- break;
- }
- case PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT: {
- let ref = (this.readHexOctet() << 8) | this.readHexOctet();
- let max = this.readHexOctet();
- let seq = this.readHexOctet();
- dataAvailable -= 4;
- if (max && seq && (seq <= max)) {
- header.segmentRef = ref;
- header.segmentMaxSeq = max;
- header.segmentSeq = seq;
- }
- break;
- }
- case PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT:
- let langShiftIndex = this.readHexOctet();
- --dataAvailable;
- if (langShiftIndex < PDU_NL_SINGLE_SHIFT_TABLES.length) {
- header.langShiftIndex = langShiftIndex;
- }
- break;
- case PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT:
- let langIndex = this.readHexOctet();
- --dataAvailable;
- if (langIndex < PDU_NL_LOCKING_SHIFT_TABLES.length) {
- header.langIndex = langIndex;
- }
- break;
- case PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION:
- let msgInd = this.readHexOctet() & 0xFF;
- let msgCount = this.readHexOctet();
- dataAvailable -= 2;
-
-
- /*
- * TS 23.040 V6.8.1 Sec 9.2.3.24.2
- * bits 1 0 : basic message indication type
- * bits 4 3 2 : extended message indication type
- * bits 6 5 : Profile id
- * bit 7 : storage type
- */
- let storeType = msgInd & PDU_MWI_STORE_TYPE_BIT;
- let mwi = msg.mwi;
- if (!mwi) {
- mwi = msg.mwi = {};
- }
-
- if (storeType == PDU_MWI_STORE_TYPE_STORE) {
- // Store message because TP_UDH indicates so, note this may override
- // the setting in DCS, but that is expected
- mwi.discard = false;
- } else if (mwi.discard === undefined) {
- // storeType == PDU_MWI_STORE_TYPE_DISCARD
- // only override mwi.discard here if it hasn't already been set
- mwi.discard = true;
- }
-
- mwi.msgCount = msgCount & 0xFF;
- mwi.active = mwi.msgCount > 0;
-
- if (DEBUG) {
- this.context.debug("MWI in TP_UDH received: " + JSON.stringify(mwi));
- }
-
- break;
- default:
- if (DEBUG) {
- this.context.debug("readUserDataHeader: unsupported IEI(" + id +
- "), " + length + " bytes.");
- }
-
- // Read out unsupported data
- if (length) {
- let octets;
- if (DEBUG) octets = new Uint8Array(length);
-
- for (let i = 0; i < length; i++) {
- let octet = this.readHexOctet();
- if (DEBUG) octets[i] = octet;
- }
- dataAvailable -= length;
-
- if (DEBUG) {
- this.context.debug("readUserDataHeader: " + Array.slice(octets));
- }
- }
- break;
- }
- }
-
- if (dataAvailable !== 0) {
- throw new Error("Illegal user data header found!");
- }
-
- msg.header = header;
- },
-
- /**
- * Write out user data header.
- *
- * @param options
- * Options containing information for user data header write-out. The
- * `userDataHeaderLength` property must be correctly pre-calculated.
- */
- writeUserDataHeader: function(options) {
- this.writeHexOctet(options.userDataHeaderLength);
-
- if (options.segmentMaxSeq > 1) {
- if (options.segmentRef16Bit) {
- this.writeHexOctet(PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT);
- this.writeHexOctet(4);
- this.writeHexOctet((options.segmentRef >> 8) & 0xFF);
- } else {
- this.writeHexOctet(PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT);
- this.writeHexOctet(3);
- }
- this.writeHexOctet(options.segmentRef & 0xFF);
- this.writeHexOctet(options.segmentMaxSeq & 0xFF);
- this.writeHexOctet(options.segmentSeq & 0xFF);
- }
-
- if (options.dcs == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- if (options.langIndex != PDU_NL_IDENTIFIER_DEFAULT) {
- this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT);
- this.writeHexOctet(1);
- this.writeHexOctet(options.langIndex);
- }
-
- if (options.langShiftIndex != PDU_NL_IDENTIFIER_DEFAULT) {
- this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT);
- this.writeHexOctet(1);
- this.writeHexOctet(options.langShiftIndex);
- }
- }
- },
-
- /**
- * Read SM-TL Address.
- *
- * @param len
- * Length of useful semi-octets within the Address-Value field. For
- * example, the lenth of "12345" should be 5, and 4 for "1234".
- *
- * @see 3GPP TS 23.040 9.1.2.5
- */
- readAddress: function(len) {
- // Address Length
- if (!len || (len < 0)) {
- if (DEBUG) {
- this.context.debug("PDU error: invalid sender address length: " + len);
- }
- return null;
- }
- if (len % 2 == 1) {
- len += 1;
- }
- if (DEBUG) this.context.debug("PDU: Going to read address: " + len);
-
- // Type-of-Address
- let toa = this.readHexOctet();
- let addr = "";
-
- if ((toa & 0xF0) == PDU_TOA_ALPHANUMERIC) {
- addr = this.readSeptetsToString(Math.floor(len * 4 / 7), 0,
- PDU_NL_IDENTIFIER_DEFAULT , PDU_NL_IDENTIFIER_DEFAULT );
- return addr;
- }
- addr = this.readSwappedNibbleExtendedBcdString(len / 2);
- if (addr.length <= 0) {
- if (DEBUG) this.context.debug("PDU error: no number provided");
- return null;
- }
- if ((toa & 0xF0) == (PDU_TOA_INTERNATIONAL)) {
- addr = '+' + addr;
- }
-
- return addr;
- },
-
- /**
- * Read TP-Protocol-Indicator(TP-PID).
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.040 9.2.3.9
- */
- readProtocolIndicator: function(msg) {
- // `The MS shall interpret reserved, obsolete, or unsupported values as the
- // value 00000000 but shall store them exactly as received.`
- msg.pid = this.readHexOctet();
-
- msg.epid = msg.pid;
- switch (msg.epid & 0xC0) {
- case 0x40:
- // Bit 7..0 = 01xxxxxx
- switch (msg.epid) {
- case PDU_PID_SHORT_MESSAGE_TYPE_0:
- case PDU_PID_ANSI_136_R_DATA:
- case PDU_PID_USIM_DATA_DOWNLOAD:
- return;
- }
- break;
- }
-
- msg.epid = PDU_PID_DEFAULT;
- },
-
- /**
- * Read TP-Data-Coding-Scheme(TP-DCS)
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.040 9.2.3.10, 3GPP TS 23.038 4.
- */
- readDataCodingScheme: function(msg) {
- let dcs = this.readHexOctet();
- if (DEBUG) this.context.debug("PDU: read SMS dcs: " + dcs);
-
- // No message class by default.
- let messageClass = PDU_DCS_MSG_CLASS_NORMAL;
- // 7 bit is the default fallback encoding.
- let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- switch (dcs & PDU_DCS_CODING_GROUP_BITS) {
- case 0x40: // bits 7..4 = 01xx
- case 0x50:
- case 0x60:
- case 0x70:
- // Bit 5..0 are coded exactly the same as Group 00xx
- case 0x00: // bits 7..4 = 00xx
- case 0x10:
- case 0x20:
- case 0x30:
- if (dcs & 0x10) {
- messageClass = dcs & PDU_DCS_MSG_CLASS_BITS;
- }
- switch (dcs & 0x0C) {
- case 0x4:
- encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
- break;
- case 0x8:
- encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
- break;
- }
- break;
-
- case 0xE0: // bits 7..4 = 1110
- encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
- // Bit 3..0 are coded exactly the same as Message Waiting Indication
- // Group 1101.
- // Fall through.
- case 0xC0: // bits 7..4 = 1100
- case 0xD0: // bits 7..4 = 1101
- // Indiciates voicemail indicator set or clear
- let active = (dcs & PDU_DCS_MWI_ACTIVE_BITS) == PDU_DCS_MWI_ACTIVE_VALUE;
-
- // If TP-UDH is present, these values will be overwritten
- switch (dcs & PDU_DCS_MWI_TYPE_BITS) {
- case PDU_DCS_MWI_TYPE_VOICEMAIL:
- let mwi = msg.mwi;
- if (!mwi) {
- mwi = msg.mwi = {};
- }
-
- mwi.active = active;
- mwi.discard = (dcs & PDU_DCS_CODING_GROUP_BITS) == 0xC0;
- mwi.msgCount = active ? GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN : 0;
-
- if (DEBUG) {
- this.context.debug("MWI in DCS received for voicemail: " +
- JSON.stringify(mwi));
- }
- break;
- case PDU_DCS_MWI_TYPE_FAX:
- if (DEBUG) this.context.debug("MWI in DCS received for fax");
- break;
- case PDU_DCS_MWI_TYPE_EMAIL:
- if (DEBUG) this.context.debug("MWI in DCS received for email");
- break;
- default:
- if (DEBUG) this.context.debug("MWI in DCS received for \"other\"");
- break;
- }
- break;
-
- case 0xF0: // bits 7..4 = 1111
- if (dcs & 0x04) {
- encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
- }
- messageClass = dcs & PDU_DCS_MSG_CLASS_BITS;
- break;
-
- default:
- // Falling back to default encoding.
- break;
- }
-
- msg.dcs = dcs;
- msg.encoding = encoding;
- msg.messageClass = GECKO_SMS_MESSAGE_CLASSES[messageClass];
-
- if (DEBUG) this.context.debug("PDU: message encoding is " + encoding + " bit.");
- },
-
- /**
- * Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
- *
- * @see 3GPP TS 23.040 9.2.3.11
- */
- readTimestamp: function() {
- let year = this.readSwappedNibbleBcdNum(1) + PDU_TIMESTAMP_YEAR_OFFSET;
- let month = this.readSwappedNibbleBcdNum(1) - 1;
- let day = this.readSwappedNibbleBcdNum(1);
- let hour = this.readSwappedNibbleBcdNum(1);
- let minute = this.readSwappedNibbleBcdNum(1);
- let second = this.readSwappedNibbleBcdNum(1);
- let timestamp = Date.UTC(year, month, day, hour, minute, second);
-
- // If the most significant bit of the least significant nibble is 1,
- // the timezone offset is negative (fourth bit from the right => 0x08):
- // localtime = UTC + tzOffset
- // therefore
- // UTC = localtime - tzOffset
- let tzOctet = this.readHexOctet();
- let tzOffset = this.octetToBCD(tzOctet & ~0x08) * 15 * 60 * 1000;
- tzOffset = (tzOctet & 0x08) ? -tzOffset : tzOffset;
- timestamp -= tzOffset;
-
- return timestamp;
- },
-
- /**
- * Write GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
- *
- * @see 3GPP TS 23.040 9.2.3.11
- */
- writeTimestamp: function(date) {
- this.writeSwappedNibbleBCDNum(date.getFullYear() - PDU_TIMESTAMP_YEAR_OFFSET);
-
- // The value returned by getMonth() is an integer between 0 and 11.
- // 0 is corresponds to January, 1 to February, and so on.
- this.writeSwappedNibbleBCDNum(date.getMonth() + 1);
- this.writeSwappedNibbleBCDNum(date.getDate());
- this.writeSwappedNibbleBCDNum(date.getHours());
- this.writeSwappedNibbleBCDNum(date.getMinutes());
- this.writeSwappedNibbleBCDNum(date.getSeconds());
-
- // the value returned by getTimezoneOffset() is the difference,
- // in minutes, between UTC and local time.
- // For example, if your time zone is UTC+10 (Australian Eastern Standard Time),
- // -600 will be returned.
- // In TS 23.040 9.2.3.11, the Time Zone field of TP-SCTS indicates
- // the different between the local time and GMT.
- // And expressed in quarters of an hours. (so need to divid by 15)
- let zone = date.getTimezoneOffset() / 15;
- let octet = this.BCDToOctet(zone);
-
- // the bit3 of the Time Zone field represents the algebraic sign.
- // (0: positive, 1: negative).
- // For example, if the time zone is -0800 GMT,
- // 480 will be returned by getTimezoneOffset().
- // In this case, need to mark sign bit as 1. => 0x08
- if (zone > 0) {
- octet = octet | 0x08;
- }
- this.writeHexOctet(octet);
- },
-
- /**
- * User data can be 7 bit (default alphabet) data, 8 bit data, or 16 bit
- * (UCS2) data.
- *
- * @param msg
- * message object for output.
- * @param length
- * length of user data to read in octets.
- */
- readUserData: function(msg, length) {
- if (DEBUG) {
- this.context.debug("Reading " + length + " bytes of user data.");
- }
-
- let paddingBits = 0;
- if (msg.udhi) {
- this.readUserDataHeader(msg);
-
- if (msg.encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- let headerBits = (msg.header.length + 1) * 8;
- let headerSeptets = Math.ceil(headerBits / 7);
-
- length -= headerSeptets;
- paddingBits = headerSeptets * 7 - headerBits;
- } else {
- length -= (msg.header.length + 1);
- }
- }
-
- if (DEBUG) {
- this.context.debug("After header, " + length + " septets left of user data");
- }
-
- msg.body = null;
- msg.data = null;
-
- if (length <= 0) {
- // No data to read.
- return;
- }
-
- switch (msg.encoding) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- // 7 bit encoding allows 140 octets, which means 160 characters
- // ((140x8) / 7 = 160 chars)
- if (length > PDU_MAX_USER_DATA_7BIT) {
- if (DEBUG) {
- this.context.debug("PDU error: user data is too long: " + length);
- }
- break;
- }
-
- let langIndex = msg.udhi ? msg.header.langIndex : PDU_NL_IDENTIFIER_DEFAULT;
- let langShiftIndex = msg.udhi ? msg.header.langShiftIndex : PDU_NL_IDENTIFIER_DEFAULT;
- msg.body = this.readSeptetsToString(length, paddingBits, langIndex,
- langShiftIndex);
- break;
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- msg.data = this.readHexOctetArray(length);
- break;
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- msg.body = this.readUCS2String(length);
- break;
- }
- },
-
- /**
- * Read extra parameters if TP-PI is set.
- *
- * @param msg
- * message object for output.
- */
- readExtraParams: function(msg) {
- // Because each PDU octet is converted to two UCS2 char2, we should always
- // get even messageStringLength in this#_processReceivedSms(). So, we'll
- // always need two delimitors at the end.
- if (this.context.Buf.getReadAvailable() <= 4) {
- return;
- }
-
- // TP-Parameter-Indicator
- let pi;
- do {
- // `The most significant bit in octet 1 and any other TP-PI octets which
- // may be added later is reserved as an extension bit which when set to a
- // 1 shall indicate that another TP-PI octet follows immediately
- // afterwards.` ~ 3GPP TS 23.040 9.2.3.27
- pi = this.readHexOctet();
- } while (pi & PDU_PI_EXTENSION);
-
- // `If the TP-UDL bit is set to "1" but the TP-DCS bit is set to "0" then
- // the receiving entity shall for TP-DCS assume a value of 0x00, i.e. the
- // 7bit default alphabet.` ~ 3GPP 23.040 9.2.3.27
- msg.dcs = 0;
- msg.encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
-
- // TP-Protocol-Identifier
- if (pi & PDU_PI_PROTOCOL_IDENTIFIER) {
- this.readProtocolIndicator(msg);
- }
- // TP-Data-Coding-Scheme
- if (pi & PDU_PI_DATA_CODING_SCHEME) {
- this.readDataCodingScheme(msg);
- }
- // TP-User-Data-Length
- if (pi & PDU_PI_USER_DATA_LENGTH) {
- let userDataLength = this.readHexOctet();
- this.readUserData(msg, userDataLength);
- }
- },
-
- /**
- * Read and decode a PDU-encoded message from the stream.
- *
- * TODO: add some basic sanity checks like:
- * - do we have the minimum number of chars available
- */
- readMessage: function() {
- // An empty message object. This gets filled below and then returned.
- let msg = {
- // D:DELIVER, DR:DELIVER-REPORT, S:SUBMIT, SR:SUBMIT-REPORT,
- // ST:STATUS-REPORT, C:COMMAND
- // M:Mandatory, O:Optional, X:Unavailable
- // D DR S SR ST C
- SMSC: null, // M M M M M M
- mti: null, // M M M M M M
- udhi: null, // M M O M M M
- sender: null, // M X X X X X
- recipient: null, // X X M X M M
- pid: null, // M O M O O M
- epid: null, // M O M O O M
- dcs: null, // M O M O O X
- mwi: null, // O O O O O O
- replace: false, // O O O O O O
- header: null, // M M O M M M
- body: null, // M O M O O O
- data: null, // M O M O O O
- sentTimestamp: null, // M X X X X X
- status: null, // X X X X M X
- scts: null, // X X X M M X
- dt: null, // X X X X M X
- };
-
- // SMSC info
- let smscLength = this.readHexOctet();
- if (smscLength > 0) {
- let smscTypeOfAddress = this.readHexOctet();
- // Subtract the type-of-address octet we just read from the length.
- msg.SMSC = this.readSwappedNibbleExtendedBcdString(smscLength - 1);
- if ((smscTypeOfAddress >> 4) == (PDU_TOA_INTERNATIONAL >> 4)) {
- msg.SMSC = '+' + msg.SMSC;
- }
- }
-
- // First octet of this SMS-DELIVER or SMS-SUBMIT message
- let firstOctet = this.readHexOctet();
- // Message Type Indicator
- msg.mti = firstOctet & 0x03;
- // User data header indicator
- msg.udhi = firstOctet & PDU_UDHI;
-
- switch (msg.mti) {
- case PDU_MTI_SMS_RESERVED:
- // `If an MS receives a TPDU with a "Reserved" value in the TP-MTI it
- // shall process the message as if it were an "SMS-DELIVER" but store
- // the message exactly as received.` ~ 3GPP TS 23.040 9.2.3.1
- case PDU_MTI_SMS_DELIVER:
- return this.readDeliverMessage(msg);
- case PDU_MTI_SMS_STATUS_REPORT:
- return this.readStatusReportMessage(msg);
- default:
- return null;
- }
- },
-
- /**
- * Helper for processing received SMS parcel data.
- *
- * @param length
- * Length of SMS string in the incoming parcel.
- *
- * @return Message parsed or null for invalid message.
- */
- processReceivedSms: function(length) {
- if (!length) {
- if (DEBUG) this.context.debug("Received empty SMS!");
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- let Buf = this.context.Buf;
-
- // An SMS is a string, but we won't read it as such, so let's read the
- // string length and then defer to PDU parsing helper.
- let messageStringLength = Buf.readInt32();
- if (DEBUG) this.context.debug("Got new SMS, length " + messageStringLength);
- let message = this.readMessage();
- if (DEBUG) this.context.debug("Got new SMS: " + JSON.stringify(message));
-
- // Read string delimiters. See Buf.readString().
- Buf.readStringDelimiter(length);
-
- // Determine result
- if (!message) {
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- if (message.epid == PDU_PID_SHORT_MESSAGE_TYPE_0) {
- // `A short message type 0 indicates that the ME must acknowledge receipt
- // of the short message but shall discard its contents.` ~ 3GPP TS 23.040
- // 9.2.3.9
- return [null, PDU_FCS_OK];
- }
-
- if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
- let RIL = this.context.RIL;
- switch (message.epid) {
- case PDU_PID_ANSI_136_R_DATA:
- case PDU_PID_USIM_DATA_DOWNLOAD:
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- if (ICCUtilsHelper.isICCServiceAvailable("DATA_DOWNLOAD_SMS_PP")) {
- // `If the service "data download via SMS Point-to-Point" is
- // allocated and activated in the (U)SIM Service Table, ... then the
- // ME shall pass the message transparently to the UICC using the
- // ENVELOPE (SMS-PP DOWNLOAD).` ~ 3GPP TS 31.111 7.1.1.1
- RIL.dataDownloadViaSMSPP(message);
-
- // `the ME shall not display the message, or alert the user of a
- // short message waiting.` ~ 3GPP TS 31.111 7.1.1.1
- return [null, PDU_FCS_RESERVED];
- }
-
- // If the service "data download via SMS-PP" is not available in the
- // (U)SIM Service Table, ..., then the ME shall store the message in
- // EFsms in accordance with TS 31.102` ~ 3GPP TS 31.111 7.1.1.1
-
- // Fall through.
- default:
- RIL.writeSmsToSIM(message);
- break;
- }
- }
-
- // TODO: Bug 739143: B2G SMS: Support SMS Storage Full event
- if ((message.messageClass != GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]) && !true) {
- // `When a mobile terminated message is class 0..., the MS shall display
- // the message immediately and send a ACK to the SC ..., irrespective of
- // whether there is memory available in the (U)SIM or ME.` ~ 3GPP 23.038
- // clause 4.
-
- if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
- // `If all the short message storage at the MS is already in use, the
- // MS shall return "memory capacity exceeded".` ~ 3GPP 23.038 clause 4.
- return [null, PDU_FCS_MEMORY_CAPACITY_EXCEEDED];
- }
-
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- return [message, PDU_FCS_OK];
- },
-
- /**
- * Read and decode a SMS-DELIVER PDU.
- *
- * @param msg
- * message object for output.
- */
- readDeliverMessage: function(msg) {
- // - Sender Address info -
- let senderAddressLength = this.readHexOctet();
- msg.sender = this.readAddress(senderAddressLength);
- // - TP-Protocolo-Identifier -
- this.readProtocolIndicator(msg);
- // - TP-Data-Coding-Scheme -
- this.readDataCodingScheme(msg);
- // - TP-Service-Center-Time-Stamp -
- msg.sentTimestamp = this.readTimestamp();
- // - TP-User-Data-Length -
- let userDataLength = this.readHexOctet();
-
- // - TP-User-Data -
- if (userDataLength > 0) {
- this.readUserData(msg, userDataLength);
- }
-
- return msg;
- },
-
- /**
- * Read and decode a SMS-STATUS-REPORT PDU.
- *
- * @param msg
- * message object for output.
- */
- readStatusReportMessage: function(msg) {
- // TP-Message-Reference
- msg.messageRef = this.readHexOctet();
- // TP-Recipient-Address
- let recipientAddressLength = this.readHexOctet();
- msg.recipient = this.readAddress(recipientAddressLength);
- // TP-Service-Centre-Time-Stamp
- msg.scts = this.readTimestamp();
- // TP-Discharge-Time
- msg.dt = this.readTimestamp();
- // TP-Status
- msg.status = this.readHexOctet();
-
- this.readExtraParams(msg);
-
- return msg;
- },
-
- /**
- * Serialize a SMS-SUBMIT PDU message and write it to the output stream.
- *
- * This method expects that a data coding scheme has been chosen already
- * and that the length of the user data payload in that encoding is known,
- * too. Both go hand in hand together anyway.
- *
- * @param address
- * String containing the address (number) of the SMS receiver
- * @param userData
- * String containing the message to be sent as user data
- * @param dcs
- * Data coding scheme. One of the PDU_DCS_MSG_CODING_*BITS_ALPHABET
- * constants.
- * @param userDataHeaderLength
- * Length of embedded user data header, in bytes. The whole header
- * size will be userDataHeaderLength + 1; 0 for no header.
- * @param encodedBodyLength
- * Length of the user data when encoded with the given DCS. For UCS2,
- * in bytes; for 7-bit, in septets.
- * @param langIndex
- * Table index used for normal 7-bit encoded character lookup.
- * @param langShiftIndex
- * Table index used for escaped 7-bit encoded character lookup.
- * @param requestStatusReport
- * Request status report.
- */
- writeMessage: function(options) {
- if (DEBUG) {
- this.context.debug("writeMessage: " + JSON.stringify(options));
- }
- let Buf = this.context.Buf;
- let address = options.number;
- let body = options.body;
- let dcs = options.dcs;
- let userDataHeaderLength = options.userDataHeaderLength;
- let encodedBodyLength = options.encodedBodyLength;
- let langIndex = options.langIndex;
- let langShiftIndex = options.langShiftIndex;
-
- // SMS-SUBMIT Format:
- //
- // PDU Type - 1 octet
- // Message Reference - 1 octet
- // DA - Destination Address - 2 to 12 octets
- // PID - Protocol Identifier - 1 octet
- // DCS - Data Coding Scheme - 1 octet
- // VP - Validity Period - 0, 1 or 7 octets
- // UDL - User Data Length - 1 octet
- // UD - User Data - 140 octets
-
- let addressFormat = PDU_TOA_ISDN; // 81
- if (address[0] == '+') {
- addressFormat = PDU_TOA_INTERNATIONAL | PDU_TOA_ISDN; // 91
- address = address.substring(1);
- }
- //TODO validity is unsupported for now
- let validity = 0;
-
- let headerOctets = (userDataHeaderLength ? userDataHeaderLength + 1 : 0);
- let paddingBits;
- let userDataLengthInSeptets;
- let userDataLengthInOctets;
- if (dcs == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- let headerSeptets = Math.ceil(headerOctets * 8 / 7);
- userDataLengthInSeptets = headerSeptets + encodedBodyLength;
- userDataLengthInOctets = Math.ceil(userDataLengthInSeptets * 7 / 8);
- paddingBits = headerSeptets * 7 - headerOctets * 8;
- } else {
- userDataLengthInOctets = headerOctets + encodedBodyLength;
- paddingBits = 0;
- }
-
- let pduOctetLength = 4 + // PDU Type, Message Ref, address length + format
- Math.ceil(address.length / 2) +
- 3 + // PID, DCS, UDL
- userDataLengthInOctets;
- if (validity) {
- //TODO: add more to pduOctetLength
- }
-
- // Start the string. Since octets are represented in hex, we will need
- // twice as many characters as octets.
- Buf.writeInt32(pduOctetLength * 2);
-
- // - PDU-TYPE-
-
- // +--------+----------+---------+---------+--------+---------+
- // | RP (1) | UDHI (1) | SRR (1) | VPF (2) | RD (1) | MTI (2) |
- // +--------+----------+---------+---------+--------+---------+
- // RP: 0 Reply path parameter is not set
- // 1 Reply path parameter is set
- // UDHI: 0 The UD Field contains only the short message
- // 1 The beginning of the UD field contains a header in addition
- // of the short message
- // SRR: 0 A status report is not requested
- // 1 A status report is requested
- // VPF: bit4 bit3
- // 0 0 VP field is not present
- // 0 1 Reserved
- // 1 0 VP field present an integer represented (relative)
- // 1 1 VP field present a semi-octet represented (absolute)
- // RD: Instruct the SMSC to accept(0) or reject(1) an SMS-SUBMIT
- // for a short message still held in the SMSC which has the same
- // MR and DA as a previously submitted short message from the
- // same OA
- // MTI: bit1 bit0 Message Type
- // 0 0 SMS-DELIVER (SMSC ==> MS)
- // 0 1 SMS-SUBMIT (MS ==> SMSC)
-
- // PDU type. MTI is set to SMS-SUBMIT
- let firstOctet = PDU_MTI_SMS_SUBMIT;
-
- // Status-Report-Request
- if (options.requestStatusReport) {
- firstOctet |= PDU_SRI_SRR;
- }
-
- // Validity period
- if (validity) {
- //TODO: not supported yet, OR with one of PDU_VPF_*
- }
- // User data header indicator
- if (headerOctets) {
- firstOctet |= PDU_UDHI;
- }
- this.writeHexOctet(firstOctet);
-
- // Message reference 00
- this.writeHexOctet(0x00);
-
- // - Destination Address -
- this.writeHexOctet(address.length);
- this.writeHexOctet(addressFormat);
- this.writeSwappedNibbleBCD(address);
-
- // - Protocol Identifier -
- this.writeHexOctet(0x00);
-
- // - Data coding scheme -
- // For now it assumes bits 7..4 = 1111 except for the 16 bits use case
- this.writeHexOctet(dcs);
-
- // - Validity Period -
- if (validity) {
- this.writeHexOctet(validity);
- }
-
- // - User Data -
- if (dcs == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- this.writeHexOctet(userDataLengthInSeptets);
- } else {
- this.writeHexOctet(userDataLengthInOctets);
- }
-
- if (headerOctets) {
- this.writeUserDataHeader(options);
- }
-
- switch (dcs) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- this.writeStringAsSeptets(body, paddingBits, langIndex, langShiftIndex);
- break;
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- // Unsupported.
- break;
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- this.writeUCS2String(body);
- break;
- }
-
- // End of the string. The string length is always even by definition, so
- // we write two \0 delimiters.
- Buf.writeUint16(0);
- Buf.writeUint16(0);
- },
-
- /**
- * Read GSM CBS message serial number.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.1
- */
- readCbSerialNumber: function(msg) {
- let Buf = this.context.Buf;
- msg.serial = Buf.readUint8() << 8 | Buf.readUint8();
- msg.geographicalScope = (msg.serial >>> 14) & 0x03;
- msg.messageCode = (msg.serial >>> 4) & 0x03FF;
- msg.updateNumber = msg.serial & 0x0F;
- },
-
- /**
- * Read GSM CBS message message identifier.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.2
- */
- readCbMessageIdentifier: function(msg) {
- let Buf = this.context.Buf;
- msg.messageId = Buf.readUint8() << 8 | Buf.readUint8();
- },
-
- /**
- * Read ETWS information from message identifier and serial Number
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.1 & 9.4.1.2.2
- */
- readCbEtwsInfo: function(msg) {
- if ((msg.format != CB_FORMAT_ETWS)
- && (msg.messageId >= CB_GSM_MESSAGEID_ETWS_BEGIN)
- && (msg.messageId <= CB_GSM_MESSAGEID_ETWS_END)) {
- // `In the case of transmitting CBS message for ETWS, a part of
- // Message Code can be used to command mobile terminals to activate
- // emergency user alert and message popup in order to alert the users.`
- msg.etws = {
- emergencyUserAlert: msg.messageCode & 0x0200 ? true : false,
- popup: msg.messageCode & 0x0100 ? true : false
- };
-
- let warningType = msg.messageId - CB_GSM_MESSAGEID_ETWS_BEGIN;
- if (warningType < CB_ETWS_WARNING_TYPE_NAMES.length) {
- msg.etws.warningType = warningType;
- }
- }
- },
-
- /**
- * Read CBS Data Coding Scheme.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.038 section 5.
- */
- readCbDataCodingScheme: function(msg) {
- let dcs = this.context.Buf.readUint8();
- if (DEBUG) this.context.debug("PDU: read CBS dcs: " + dcs);
-
- let language = null, hasLanguageIndicator = false;
- // `Any reserved codings shall be assumed to be the GSM 7bit default
- // alphabet.`
- let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- let messageClass = PDU_DCS_MSG_CLASS_NORMAL;
-
- switch (dcs & PDU_DCS_CODING_GROUP_BITS) {
- case 0x00: // 0000
- language = CB_DCS_LANG_GROUP_1[dcs & 0x0F];
- break;
-
- case 0x10: // 0001
- switch (dcs & 0x0F) {
- case 0x00:
- hasLanguageIndicator = true;
- break;
- case 0x01:
- encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
- hasLanguageIndicator = true;
- break;
- }
- break;
-
- case 0x20: // 0010
- language = CB_DCS_LANG_GROUP_2[dcs & 0x0F];
- break;
-
- case 0x40: // 01xx
- case 0x50:
- //case 0x60: Text Compression, not supported
- //case 0x70: Text Compression, not supported
- case 0x90: // 1001
- encoding = (dcs & 0x0C);
- if (encoding == 0x0C) {
- encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- }
- messageClass = (dcs & PDU_DCS_MSG_CLASS_BITS);
- break;
-
- case 0xF0:
- encoding = (dcs & 0x04) ? PDU_DCS_MSG_CODING_8BITS_ALPHABET
- : PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- switch(dcs & PDU_DCS_MSG_CLASS_BITS) {
- case 0x01: messageClass = PDU_DCS_MSG_CLASS_USER_1; break;
- case 0x02: messageClass = PDU_DCS_MSG_CLASS_USER_2; break;
- case 0x03: messageClass = PDU_DCS_MSG_CLASS_3; break;
- }
- break;
-
- case 0x30: // 0011 (Reserved)
- case 0x80: // 1000 (Reserved)
- case 0xA0: // 1010..1100 (Reserved)
- case 0xB0:
- case 0xC0:
- break;
-
- default:
- throw new Error("Unsupported CBS data coding scheme: " + dcs);
- }
-
- msg.dcs = dcs;
- msg.encoding = encoding;
- msg.language = language;
- msg.messageClass = GECKO_SMS_MESSAGE_CLASSES[messageClass];
- msg.hasLanguageIndicator = hasLanguageIndicator;
- },
-
- /**
- * Read GSM CBS message page parameter.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.4
- */
- readCbPageParameter: function(msg) {
- let octet = this.context.Buf.readUint8();
- msg.pageIndex = (octet >>> 4) & 0x0F;
- msg.numPages = octet & 0x0F;
- if (!msg.pageIndex || !msg.numPages) {
- // `If a mobile receives the code 0000 in either the first field or the
- // second field then it shall treat the CBS message exactly the same as a
- // CBS message with page parameter 0001 0001 (i.e. a single page message).`
- msg.pageIndex = msg.numPages = 1;
- }
- },
-
- /**
- * Read ETWS Primary Notification message warning type.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.3.24
- */
- readCbWarningType: function(msg) {
- let Buf = this.context.Buf;
- let word = Buf.readUint8() << 8 | Buf.readUint8();
- msg.etws = {
- warningType: (word >>> 9) & 0x7F,
- popup: word & 0x80 ? true : false,
- emergencyUserAlert: word & 0x100 ? true : false
- };
- },
-
- /**
- * Read GSM CB Data
- *
- * This parameter is a copy of the 'CBS-Message-Information-Page' as sent
- * from the CBC to the BSC.
- *
- * @see 3GPP TS 23.041 section 9.4.1.2.5
- */
- readGsmCbData: function(msg, length) {
- let Buf = this.context.Buf;
- let bufAdapter = {
- context: this.context,
- readHexOctet: function() {
- return Buf.readUint8();
- }
- };
-
- msg.body = null;
- msg.data = null;
- switch (msg.encoding) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- msg.body = this.readSeptetsToString.call(bufAdapter,
- Math.floor(length * 8 / 7), 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- if (msg.hasLanguageIndicator) {
- msg.language = msg.body.substring(0, 2);
- msg.body = msg.body.substring(3);
- }
- break;
-
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- msg.data = Buf.readUint8Array(length);
- break;
-
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- if (msg.hasLanguageIndicator) {
- msg.language = this.readSeptetsToString.call(bufAdapter, 2, 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- length -= 2;
- }
- msg.body = this.readUCS2String.call(bufAdapter, length);
- break;
- }
-
- if (msg.data || !msg.body) {
- return;
- }
-
- // According to 9.3.19 CBS-Message-Information-Page in TS 23.041:
- // "
- // This parameter is of a fixed length of 82 octets and carries up to and
- // including 82 octets of user information. Where the user information is
- // less than 82 octets, the remaining octets must be filled with padding.
- // "
- // According to 6.2.1.1 GSM 7 bit Default Alphabet and 6.2.3 UCS2 in
- // TS 23.038, the padding character is <CR>.
- for (let i = msg.body.length - 1; i >= 0; i--) {
- if (msg.body.charAt(i) !== '\r') {
- msg.body = msg.body.substring(0, i + 1);
- break;
- }
- }
- },
-
- /**
- * Read UMTS CB Data
- *
- * Octet Number(s) Parameter
- * 1 Number-of-Pages
- * 2 - 83 CBS-Message-Information-Page 1
- * 84 CBS-Message-Information-Length 1
- * ...
- * CBS-Message-Information-Page n
- * CBS-Message-Information-Length n
- *
- * @see 3GPP TS 23.041 section 9.4.2.2.5
- */
- readUmtsCbData: function(msg) {
- let Buf = this.context.Buf;
- let numOfPages = Buf.readUint8();
- if (numOfPages < 0 || numOfPages > 15) {
- throw new Error("Invalid numOfPages: " + numOfPages);
- }
-
- let bufAdapter = {
- context: this.context,
- readHexOctet: function() {
- return Buf.readUint8();
- }
- };
-
- let removePaddingCharactors = function (text) {
- for (let i = text.length - 1; i >= 0; i--) {
- if (text.charAt(i) !== '\r') {
- return text.substring(0, i + 1);
- }
- }
- return text;
- };
-
- let totalLength = 0, length, pageLengths = [];
- for (let i = 0; i < numOfPages; i++) {
- Buf.seekIncoming(CB_MSG_PAGE_INFO_SIZE);
- length = Buf.readUint8();
- totalLength += length;
- pageLengths.push(length);
- }
-
- // Seek back to beginning of CB Data.
- Buf.seekIncoming(-numOfPages * (CB_MSG_PAGE_INFO_SIZE + 1));
-
- switch (msg.encoding) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET: {
- let body;
- msg.body = "";
- for (let i = 0; i < numOfPages; i++) {
- body = this.readSeptetsToString.call(bufAdapter,
- Math.floor(pageLengths[i] * 8 / 7),
- 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- if (msg.hasLanguageIndicator) {
- if (!msg.language) {
- msg.language = body.substring(0, 2);
- }
- body = body.substring(3);
- }
-
- msg.body += removePaddingCharactors(body);
-
- // Skip padding octets
- Buf.seekIncoming(CB_MSG_PAGE_INFO_SIZE - pageLengths[i]);
- // Read the octet of CBS-Message-Information-Length
- Buf.readUint8();
- }
-
- break;
- }
-
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET: {
- msg.data = new Uint8Array(totalLength);
- for (let i = 0, j = 0; i < numOfPages; i++) {
- for (let pageLength = pageLengths[i]; pageLength > 0; pageLength--) {
- msg.data[j++] = Buf.readUint8();
- }
-
- // Skip padding octets
- Buf.seekIncoming(CB_MSG_PAGE_INFO_SIZE - pageLengths[i]);
- // Read the octet of CBS-Message-Information-Length
- Buf.readUint8();
- }
-
- break;
- }
-
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET: {
- msg.body = "";
- for (let i = 0; i < numOfPages; i++) {
- let pageLength = pageLengths[i];
- if (msg.hasLanguageIndicator) {
- if (!msg.language) {
- msg.language = this.readSeptetsToString.call(bufAdapter,
- 2,
- 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- } else {
- Buf.readUint16();
- }
-
- pageLength -= 2;
- }
-
- msg.body += removePaddingCharactors(
- this.readUCS2String.call(bufAdapter, pageLength));
-
- // Skip padding octets
- Buf.seekIncoming(CB_MSG_PAGE_INFO_SIZE - pageLengths[i]);
- // Read the octet of CBS-Message-Information-Length
- Buf.readUint8();
- }
-
- break;
- }
- }
- },
-
- /**
- * Read Cell GSM/ETWS/UMTS Broadcast Message.
- *
- * @param pduLength
- * total length of the incoming PDU in octets.
- */
- readCbMessage: function(pduLength) {
- // Validity GSM ETWS UMTS
- let msg = {
- // Internally used in ril_worker:
- serial: null, // O O O
- updateNumber: null, // O O O
- format: null, // O O O
- dcs: 0x0F, // O X O
- encoding: PDU_DCS_MSG_CODING_7BITS_ALPHABET, // O X O
- hasLanguageIndicator: false, // O X O
- data: null, // O X O
- body: null, // O X O
- pageIndex: 1, // O X X
- numPages: 1, // O X X
-
- // DOM attributes:
- geographicalScope: null, // O O O
- messageCode: null, // O O O
- messageId: null, // O O O
- language: null, // O X O
- fullBody: null, // O X O
- fullData: null, // O X O
- messageClass: GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL], // O x O
- etws: null // ? O ?
- /*{
- warningType: null, // X O X
- popup: false, // X O X
- emergencyUserAlert: false, // X O X
- }*/
- };
-
- if (pduLength <= CB_MESSAGE_SIZE_ETWS) {
- msg.format = CB_FORMAT_ETWS;
- return this.readEtwsCbMessage(msg);
- }
-
- if (pduLength <= CB_MESSAGE_SIZE_GSM) {
- msg.format = CB_FORMAT_GSM;
- return this.readGsmCbMessage(msg, pduLength);
- }
-
- if (pduLength >= CB_MESSAGE_SIZE_UMTS_MIN &&
- pduLength <= CB_MESSAGE_SIZE_UMTS_MAX) {
- msg.format = CB_FORMAT_UMTS;
- return this.readUmtsCbMessage(msg);
- }
-
- throw new Error("Invalid PDU Length: " + pduLength);
- },
-
- /**
- * Read UMTS CBS Message.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 section 9.4.2
- * @see 3GPP TS 25.324 section 10.2
- */
- readUmtsCbMessage: function(msg) {
- let Buf = this.context.Buf;
- let type = Buf.readUint8();
- if (type != CB_UMTS_MESSAGE_TYPE_CBS) {
- throw new Error("Unsupported UMTS Cell Broadcast message type: " + type);
- }
-
- this.readCbMessageIdentifier(msg);
- this.readCbSerialNumber(msg);
- this.readCbEtwsInfo(msg);
- this.readCbDataCodingScheme(msg);
- this.readUmtsCbData(msg);
-
- return msg;
- },
-
- /**
- * Read GSM Cell Broadcast Message.
- *
- * @param msg
- * message object for output.
- * @param pduLength
- * total length of the incomint PDU in octets.
- *
- * @see 3GPP TS 23.041 clause 9.4.1.2
- */
- readGsmCbMessage: function(msg, pduLength) {
- this.readCbSerialNumber(msg);
- this.readCbMessageIdentifier(msg);
- this.readCbEtwsInfo(msg);
- this.readCbDataCodingScheme(msg);
- this.readCbPageParameter(msg);
-
- // GSM CB message header takes 6 octets.
- this.readGsmCbData(msg, pduLength - 6);
-
- return msg;
- },
-
- /**
- * Read ETWS Primary Notification Message.
- *
- * @param msg
- * message object for output.
- *
- * @see 3GPP TS 23.041 clause 9.4.1.3
- */
- readEtwsCbMessage: function(msg) {
- this.readCbSerialNumber(msg);
- this.readCbMessageIdentifier(msg);
- this.readCbWarningType(msg);
-
- // Octet 7..56 is Warning Security Information. However, according to
- // section 9.4.1.3.6, `The UE shall ignore this parameter.` So we just skip
- // processing it here.
-
- return msg;
- },
-
- /**
- * Read network name.
- *
- * @param len Length of the information element.
- * @return
- * {
- * networkName: network name.
- * shouldIncludeCi: Should Country's initials included in text string.
- * }
- * @see TS 24.008 clause 10.5.3.5a.
- */
- readNetworkName: function(len) {
- // According to TS 24.008 Sec. 10.5.3.5a, the first octet is:
- // bit 8: must be 1.
- // bit 5-7: Text encoding.
- // 000 - GSM default alphabet.
- // 001 - UCS2 (16 bit).
- // else - reserved.
- // bit 4: MS should add the letters for Country's Initials and a space
- // to the text string if this bit is true.
- // bit 1-3: number of spare bits in last octet.
-
- let codingInfo = this.readHexOctet();
- if (!(codingInfo & 0x80)) {
- return null;
- }
-
- let textEncoding = (codingInfo & 0x70) >> 4;
- let shouldIncludeCountryInitials = !!(codingInfo & 0x08);
- let spareBits = codingInfo & 0x07;
- let resultString;
-
- switch (textEncoding) {
- case 0:
- // GSM Default alphabet.
- resultString = this.readSeptetsToString(
- Math.floor(((len - 1) * 8 - spareBits) / 7), 0,
- PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- break;
- case 1:
- // UCS2 encoded.
- resultString = this.context.ICCPDUHelper.readAlphaIdentifier(len - 1);
- break;
- default:
- // Not an available text coding.
- return null;
- }
-
- // TODO - Bug 820286: According to shouldIncludeCountryInitials, add
- // country initials to the resulting string.
- return resultString;
- }
-};
-
-/**
- * Provide buffer with bitwise read/write function so make encoding/decoding easier.
- */
-function BitBufferHelperObject(/* unused */aContext) {
- this.readBuffer = [];
- this.writeBuffer = [];
-}
-BitBufferHelperObject.prototype = {
- readCache: 0,
- readCacheSize: 0,
- readBuffer: null,
- readIndex: 0,
- writeCache: 0,
- writeCacheSize: 0,
- writeBuffer: null,
-
- // Max length is 32 because we use integer as read/write cache.
- // All read/write functions are implemented based on bitwise operation.
- readBits: function(length) {
- if (length <= 0 || length > 32) {
- return null;
- }
-
- if (length > this.readCacheSize) {
- let bytesToRead = Math.ceil((length - this.readCacheSize) / 8);
- for(let i = 0; i < bytesToRead; i++) {
- this.readCache = (this.readCache << 8) | (this.readBuffer[this.readIndex++] & 0xFF);
- this.readCacheSize += 8;
- }
- }
-
- let bitOffset = (this.readCacheSize - length),
- resultMask = (1 << length) - 1,
- result = 0;
-
- result = (this.readCache >> bitOffset) & resultMask;
- this.readCacheSize -= length;
-
- return result;
- },
-
- backwardReadPilot: function(length) {
- if (length <= 0) {
- return;
- }
-
- // Zero-based position.
- let bitIndexToRead = this.readIndex * 8 - this.readCacheSize - length;
-
- if (bitIndexToRead < 0) {
- return;
- }
-
- // Update readIndex, readCache, readCacheSize accordingly.
- let readBits = bitIndexToRead % 8;
- this.readIndex = Math.floor(bitIndexToRead / 8) + ((readBits) ? 1 : 0);
- this.readCache = (readBits) ? this.readBuffer[this.readIndex - 1] : 0;
- this.readCacheSize = (readBits) ? (8 - readBits) : 0;
- },
-
- writeBits: function(value, length) {
- if (length <= 0 || length > 32) {
- return;
- }
-
- let totalLength = length + this.writeCacheSize;
-
- // 8-byte cache not full
- if (totalLength < 8) {
- let valueMask = (1 << length) - 1;
- this.writeCache = (this.writeCache << length) | (value & valueMask);
- this.writeCacheSize += length;
- return;
- }
-
- // Deal with unaligned part
- if (this.writeCacheSize) {
- let mergeLength = 8 - this.writeCacheSize,
- valueMask = (1 << mergeLength) - 1;
-
- this.writeCache = (this.writeCache << mergeLength) | ((value >> (length - mergeLength)) & valueMask);
- this.writeBuffer.push(this.writeCache & 0xFF);
- length -= mergeLength;
- }
-
- // Aligned part, just copy
- while (length >= 8) {
- length -= 8;
- this.writeBuffer.push((value >> length) & 0xFF);
- }
-
- // Rest part is saved into cache
- this.writeCacheSize = length;
- this.writeCache = value & ((1 << length) - 1);
-
- return;
- },
-
- // Drop what still in read cache and goto next 8-byte alignment.
- // There might be a better naming.
- nextOctetAlign: function() {
- this.readCache = 0;
- this.readCacheSize = 0;
- },
-
- // Flush current write cache to Buf with padding 0s.
- // There might be a better naming.
- flushWithPadding: function() {
- if (this.writeCacheSize) {
- this.writeBuffer.push(this.writeCache << (8 - this.writeCacheSize));
- }
- this.writeCache = 0;
- this.writeCacheSize = 0;
- },
-
- startWrite: function(dataBuffer) {
- this.writeBuffer = dataBuffer;
- this.writeCache = 0;
- this.writeCacheSize = 0;
- },
-
- startRead: function(dataBuffer) {
- this.readBuffer = dataBuffer;
- this.readCache = 0;
- this.readCacheSize = 0;
- this.readIndex = 0;
- },
-
- getWriteBufferSize: function() {
- return this.writeBuffer.length;
- },
-
- overwriteWriteBuffer: function(position, data) {
- let writeLength = data.length;
- if (writeLength + position >= this.writeBuffer.length) {
- writeLength = this.writeBuffer.length - position;
- }
- for (let i = 0; i < writeLength; i++) {
- this.writeBuffer[i + position] = data[i];
- }
- }
-};
-
-/**
- * Helper for CDMA PDU
- *
- * Currently, some function are shared with GsmPDUHelper, they should be
- * moved from GsmPDUHelper to a common object shared among GsmPDUHelper and
- * CdmaPDUHelper.
- */
-function CdmaPDUHelperObject(aContext) {
- this.context = aContext;
-}
-CdmaPDUHelperObject.prototype = {
- context: null,
-
- // 1..........C
- // Only "1234567890*#" is defined in C.S0005-D v2.0
- dtmfChars: ".1234567890*#...",
-
- /**
- * Entry point for SMS encoding, the options object is made compatible
- * with existing writeMessage() of GsmPDUHelper, but less key is used.
- *
- * Current used key in options:
- * @param number
- * String containing the address (number) of the SMS receiver
- * @param body
- * String containing the message to be sent, segmented part
- * @param dcs
- * Data coding scheme. One of the PDU_DCS_MSG_CODING_*BITS_ALPHABET
- * constants.
- * @param encodedBodyLength
- * Length of the user data when encoded with the given DCS. For UCS2,
- * in bytes; for 7-bit, in septets.
- * @param requestStatusReport
- * Request status report.
- * @param segmentRef
- * Reference number of concatenated SMS message
- * @param segmentMaxSeq
- * Total number of concatenated SMS message
- * @param segmentSeq
- * Sequence number of concatenated SMS message
- */
- writeMessage: function(options) {
- if (DEBUG) {
- this.context.debug("cdma_writeMessage: " + JSON.stringify(options));
- }
-
- // Get encoding
- options.encoding = this.gsmDcsToCdmaEncoding(options.dcs);
-
- // Common Header
- if (options.segmentMaxSeq > 1) {
- this.writeInt(PDU_CDMA_MSG_TELESERIVCIE_ID_WEMT);
- } else {
- this.writeInt(PDU_CDMA_MSG_TELESERIVCIE_ID_SMS);
- }
-
- this.writeInt(0);
- this.writeInt(PDU_CDMA_MSG_CATEGORY_UNSPEC);
-
- // Just fill out address info in byte, rild will encap them for us
- let addrInfo = this.encodeAddr(options.number);
- this.writeByte(addrInfo.digitMode);
- this.writeByte(addrInfo.numberMode);
- this.writeByte(addrInfo.numberType);
- this.writeByte(addrInfo.numberPlan);
- this.writeByte(addrInfo.address.length);
- for (let i = 0; i < addrInfo.address.length; i++) {
- this.writeByte(addrInfo.address[i]);
- }
-
- // Subaddress, not supported
- this.writeByte(0); // Subaddress : Type
- this.writeByte(0); // Subaddress : Odd
- this.writeByte(0); // Subaddress : length
-
- // User Data
- let encodeResult = this.encodeUserData(options);
- this.writeByte(encodeResult.length);
- for (let i = 0; i < encodeResult.length; i++) {
- this.writeByte(encodeResult[i]);
- }
-
- encodeResult = null;
- },
-
- /**
- * Data writters
- */
- writeInt: function(value) {
- this.context.Buf.writeInt32(value);
- },
-
- writeByte: function(value) {
- this.context.Buf.writeInt32(value & 0xFF);
- },
-
- /**
- * Transform GSM DCS to CDMA encoding.
- */
- gsmDcsToCdmaEncoding: function(encoding) {
- switch (encoding) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- return PDU_CDMA_MSG_CODING_7BITS_ASCII;
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- return PDU_CDMA_MSG_CODING_OCTET;
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- return PDU_CDMA_MSG_CODING_UNICODE;
- }
- throw new Error("gsmDcsToCdmaEncoding(): Invalid GSM SMS DCS value: " + encoding);
- },
-
- /**
- * Encode address into CDMA address format, as a byte array.
- *
- * @see 3GGP2 C.S0015-B 2.0, 3.4.3.3 Address Parameters
- *
- * @param address
- * String of address to be encoded
- */
- encodeAddr: function(address) {
- let result = {};
-
- result.numberType = PDU_CDMA_MSG_ADDR_NUMBER_TYPE_UNKNOWN;
- result.numberPlan = PDU_CDMA_MSG_ADDR_NUMBER_TYPE_UNKNOWN;
-
- if (address[0] === '+') {
- address = address.substring(1);
- }
-
- // Try encode with DTMF first
- result.digitMode = PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF;
- result.numberMode = PDU_CDMA_MSG_ADDR_NUMBER_MODE_ANSI;
-
- result.address = [];
- for (let i = 0; i < address.length; i++) {
- let addrDigit = this.dtmfChars.indexOf(address.charAt(i));
- if (addrDigit < 0) {
- result.digitMode = PDU_CDMA_MSG_ADDR_DIGIT_MODE_ASCII;
- result.numberMode = PDU_CDMA_MSG_ADDR_NUMBER_MODE_ASCII;
- result.address = [];
- break;
- }
- result.address.push(addrDigit);
- }
-
- // Address can't be encoded with DTMF, then use 7-bit ASCII
- if (result.digitMode !== PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF) {
- if (address.indexOf("@") !== -1) {
- result.numberType = PDU_CDMA_MSG_ADDR_NUMBER_TYPE_NATIONAL;
- }
-
- for (let i = 0; i < address.length; i++) {
- result.address.push(address.charCodeAt(i) & 0x7F);
- }
- }
-
- return result;
- },
-
- /**
- * Encode SMS contents in options into CDMA userData field.
- * Corresponding and required subparameters will be added automatically.
- *
- * @see 3GGP2 C.S0015-B 2.0, 3.4.3.7 Bearer Data
- * 4.5 Bearer Data Parameters
- *
- * Current used key in options:
- * @param body
- * String containing the message to be sent, segmented part
- * @param encoding
- * Encoding method of CDMA, can be transformed from GSM DCS by function
- * cdmaPduHelp.gsmDcsToCdmaEncoding()
- * @param encodedBodyLength
- * Length of the user data when encoded with the given DCS. For UCS2,
- * in bytes; for 7-bit, in septets.
- * @param requestStatusReport
- * Request status report.
- * @param segmentRef
- * Reference number of concatenated SMS message
- * @param segmentMaxSeq
- * Total number of concatenated SMS message
- * @param segmentSeq
- * Sequence number of concatenated SMS message
- */
- encodeUserData: function(options) {
- let userDataBuffer = [];
- this.context.BitBufferHelper.startWrite(userDataBuffer);
-
- // Message Identifier
- this.encodeUserDataMsgId(options);
-
- // User Data
- this.encodeUserDataMsg(options);
-
- // Reply Option
- this.encodeUserDataReplyOption(options);
-
- return userDataBuffer;
- },
-
- /**
- * User data subparameter encoder : Message Identifier
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.1 Message Identifier
- */
- encodeUserDataMsgId: function(options) {
- let BitBufferHelper = this.context.BitBufferHelper;
- BitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_MSG_ID, 8);
- BitBufferHelper.writeBits(3, 8);
- BitBufferHelper.writeBits(PDU_CDMA_MSG_TYPE_SUBMIT, 4);
- BitBufferHelper.writeBits(1, 16); // TODO: How to get message ID?
- if (options.segmentMaxSeq > 1) {
- BitBufferHelper.writeBits(1, 1);
- } else {
- BitBufferHelper.writeBits(0, 1);
- }
-
- BitBufferHelper.flushWithPadding();
- },
-
- /**
- * User data subparameter encoder : User Data
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.2 User Data
- */
- encodeUserDataMsg: function(options) {
- let BitBufferHelper = this.context.BitBufferHelper;
- BitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_BODY, 8);
- // Reserve space for length
- BitBufferHelper.writeBits(0, 8);
- let lengthPosition = BitBufferHelper.getWriteBufferSize();
-
- BitBufferHelper.writeBits(options.encoding, 5);
-
- // Add user data header for message segement
- let msgBody = options.body,
- msgBodySize = (options.encoding === PDU_CDMA_MSG_CODING_7BITS_ASCII ?
- options.encodedBodyLength :
- msgBody.length);
- if (options.segmentMaxSeq > 1) {
- if (options.encoding === PDU_CDMA_MSG_CODING_7BITS_ASCII) {
- BitBufferHelper.writeBits(msgBodySize + 7, 8); // Required length for user data header, in septet(7-bit)
-
- BitBufferHelper.writeBits(5, 8); // total header length 5 bytes
- BitBufferHelper.writeBits(PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT, 8); // header id 0
- BitBufferHelper.writeBits(3, 8); // length of element for id 0 is 3
- BitBufferHelper.writeBits(options.segmentRef & 0xFF, 8); // Segement reference
- BitBufferHelper.writeBits(options.segmentMaxSeq & 0xFF, 8); // Max segment
- BitBufferHelper.writeBits(options.segmentSeq & 0xFF, 8); // Current segment
- BitBufferHelper.writeBits(0, 1); // Padding to make header data septet(7-bit) aligned
- } else {
- if (options.encoding === PDU_CDMA_MSG_CODING_UNICODE) {
- BitBufferHelper.writeBits(msgBodySize + 3, 8); // Required length for user data header, in 16-bit
- } else {
- BitBufferHelper.writeBits(msgBodySize + 6, 8); // Required length for user data header, in octet(8-bit)
- }
-
- BitBufferHelper.writeBits(5, 8); // total header length 5 bytes
- BitBufferHelper.writeBits(PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT, 8); // header id 0
- BitBufferHelper.writeBits(3, 8); // length of element for id 0 is 3
- BitBufferHelper.writeBits(options.segmentRef & 0xFF, 8); // Segement reference
- BitBufferHelper.writeBits(options.segmentMaxSeq & 0xFF, 8); // Max segment
- BitBufferHelper.writeBits(options.segmentSeq & 0xFF, 8); // Current segment
- }
- } else {
- BitBufferHelper.writeBits(msgBodySize, 8);
- }
-
- // Encode message based on encoding method
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- for (let i = 0; i < msgBody.length; i++) {
- switch (options.encoding) {
- case PDU_CDMA_MSG_CODING_OCTET: {
- let msgDigit = msgBody.charCodeAt(i);
- BitBufferHelper.writeBits(msgDigit, 8);
- break;
- }
- case PDU_CDMA_MSG_CODING_7BITS_ASCII: {
- let msgDigit = msgBody.charCodeAt(i),
- msgDigitChar = msgBody.charAt(i);
-
- if (msgDigit >= 32) {
- BitBufferHelper.writeBits(msgDigit, 7);
- } else {
- msgDigit = langTable.indexOf(msgDigitChar);
-
- if (msgDigit === PDU_NL_EXTENDED_ESCAPE) {
- break;
- }
- if (msgDigit >= 0) {
- BitBufferHelper.writeBits(msgDigit, 7);
- } else {
- msgDigit = langShiftTable.indexOf(msgDigitChar);
- if (msgDigit == -1) {
- throw new Error("'" + msgDigitChar + "' is not in 7 bit alphabet "
- + langIndex + ":" + langShiftIndex + "!");
- }
-
- if (msgDigit === PDU_NL_RESERVED_CONTROL) {
- break;
- }
-
- BitBufferHelper.writeBits(PDU_NL_EXTENDED_ESCAPE, 7);
- BitBufferHelper.writeBits(msgDigit, 7);
- }
- }
- break;
- }
- case PDU_CDMA_MSG_CODING_UNICODE: {
- let msgDigit = msgBody.charCodeAt(i);
- BitBufferHelper.writeBits(msgDigit, 16);
- break;
- }
- }
- }
- BitBufferHelper.flushWithPadding();
-
- // Fill length
- let currentPosition = BitBufferHelper.getWriteBufferSize();
- BitBufferHelper.overwriteWriteBuffer(lengthPosition - 1, [currentPosition - lengthPosition]);
- },
-
- /**
- * User data subparameter encoder : Reply Option
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.11 Reply Option
- */
- encodeUserDataReplyOption: function(options) {
- if (options.requestStatusReport) {
- let BitBufferHelper = this.context.BitBufferHelper;
- BitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_REPLY_OPTION, 8);
- BitBufferHelper.writeBits(1, 8);
- BitBufferHelper.writeBits(0, 1); // USER_ACK_REQ
- BitBufferHelper.writeBits(1, 1); // DAK_REQ
- BitBufferHelper.flushWithPadding();
- }
- },
-
- /**
- * Entry point for SMS decoding, the returned object is made compatible
- * with existing readMessage() of GsmPDUHelper
- */
- readMessage: function() {
- let message = {};
-
- // Teleservice Identifier
- message.teleservice = this.readInt();
-
- // Message Type
- let isServicePresent = this.readByte();
- if (isServicePresent) {
- message.messageType = PDU_CDMA_MSG_TYPE_BROADCAST;
- } else {
- if (message.teleservice) {
- message.messageType = PDU_CDMA_MSG_TYPE_P2P;
- } else {
- message.messageType = PDU_CDMA_MSG_TYPE_ACK;
- }
- }
-
- // Service Category
- message.service = this.readInt();
-
- // Originated Address
- let addrInfo = {};
- addrInfo.digitMode = (this.readInt() & 0x01);
- addrInfo.numberMode = (this.readInt() & 0x01);
- addrInfo.numberType = (this.readInt() & 0x01);
- addrInfo.numberPlan = (this.readInt() & 0x01);
- addrInfo.addrLength = this.readByte();
- addrInfo.address = [];
- for (let i = 0; i < addrInfo.addrLength; i++) {
- addrInfo.address.push(this.readByte());
- }
- message.sender = this.decodeAddr(addrInfo);
-
- // Originated Subaddress
- addrInfo.Type = (this.readInt() & 0x07);
- addrInfo.Odd = (this.readByte() & 0x01);
- addrInfo.addrLength = this.readByte();
- for (let i = 0; i < addrInfo.addrLength; i++) {
- let addrDigit = this.readByte();
- message.sender += String.fromCharCode(addrDigit);
- }
-
- // Bearer Data
- this.decodeUserData(message);
-
- // Bearer Data Sub-Parameter: User Data
- let userData = message[PDU_CDMA_MSG_USERDATA_BODY];
- [message.header, message.body, message.encoding, message.data] =
- (userData) ? [userData.header, userData.body, userData.encoding, userData.data]
- : [null, null, null, null];
-
- // Bearer Data Sub-Parameter: Message Status
- // Success Delivery (0) if both Message Status and User Data are absent.
- // Message Status absent (-1) if only User Data is available.
- let msgStatus = message[PDU_CDMA_MSG_USER_DATA_MSG_STATUS];
- [message.errorClass, message.msgStatus] =
- (msgStatus) ? [msgStatus.errorClass, msgStatus.msgStatus]
- : ((message.body) ? [-1, -1] : [0, 0]);
-
- // Transform message to GSM msg
- let msg = {
- SMSC: "",
- mti: 0,
- udhi: 0,
- sender: message.sender,
- recipient: null,
- pid: PDU_PID_DEFAULT,
- epid: PDU_PID_DEFAULT,
- dcs: 0,
- mwi: null,
- replace: false,
- header: message.header,
- body: message.body,
- data: message.data,
- sentTimestamp: message[PDU_CDMA_MSG_USERDATA_TIMESTAMP],
- language: message[PDU_CDMA_LANGUAGE_INDICATOR],
- status: null,
- scts: null,
- dt: null,
- encoding: message.encoding,
- messageClass: GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- messageType: message.messageType,
- serviceCategory: message.service,
- subMsgType: message[PDU_CDMA_MSG_USERDATA_MSG_ID].msgType,
- msgId: message[PDU_CDMA_MSG_USERDATA_MSG_ID].msgId,
- errorClass: message.errorClass,
- msgStatus: message.msgStatus,
- teleservice: message.teleservice
- };
-
- return msg;
- },
-
- /**
- * Helper for processing received SMS parcel data.
- *
- * @param length
- * Length of SMS string in the incoming parcel.
- *
- * @return Message parsed or null for invalid message.
- */
- processReceivedSms: function(length) {
- if (!length) {
- if (DEBUG) this.context.debug("Received empty SMS!");
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- let message = this.readMessage();
- if (DEBUG) this.context.debug("Got new SMS: " + JSON.stringify(message));
-
- // Determine result
- if (!message) {
- return [null, PDU_FCS_UNSPECIFIED];
- }
-
- return [message, PDU_FCS_OK];
- },
-
- /**
- * Data readers
- */
- readInt: function() {
- return this.context.Buf.readInt32();
- },
-
- readByte: function() {
- return (this.context.Buf.readInt32() & 0xFF);
- },
-
- /**
- * Decode CDMA address data into address string
- *
- * @see 3GGP2 C.S0015-B 2.0, 3.4.3.3 Address Parameters
- *
- * Required key in addrInfo
- * @param addrLength
- * Length of address
- * @param digitMode
- * Address encoding method
- * @param address
- * Array of encoded address data
- */
- decodeAddr: function(addrInfo) {
- let result = "";
- for (let i = 0; i < addrInfo.addrLength; i++) {
- if (addrInfo.digitMode === PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF) {
- result += this.dtmfChars.charAt(addrInfo.address[i]);
- } else {
- result += String.fromCharCode(addrInfo.address[i]);
- }
- }
- return result;
- },
-
- /**
- * Read userData in parcel buffer and decode into message object.
- * Each subparameter will be stored in corresponding key.
- *
- * @see 3GGP2 C.S0015-B 2.0, 3.4.3.7 Bearer Data
- * 4.5 Bearer Data Parameters
- */
- decodeUserData: function(message) {
- let userDataLength = this.readInt();
-
- while (userDataLength > 0) {
- let id = this.readByte(),
- length = this.readByte(),
- userDataBuffer = [];
-
- for (let i = 0; i < length; i++) {
- userDataBuffer.push(this.readByte());
- }
-
- this.context.BitBufferHelper.startRead(userDataBuffer);
-
- switch (id) {
- case PDU_CDMA_MSG_USERDATA_MSG_ID:
- message[id] = this.decodeUserDataMsgId();
- break;
- case PDU_CDMA_MSG_USERDATA_BODY:
- message[id] = this.decodeUserDataMsg(message[PDU_CDMA_MSG_USERDATA_MSG_ID].userHeader);
- break;
- case PDU_CDMA_MSG_USERDATA_TIMESTAMP:
- message[id] = this.decodeUserDataTimestamp();
- break;
- case PDU_CDMA_MSG_USERDATA_REPLY_OPTION:
- message[id] = this.decodeUserDataReplyOption();
- break;
- case PDU_CDMA_LANGUAGE_INDICATOR:
- message[id] = this.decodeLanguageIndicator();
- break;
- case PDU_CDMA_MSG_USERDATA_CALLBACK_NUMBER:
- message[id] = this.decodeUserDataCallbackNumber();
- break;
- case PDU_CDMA_MSG_USER_DATA_MSG_STATUS:
- message[id] = this.decodeUserDataMsgStatus();
- break;
- }
-
- userDataLength -= (length + 2);
- userDataBuffer = [];
- }
- },
-
- /**
- * User data subparameter decoder: Message Identifier
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.1 Message Identifier
- */
- decodeUserDataMsgId: function() {
- let result = {};
- let BitBufferHelper = this.context.BitBufferHelper;
- result.msgType = BitBufferHelper.readBits(4);
- result.msgId = BitBufferHelper.readBits(16);
- result.userHeader = BitBufferHelper.readBits(1);
-
- return result;
- },
-
- /**
- * Decode user data header, we only care about segment information
- * on CDMA.
- *
- * This function is mostly copied from gsmPduHelper.readUserDataHeader() but
- * change the read function, because CDMA user header decoding is't byte-wise
- * aligned.
- */
- decodeUserDataHeader: function(encoding) {
- let BitBufferHelper = this.context.BitBufferHelper;
- let header = {},
- headerSize = BitBufferHelper.readBits(8),
- userDataHeaderSize = headerSize + 1,
- headerPaddingBits = 0;
-
- // Calculate header size
- if (encoding === PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
- // Length is in 7-bit
- header.length = Math.ceil(userDataHeaderSize * 8 / 7);
- // Calulate padding length
- headerPaddingBits = (header.length * 7) - (userDataHeaderSize * 8);
- } else if (encoding === PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
- header.length = userDataHeaderSize;
- } else {
- header.length = userDataHeaderSize / 2;
- }
-
- while (headerSize) {
- let identifier = BitBufferHelper.readBits(8),
- length = BitBufferHelper.readBits(8);
-
- headerSize -= (2 + length);
-
- switch (identifier) {
- case PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT: {
- let ref = BitBufferHelper.readBits(8),
- max = BitBufferHelper.readBits(8),
- seq = BitBufferHelper.readBits(8);
- if (max && seq && (seq <= max)) {
- header.segmentRef = ref;
- header.segmentMaxSeq = max;
- header.segmentSeq = seq;
- }
- break;
- }
- case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_8BIT: {
- let dstp = BitBufferHelper.readBits(8),
- orip = BitBufferHelper.readBits(8);
- if ((dstp < PDU_APA_RESERVED_8BIT_PORTS)
- || (orip < PDU_APA_RESERVED_8BIT_PORTS)) {
- // 3GPP TS 23.040 clause 9.2.3.24.3: "A receiving entity shall
- // ignore any information element where the value of the
- // Information-Element-Data is Reserved or not supported"
- break;
- }
- header.destinationPort = dstp;
- header.originatorPort = orip;
- break;
- }
- case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_16BIT: {
- let dstp = (BitBufferHelper.readBits(8) << 8) | BitBufferHelper.readBits(8),
- orip = (BitBufferHelper.readBits(8) << 8) | BitBufferHelper.readBits(8);
- // 3GPP TS 23.040 clause 9.2.3.24.4: "A receiving entity shall
- // ignore any information element where the value of the
- // Information-Element-Data is Reserved or not supported"
- if ((dstp < PDU_APA_VALID_16BIT_PORTS)
- && (orip < PDU_APA_VALID_16BIT_PORTS)) {
- header.destinationPort = dstp;
- header.originatorPort = orip;
- }
- break;
- }
- case PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT: {
- let ref = (BitBufferHelper.readBits(8) << 8) | BitBufferHelper.readBits(8),
- max = BitBufferHelper.readBits(8),
- seq = BitBufferHelper.readBits(8);
- if (max && seq && (seq <= max)) {
- header.segmentRef = ref;
- header.segmentMaxSeq = max;
- header.segmentSeq = seq;
- }
- break;
- }
- case PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT: {
- let langShiftIndex = BitBufferHelper.readBits(8);
- if (langShiftIndex < PDU_NL_SINGLE_SHIFT_TABLES.length) {
- header.langShiftIndex = langShiftIndex;
- }
- break;
- }
- case PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT: {
- let langIndex = BitBufferHelper.readBits(8);
- if (langIndex < PDU_NL_LOCKING_SHIFT_TABLES.length) {
- header.langIndex = langIndex;
- }
- break;
- }
- case PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION: {
- let msgInd = BitBufferHelper.readBits(8) & 0xFF,
- msgCount = BitBufferHelper.readBits(8);
- /*
- * TS 23.040 V6.8.1 Sec 9.2.3.24.2
- * bits 1 0 : basic message indication type
- * bits 4 3 2 : extended message indication type
- * bits 6 5 : Profile id
- * bit 7 : storage type
- */
- let storeType = msgInd & PDU_MWI_STORE_TYPE_BIT;
- header.mwi = {};
- mwi = header.mwi;
-
- if (storeType == PDU_MWI_STORE_TYPE_STORE) {
- // Store message because TP_UDH indicates so, note this may override
- // the setting in DCS, but that is expected
- mwi.discard = false;
- } else if (mwi.discard === undefined) {
- // storeType == PDU_MWI_STORE_TYPE_DISCARD
- // only override mwi.discard here if it hasn't already been set
- mwi.discard = true;
- }
-
- mwi.msgCount = msgCount & 0xFF;
- mwi.active = mwi.msgCount > 0;
-
- if (DEBUG) {
- this.context.debug("MWI in TP_UDH received: " + JSON.stringify(mwi));
- }
- break;
- }
- default:
- // Drop unsupported id
- for (let i = 0; i < length; i++) {
- BitBufferHelper.readBits(8);
- }
- }
- }
-
- // Consume padding bits
- if (headerPaddingBits) {
- BitBufferHelper.readBits(headerPaddingBits);
- }
-
- return header;
- },
-
- getCdmaMsgEncoding: function(encoding) {
- // Determine encoding method
- switch (encoding) {
- case PDU_CDMA_MSG_CODING_7BITS_ASCII:
- case PDU_CDMA_MSG_CODING_IA5:
- case PDU_CDMA_MSG_CODING_7BITS_GSM:
- return PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- case PDU_CDMA_MSG_CODING_OCTET:
- case PDU_CDMA_MSG_CODING_IS_91:
- case PDU_CDMA_MSG_CODING_LATIN_HEBREW:
- case PDU_CDMA_MSG_CODING_LATIN:
- return PDU_DCS_MSG_CODING_8BITS_ALPHABET;
- case PDU_CDMA_MSG_CODING_UNICODE:
- case PDU_CDMA_MSG_CODING_SHIFT_JIS:
- case PDU_CDMA_MSG_CODING_KOREAN:
- return PDU_DCS_MSG_CODING_16BITS_ALPHABET;
- }
- return null;
- },
-
- decodeCdmaPDUMsg: function(encoding, msgType, msgBodySize) {
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- let BitBufferHelper = this.context.BitBufferHelper;
- let result = "";
- let msgDigit;
- switch (encoding) {
- case PDU_CDMA_MSG_CODING_OCTET: // TODO : Require Test
- while(msgBodySize > 0) {
- msgDigit = String.fromCharCode(BitBufferHelper.readBits(8));
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_IS_91: // TODO : Require Test
- // Referenced from android code
- switch (msgType) {
- case PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS:
- case PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS_FULL:
- case PDU_CDMA_MSG_CODING_IS_91_TYPE_VOICEMAIL_STATUS:
- while(msgBodySize > 0) {
- msgDigit = String.fromCharCode(BitBufferHelper.readBits(6) + 0x20);
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_IS_91_TYPE_CLI:
- let addrInfo = {};
- addrInfo.digitMode = PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF;
- addrInfo.numberMode = PDU_CDMA_MSG_ADDR_NUMBER_MODE_ANSI;
- addrInfo.numberType = PDU_CDMA_MSG_ADDR_NUMBER_TYPE_UNKNOWN;
- addrInfo.numberPlan = PDU_CDMA_MSG_ADDR_NUMBER_PLAN_UNKNOWN;
- addrInfo.addrLength = msgBodySize;
- addrInfo.address = [];
- for (let i = 0; i < addrInfo.addrLength; i++) {
- addrInfo.address.push(BitBufferHelper.readBits(4));
- }
- result = this.decodeAddr(addrInfo);
- break;
- }
- // Fall through.
- case PDU_CDMA_MSG_CODING_7BITS_ASCII:
- case PDU_CDMA_MSG_CODING_IA5: // TODO : Require Test
- while(msgBodySize > 0) {
- msgDigit = BitBufferHelper.readBits(7);
- if (msgDigit >= 32) {
- msgDigit = String.fromCharCode(msgDigit);
- } else {
- if (msgDigit !== PDU_NL_EXTENDED_ESCAPE) {
- msgDigit = langTable[msgDigit];
- } else {
- msgDigit = BitBufferHelper.readBits(7);
- msgBodySize--;
- msgDigit = langShiftTable[msgDigit];
- }
- }
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_UNICODE:
- while(msgBodySize > 0) {
- msgDigit = String.fromCharCode(BitBufferHelper.readBits(16));
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_7BITS_GSM: // TODO : Require Test
- while(msgBodySize > 0) {
- msgDigit = BitBufferHelper.readBits(7);
- if (msgDigit !== PDU_NL_EXTENDED_ESCAPE) {
- msgDigit = langTable[msgDigit];
- } else {
- msgDigit = BitBufferHelper.readBits(7);
- msgBodySize--;
- msgDigit = langShiftTable[msgDigit];
- }
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_LATIN: // TODO : Require Test
- // Reference : http://en.wikipedia.org/wiki/ISO/IEC_8859-1
- while(msgBodySize > 0) {
- msgDigit = String.fromCharCode(BitBufferHelper.readBits(8));
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_LATIN_HEBREW: // TODO : Require Test
- // Reference : http://en.wikipedia.org/wiki/ISO/IEC_8859-8
- while(msgBodySize > 0) {
- msgDigit = BitBufferHelper.readBits(8);
- if (msgDigit === 0xDF) {
- msgDigit = String.fromCharCode(0x2017);
- } else if (msgDigit === 0xFD) {
- msgDigit = String.fromCharCode(0x200E);
- } else if (msgDigit === 0xFE) {
- msgDigit = String.fromCharCode(0x200F);
- } else if (msgDigit >= 0xE0 && msgDigit <= 0xFA) {
- msgDigit = String.fromCharCode(0x4F0 + msgDigit);
- } else {
- msgDigit = String.fromCharCode(msgDigit);
- }
- result += msgDigit;
- msgBodySize--;
- }
- break;
- case PDU_CDMA_MSG_CODING_SHIFT_JIS:
- // Reference : http://msdn.microsoft.com/en-US/goglobal/cc305152.aspx
- // http://demo.icu-project.org/icu-bin/convexp?conv=Shift_JIS
- let shift_jis_message = [];
-
- while (msgBodySize > 0) {
- shift_jis_message.push(BitBufferHelper.readBits(8));
- msgBodySize--;
- }
-
- let decoder = new TextDecoder("shift_jis");
- result = decoder.decode(new Uint8Array(shift_jis_message));
- break;
- case PDU_CDMA_MSG_CODING_KOREAN:
- case PDU_CDMA_MSG_CODING_GSM_DCS:
- // Fall through.
- default:
- break;
- }
- return result;
- },
-
- /**
- * User data subparameter decoder : User Data
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.2 User Data
- */
- decodeUserDataMsg: function(hasUserHeader) {
- let BitBufferHelper = this.context.BitBufferHelper;
- let result = {},
- encoding = BitBufferHelper.readBits(5),
- msgType;
-
- if (encoding === PDU_CDMA_MSG_CODING_IS_91) {
- msgType = BitBufferHelper.readBits(8);
- }
- result.encoding = this.getCdmaMsgEncoding(encoding);
-
- let msgBodySize = BitBufferHelper.readBits(8);
-
- // For segmented SMS, a user header is included before sms content
- if (hasUserHeader) {
- result.header = this.decodeUserDataHeader(result.encoding);
- // header size is included in body size, they are decoded
- msgBodySize -= result.header.length;
- }
-
- // Store original payload if enconding is OCTET for further handling of WAP Push, etc.
- if (encoding === PDU_CDMA_MSG_CODING_OCTET && msgBodySize > 0) {
- result.data = new Uint8Array(msgBodySize);
- for (let i = 0; i < msgBodySize; i++) {
- result.data[i] = BitBufferHelper.readBits(8);
- }
- BitBufferHelper.backwardReadPilot(8 * msgBodySize);
- }
-
- // Decode sms content
- result.body = this.decodeCdmaPDUMsg(encoding, msgType, msgBodySize);
-
- return result;
- },
-
- decodeBcd: function(value) {
- return ((value >> 4) & 0xF) * 10 + (value & 0x0F);
- },
-
- /**
- * User data subparameter decoder : Time Stamp
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.4 Message Center Time Stamp
- */
- decodeUserDataTimestamp: function() {
- let BitBufferHelper = this.context.BitBufferHelper;
- let year = this.decodeBcd(BitBufferHelper.readBits(8)),
- month = this.decodeBcd(BitBufferHelper.readBits(8)) - 1,
- date = this.decodeBcd(BitBufferHelper.readBits(8)),
- hour = this.decodeBcd(BitBufferHelper.readBits(8)),
- min = this.decodeBcd(BitBufferHelper.readBits(8)),
- sec = this.decodeBcd(BitBufferHelper.readBits(8));
-
- if (year >= 96 && year <= 99) {
- year += 1900;
- } else {
- year += 2000;
- }
-
- let result = (new Date(year, month, date, hour, min, sec, 0)).valueOf();
-
- return result;
- },
-
- /**
- * User data subparameter decoder : Reply Option
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.11 Reply Option
- */
- decodeUserDataReplyOption: function() {
- let replyAction = this.context.BitBufferHelper.readBits(4),
- result = { userAck: (replyAction & 0x8) ? true : false,
- deliverAck: (replyAction & 0x4) ? true : false,
- readAck: (replyAction & 0x2) ? true : false,
- report: (replyAction & 0x1) ? true : false
- };
-
- return result;
- },
-
- /**
- * User data subparameter decoder : Language Indicator
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.14 Language Indicator
- */
- decodeLanguageIndicator: function() {
- let language = this.context.BitBufferHelper.readBits(8);
- let result = CB_CDMA_LANG_GROUP[language];
- return result;
- },
-
- /**
- * User data subparameter decoder : Call-Back Number
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.15 Call-Back Number
- */
- decodeUserDataCallbackNumber: function() {
- let BitBufferHelper = this.context.BitBufferHelper;
- let digitMode = BitBufferHelper.readBits(1);
- if (digitMode) {
- let numberType = BitBufferHelper.readBits(3),
- numberPlan = BitBufferHelper.readBits(4);
- }
- let numberFields = BitBufferHelper.readBits(8),
- result = "";
- for (let i = 0; i < numberFields; i++) {
- if (digitMode === PDU_CDMA_MSG_ADDR_DIGIT_MODE_DTMF) {
- let addrDigit = BitBufferHelper.readBits(4);
- result += this.dtmfChars.charAt(addrDigit);
- } else {
- let addrDigit = BitBufferHelper.readBits(8);
- result += String.fromCharCode(addrDigit);
- }
- }
-
- return result;
- },
-
- /**
- * User data subparameter decoder : Message Status
- *
- * @see 3GGP2 C.S0015-B 2.0, 4.5.21 Message Status
- */
- decodeUserDataMsgStatus: function() {
- let BitBufferHelper = this.context.BitBufferHelper;
- let result = {
- errorClass: BitBufferHelper.readBits(2),
- msgStatus: BitBufferHelper.readBits(6)
- };
-
- return result;
- },
-
- /**
- * Decode information record parcel.
- */
- decodeInformationRecord: function() {
- let Buf = this.context.Buf;
- let records = [];
- let numOfRecords = Buf.readInt32();
-
- let type;
- let record;
- for (let i = 0; i < numOfRecords; i++) {
- record = {};
- type = Buf.readInt32();
-
- switch (type) {
- /*
- * Every type is encaped by ril, except extended display
- */
- case PDU_CDMA_INFO_REC_TYPE_DISPLAY:
- case PDU_CDMA_INFO_REC_TYPE_EXTENDED_DISPLAY:
- record.display = Buf.readString();
- break;
- case PDU_CDMA_INFO_REC_TYPE_CALLED_PARTY_NUMBER:
- record.calledNumber = {};
- record.calledNumber.number = Buf.readString();
- record.calledNumber.type = Buf.readInt32();
- record.calledNumber.plan = Buf.readInt32();
- record.calledNumber.pi = Buf.readInt32();
- record.calledNumber.si = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_CALLING_PARTY_NUMBER:
- record.callingNumber = {};
- record.callingNumber.number = Buf.readString();
- record.callingNumber.type = Buf.readInt32();
- record.callingNumber.plan = Buf.readInt32();
- record.callingNumber.pi = Buf.readInt32();
- record.callingNumber.si = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_CONNECTED_NUMBER:
- record.connectedNumber = {};
- record.connectedNumber.number = Buf.readString();
- record.connectedNumber.type = Buf.readInt32();
- record.connectedNumber.plan = Buf.readInt32();
- record.connectedNumber.pi = Buf.readInt32();
- record.connectedNumber.si = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_SIGNAL:
- record.signal = {};
- if (!Buf.readInt32()) { // Non-zero if signal is present.
- Buf.seekIncoming(3 * Buf.UINT32_SIZE);
- continue;
- }
- record.signal.type = Buf.readInt32();
- record.signal.alertPitch = Buf.readInt32();
- record.signal.signal = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_REDIRECTING_NUMBER:
- record.redirect = {};
- record.redirect.number = Buf.readString();
- record.redirect.type = Buf.readInt32();
- record.redirect.plan = Buf.readInt32();
- record.redirect.pi = Buf.readInt32();
- record.redirect.si = Buf.readInt32();
- record.redirect.reason = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_LINE_CONTROL:
- record.lineControl = {};
- record.lineControl.polarityIncluded = Buf.readInt32();
- record.lineControl.toggle = Buf.readInt32();
- record.lineControl.reverse = Buf.readInt32();
- record.lineControl.powerDenial = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_T53_CLIR:
- record.clirCause = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_T53_AUDIO_CONTROL:
- record.audioControl = {};
- record.audioControl.upLink = Buf.readInt32();
- record.audioControl.downLink = Buf.readInt32();
- break;
- case PDU_CDMA_INFO_REC_TYPE_T53_RELEASE:
- // Fall through
- default:
- throw new Error("UNSOLICITED_CDMA_INFO_REC(), Unsupported information record type " + type + "\n");
- }
-
- records.push(record);
- }
-
- return records;
- }
-};
-
-/**
- * Helper for processing ICC PDUs.
- */
-function ICCPDUHelperObject(aContext) {
- this.context = aContext;
-}
-ICCPDUHelperObject.prototype = {
- context: null,
-
- /**
- * Read GSM 8-bit unpacked octets,
- * which are default 7-bit alphabets with bit 8 set to 0.
- *
- * @param numOctets
- * Number of octets to be read.
- */
- read8BitUnpackedToString: function(numOctets) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let ret = "";
- let escapeFound = false;
- let i;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- for(i = 0; i < numOctets; i++) {
- let octet = GsmPDUHelper.readHexOctet();
- if (octet == 0xff) {
- i++;
- break;
- }
-
- if (escapeFound) {
- escapeFound = false;
- if (octet == PDU_NL_EXTENDED_ESCAPE) {
- // According to 3GPP TS 23.038, section 6.2.1.1, NOTE 1, "On
- // receipt of this code, a receiving entity shall display a space
- // until another extensiion table is defined."
- ret += " ";
- } else if (octet == PDU_NL_RESERVED_CONTROL) {
- // According to 3GPP TS 23.038 B.2, "This code represents a control
- // character and therefore must not be used for language specific
- // characters."
- ret += " ";
- } else {
- ret += langShiftTable[octet];
- }
- } else if (octet == PDU_NL_EXTENDED_ESCAPE) {
- escapeFound = true;
- } else {
- ret += langTable[octet];
- }
- }
-
- let Buf = this.context.Buf;
- Buf.seekIncoming((numOctets - i) * Buf.PDU_HEX_OCTET_SIZE);
- return ret;
- },
-
- /**
- * Write GSM 8-bit unpacked octets.
- *
- * @param numOctets Number of total octets to be writen, including trailing
- * 0xff.
- * @param str String to be written. Could be null.
- *
- * @return The string has been written into Buf. "" if str is null.
- */
- writeStringTo8BitUnpacked: function(numOctets, str) {
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // If the character is GSM extended alphabet, two octets will be written.
- // So we need to keep track of number of octets to be written.
- let i, j;
- let len = str ? str.length : 0;
- for (i = 0, j = 0; i < len && j < numOctets; i++) {
- let c = str.charAt(i);
- let octet = langTable.indexOf(c);
-
- if (octet == -1) {
- // Make sure we still have enough space to write two octets.
- if (j + 2 > numOctets) {
- break;
- }
-
- octet = langShiftTable.indexOf(c);
- if (octet == -1) {
- // Fallback to ASCII space.
- octet = langTable.indexOf(' ');
- } else {
- GsmPDUHelper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
- j++;
- }
- }
- GsmPDUHelper.writeHexOctet(octet);
- j++;
- }
-
- // trailing 0xff
- while (j++ < numOctets) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
-
- return (str) ? str.substring(0, i) : "";
- },
-
- /**
- * Write UCS2 String on UICC.
- * The default choose 0x81 or 0x82 encode, otherwise use 0x80 encode.
- *
- * @see TS 102.221, Annex A.
- * @param numOctets
- * Total number of octets to be written. This includes the length of
- * alphaId and the length of trailing unused octets(0xff).
- * @param str
- * String to be written.
- *
- * @return The string has been written into Buf.
- */
- writeICCUCS2String: function(numOctets, str) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let scheme = 0x80;
- let basePointer;
-
- if (str.length > 2) {
- let min = 0xFFFF;
- let max = 0;
- for (let i = 0; i < str.length; i++) {
- let code = str.charCodeAt(i);
- // filter out GSM Default Alphabet character
- if (code & 0xFF80) {
- if (min > code) {
- min = code;
- }
- if (max < code) {
- max = code;
- }
- }
- }
-
- // 0x81 and 0x82 only support 'half-page', i.e., 128 characters.
- if ((max - min) >= 0 && (max - min) < 128) {
- // 0x81 base pointer is 0hhh hhhh h000 0000, and bit 16 is set to zero,
- // therefore it can't compute 0x8000~0xFFFF.
- // Since 0x81 only support 128 characters,
- // either XX00~XX7f(bit 8 are 0) or XX80~XXff(bit 8 are 1)
- if (((min & 0x7f80) == (max & 0x7f80)) &&
- ((max & 0x8000) == 0)) {
- scheme = 0x81;
- basePointer = min & 0x7f80;
- } else {
- scheme = 0x82;
- basePointer = min;
- }
- }
- }
-
- switch (scheme) {
- /**
- * +------+---------+---------+---------+---------+------+------+
- * | 0x80 | Ch1_msb | Ch1_lsb | Ch2_msb | Ch2_lsb | 0xff | 0xff |
- * +------+---------+---------+---------+---------+------+------+
- */
- case 0x80: {
- // 0x80 support UCS2 0000~ffff
- GsmPDUHelper.writeHexOctet(0x80);
- numOctets--;
- // Now the str is UCS2 string, each character will take 2 octets.
- if (str.length * 2 > numOctets) {
- str = str.substring(0, Math.floor(numOctets / 2));
- }
- GsmPDUHelper.writeUCS2String(str);
-
- // trailing 0xff
- for (let i = str.length * 2; i < numOctets; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- return str;
- }
- /**
- * +------+-----+--------------+-----+-----+-----+--------+------+
- * | 0x81 | len | base_pointer | Ch1 | Ch2 | ... | Ch_len | 0xff |
- * +------+-----+--------------+-----+-----+-----+--------+------+
- *
- * len: The length of characters.
- * base_pointer: 0hhh hhhh h000 0000
- * Ch_n: bit 8 = 0
- * GSM default alphabets
- * bit 8 = 1
- * UCS2 character whose char code is (Ch_n - base_pointer) | 0x80
- *
- */
- case 0x81: {
- GsmPDUHelper.writeHexOctet(0x81);
-
- if (str.length > (numOctets - 3)) {
- str = str.substring(0, numOctets - 3);
- }
-
- GsmPDUHelper.writeHexOctet(str.length);
- GsmPDUHelper.writeHexOctet((basePointer >> 7) & 0xff);
- numOctets -= 3;
- break;
- }
- /* +------+-----+------------------+------------------+-----+-----+-----+--------+
- * | 0x82 | len | base_pointer_msb | base_pointer_lsb | Ch1 | Ch2 | ... | Ch_len |
- * +------+-----+------------------+------------------+-----+-----+-----+--------+
- *
- * len: The length of characters.
- * base_pointer_msb, base_pointer_lsn: base_pointer
- * Ch_n: bit 8 = 0
- * GSM default alphabets
- * bit 8 = 1
- * UCS2 character whose char code is (Ch_n - base_pointer) | 0x80
- */
- case 0x82: {
- GsmPDUHelper.writeHexOctet(0x82);
-
- if (str.length > (numOctets - 4)) {
- str = str.substring(0, numOctets - 4);
- }
-
- GsmPDUHelper.writeHexOctet(str.length);
- GsmPDUHelper.writeHexOctet((basePointer >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(basePointer & 0xff);
- numOctets -= 4;
- break;
- }
- }
-
- if (scheme == 0x81 || scheme == 0x82) {
- for (let i = 0; i < str.length; i++) {
- let code = str.charCodeAt(i);
-
- // bit 8 = 0,
- // GSM default alphabets
- if (code >> 8 == 0) {
- GsmPDUHelper.writeHexOctet(code & 0x7F);
- } else {
- // bit 8 = 1,
- // UCS2 character whose char code is (code - basePointer) | 0x80
- GsmPDUHelper.writeHexOctet((code - basePointer) | 0x80);
- }
- }
-
- // trailing 0xff
- for (let i = 0; i < numOctets - str.length; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- }
- return str;
- },
-
- /**
- * Read UCS2 String on UICC.
- *
- * @see TS 101.221, Annex A.
- * @param scheme
- * Coding scheme for UCS2 on UICC. One of 0x80, 0x81 or 0x82.
- * @param numOctets
- * Number of octets to be read as UCS2 string.
- */
- readICCUCS2String: function(scheme, numOctets) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let str = "";
- switch (scheme) {
- /**
- * +------+---------+---------+---------+---------+------+------+
- * | 0x80 | Ch1_msb | Ch1_lsb | Ch2_msb | Ch2_lsb | 0xff | 0xff |
- * +------+---------+---------+---------+---------+------+------+
- */
- case 0x80:
- let isOdd = numOctets % 2;
- let i;
- for (i = 0; i < numOctets - isOdd; i += 2) {
- let code = (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- if (code == 0xffff) {
- i += 2;
- break;
- }
- str += String.fromCharCode(code);
- }
-
- // Skip trailing 0xff
- Buf.seekIncoming((numOctets - i) * Buf.PDU_HEX_OCTET_SIZE);
- break;
- case 0x81: // Fall through
- case 0x82:
- /**
- * +------+-----+--------+-----+-----+-----+--------+------+
- * | 0x81 | len | offset | Ch1 | Ch2 | ... | Ch_len | 0xff |
- * +------+-----+--------+-----+-----+-----+--------+------+
- *
- * len : The length of characters.
- * offset : 0hhh hhhh h000 0000
- * Ch_n: bit 8 = 0
- * GSM default alphabets
- * bit 8 = 1
- * UCS2 character whose char code is (Ch_n & 0x7f) + offset
- *
- * +------+-----+------------+------------+-----+-----+-----+--------+
- * | 0x82 | len | offset_msb | offset_lsb | Ch1 | Ch2 | ... | Ch_len |
- * +------+-----+------------+------------+-----+-----+-----+--------+
- *
- * len : The length of characters.
- * offset_msb, offset_lsn: offset
- * Ch_n: bit 8 = 0
- * GSM default alphabets
- * bit 8 = 1
- * UCS2 character whose char code is (Ch_n & 0x7f) + offset
- */
- let len = GsmPDUHelper.readHexOctet();
- let offset, headerLen;
- if (scheme == 0x81) {
- offset = GsmPDUHelper.readHexOctet() << 7;
- headerLen = 2;
- } else {
- offset = (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- headerLen = 3;
- }
-
- for (let i = 0; i < len; i++) {
- let ch = GsmPDUHelper.readHexOctet();
- if (ch & 0x80) {
- // UCS2
- str += String.fromCharCode((ch & 0x7f) + offset);
- } else {
- // GSM 8bit
- let count = 0, gotUCS2 = 0;
- while ((i + count + 1 < len)) {
- count++;
- if (GsmPDUHelper.readHexOctet() & 0x80) {
- gotUCS2 = 1;
- break;
- }
- }
- // Unread.
- // +1 for the GSM alphabet indexed at i,
- Buf.seekIncoming(-1 * (count + 1) * Buf.PDU_HEX_OCTET_SIZE);
- str += this.read8BitUnpackedToString(count + 1 - gotUCS2);
- i += count - gotUCS2;
- }
- }
-
- // Skipping trailing 0xff
- Buf.seekIncoming((numOctets - len - headerLen) * Buf.PDU_HEX_OCTET_SIZE);
- break;
- }
- return str;
- },
-
- /**
- * Read Alpha Id and Dialling number from TS TS 151.011 clause 10.5.1
- *
- * @param recordSize The size of linear fixed record.
- */
- readAlphaIdDiallingNumber: function(recordSize) {
- let Buf = this.context.Buf;
- let length = Buf.readInt32();
-
- let alphaLen = recordSize - ADN_FOOTER_SIZE_BYTES;
- let alphaId = this.readAlphaIdentifier(alphaLen);
-
- let number = this.readNumberWithLength();
-
- // Skip unused octet, CCP
- Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
-
- let extRecordNumber = this.context.GsmPDUHelper.readHexOctet();
- Buf.readStringDelimiter(length);
-
- let contact = null;
- if (alphaId || number) {
- contact = {alphaId: alphaId,
- number: number,
- extRecordNumber: extRecordNumber};
- }
-
- return contact;
- },
-
- /**
- * Write Alpha Identifier and Dialling number from TS 151.011 clause 10.5.1
- *
- * @param recordSize The size of linear fixed record.
- * @param alphaId Alpha Identifier to be written.
- * @param number Dialling Number to be written.
- * @param extRecordNumber The record identifier of the EXT.
- *
- * @return An object contains the alphaId and number
- * that have been written into Buf.
- */
- writeAlphaIdDiallingNumber: function(recordSize, alphaId, number, extRecordNumber) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // Write String length
- let strLen = recordSize * 2;
- Buf.writeInt32(strLen);
-
- let alphaLen = recordSize - ADN_FOOTER_SIZE_BYTES;
- let writtenAlphaId = this.writeAlphaIdentifier(alphaLen, alphaId);
- let writtenNumber = this.writeNumberWithLength(number);
-
- // Write unused CCP octet 0xff.
- GsmPDUHelper.writeHexOctet(0xff);
- GsmPDUHelper.writeHexOctet((extRecordNumber != null) ? extRecordNumber : 0xff);
-
- Buf.writeStringDelimiter(strLen);
-
- return {alphaId: writtenAlphaId,
- number: writtenNumber};
- },
-
- /**
- * Read Alpha Identifier.
- *
- * @see TS 131.102
- *
- * @param numOctets
- * Number of octets to be read.
- *
- * It uses either
- * 1. SMS default 7-bit alphabet with bit 8 set to 0.
- * 2. UCS2 string.
- *
- * Unused bytes should be set to 0xff.
- */
- readAlphaIdentifier: function(numOctets) {
- if (numOctets === 0) {
- return "";
- }
-
- let temp;
- // Read the 1st octet to determine the encoding.
- if ((temp = this.context.GsmPDUHelper.readHexOctet()) == 0x80 ||
- temp == 0x81 ||
- temp == 0x82) {
- numOctets--;
- return this.readICCUCS2String(temp, numOctets);
- } else {
- let Buf = this.context.Buf;
- Buf.seekIncoming(-1 * Buf.PDU_HEX_OCTET_SIZE);
- return this.read8BitUnpackedToString(numOctets);
- }
- },
-
- /**
- * Write Alpha Identifier.
- *
- * @param numOctets
- * Total number of octets to be written. This includes the length of
- * alphaId and the length of trailing unused octets(0xff).
- * @param alphaId
- * Alpha Identifier to be written.
- *
- * @return The Alpha Identifier has been written into Buf.
- *
- * Unused octets will be written as 0xff.
- */
- writeAlphaIdentifier: function(numOctets, alphaId) {
- if (numOctets === 0) {
- return "";
- }
-
- // If alphaId is empty or it's of GSM 8 bit.
- if (!alphaId || this.context.ICCUtilsHelper.isGsm8BitAlphabet(alphaId)) {
- return this.writeStringTo8BitUnpacked(numOctets, alphaId);
- } else {
- return this.writeICCUCS2String(numOctets, alphaId);
- }
- },
-
- /**
- * Read Dialling number.
- *
- * @see TS 131.102
- *
- * @param len
- * The Length of BCD number.
- *
- * From TS 131.102, in EF_ADN, EF_FDN, the field 'Length of BCD number'
- * means the total bytes should be allocated to store the TON/NPI and
- * the dialing number.
- * For example, if the dialing number is 1234567890,
- * and the TON/NPI is 0x81,
- * The field 'Length of BCD number' should be 06, which is
- * 1 byte to store the TON/NPI, 0x81
- * 5 bytes to store the BCD number 2143658709.
- *
- * Here the definition of the length is different from SMS spec,
- * TS 23.040 9.1.2.5, which the length means
- * "number of useful semi-octets within the Address-Value field".
- */
- readDiallingNumber: function(len) {
- if (DEBUG) this.context.debug("PDU: Going to read Dialling number: " + len);
- if (len === 0) {
- return "";
- }
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // TOA = TON + NPI
- let toa = GsmPDUHelper.readHexOctet();
-
- let number = GsmPDUHelper.readSwappedNibbleExtendedBcdString(len - 1);
- if (number.length <= 0) {
- if (DEBUG) this.context.debug("No number provided");
- return "";
- }
- if ((toa >> 4) == (PDU_TOA_INTERNATIONAL >> 4)) {
- number = '+' + number;
- }
- return number;
- },
-
- /**
- * Write Dialling Number.
- *
- * @param number The Dialling number
- */
- writeDiallingNumber: function(number) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let toa = PDU_TOA_ISDN; // 81
- if (number[0] == '+') {
- toa = PDU_TOA_INTERNATIONAL | PDU_TOA_ISDN; // 91
- number = number.substring(1);
- }
- GsmPDUHelper.writeHexOctet(toa);
- GsmPDUHelper.writeSwappedNibbleBCD(number);
- },
-
- readNumberWithLength: function() {
- let Buf = this.context.Buf;
- let number = "";
- let numLen = this.context.GsmPDUHelper.readHexOctet();
- if (numLen != 0xff) {
- if (numLen > ADN_MAX_BCD_NUMBER_BYTES) {
- if (DEBUG) {
- this.context.debug(
- "Error: invalid length of BCD number/SSC contents - " + numLen);
- }
- Buf.seekIncoming(ADN_MAX_BCD_NUMBER_BYTES * Buf.PDU_HEX_OCTET_SIZE);
- return number;
- }
-
- number = this.readDiallingNumber(numLen);
- Buf.seekIncoming((ADN_MAX_BCD_NUMBER_BYTES - numLen) * Buf.PDU_HEX_OCTET_SIZE);
- } else {
- Buf.seekIncoming(ADN_MAX_BCD_NUMBER_BYTES * Buf.PDU_HEX_OCTET_SIZE);
- }
-
- return number;
- },
-
- /**
- * Write Number with Length
- *
- * @param number The value to be written.
- *
- * @return The number has been written into Buf.
- */
- writeNumberWithLength: function(number) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- if (number) {
- let numStart = number[0] == "+" ? 1 : 0;
- let writtenNumber = number.substring(0, numStart) +
- number.substring(numStart)
- .replace(/[^0-9*#,]/g, "");
- let numDigits = writtenNumber.length - numStart;
-
- if (numDigits > ADN_MAX_NUMBER_DIGITS) {
- writtenNumber = writtenNumber.substring(0, ADN_MAX_NUMBER_DIGITS + numStart);
- numDigits = writtenNumber.length - numStart;
- }
-
- // +1 for TON/NPI
- let numLen = Math.ceil(numDigits / 2) + 1;
- GsmPDUHelper.writeHexOctet(numLen);
- this.writeDiallingNumber(writtenNumber.replace(/\*/g, "a")
- .replace(/\#/g, "b")
- .replace(/\,/g, "c"));
- // Write trailing 0xff of Dialling Number.
- for (let i = 0; i < ADN_MAX_BCD_NUMBER_BYTES - numLen; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- return writtenNumber;
- } else {
- // +1 for numLen
- for (let i = 0; i < ADN_MAX_BCD_NUMBER_BYTES + 1; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- return "";
- }
- }
-};
-
-function StkCommandParamsFactoryObject(aContext) {
- this.context = aContext;
-}
-StkCommandParamsFactoryObject.prototype = {
- context: null,
-
- createParam: function(cmdDetails, ctlvs, onComplete) {
- let method = this[cmdDetails.typeOfCommand];
- if (typeof method != "function") {
- if (DEBUG) {
- this.context.debug("Unknown proactive command " +
- cmdDetails.typeOfCommand.toString(16));
- }
- return;
- }
- method.call(this, cmdDetails, ctlvs, onComplete);
- },
-
- loadIcons: function(iconIdCtlvs, callback) {
- if (!iconIdCtlvs ||
- !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
- callback(null);
- return;
- }
-
- let onerror = (function() {
- callback(null);
- }).bind(this);
-
- let onsuccess = (function(aIcons) {
- callback(aIcons);
- }).bind(this);
-
- this.context.IconLoader.loadIcons(iconIdCtlvs.map(aCtlv => aCtlv.value.identifier),
- onsuccess,
- onerror);
- },
-
- appendIconIfNecessary: function(iconIdCtlvs, result, onComplete) {
- this.loadIcons(iconIdCtlvs, (aIcons) => {
- if (aIcons) {
- result.icons = aIcons[0];
- result.iconSelfExplanatory =
- iconIdCtlvs[0].value.qualifier == 0 ? true : false;
- }
-
- onComplete(result);
- });
- },
-
- /**
- * Construct a param for Refresh.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processRefresh: function(cmdDetails, ctlvs, onComplete) {
- let refreshType = cmdDetails.commandQualifier;
- switch (refreshType) {
- case STK_REFRESH_FILE_CHANGE:
- case STK_REFRESH_NAA_INIT_AND_FILE_CHANGE:
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_FILE_LIST, ctlvs);
- if (ctlv) {
- let list = ctlv.value.fileList;
- if (DEBUG) {
- this.context.debug("Refresh, list = " + list);
- }
- this.context.ICCRecordHelper.fetchICCRecords();
- }
- break;
- }
-
- onComplete(null);
- },
-
- /**
- * Construct a param for Poll Interval.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processPollInterval: function(cmdDetails, ctlvs, onComplete) {
- // Duration is mandatory.
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_DURATION, ctlvs);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Poll Interval: Required value missing : Duration");
- }
-
- onComplete(ctlv.value);
- },
-
- /**
- * Construct a param for Poll Off.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processPollOff: function(cmdDetails, ctlvs, onComplete) {
- onComplete(null);
- },
-
- /**
- * Construct a param for Set Up Event list.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSetUpEventList: function(cmdDetails, ctlvs, onComplete) {
- // Event list is mandatory.
- let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
- COMPREHENSIONTLV_TAG_EVENT_LIST, ctlvs);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Event List: Required value missing : Event List");
- }
-
- onComplete(ctlv.value || { eventList: null });
- },
-
- /**
- * Construct a param for Setup Menu.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSetupMenu: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let menu = {
- // Help information available.
- isHelpAvailable: !!(cmdDetails.commandQualifier & 0x80)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ITEM,
- COMPREHENSIONTLV_TAG_ITEM_ID,
- COMPREHENSIONTLV_TAG_NEXT_ACTION_IND,
- COMPREHENSIONTLV_TAG_ICON_ID,
- COMPREHENSIONTLV_TAG_ICON_ID_LIST
- ]);
-
- // Alpha identifier is optional.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- menu.title = ctlv.value.identifier;
- }
-
- // Item data object for item 1 is mandatory.
- let menuCtlvs = selectedCtlvs[COMPREHENSIONTLV_TAG_ITEM];
- if (!menuCtlvs) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Menu: Required value missing : items");
- }
- menu.items = menuCtlvs.map(aCtlv => aCtlv.value);
-
- // Item identifier is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ITEM_ID);
- if (ctlv) {
- menu.defaultItem = ctlv.value.identifier - 1;
- }
-
- // Items next action indicator is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_NEXT_ACTION_IND);
- if (ctlv) {
- menu.nextActionList = ctlv.value;
- }
-
- // Icon identifier is optional.
- let iconIdCtlvs = null;
- let menuIconCtlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ICON_ID);
- if (menuIconCtlv) {
- iconIdCtlvs = [menuIconCtlv];
- }
-
- // Item icon identifier list is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ICON_ID_LIST);
- if (ctlv) {
- if (!iconIdCtlvs) {
- iconIdCtlvs = [];
- };
- let iconIdList = ctlv.value;
- iconIdCtlvs = iconIdCtlvs.concat(iconIdList.identifiers.map((aId) => {
- return {
- value: { qualifier: iconIdList.qualifier, identifier: aId }
- };
- }));
- }
-
- this.loadIcons(iconIdCtlvs, (aIcons) => {
- if (aIcons) {
- if (menuIconCtlv) {
- menu.iconSelfExplanatory =
- (iconIdCtlvs.shift().value.qualifier == 0) ? true: false;
- menu.icons = aIcons.shift();
- }
-
- for (let i = 0; i < aIcons.length; i++) {
- menu.items[i].icons = aIcons[i];
- menu.items[i].iconSelfExplanatory =
- (iconIdCtlvs[i].value.qualifier == 0) ? true: false;
- }
- }
-
- onComplete(menu);
- });
- },
-
- /**
- * Construct a param for Select Item.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSelectItem: function(cmdDetails, ctlvs, onComplete) {
- this.processSetupMenu(cmdDetails, ctlvs, (menu) => {
- // The 1st bit and 2nd bit determines the presentation type.
- menu.presentationType = cmdDetails.commandQualifier & 0x03;
- onComplete(menu);
- });
- },
-
- /**
- * Construct a param for Display Text.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processDisplayText: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let textMsg = {
- isHighPriority: !!(cmdDetails.commandQualifier & 0x01),
- userClear: !!(cmdDetails.commandQualifier & 0x80)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TEXT_STRING,
- COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE,
- COMPREHENSIONTLV_TAG_DURATION,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Text string is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TEXT_STRING);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Display Text: Required value missing : Text String");
- }
- textMsg.text = ctlv.value.textString;
-
- // Immediate response is optional.
- textMsg.responseNeeded =
- !!(selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE));
-
- // Duration is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DURATION);
- if (ctlv) {
- textMsg.duration = ctlv.value;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- textMsg,
- onComplete);
- },
-
- /**
- * Construct a param for Setup Idle Mode Text.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSetUpIdleModeText: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let textMsg = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TEXT_STRING,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Text string is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TEXT_STRING);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Set Up Idle Text: Required value missing : Text String");
- }
- textMsg.text = ctlv.value.textString;
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- textMsg,
- onComplete);
- },
-
- /**
- * Construct a param for Get Inkey.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processGetInkey: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let input = {
- minLength: 1,
- maxLength: 1,
- isAlphabet: !!(cmdDetails.commandQualifier & 0x01),
- isUCS2: !!(cmdDetails.commandQualifier & 0x02),
- // Character sets defined in bit 1 and bit 2 are disable and
- // the YES/NO reponse is required.
- isYesNoRequested: !!(cmdDetails.commandQualifier & 0x04),
- // Help information available.
- isHelpAvailable: !!(cmdDetails.commandQualifier & 0x80)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TEXT_STRING,
- COMPREHENSIONTLV_TAG_DURATION,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Text string is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TEXT_STRING);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Get InKey: Required value missing : Text String");
- }
- input.text = ctlv.value.textString;
-
- // Duration is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DURATION);
- if (ctlv) {
- input.duration = ctlv.value;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- input,
- onComplete);
- },
-
- /**
- * Construct a param for Get Input.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processGetInput: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let input = {
- isAlphabet: !!(cmdDetails.commandQualifier & 0x01),
- isUCS2: !!(cmdDetails.commandQualifier & 0x02),
- // User input shall not be revealed
- hideInput: !!(cmdDetails.commandQualifier & 0x04),
- // User input in SMS packed format
- isPacked: !!(cmdDetails.commandQualifier & 0x08),
- // Help information available.
- isHelpAvailable: !!(cmdDetails.commandQualifier & 0x80)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TEXT_STRING,
- COMPREHENSIONTLV_TAG_RESPONSE_LENGTH,
- COMPREHENSIONTLV_TAG_DEFAULT_TEXT,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Text string is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TEXT_STRING);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Get Input: Required value missing : Text String");
- }
- input.text = ctlv.value.textString;
-
- // Response length is mandatory.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_RESPONSE_LENGTH);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Get Input: Required value missing : Response Length");
- }
- input.minLength = ctlv.value.minLength;
- input.maxLength = ctlv.value.maxLength;
-
- // Default text is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DEFAULT_TEXT);
- if (ctlv) {
- input.defaultText = ctlv.value.textString;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- input,
- onComplete);
- },
-
- /**
- * Construct a param for SendSS/SMS/USSD/DTMF.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processEventNotify: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let textMsg = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Alpha identifier is optional.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- textMsg.text = ctlv.value.identifier;
- }
-
- // According to section 6.4.10 of |ETSI TS 102 223|:
- //
- // - if the alpha identifier is provided by the UICC and is a null data
- // object (i.e. length = '00' and no value part), this is an indication
- // that the terminal should not give any information to the user on the
- // fact that the terminal is sending a short message;
- //
- // - if the alpha identifier is not provided by the UICC, the terminal may
- // give information to the user concerning what is happening.
- //
- // ICCPDUHelper reads alpha id as an empty string if the length is zero,
- // hence we'll notify the caller when it's not an empty string.
- if (textMsg.text !== "") {
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- textMsg,
- onComplete);
- }
- },
-
- /**
- * Construct a param for Setup Call.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processSetupCall: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let call = {};
- let confirmMessage = {};
- let callMessage = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ADDRESS,
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ICON_ID,
- COMPREHENSIONTLV_TAG_DURATION
- ]);
-
- // Address is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ADDRESS);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Set Up Call: Required value missing : Address");
- }
- call.address = ctlv.value.number;
-
- // Alpha identifier (user confirmation phase) is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- confirmMessage.text = ctlv.value.identifier;
- call.confirmMessage = confirmMessage;
- }
-
- // Alpha identifier (call set up phase) is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- callMessage.text = ctlv.value.identifier;
- call.callMessage = callMessage;
- }
-
- // Duration is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DURATION);
- if (ctlv) {
- call.duration = ctlv.value;
- }
-
- // Icon identifier is optional.
- let iconIdCtlvs = selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null;
- this.loadIcons(iconIdCtlvs, (aIcons) => {
- if (aIcons) {
- confirmMessage.icons = aIcons[0];
- confirmMessage.iconSelfExplanatory =
- (iconIdCtlvs[0].value.qualifier == 0) ? true: false;
- call.confirmMessage = confirmMessage;
-
- if (aIcons.length > 1) {
- callMessage.icons = aIcons[1];
- callMessage.iconSelfExplanatory =
- (iconIdCtlvs[1].value.qualifier == 0) ? true: false;
- call.callMessage = callMessage;
- }
- }
-
- onComplete(call);
- });
- },
-
- /**
- * Construct a param for Launch Browser.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processLaunchBrowser: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let browser = {
- mode: cmdDetails.commandQualifier & 0x03
- };
- let confirmMessage = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_URL,
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // URL is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_URL);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Launch Browser: Required value missing : URL");
- }
- browser.url = ctlv.value.url;
-
- // Alpha identifier is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- confirmMessage.text = ctlv.value.identifier;
- browser.confirmMessage = confirmMessage;
- }
-
- // Icon identifier is optional.
- let iconIdCtlvs = selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null;
- this.loadIcons(iconIdCtlvs, (aIcons) => {
- if (aIcons) {
- confirmMessage.icons = aIcons[0];
- confirmMessage.iconSelfExplanatory =
- (iconIdCtlvs[0].value.qualifier == 0) ? true: false;
- browser.confirmMessage = confirmMessage;
- }
-
- onComplete(browser);
- });
- },
-
- /**
- * Construct a param for Play Tone.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processPlayTone: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let playTone = {
- // The vibrate is only defined in TS 102.223.
- isVibrate: !!(cmdDetails.commandQualifier & 0x01)
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_TONE,
- COMPREHENSIONTLV_TAG_DURATION,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Alpha identifier is optional.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- playTone.text = ctlv.value.identifier;
- }
-
- // Tone is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TONE);
- if (ctlv) {
- playTone.tone = ctlv.value.tone;
- }
-
- // Duration is optional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_DURATION);
- if (ctlv) {
- playTone.duration = ctlv.value;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- playTone,
- onComplete);
- },
-
- /**
- * Construct a param for Provide Local Information.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processProvideLocalInfo: function(cmdDetails, ctlvs, onComplete) {
- let provideLocalInfo = {
- localInfoType: cmdDetails.commandQualifier
- };
-
- onComplete(provideLocalInfo);
- },
-
- /**
- * Construct a param for Timer Management.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processTimerManagement: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let timer = {
- timerAction: cmdDetails.commandQualifier
- };
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER,
- COMPREHENSIONTLV_TAG_TIMER_VALUE
- ]);
-
- // Timer identifier is mandatory.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER);
- if (!ctlv) {
- this.context.RIL.sendStkTerminalResponse({
- command: cmdDetails,
- resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
- throw new Error("Stk Timer Management: Required value missing : Timer Identifier");
- }
- timer.timerId = ctlv.value.timerId;
-
- // Timer value is conditional.
- ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_TIMER_VALUE);
- if (ctlv) {
- timer.timerValue = ctlv.value.timerValue;
- }
-
- onComplete(timer);
- },
-
- /**
- * Construct a param for BIP commands.
- *
- * @param cmdDetails
- * The value object of CommandDetails TLV.
- * @param ctlvs
- * The all TLVs in this proactive command.
- * @param onComplete
- * Callback to be called when complete.
- */
- processBipMessage: function(cmdDetails, ctlvs, onComplete) {
- let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
- let bipMsg = {};
-
- let selectedCtlvs = StkProactiveCmdHelper.searchForSelectedTags(ctlvs, [
- COMPREHENSIONTLV_TAG_ALPHA_ID,
- COMPREHENSIONTLV_TAG_ICON_ID
- ]);
-
- // Alpha identifier is optional.
- let ctlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- if (ctlv) {
- bipMsg.text = ctlv.value.identifier;
- }
-
- // Icon identifier is optional.
- this.appendIconIfNecessary(selectedCtlvs[COMPREHENSIONTLV_TAG_ICON_ID] || null,
- bipMsg,
- onComplete);
- }
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_REFRESH] = function STK_CMD_REFRESH(cmdDetails, ctlvs, onComplete) {
- return this.processRefresh(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_POLL_INTERVAL] = function STK_CMD_POLL_INTERVAL(cmdDetails, ctlvs, onComplete) {
- return this.processPollInterval(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_POLL_OFF] = function STK_CMD_POLL_OFF(cmdDetails, ctlvs, onComplete) {
- return this.processPollOff(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_PROVIDE_LOCAL_INFO] = function STK_CMD_PROVIDE_LOCAL_INFO(cmdDetails, ctlvs, onComplete) {
- return this.processProvideLocalInfo(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_EVENT_LIST] = function STK_CMD_SET_UP_EVENT_LIST(cmdDetails, ctlvs, onComplete) {
- return this.processSetUpEventList(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_MENU] = function STK_CMD_SET_UP_MENU(cmdDetails, ctlvs, onComplete) {
- return this.processSetupMenu(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SELECT_ITEM] = function STK_CMD_SELECT_ITEM(cmdDetails, ctlvs, onComplete) {
- return this.processSelectItem(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_DISPLAY_TEXT] = function STK_CMD_DISPLAY_TEXT(cmdDetails, ctlvs, onComplete) {
- return this.processDisplayText(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_IDLE_MODE_TEXT] = function STK_CMD_SET_UP_IDLE_MODE_TEXT(cmdDetails, ctlvs, onComplete) {
- return this.processSetUpIdleModeText(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_GET_INKEY] = function STK_CMD_GET_INKEY(cmdDetails, ctlvs, onComplete) {
- return this.processGetInkey(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_GET_INPUT] = function STK_CMD_GET_INPUT(cmdDetails, ctlvs, onComplete) {
- return this.processGetInput(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_SS] = function STK_CMD_SEND_SS(cmdDetails, ctlvs, onComplete) {
- return this.processEventNotify(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_USSD] = function STK_CMD_SEND_USSD(cmdDetails, ctlvs, onComplete) {
- return this.processEventNotify(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_SMS] = function STK_CMD_SEND_SMS(cmdDetails, ctlvs, onComplete) {
- return this.processEventNotify(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_DTMF] = function STK_CMD_SEND_DTMF(cmdDetails, ctlvs, onComplete) {
- return this.processEventNotify(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_CALL] = function STK_CMD_SET_UP_CALL(cmdDetails, ctlvs, onComplete) {
- return this.processSetupCall(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_LAUNCH_BROWSER] = function STK_CMD_LAUNCH_BROWSER(cmdDetails, ctlvs, onComplete) {
- return this.processLaunchBrowser(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_PLAY_TONE] = function STK_CMD_PLAY_TONE(cmdDetails, ctlvs, onComplete) {
- return this.processPlayTone(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_TIMER_MANAGEMENT] = function STK_CMD_TIMER_MANAGEMENT(cmdDetails, ctlvs, onComplete) {
- return this.processTimerManagement(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_OPEN_CHANNEL] = function STK_CMD_OPEN_CHANNEL(cmdDetails, ctlvs, onComplete) {
- return this.processBipMessage(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_CLOSE_CHANNEL] = function STK_CMD_CLOSE_CHANNEL(cmdDetails, ctlvs, onComplete) {
- return this.processBipMessage(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_RECEIVE_DATA] = function STK_CMD_RECEIVE_DATA(cmdDetails, ctlvs, onComplete) {
- return this.processBipMessage(cmdDetails, ctlvs, onComplete);
-};
-StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_DATA] = function STK_CMD_SEND_DATA(cmdDetails, ctlvs, onComplete) {
- return this.processBipMessage(cmdDetails, ctlvs, onComplete);
-};
-
-function StkProactiveCmdHelperObject(aContext) {
- this.context = aContext;
-}
-StkProactiveCmdHelperObject.prototype = {
- context: null,
-
- retrieve: function(tag, length) {
- let method = this[tag];
- if (typeof method != "function") {
- if (DEBUG) {
- this.context.debug("Unknown comprehension tag " + tag.toString(16));
- }
- let Buf = this.context.Buf;
- Buf.seekIncoming(length * Buf.PDU_HEX_OCTET_SIZE);
- return null;
- }
- return method.call(this, length);
- },
-
- /**
- * Command Details.
- *
- * | Byte | Description | Length |
- * | 1 | Command details Tag | 1 |
- * | 2 | Length = 03 | 1 |
- * | 3 | Command number | 1 |
- * | 4 | Type of Command | 1 |
- * | 5 | Command Qualifier | 1 |
- */
- retrieveCommandDetails: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let cmdDetails = {
- commandNumber: GsmPDUHelper.readHexOctet(),
- typeOfCommand: GsmPDUHelper.readHexOctet(),
- commandQualifier: GsmPDUHelper.readHexOctet()
- };
- return cmdDetails;
- },
-
- /**
- * Device Identities.
- *
- * | Byte | Description | Length |
- * | 1 | Device Identity Tag | 1 |
- * | 2 | Length = 02 | 1 |
- * | 3 | Source device Identity | 1 |
- * | 4 | Destination device Id | 1 |
- */
- retrieveDeviceId: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let deviceId = {
- sourceId: GsmPDUHelper.readHexOctet(),
- destinationId: GsmPDUHelper.readHexOctet()
- };
- return deviceId;
- },
-
- /**
- * Alpha Identifier.
- *
- * | Byte | Description | Length |
- * | 1 | Alpha Identifier Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 ~ | Alpha identfier | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveAlphaId: function(length) {
- let alphaId = {
- identifier: this.context.ICCPDUHelper.readAlphaIdentifier(length)
- };
- return alphaId;
- },
-
- /**
- * Duration.
- *
- * | Byte | Description | Length |
- * | 1 | Response Length Tag | 1 |
- * | 2 | Lenth = 02 | 1 |
- * | 3 | Time unit | 1 |
- * | 4 | Time interval | 1 |
- */
- retrieveDuration: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let duration = {
- timeUnit: GsmPDUHelper.readHexOctet(),
- timeInterval: GsmPDUHelper.readHexOctet(),
- };
- return duration;
- },
-
- /**
- * Address.
- *
- * | Byte | Description | Length |
- * | 1 | Alpha Identifier Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 | TON and NPI | 1 |
- * | (Y-1)+4 ~ | Dialling number | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveAddress: function(length) {
- let address = {
- number : this.context.ICCPDUHelper.readDiallingNumber(length)
- };
- return address;
- },
-
- /**
- * Text String.
- *
- * | Byte | Description | Length |
- * | 1 | Text String Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 | Data coding scheme | 1 |
- * | (Y-1)+4~ | Text String | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveTextString: function(length) {
- if (!length) {
- // null string.
- return {textString: null};
- }
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let text = {
- codingScheme: GsmPDUHelper.readHexOctet()
- };
-
- length--; // -1 for the codingScheme.
- switch (text.codingScheme & 0x0c) {
- case STK_TEXT_CODING_GSM_7BIT_PACKED:
- text.textString =
- GsmPDUHelper.readSeptetsToString(Math.floor(length * 8 / 7), 0, 0, 0);
- break;
- case STK_TEXT_CODING_GSM_8BIT:
- text.textString =
- this.context.ICCPDUHelper.read8BitUnpackedToString(length);
- break;
- case STK_TEXT_CODING_UCS2:
- text.textString = GsmPDUHelper.readUCS2String(length);
- break;
- }
- return text;
- },
-
- /**
- * Tone.
- *
- * | Byte | Description | Length |
- * | 1 | Tone Tag | 1 |
- * | 2 | Lenth = 01 | 1 |
- * | 3 | Tone | 1 |
- */
- retrieveTone: function(length) {
- let tone = {
- tone: this.context.GsmPDUHelper.readHexOctet(),
- };
- return tone;
- },
-
- /**
- * Item.
- *
- * | Byte | Description | Length |
- * | 1 | Item Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 | Identifier of item | 1 |
- * | (Y-1)+4 ~ | Text string of item | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveItem: function(length) {
- // TS 102.223 ,clause 6.6.7 SET-UP MENU
- // If the "Item data object for item 1" is a null data object
- // (i.e. length = '00' and no value part), this is an indication to the ME
- // to remove the existing menu from the menu system in the ME.
- if (!length) {
- return null;
- }
- let item = {
- identifier: this.context.GsmPDUHelper.readHexOctet(),
- text: this.context.ICCPDUHelper.readAlphaIdentifier(length - 1)
- };
- return item;
- },
-
- /**
- * Item Identifier.
- *
- * | Byte | Description | Length |
- * | 1 | Item Identifier Tag | 1 |
- * | 2 | Lenth = 01 | 1 |
- * | 3 | Identifier of Item chosen | 1 |
- */
- retrieveItemId: function(length) {
- let itemId = {
- identifier: this.context.GsmPDUHelper.readHexOctet()
- };
- return itemId;
- },
-
- /**
- * Response Length.
- *
- * | Byte | Description | Length |
- * | 1 | Response Length Tag | 1 |
- * | 2 | Lenth = 02 | 1 |
- * | 3 | Minimum length of response | 1 |
- * | 4 | Maximum length of response | 1 |
- */
- retrieveResponseLength: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let rspLength = {
- minLength : GsmPDUHelper.readHexOctet(),
- maxLength : GsmPDUHelper.readHexOctet()
- };
- return rspLength;
- },
-
- /**
- * File List.
- *
- * | Byte | Description | Length |
- * | 1 | File List Tag | 1 |
- * | 2 ~ (Y-1)+2 | Length (X) | Y |
- * | (Y-1)+3 | Number of files | 1 |
- * | (Y-1)+4 ~ | Files | X |
- * | (Y-1)+X+2 | | |
- */
- retrieveFileList: function(length) {
- let num = this.context.GsmPDUHelper.readHexOctet();
- let fileList = "";
- length--; // -1 for the num octet.
- for (let i = 0; i < 2 * length; i++) {
- // Didn't use readHexOctet here,
- // otherwise 0x00 will be "0", not "00"
- fileList += String.fromCharCode(this.context.Buf.readUint16());
- }
- return {
- fileList: fileList
- };
- },
-
- /**
- * Default Text.
- *
- * Same as Text String.
- */
- retrieveDefaultText: function(length) {
- return this.retrieveTextString(length);
- },
-
- /**
- * Event List.
- */
- retrieveEventList: function(length) {
- if (!length) {
- // null means an indication to ME to remove the existing list of events
- // in ME.
- return null;
- }
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let eventList = [];
- for (let i = 0; i < length; i++) {
- eventList.push(GsmPDUHelper.readHexOctet());
- }
- return {
- eventList: eventList
- };
- },
-
- /**
- * Icon Id.
- *
- * | Byte | Description | Length |
- * | 1 | Icon Identifier Tag | 1 |
- * | 2 | Length = 02 | 1 |
- * | 3 | Icon qualifier | 1 |
- * | 4 | Icon identifier | 1 |
- */
- retrieveIconId: function(length) {
- if (!length) {
- return null;
- }
-
- let iconId = {
- qualifier: this.context.GsmPDUHelper.readHexOctet(),
- identifier: this.context.GsmPDUHelper.readHexOctet()
- };
- return iconId;
- },
-
- /**
- * Icon Id List.
- *
- * | Byte | Description | Length |
- * | 1 | Icon Identifier Tag | 1 |
- * | 2 | Length = X | 1 |
- * | 3 | Icon qualifier | 1 |
- * | 4~ | Icon identifier | X-1 |
- * | 4+X-2 | | |
- */
- retrieveIconIdList: function(length) {
- if (!length) {
- return null;
- }
-
- let iconIdList = {
- qualifier: this.context.GsmPDUHelper.readHexOctet(),
- identifiers: []
- };
- for (let i = 0; i < length - 1; i++) {
- iconIdList.identifiers.push(this.context.GsmPDUHelper.readHexOctet());
- }
- return iconIdList;
- },
-
- /**
- * Timer Identifier.
- *
- * | Byte | Description | Length |
- * | 1 | Timer Identifier Tag | 1 |
- * | 2 | Length = 01 | 1 |
- * | 3 | Timer Identifier | 1 |
- */
- retrieveTimerId: function(length) {
- let id = {
- timerId: this.context.GsmPDUHelper.readHexOctet()
- };
- return id;
- },
-
- /**
- * Timer Value.
- *
- * | Byte | Description | Length |
- * | 1 | Timer Value Tag | 1 |
- * | 2 | Length = 03 | 1 |
- * | 3 | Hour | 1 |
- * | 4 | Minute | 1 |
- * | 5 | Second | 1 |
- */
- retrieveTimerValue: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let value = {
- timerValue: (GsmPDUHelper.readSwappedNibbleBcdNum(1) * 60 * 60) +
- (GsmPDUHelper.readSwappedNibbleBcdNum(1) * 60) +
- (GsmPDUHelper.readSwappedNibbleBcdNum(1))
- };
- return value;
- },
-
- /**
- * Immediate Response.
- *
- * | Byte | Description | Length |
- * | 1 | Immediate Response Tag | 1 |
- * | 2 | Length = 00 | 1 |
- */
- retrieveImmediaResponse: function(length) {
- return {};
- },
-
- /**
- * URL
- *
- * | Byte | Description | Length |
- * | 1 | URL Tag | 1 |
- * | 2 ~ (Y+1) | Length(X) | Y |
- * | (Y+2) ~ | URL | X |
- * | (Y+1+X) | | |
- */
- retrieveUrl: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let s = "";
- for (let i = 0; i < length; i++) {
- s += String.fromCharCode(GsmPDUHelper.readHexOctet());
- }
- return {url: s};
- },
-
- /**
- * Next Action Indicator List.
- *
- * | Byte | Description | Length |
- * | 1 | Next Action tag | 1 |
- * | 1 | Length(X) | 1 |
- * | 3~ | Next Action List | X |
- * | 3+X-1 | | |
- */
- retrieveNextActionList: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let nextActionList = [];
- for (let i = 0; i < length; i++) {
- nextActionList.push(GsmPDUHelper.readHexOctet());
- }
- return nextActionList;
- },
-
- searchForTag: function(tag, ctlvs) {
- for (let ctlv of ctlvs) {
- if ((ctlv.tag & ~COMPREHENSIONTLV_FLAG_CR) == tag) {
- return ctlv;
- }
- }
- return null;
- },
-
- searchForSelectedTags: function(ctlvs, tags) {
- let ret = {
- // Handy utility to de-queue the 1st ctlv of the specified tag.
- retrieve: function(aTag) {
- return (this[aTag]) ? this[aTag].shift() : null;
- }
- };
-
- ctlvs.forEach((aCtlv) => {
- tags.forEach((aTag) => {
- if ((aCtlv.tag & ~COMPREHENSIONTLV_FLAG_CR) == aTag) {
- if (!ret[aTag]) {
- ret[aTag] = [];
- }
- ret[aTag].push(aCtlv);
- }
- });
- });
-
- return ret;
- },
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_COMMAND_DETAILS] = function COMPREHENSIONTLV_TAG_COMMAND_DETAILS(length) {
- return this.retrieveCommandDetails(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DEVICE_ID] = function COMPREHENSIONTLV_TAG_DEVICE_ID(length) {
- return this.retrieveDeviceId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ALPHA_ID] = function COMPREHENSIONTLV_TAG_ALPHA_ID(length) {
- return this.retrieveAlphaId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DURATION] = function COMPREHENSIONTLV_TAG_DURATION(length) {
- return this.retrieveDuration(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ADDRESS] = function COMPREHENSIONTLV_TAG_ADDRESS(length) {
- return this.retrieveAddress(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TEXT_STRING] = function COMPREHENSIONTLV_TAG_TEXT_STRING(length) {
- return this.retrieveTextString(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TONE] = function COMPREHENSIONTLV_TAG_TONE(length) {
- return this.retrieveTone(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ITEM] = function COMPREHENSIONTLV_TAG_ITEM(length) {
- return this.retrieveItem(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ITEM_ID] = function COMPREHENSIONTLV_TAG_ITEM_ID(length) {
- return this.retrieveItemId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_RESPONSE_LENGTH] = function COMPREHENSIONTLV_TAG_RESPONSE_LENGTH(length) {
- return this.retrieveResponseLength(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_FILE_LIST] = function COMPREHENSIONTLV_TAG_FILE_LIST(length) {
- return this.retrieveFileList(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DEFAULT_TEXT] = function COMPREHENSIONTLV_TAG_DEFAULT_TEXT(length) {
- return this.retrieveDefaultText(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_EVENT_LIST] = function COMPREHENSIONTLV_TAG_EVENT_LIST(length) {
- return this.retrieveEventList(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ICON_ID] = function COMPREHENSIONTLV_TAG_ICON_ID(length) {
- return this.retrieveIconId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ICON_ID_LIST] = function COMPREHENSIONTLV_TAG_ICON_ID_LIST(length) {
- return this.retrieveIconIdList(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER] = function COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER(length) {
- return this.retrieveTimerId(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TIMER_VALUE] = function COMPREHENSIONTLV_TAG_TIMER_VALUE(length) {
- return this.retrieveTimerValue(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE] = function COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE(length) {
- return this.retrieveImmediaResponse(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_URL] = function COMPREHENSIONTLV_TAG_URL(length) {
- return this.retrieveUrl(length);
-};
-StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_NEXT_ACTION_IND] = function COMPREHENSIONTLV_TAG_NEXT_ACTION_IND(length) {
- return this.retrieveNextActionList(length);
-};
-
-function ComprehensionTlvHelperObject(aContext) {
- this.context = aContext;
-}
-ComprehensionTlvHelperObject.prototype = {
- context: null,
-
- /**
- * Decode raw data to a Comprehension-TLV.
- */
- decode: function() {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let hlen = 0; // For header(tag field + length field) length.
- let temp = GsmPDUHelper.readHexOctet();
- hlen++;
-
- // TS 101.220, clause 7.1.1
- let tag, cr;
- switch (temp) {
- // TS 101.220, clause 7.1.1
- case 0x0: // Not used.
- case 0xff: // Not used.
- case 0x80: // Reserved for future use.
- throw new Error("Invalid octet when parsing Comprehension TLV :" + temp);
- case 0x7f: // Tag is three byte format.
- // TS 101.220 clause 7.1.1.2.
- // | Byte 1 | Byte 2 | Byte 3 |
- // | | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | |
- // | 0x7f |CR | Tag Value |
- tag = (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- hlen += 2;
- cr = (tag & 0x8000) !== 0;
- tag &= ~0x8000;
- break;
- default: // Tag is single byte format.
- tag = temp;
- // TS 101.220 clause 7.1.1.1.
- // | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
- // |CR | Tag Value |
- cr = (tag & 0x80) !== 0;
- tag &= ~0x80;
- }
-
- // TS 101.220 clause 7.1.2, Length Encoding.
- // Length | Byte 1 | Byte 2 | Byte 3 | Byte 4 |
- // 0 - 127 | 00 - 7f | N/A | N/A | N/A |
- // 128-255 | 81 | 80 - ff| N/A | N/A |
- // 256-65535| 82 | 0100 - ffff | N/A |
- // 65536- | 83 | 010000 - ffffff |
- // 16777215
- //
- // Length errors: TS 11.14, clause 6.10.6
-
- let length; // Data length.
- temp = GsmPDUHelper.readHexOctet();
- hlen++;
- if (temp < 0x80) {
- length = temp;
- } else if (temp == 0x81) {
- length = GsmPDUHelper.readHexOctet();
- hlen++;
- if (length < 0x80) {
- throw new Error("Invalid length in Comprehension TLV :" + length);
- }
- } else if (temp == 0x82) {
- length = (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- hlen += 2;
- if (lenth < 0x0100) {
- throw new Error("Invalid length in 3-byte Comprehension TLV :" + length);
- }
- } else if (temp == 0x83) {
- length = (GsmPDUHelper.readHexOctet() << 16) |
- (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet();
- hlen += 3;
- if (length < 0x010000) {
- throw new Error("Invalid length in 4-byte Comprehension TLV :" + length);
- }
- } else {
- throw new Error("Invalid octet in Comprehension TLV :" + temp);
- }
-
- let ctlv = {
- tag: tag,
- length: length,
- value: this.context.StkProactiveCmdHelper.retrieve(tag, length),
- cr: cr,
- hlen: hlen
- };
- return ctlv;
- },
-
- decodeChunks: function(length) {
- let chunks = [];
- let index = 0;
- while (index < length) {
- let tlv = this.decode();
- chunks.push(tlv);
- index += tlv.length;
- index += tlv.hlen;
- }
- return chunks;
- },
-
- /**
- * Write Location Info Comprehension TLV.
- *
- * @param loc location Information.
- */
- writeLocationInfoTlv: function(loc) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(loc.gsmCellId > 0xffff ? 9 : 7);
- // From TS 11.14, clause 12.19
- // "The mobile country code (MCC), the mobile network code (MNC),
- // the location area code (LAC) and the cell ID are
- // coded as in TS 04.08."
- // And from TS 04.08 and TS 24.008,
- // the format is as follows:
- //
- // MCC = MCC_digit_1 + MCC_digit_2 + MCC_digit_3
- //
- // 8 7 6 5 4 3 2 1
- // +-------------+-------------+
- // | MCC digit 2 | MCC digit 1 | octet 2
- // | MNC digit 3 | MCC digit 3 | octet 3
- // | MNC digit 2 | MNC digit 1 | octet 4
- // +-------------+-------------+
- //
- // Also in TS 24.008
- // "However a network operator may decide to
- // use only two digits in the MNC in the LAI over the
- // radio interface. In this case, bits 5 to 8 of octet 3
- // shall be coded as '1111'".
-
- // MCC & MNC, 3 octets
- let mcc = loc.mcc, mnc;
- if (loc.mnc.length == 2) {
- mnc = "F" + loc.mnc;
- } else {
- mnc = loc.mnc[2] + loc.mnc[0] + loc.mnc[1];
- }
- GsmPDUHelper.writeSwappedNibbleBCD(mcc + mnc);
-
- // LAC, 2 octets
- GsmPDUHelper.writeHexOctet((loc.gsmLocationAreaCode >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(loc.gsmLocationAreaCode & 0xff);
-
- // Cell Id
- if (loc.gsmCellId > 0xffff) {
- // UMTS/WCDMA, gsmCellId is 28 bits.
- GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 24) & 0xff);
- GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 16) & 0xff);
- GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(loc.gsmCellId & 0xff);
- } else {
- // GSM, gsmCellId is 16 bits.
- GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(loc.gsmCellId & 0xff);
- }
- },
-
- /**
- * Given a geckoError string, this function translates it into cause value
- * and write the value into buffer.
- *
- * @param geckoError Error string that is passed to gecko.
- */
- writeCauseTlv: function(geckoError) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let cause = -1;
- for (let errorNo in RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR) {
- if (geckoError == RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[errorNo]) {
- cause = errorNo;
- break;
- }
- }
-
- // Causes specified in 10.5.4.11 of TS 04.08 are less than 128.
- // we can ignore causes > 127 since Cause TLV is optional in
- // STK_EVENT_TYPE_CALL_DISCONNECTED.
- if (cause > 127) {
- return;
- }
-
- cause = (cause == -1) ? ERROR_SUCCESS : cause;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_CAUSE |
- COMPREHENSIONTLV_FLAG_CR);
- GsmPDUHelper.writeHexOctet(2); // For single cause value.
-
- // TS 04.08, clause 10.5.4.11:
- // Code Standard : Standard defined for GSM PLMNS
- // Location: User
- GsmPDUHelper.writeHexOctet(0x60);
-
- // TS 04.08, clause 10.5.4.11: ext bit = 1 + 7 bits for cause.
- // +-----------------+----------------------------------+
- // | Ext = 1 (1 bit) | Cause (7 bits) |
- // +-----------------+----------------------------------+
- GsmPDUHelper.writeHexOctet(0x80 | cause);
- },
-
- writeDateTimeZoneTlv: function(date) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DATE_TIME_ZONE);
- GsmPDUHelper.writeHexOctet(7);
- GsmPDUHelper.writeTimestamp(date);
- },
-
- writeLanguageTlv: function(language) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LANGUAGE);
- GsmPDUHelper.writeHexOctet(2);
-
- // ISO 639-1, Alpha-2 code
- // TS 123.038, clause 6.2.1, GSM 7 bit Default Alphabet
- GsmPDUHelper.writeHexOctet(
- PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[0]));
- GsmPDUHelper.writeHexOctet(
- PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[1]));
- },
-
- /**
- * Write Timer Value Comprehension TLV.
- *
- * @param seconds length of time during of the timer.
- * @param cr Comprehension Required or not
- */
- writeTimerValueTlv: function(seconds, cr) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_VALUE |
- (cr ? COMPREHENSIONTLV_FLAG_CR : 0));
- GsmPDUHelper.writeHexOctet(3);
-
- // TS 102.223, clause 8.38
- // +----------------+------------------+-------------------+
- // | hours (1 byte) | minutes (1 btye) | seconds (1 byte) |
- // +----------------+------------------+-------------------+
- GsmPDUHelper.writeSwappedNibbleBCDNum(Math.floor(seconds / 60 / 60));
- GsmPDUHelper.writeSwappedNibbleBCDNum(Math.floor(seconds / 60) % 60);
- GsmPDUHelper.writeSwappedNibbleBCDNum(Math.floor(seconds) % 60);
- },
-
- writeTextStringTlv: function(text, coding) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let buf = GsmPDUHelper.writeWithBuffer(() => {
- // Write Coding.
- GsmPDUHelper.writeHexOctet(coding);
-
- // Write Text String.
- switch (coding) {
- case STK_TEXT_CODING_UCS2:
- GsmPDUHelper.writeUCS2String(text);
- break;
- case STK_TEXT_CODING_GSM_7BIT_PACKED:
- GsmPDUHelper.writeStringAsSeptets(text, 0, 0, 0);
- break;
- case STK_TEXT_CODING_GSM_8BIT:
- GsmPDUHelper.writeStringAs8BitUnpacked(text);
- break;
- }
- });
-
- let length = buf.length;
- if (length) {
- // Write Tag.
- GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- // Write Length.
- this.writeLength(length);
- // Write Value.
- for (let i = 0; i < length; i++) {
- GsmPDUHelper.writeHexOctet(buf[i]);
- }
- }
- },
-
- getSizeOfLengthOctets: function(length) {
- if (length >= 0x10000) {
- return 4; // 0x83, len_1, len_2, len_3
- } else if (length >= 0x100) {
- return 3; // 0x82, len_1, len_2
- } else if (length >= 0x80) {
- return 2; // 0x81, len
- } else {
- return 1; // len
- }
- },
-
- writeLength: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // TS 101.220 clause 7.1.2, Length Encoding.
- // Length | Byte 1 | Byte 2 | Byte 3 | Byte 4 |
- // 0 - 127 | 00 - 7f | N/A | N/A | N/A |
- // 128-255 | 81 | 80 - ff| N/A | N/A |
- // 256-65535| 82 | 0100 - ffff | N/A |
- // 65536- | 83 | 010000 - ffffff |
- // 16777215
- if (length < 0x80) {
- GsmPDUHelper.writeHexOctet(length);
- } else if (0x80 <= length && length < 0x100) {
- GsmPDUHelper.writeHexOctet(0x81);
- GsmPDUHelper.writeHexOctet(length);
- } else if (0x100 <= length && length < 0x10000) {
- GsmPDUHelper.writeHexOctet(0x82);
- GsmPDUHelper.writeHexOctet((length >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(length & 0xff);
- } else if (0x10000 <= length && length < 0x1000000) {
- GsmPDUHelper.writeHexOctet(0x83);
- GsmPDUHelper.writeHexOctet((length >> 16) & 0xff);
- GsmPDUHelper.writeHexOctet((length >> 8) & 0xff);
- GsmPDUHelper.writeHexOctet(length & 0xff);
- } else {
- throw new Error("Invalid length value :" + length);
- }
- },
-};
-
-function BerTlvHelperObject(aContext) {
- this.context = aContext;
-}
-BerTlvHelperObject.prototype = {
- context: null,
-
- /**
- * Decode Ber TLV.
- *
- * @param dataLen
- * The length of data in bytes.
- */
- decode: function(dataLen) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let hlen = 0;
- let tag = GsmPDUHelper.readHexOctet();
- hlen++;
-
- // The length is coded onto 1 or 2 bytes.
- // Length | Byte 1 | Byte 2
- // 0 - 127 | length ('00' to '7f') | N/A
- // 128 - 255 | '81' | length ('80' to 'ff')
- let length;
- let temp = GsmPDUHelper.readHexOctet();
- hlen++;
- if (temp < 0x80) {
- length = temp;
- } else if (temp === 0x81) {
- length = GsmPDUHelper.readHexOctet();
- hlen++;
- if (length < 0x80) {
- throw new Error("Invalid length " + length);
- }
- } else {
- throw new Error("Invalid length octet " + temp);
- }
-
- // Header + body length check.
- if (dataLen - hlen !== length) {
- throw new Error("Unexpected BerTlvHelper value length!!");
- }
-
- let method = this[tag];
- if (typeof method != "function") {
- throw new Error("Unknown Ber tag 0x" + tag.toString(16));
- }
-
- let value = method.call(this, length);
-
- return {
- tag: tag,
- length: length,
- value: value
- };
- },
-
- /**
- * Process the value part for FCP template TLV.
- *
- * @param length
- * The length of data in bytes.
- */
- processFcpTemplate: function(length) {
- let tlvs = this.decodeChunks(length);
- return tlvs;
- },
-
- /**
- * Process the value part for proactive command TLV.
- *
- * @param length
- * The length of data in bytes.
- */
- processProactiveCommand: function(length) {
- let ctlvs = this.context.ComprehensionTlvHelper.decodeChunks(length);
- return ctlvs;
- },
-
- /**
- * Decode raw data to a Ber-TLV.
- */
- decodeInnerTlv: function() {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let tag = GsmPDUHelper.readHexOctet();
- let length = GsmPDUHelper.readHexOctet();
- return {
- tag: tag,
- length: length,
- value: this.retrieve(tag, length)
- };
- },
-
- decodeChunks: function(length) {
- let chunks = [];
- let index = 0;
- while (index < length) {
- let tlv = this.decodeInnerTlv();
- if (tlv.value) {
- chunks.push(tlv);
- }
- index += tlv.length;
- // tag + length fields consume 2 bytes.
- index += 2;
- }
- return chunks;
- },
-
- retrieve: function(tag, length) {
- let method = this[tag];
- if (typeof method != "function") {
- if (DEBUG) {
- this.context.debug("Unknown Ber tag : 0x" + tag.toString(16));
- }
- let Buf = this.context.Buf;
- Buf.seekIncoming(length * Buf.PDU_HEX_OCTET_SIZE);
- return null;
- }
- return method.call(this, length);
- },
-
- /**
- * File Size Data.
- *
- * | Byte | Description | Length |
- * | 1 | Tag | 1 |
- * | 2 | Length | 1 |
- * | 3 to X+24 | Number of allocated data bytes in the file | X |
- * | | , excluding structural information | |
- */
- retrieveFileSizeData: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let fileSizeData = 0;
- for (let i = 0; i < length; i++) {
- fileSizeData = fileSizeData << 8;
- fileSizeData += GsmPDUHelper.readHexOctet();
- }
-
- return {fileSizeData: fileSizeData};
- },
-
- /**
- * File Descriptor.
- *
- * | Byte | Description | Length |
- * | 1 | Tag | 1 |
- * | 2 | Length | 1 |
- * | 3 | File descriptor byte | 1 |
- * | 4 | Data coding byte | 1 |
- * | 5 ~ 6 | Record length | 2 |
- * | 7 | Number of records | 1 |
- */
- retrieveFileDescriptor: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let fileDescriptorByte = GsmPDUHelper.readHexOctet();
- let dataCodingByte = GsmPDUHelper.readHexOctet();
- // See TS 102 221 Table 11.5, we only care the least 3 bits for the
- // structure of file.
- let fileStructure = fileDescriptorByte & 0x07;
-
- let fileDescriptor = {
- fileStructure: fileStructure
- };
- // byte 5 ~ 7 are mandatory for linear fixed and cyclic files, otherwise
- // they are not applicable.
- if (fileStructure === UICC_EF_STRUCTURE[EF_STRUCTURE_LINEAR_FIXED] ||
- fileStructure === UICC_EF_STRUCTURE[EF_STRUCTURE_CYCLIC]) {
- fileDescriptor.recordLength = (GsmPDUHelper.readHexOctet() << 8) +
- GsmPDUHelper.readHexOctet();
- fileDescriptor.numOfRecords = GsmPDUHelper.readHexOctet();
- }
-
- return fileDescriptor;
- },
-
- /**
- * File identifier.
- *
- * | Byte | Description | Length |
- * | 1 | Tag | 1 |
- * | 2 | Length | 1 |
- * | 3 ~ 4 | File identifier | 2 |
- */
- retrieveFileIdentifier: function(length) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- return {fileId : (GsmPDUHelper.readHexOctet() << 8) +
- GsmPDUHelper.readHexOctet()};
- },
-
- searchForNextTag: function(tag, iter) {
- for (let tlv of iter) {
- if (tlv.tag === tag) {
- return tlv;
- }
- }
- return null;
- }
-};
-BerTlvHelperObject.prototype[BER_FCP_TEMPLATE_TAG] = function BER_FCP_TEMPLATE_TAG(length) {
- return this.processFcpTemplate(length);
-};
-BerTlvHelperObject.prototype[BER_PROACTIVE_COMMAND_TAG] = function BER_PROACTIVE_COMMAND_TAG(length) {
- return this.processProactiveCommand(length);
-};
-BerTlvHelperObject.prototype[BER_FCP_FILE_SIZE_DATA_TAG] = function BER_FCP_FILE_SIZE_DATA_TAG(length) {
- return this.retrieveFileSizeData(length);
-};
-BerTlvHelperObject.prototype[BER_FCP_FILE_DESCRIPTOR_TAG] = function BER_FCP_FILE_DESCRIPTOR_TAG(length) {
- return this.retrieveFileDescriptor(length);
-};
-BerTlvHelperObject.prototype[BER_FCP_FILE_IDENTIFIER_TAG] = function BER_FCP_FILE_IDENTIFIER_TAG(length) {
- return this.retrieveFileIdentifier(length);
-};
-
-/**
- * ICC Helper for getting EF path.
- */
-function ICCFileHelperObject(aContext) {
- this.context = aContext;
-}
-ICCFileHelperObject.prototype = {
- context: null,
-
- /**
- * This function handles only EFs that are common to RUIM, SIM, USIM
- * and other types of ICC cards.
- */
- getCommonEFPath: function(fileId) {
- switch (fileId) {
- case ICC_EF_ICCID:
- return EF_PATH_MF_SIM;
- case ICC_EF_ADN:
- case ICC_EF_SDN: // Fall through.
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
- case ICC_EF_PBR:
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
- case ICC_EF_IMG:
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_GRAPHICS;
- }
- return null;
- },
-
- /**
- * This function handles EFs for SIM.
- */
- getSimEFPath: function(fileId) {
- switch (fileId) {
- case ICC_EF_FDN:
- case ICC_EF_MSISDN:
- case ICC_EF_SMS:
- case ICC_EF_EXT1:
- case ICC_EF_EXT2:
- case ICC_EF_EXT3:
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
- case ICC_EF_AD:
- case ICC_EF_MBDN:
- case ICC_EF_MWIS:
- case ICC_EF_PLMNsel:
- case ICC_EF_SPN:
- case ICC_EF_SPDI:
- case ICC_EF_SST:
- case ICC_EF_PHASE:
- case ICC_EF_CBMI:
- case ICC_EF_CBMID:
- case ICC_EF_CBMIR:
- case ICC_EF_OPL:
- case ICC_EF_PNN:
- case ICC_EF_GID1:
- case ICC_EF_CPHS_INFO:
- case ICC_EF_CPHS_MBN:
- return EF_PATH_MF_SIM + EF_PATH_DF_GSM;
- default:
- return null;
- }
- },
-
- /**
- * This function handles EFs for USIM.
- */
- getUSimEFPath: function(fileId) {
- switch (fileId) {
- case ICC_EF_AD:
- case ICC_EF_FDN:
- case ICC_EF_MBDN:
- case ICC_EF_MWIS:
- case ICC_EF_UST:
- case ICC_EF_MSISDN:
- case ICC_EF_SPN:
- case ICC_EF_SPDI:
- case ICC_EF_CBMI:
- case ICC_EF_CBMID:
- case ICC_EF_CBMIR:
- case ICC_EF_OPL:
- case ICC_EF_PNN:
- case ICC_EF_SMS:
- case ICC_EF_GID1:
- // CPHS spec was provided in 1997 based on SIM requirement, there is no
- // detailed info about how these ICC_EF_CPHS_XXX are allocated in USIM.
- // What we can do now is to follow what has been done in AOSP to have file
- // path equal to MF_SIM/DF_GSM.
- case ICC_EF_CPHS_INFO:
- case ICC_EF_CPHS_MBN:
- return EF_PATH_MF_SIM + EF_PATH_ADF_USIM;
- default:
- // The file ids in USIM phone book entries are decided by the
- // card manufacturer. So if we don't match any of the cases
- // above and if its a USIM return the phone book path.
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
- }
- },
-
- /**
- * This function handles EFs for RUIM
- */
- getRuimEFPath: function(fileId) {
- switch(fileId) {
- case ICC_EF_CSIM_IMSI_M:
- case ICC_EF_CSIM_CDMAHOME:
- case ICC_EF_CSIM_CST:
- case ICC_EF_CSIM_SPN:
- return EF_PATH_MF_SIM + EF_PATH_DF_CDMA;
- case ICC_EF_FDN:
- case ICC_EF_EXT1:
- case ICC_EF_EXT2:
- case ICC_EF_EXT3:
- return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
- default:
- return null;
- }
- },
-
- /**
- * Helper function for getting the pathId for the specific ICC record
- * depeding on which type of ICC card we are using.
- *
- * @param fileId
- * File id.
- * @return The pathId or null in case of an error or invalid input.
- */
- getEFPath: function(fileId) {
- let path = this.getCommonEFPath(fileId);
- if (path) {
- return path;
- }
-
- switch (this.context.RIL.appType) {
- case CARD_APPTYPE_SIM:
- return this.getSimEFPath(fileId);
- case CARD_APPTYPE_USIM:
- return this.getUSimEFPath(fileId);
- case CARD_APPTYPE_RUIM:
- return this.getRuimEFPath(fileId);
- default:
- return null;
- }
- }
-};
-
-/**
- * Helper for ICC IO functionalities.
- */
-function ICCIOHelperObject(aContext) {
- this.context = aContext;
-}
-ICCIOHelperObject.prototype = {
- context: null,
-
- /**
- * Load EF with type 'Linear Fixed'.
- *
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- * @param recordNumber [optional]
- * The number of the record shall be loaded.
- * @param recordSize [optional]
- * The size of the record.
- * @param callback [optional]
- * The callback function shall be called when the record(s) is read.
- * @param onerror [optional]
- * The callback function shall be called when failure.
- */
- loadLinearFixedEF: function(options) {
- let cb;
- let readRecord = (function(options) {
- options.command = ICC_COMMAND_READ_RECORD;
- options.p1 = options.recordNumber || 1; // Record number
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = options.recordSize;
- options.callback = cb || options.callback;
- this.context.RIL.iccIO(options);
- }).bind(this);
-
- options.structure = EF_STRUCTURE_LINEAR_FIXED;
- options.pathId = this.context.ICCFileHelper.getEFPath(options.fileId);
- if (options.recordSize) {
- readRecord(options);
- return;
- }
-
- cb = options.callback;
- options.callback = readRecord;
- this.getResponse(options);
- },
-
- /**
- * Load next record from current record Id.
- */
- loadNextRecord: function(options) {
- options.p1++;
- this.context.RIL.iccIO(options);
- },
-
- /**
- * Update EF with type 'Linear Fixed'.
- *
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- * @param recordNumber
- * The number of the record shall be updated.
- * @param dataWriter [optional]
- * The function for writing string parameter for the ICC_COMMAND_UPDATE_RECORD.
- * @param pin2 [optional]
- * PIN2 is required when updating ICC_EF_FDN.
- * @param callback [optional]
- * The callback function shall be called when the record is updated.
- * @param onerror [optional]
- * The callback function shall be called when failure.
- */
- updateLinearFixedEF: function(options) {
- if (!options.fileId || !options.recordNumber) {
- throw new Error("Unexpected fileId " + options.fileId +
- " or recordNumber " + options.recordNumber);
- }
-
- options.structure = EF_STRUCTURE_LINEAR_FIXED;
- options.pathId = this.context.ICCFileHelper.getEFPath(options.fileId);
- let cb = options.callback;
- options.callback = function callback(options) {
- options.callback = cb;
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = options.recordSize;
- this.context.RIL.iccIO(options);
- }.bind(this);
- this.getResponse(options);
- },
-
- /**
- * Load EF with type 'Transparent'.
- *
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- * @param callback [optional]
- * The callback function shall be called when the record(s) is read.
- * @param onerror [optional]
- * The callback function shall be called when failure.
- */
- loadTransparentEF: function(options) {
- options.structure = EF_STRUCTURE_TRANSPARENT;
- let cb = options.callback;
- options.callback = function callback(options) {
- options.callback = cb;
- options.command = ICC_COMMAND_READ_BINARY;
- options.p2 = 0x00;
- options.p3 = options.fileSize;
- this.context.RIL.iccIO(options);
- }.bind(this);
- this.getResponse(options);
- },
-
- /**
- * Use ICC_COMMAND_GET_RESPONSE to query the EF.
- *
- * @param fileId
- * The file to operate on, one of the ICC_EF_* constants.
- */
- getResponse: function(options) {
- options.command = ICC_COMMAND_GET_RESPONSE;
- options.pathId = options.pathId ||
- this.context.ICCFileHelper.getEFPath(options.fileId);
- if (!options.pathId) {
- throw new Error("Unknown pathId for " + options.fileId.toString(16));
- }
- options.p1 = 0; // For GET_RESPONSE, p1 = 0
- switch (this.context.RIL.appType) {
- case CARD_APPTYPE_USIM:
- options.p2 = GET_RESPONSE_FCP_TEMPLATE;
- options.p3 = 0x00;
- break;
- // For RUIM, CSIM and ISIM, cf bug 955946: keep the old behavior
- case CARD_APPTYPE_RUIM:
- case CARD_APPTYPE_CSIM:
- case CARD_APPTYPE_ISIM:
- // For SIM, this is what we want
- case CARD_APPTYPE_SIM:
- default:
- options.p2 = 0x00;
- options.p3 = GET_RESPONSE_EF_SIZE_BYTES;
- break;
- }
- this.context.RIL.iccIO(options);
- },
-
- /**
- * Process ICC I/O response.
- */
- processICCIO: function(options) {
- let func = this[options.command];
- func.call(this, options);
- },
-
- /**
- * Process a ICC_COMMAND_GET_RESPONSE type command for REQUEST_SIM_IO.
- */
- processICCIOGetResponse: function(options) {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
-
- let peek = this.context.GsmPDUHelper.readHexOctet();
- Buf.seekIncoming(-1 * Buf.PDU_HEX_OCTET_SIZE);
- if (peek === BER_FCP_TEMPLATE_TAG) {
- this.processUSimGetResponse(options, strLen / 2);
- } else {
- this.processSimGetResponse(options);
- }
- Buf.readStringDelimiter(strLen);
-
- if (options.callback) {
- options.callback(options);
- }
- },
-
- /**
- * Helper function for processing USIM get response.
- */
- processUSimGetResponse: function(options, octetLen) {
- let BerTlvHelper = this.context.BerTlvHelper;
-
- let berTlv = BerTlvHelper.decode(octetLen);
- // See TS 102 221 Table 11.4 for the content order of getResponse.
- let iter = berTlv.value.values();
- let tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG,
- iter);
- if (!tlv ||
- (tlv.value.fileStructure !== UICC_EF_STRUCTURE[options.structure])) {
- throw new Error("Expected EF structure " +
- UICC_EF_STRUCTURE[options.structure] +
- " but read " + tlv.value.fileStructure);
- }
-
- if (tlv.value.fileStructure === UICC_EF_STRUCTURE[EF_STRUCTURE_LINEAR_FIXED] ||
- tlv.value.fileStructure === UICC_EF_STRUCTURE[EF_STRUCTURE_CYCLIC]) {
- options.recordSize = tlv.value.recordLength;
- options.totalRecords = tlv.value.numOfRecords;
- }
-
- tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
- if (!tlv || (tlv.value.fileId !== options.fileId)) {
- throw new Error("Expected file ID " + options.fileId.toString(16) +
- " but read " + fileId.toString(16));
- }
-
- tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
- if (!tlv) {
- throw new Error("Unexpected file size data");
- }
- options.fileSize = tlv.value.fileSizeData;
- },
-
- /**
- * Helper function for processing SIM get response.
- */
- processSimGetResponse: function(options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // The format is from TS 51.011, clause 9.2.1
-
- // Skip RFU, data[0] data[1].
- Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
-
- // File size, data[2], data[3]
- options.fileSize = (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet();
-
- // 2 bytes File id. data[4], data[5]
- let fileId = (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet();
- if (fileId != options.fileId) {
- throw new Error("Expected file ID " + options.fileId.toString(16) +
- " but read " + fileId.toString(16));
- }
-
- // Type of file, data[6]
- let fileType = GsmPDUHelper.readHexOctet();
- if (fileType != TYPE_EF) {
- throw new Error("Unexpected file type " + fileType);
- }
-
- // Skip 1 byte RFU, data[7],
- // 3 bytes Access conditions, data[8] data[9] data[10],
- // 1 byte File status, data[11],
- // 1 byte Length of the following data, data[12].
- Buf.seekIncoming(((RESPONSE_DATA_STRUCTURE - RESPONSE_DATA_FILE_TYPE - 1) *
- Buf.PDU_HEX_OCTET_SIZE));
-
- // Read Structure of EF, data[13]
- let efStructure = GsmPDUHelper.readHexOctet();
- if (efStructure != options.structure) {
- throw new Error("Expected EF structure " + options.structure +
- " but read " + efStructure);
- }
-
- // Length of a record, data[14].
- // Only available for LINEAR_FIXED and CYCLIC.
- if (efStructure == EF_STRUCTURE_LINEAR_FIXED ||
- efStructure == EF_STRUCTURE_CYCLIC) {
- options.recordSize = GsmPDUHelper.readHexOctet();
- options.totalRecords = options.fileSize / options.recordSize;
- } else {
- Buf.seekIncoming(1 * Buf.PDU_HEX_OCTET_SIZE);
- }
- },
-
- /**
- * Process a ICC_COMMAND_READ_RECORD type command for REQUEST_SIM_IO.
- */
- processICCIOReadRecord: function(options) {
- if (options.callback) {
- options.callback(options);
- }
- },
-
- /**
- * Process a ICC_COMMAND_READ_BINARY type command for REQUEST_SIM_IO.
- */
- processICCIOReadBinary: function(options) {
- if (options.callback) {
- options.callback(options);
- }
- },
-
- /**
- * Process a ICC_COMMAND_UPDATE_RECORD type command for REQUEST_SIM_IO.
- */
- processICCIOUpdateRecord: function(options) {
- if (options.callback) {
- options.callback(options);
- }
- },
-};
-ICCIOHelperObject.prototype[ICC_COMMAND_SEEK] = null;
-ICCIOHelperObject.prototype[ICC_COMMAND_READ_BINARY] = function ICC_COMMAND_READ_BINARY(options) {
- this.processICCIOReadBinary(options);
-};
-ICCIOHelperObject.prototype[ICC_COMMAND_READ_RECORD] = function ICC_COMMAND_READ_RECORD(options) {
- this.processICCIOReadRecord(options);
-};
-ICCIOHelperObject.prototype[ICC_COMMAND_GET_RESPONSE] = function ICC_COMMAND_GET_RESPONSE(options) {
- this.processICCIOGetResponse(options);
-};
-ICCIOHelperObject.prototype[ICC_COMMAND_UPDATE_BINARY] = null;
-ICCIOHelperObject.prototype[ICC_COMMAND_UPDATE_RECORD] = function ICC_COMMAND_UPDATE_RECORD(options) {
- this.processICCIOUpdateRecord(options);
-};
-
-/**
- * Helper for ICC records.
- */
-function ICCRecordHelperObject(aContext) {
- this.context = aContext;
- // Cache the possible free record id for all files, use fileId as key.
- this._freeRecordIds = {};
-}
-ICCRecordHelperObject.prototype = {
- context: null,
-
- /**
- * Fetch ICC records.
- */
- fetchICCRecords: function() {
- switch (this.context.RIL.appType) {
- case CARD_APPTYPE_SIM:
- case CARD_APPTYPE_USIM:
- this.context.SimRecordHelper.fetchSimRecords();
- break;
- case CARD_APPTYPE_RUIM:
- this.context.RuimRecordHelper.fetchRuimRecords();
- break;
- }
- },
-
- /**
- * Read the ICCID.
- */
- readICCID: function() {
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- RIL.iccInfo.iccid =
- GsmPDUHelper.readSwappedNibbleBcdString(octetLen, true);
- // Consumes the remaining buffer if any.
- let unReadBuffer = this.context.Buf.getReadAvailable() -
- this.context.Buf.PDU_HEX_OCTET_SIZE;
- if (unReadBuffer > 0) {
- this.context.Buf.seekIncoming(unReadBuffer);
- }
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) this.context.debug("ICCID: " + RIL.iccInfo.iccid);
- if (RIL.iccInfo.iccid) {
- this.context.ICCUtilsHelper.handleICCInfoChange();
- RIL.reportStkServiceIsRunning();
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_ICCID,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read ICC ADN like EF, i.e. EF_ADN, EF_FDN.
- *
- * @param fileId EF id of the ADN, FDN or SDN.
- * @param extFileId EF id of the EXT.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readADNLike: function(fileId, extFileId, onsuccess, onerror) {
- let ICCIOHelper = this.context.ICCIOHelper;
-
- function callback(options) {
- let loadNextContactRecord = () => {
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- return;
- }
- if (DEBUG) {
- for (let i = 0; i < contacts.length; i++) {
- this.context.debug("contact [" + i + "] " +
- JSON.stringify(contacts[i]));
- }
- }
- if (onsuccess) {
- onsuccess(contacts);
- }
- };
-
- let contact =
- this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
- if (contact) {
- let record = {
- recordId: options.p1,
- alphaId: contact.alphaId,
- number: contact.number
- };
- contacts.push(record);
-
- if (extFileId && contact.extRecordNumber != 0xff) {
- this.readExtension(extFileId, contact.extRecordNumber, (number) => {
- if (number) {
- record.number += number;
- }
- loadNextContactRecord();
- }, () => loadNextContactRecord());
- return;
- }
- }
- loadNextContactRecord();
- }
-
- let contacts = [];
- ICCIOHelper.loadLinearFixedEF({fileId: fileId,
- callback: callback.bind(this),
- onerror: onerror});
- },
-
- /**
- * Update ICC ADN like EFs, like EF_ADN, EF_FDN.
- *
- * @param fileId EF id of the ADN or FDN.
- * @param extRecordNumber The record identifier of the EXT.
- * @param contact The contact will be updated. (Shall have recordId property)
- * @param pin2 PIN2 is required when updating ICC_EF_FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateADNLike: function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- let updatedContact;
- function dataWriter(recordSize) {
- updatedContact = this.context.ICCPDUHelper.writeAlphaIdDiallingNumber(recordSize,
- contact.alphaId,
- contact.number,
- extRecordNumber);
- }
-
- function callback(options) {
- if (onsuccess) {
- onsuccess(updatedContact);
- }
- }
-
- if (!contact || !contact.recordId) {
- if (onerror) onerror(GECKO_ERROR_INVALID_PARAMETER);
- return;
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: contact.recordId,
- dataWriter: dataWriter.bind(this),
- pin2: pin2,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Read USIM/RUIM Phonebook.
- *
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readPBR: function(onsuccess, onerror) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let ICCIOHelper = this.context.ICCIOHelper;
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- let RIL = this.context.RIL;
-
- function callback(options) {
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2, readLen = 0;
-
- let pbrTlvs = [];
- while (readLen < octetLen) {
- let tag = GsmPDUHelper.readHexOctet();
- if (tag == 0xff) {
- readLen++;
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- break;
- }
-
- let tlvLen = GsmPDUHelper.readHexOctet();
- let tlvs = ICCUtilsHelper.decodeSimTlvs(tlvLen);
- pbrTlvs.push({tag: tag,
- length: tlvLen,
- value: tlvs});
-
- readLen += tlvLen + 2; // +2 for tag and tlvLen
- }
- Buf.readStringDelimiter(strLen);
-
- if (pbrTlvs.length > 0) {
- let pbr = ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
- // EF_ADN is mandatory if and only if DF_PHONEBOOK is present.
- if (!pbr.adn) {
- if (onerror) onerror("Cannot access ADN.");
- return;
- }
- pbrs.push(pbr);
- }
-
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- } else {
- if (onsuccess) {
- RIL.iccInfoPrivate.pbrs = pbrs;
- onsuccess(pbrs);
- }
- }
- }
-
- if (RIL.iccInfoPrivate.pbrs) {
- onsuccess(RIL.iccInfoPrivate.pbrs);
- return;
- }
-
- let pbrs = [];
- ICCIOHelper.loadLinearFixedEF({fileId : ICC_EF_PBR,
- callback: callback.bind(this),
- onerror: onerror});
- },
-
- /**
- * Cache EF_IAP record size.
- */
- _iapRecordSize: null,
-
- /**
- * Read ICC EF_IAP. (Index Administration Phonebook)
- *
- * @see TS 131.102, clause 4.4.2.2
- *
- * @param fileId EF id of the IAP.
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readIAP: function(fileId, recordNumber, onsuccess, onerror) {
- function callback(options) {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- this._iapRecordSize = options.recordSize;
-
- let iap = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
-
- if (onsuccess) {
- onsuccess(iap);
- }
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- recordSize: this._iapRecordSize,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Update USIM/RUIM Phonebook EF_IAP.
- *
- * @see TS 131.102, clause 4.4.2.13
- *
- * @param fileId EF id of the IAP.
- * @param recordNumber The identifier of the record shall be updated.
- * @param iap The IAP value to be written.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateIAP: function(fileId, recordNumber, iap, onsuccess, onerror) {
- let dataWriter = function dataWriter(recordSize) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // Write String length
- let strLen = recordSize * 2;
- Buf.writeInt32(strLen);
-
- for (let i = 0; i < iap.length; i++) {
- GsmPDUHelper.writeHexOctet(iap[i]);
- }
-
- Buf.writeStringDelimiter(strLen);
- }.bind(this);
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: onsuccess,
- onerror: onerror
- });
- },
-
- /**
- * Cache EF_Email record size.
- */
- _emailRecordSize: null,
-
- /**
- * Read USIM/RUIM Phonebook EF_EMAIL.
- *
- * @see TS 131.102, clause 4.4.2.13
- *
- * @param fileId EF id of the EMAIL.
- * @param fileType The type of the EMAIL, one of the ICC_USIM_TYPE* constants.
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readEmail: function(fileId, fileType, recordNumber, onsuccess, onerror) {
- function callback(options) {
- let Buf = this.context.Buf;
- let ICCPDUHelper = this.context.ICCPDUHelper;
-
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- let email = null;
- this._emailRecordSize = options.recordSize;
-
- // Read contact's email
- //
- // | Byte | Description | Length | M/O
- // | 1 ~ X | E-mail Address | X | M
- // | X+1 | ADN file SFI | 1 | C
- // | X+2 | ADN file Record Identifier | 1 | C
- // Note: The fields marked as C above are mandatort if the file
- // is not type 1 (as specified in EF_PBR)
- if (fileType == ICC_USIM_TYPE1_TAG) {
- email = ICCPDUHelper.read8BitUnpackedToString(octetLen);
- } else {
- email = ICCPDUHelper.read8BitUnpackedToString(octetLen - 2);
-
- // Consumes the remaining buffer
- Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE); // For ADN SFI and Record Identifier
- }
-
- Buf.readStringDelimiter(strLen);
-
- if (onsuccess) {
- onsuccess(email);
- }
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- recordSize: this._emailRecordSize,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Update USIM/RUIM Phonebook EF_EMAIL.
- *
- * @see TS 131.102, clause 4.4.2.13
- *
- * @param pbr Phonebook Reference File.
- * @param recordNumber The identifier of the record shall be updated.
- * @param email The value to be written.
- * @param adnRecordId The record Id of ADN, only needed if the fileType of Email is TYPE2.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateEmail: function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
- let fileId = pbr[USIM_PBR_EMAIL].fileId;
- let fileType = pbr[USIM_PBR_EMAIL].fileType;
- let writtenEmail;
- let dataWriter = function dataWriter(recordSize) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let ICCPDUHelper = this.context.ICCPDUHelper;
-
- // Write String length
- let strLen = recordSize * 2;
- Buf.writeInt32(strLen);
-
- if (fileType == ICC_USIM_TYPE1_TAG) {
- writtenEmail = ICCPDUHelper.writeStringTo8BitUnpacked(recordSize, email);
- } else {
- writtenEmail = ICCPDUHelper.writeStringTo8BitUnpacked(recordSize - 2, email);
- GsmPDUHelper.writeHexOctet(pbr.adn.sfi || 0xff);
- GsmPDUHelper.writeHexOctet(adnRecordId);
- }
-
- Buf.writeStringDelimiter(strLen);
- }.bind(this);
-
- let callback = (options) => {
- if (onsuccess) {
- onsuccess(writtenEmail);
- }
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: callback,
- onerror: onerror
- });
- },
-
- /**
- * Cache EF_ANR record size.
- */
- _anrRecordSize: null,
-
- /**
- * Read USIM/RUIM Phonebook EF_ANR.
- *
- * @see TS 131.102, clause 4.4.2.9
- *
- * @param fileId EF id of the ANR.
- * @param fileType One of the ICC_USIM_TYPE* constants.
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readANR: function(fileId, fileType, recordNumber, onsuccess, onerror) {
- function callback(options) {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let number = null;
- this._anrRecordSize = options.recordSize;
-
- // Skip EF_AAS Record ID.
- Buf.seekIncoming(1 * Buf.PDU_HEX_OCTET_SIZE);
-
- number = this.context.ICCPDUHelper.readNumberWithLength();
-
- // Skip 2 unused octets, CCP and EXT1.
- Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
-
- // For Type 2 there are two extra octets.
- if (fileType == ICC_USIM_TYPE2_TAG) {
- // Skip 2 unused octets, ADN SFI and Record Identifier.
- Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
- }
-
- Buf.readStringDelimiter(strLen);
-
- if (onsuccess) {
- onsuccess(number);
- }
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- recordSize: this._anrRecordSize,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Update USIM/RUIM Phonebook EF_ANR.
- *
- * @see TS 131.102, clause 4.4.2.9
- *
- * @param pbr Phonebook Reference File.
- * @param recordNumber The identifier of the record shall be updated.
- * @param number The value to be written.
- * @param adnRecordId The record Id of ADN, only needed if the fileType of Email is TYPE2.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateANR: function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
- let fileId = pbr[USIM_PBR_ANR0].fileId;
- let fileType = pbr[USIM_PBR_ANR0].fileType;
- let writtenNumber;
- let dataWriter = function dataWriter(recordSize) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- // Write String length
- let strLen = recordSize * 2;
- Buf.writeInt32(strLen);
-
- // EF_AAS record Id. Unused for now.
- GsmPDUHelper.writeHexOctet(0xff);
-
- writtenNumber = this.context.ICCPDUHelper.writeNumberWithLength(number);
-
- // Write unused octets 0xff, CCP and EXT1.
- GsmPDUHelper.writeHexOctet(0xff);
- GsmPDUHelper.writeHexOctet(0xff);
-
- // For Type 2 there are two extra octets.
- if (fileType == ICC_USIM_TYPE2_TAG) {
- GsmPDUHelper.writeHexOctet(pbr.adn.sfi || 0xff);
- GsmPDUHelper.writeHexOctet(adnRecordId);
- }
-
- Buf.writeStringDelimiter(strLen);
- }.bind(this);
-
- let callback = (options) => {
- if (onsuccess) {
- onsuccess(writtenNumber);
- }
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: callback,
- onerror: onerror
- });
- },
-
- /**
- * Cache the possible free record id for all files.
- */
- _freeRecordIds: null,
-
- /**
- * Find free record id.
- *
- * @param fileId EF id.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- findFreeRecordId: function(fileId, onsuccess, onerror) {
- let ICCIOHelper = this.context.ICCIOHelper;
-
- function callback(options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- let readLen = 0;
-
- while (readLen < octetLen) {
- let octet = GsmPDUHelper.readHexOctet();
- readLen++;
- if (octet != 0xff) {
- break;
- }
- }
-
- let nextRecord = (options.p1 % options.totalRecords) + 1;
-
- if (readLen == octetLen) {
- // Find free record, assume next record is probably free.
- this._freeRecordIds[fileId] = nextRecord;
- if (onsuccess) {
- onsuccess(options.p1);
- }
- return;
- } else {
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- }
-
- Buf.readStringDelimiter(strLen);
-
- if (nextRecord !== recordNumber) {
- options.p1 = nextRecord;
- this.context.RIL.iccIO(options);
- } else {
- // No free record found.
- delete this._freeRecordIds[fileId];
- if (DEBUG) {
- this.context.debug(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- }
- onerror(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- }
- }
-
- // Start searching free records from the possible one.
- let recordNumber = this._freeRecordIds[fileId] || 1;
- ICCIOHelper.loadLinearFixedEF({fileId: fileId,
- recordNumber: recordNumber,
- callback: callback.bind(this),
- onerror: onerror});
- },
-
- /**
- * Read Extension Number from TS 151.011 clause 10.5.10, TS 31.102, clause 4.4.2.4
- *
- * @param fileId EF Extension id
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readExtension: function(fileId, recordNumber, onsuccess, onerror) {
- let callback = (options) => {
- let Buf = this.context.Buf;
- let length = Buf.readInt32();
- let recordType = this.context.GsmPDUHelper.readHexOctet();
- let number = "";
-
- // TS 31.102, clause 4.4.2.4 EFEXT1
- // Case 1, Extension1 record is additional data
- if (recordType & 0x02) {
- let numLen = this.context.GsmPDUHelper.readHexOctet();
- if (numLen != 0xff) {
- if (numLen > EXT_MAX_BCD_NUMBER_BYTES) {
- if (DEBUG) {
- this.context.debug(
- "Error: invalid length of BCD number/SSC contents - " + numLen);
- }
- // +1 to skip Identifier
- Buf.seekIncoming((EXT_MAX_BCD_NUMBER_BYTES + 1) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(length);
- onerror();
- return;
- }
-
- number = this.context.GsmPDUHelper.readSwappedNibbleExtendedBcdString(numLen);
- if (DEBUG) this.context.debug("Contact Extension Number: "+ number);
- Buf.seekIncoming((EXT_MAX_BCD_NUMBER_BYTES - numLen) * Buf.PDU_HEX_OCTET_SIZE);
- } else {
- Buf.seekIncoming(EXT_MAX_BCD_NUMBER_BYTES * Buf.PDU_HEX_OCTET_SIZE);
- }
- } else {
- // Don't support Case 2, Extension1 record is Called Party Subaddress.
- // +1 skip numLen
- Buf.seekIncoming((EXT_MAX_BCD_NUMBER_BYTES + 1) * Buf.PDU_HEX_OCTET_SIZE);
- }
-
- // Skip Identifier
- Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(length);
- onsuccess(number);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- callback: callback,
- onerror: onerror
- });
- },
-
- /**
- * Update Extension.
- *
- * @param fileId EF id of the EXT.
- * @param recordNumber The number of the record shall be updated.
- * @param number Dialling Number to be written.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateExtension: function(fileId, recordNumber, number, onsuccess, onerror) {
- let dataWriter = (recordSize) => {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- // Write String length
- let strLen = recordSize * 2;
- let Buf = this.context.Buf;
- Buf.writeInt32(strLen);
-
- // We don't support extension chain.
- if (number.length > EXT_MAX_NUMBER_DIGITS) {
- number = number.substring(0, EXT_MAX_NUMBER_DIGITS);
- }
-
- let numLen = Math.ceil(number.length / 2);
- // Write Extension record
- GsmPDUHelper.writeHexOctet(0x02);
- GsmPDUHelper.writeHexOctet(numLen);
- GsmPDUHelper.writeSwappedNibbleBCD(number);
- // Write trailing 0xff of Extension data.
- for (let i = 0; i < EXT_MAX_BCD_NUMBER_BYTES - numLen; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- // Write trailing 0xff for Identifier.
- GsmPDUHelper.writeHexOctet(0xff);
- Buf.writeStringDelimiter(strLen);
- };
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: onsuccess,
- onerror: onerror
- });
- },
-
- /**
- * Clean an EF record.
- *
- * @param fileId EF id.
- * @param recordNumber The number of the record shall be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- cleanEFRecord: function(fileId, recordNumber, onsuccess, onerror) {
- let dataWriter = (recordSize) => {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let Buf = this.context.Buf;
- // Write String length
- let strLen = recordSize * 2;
-
- Buf.writeInt32(strLen);
- // Write record to 0xff
- for (let i = 0; i < recordSize; i++) {
- GsmPDUHelper.writeHexOctet(0xff);
- }
- Buf.writeStringDelimiter(strLen);
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- dataWriter: dataWriter,
- callback: onsuccess,
- onerror: onerror
- });
- },
-
- /**
- * Get ADNLike extension record number.
- *
- * @param fileId EF id of the ADN or FDN.
- * @param recordNumber EF record id of the ADN or FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- getADNLikeExtensionRecordNumber: function(fileId, recordNumber, onsuccess, onerror) {
- let callback = (options) => {
- let Buf = this.context.Buf;
- let length = Buf.readInt32();
-
- // Skip alphaLen, numLen, BCD Number, CCP octets.
- Buf.seekIncoming((options.recordSize -1) * Buf.PDU_HEX_OCTET_SIZE);
-
- let extRecordNumber = this.context.GsmPDUHelper.readHexOctet();
- Buf.readStringDelimiter(length);
-
- onsuccess(extRecordNumber);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: fileId,
- recordNumber: recordNumber,
- callback: callback,
- onerror: onerror
- });
- },
-};
-
-/**
- * Helper for (U)SIM Records.
- */
-function SimRecordHelperObject(aContext) {
- this.context = aContext;
-}
-SimRecordHelperObject.prototype = {
- context: null,
-
- /**
- * Fetch (U)SIM records.
- */
- fetchSimRecords: function() {
- this.context.RIL.getIMSI();
- this.readAD();
- // CPHS was widely introduced in Europe during GSM(2G) era to provide easier
- // access to carrier's core service like voicemail, call forwarding, manual
- // PLMN selection, and etc.
- // Addition EF like EF_CPHS_MBN, EF_CPHS_CPHS_CFF, EF_CPHS_VWI, etc are
- // introduced to support these feature.
- // In USIM, the replancement of these EFs are provided. (EF_MBDN, EF_MWIS, ...)
- // However, some carriers in Europe still rely on these EFs.
- this.readCphsInfo(() => this.readSST(),
- (aErrorMsg) => {
- this.context.debug("Failed to read CPHS_INFO: " + aErrorMsg);
- this.readSST();
- });
- },
-
- /**
- * Read EF_phase.
- * This EF is only available in SIM.
- */
- readSimPhase: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let phase = GsmPDUHelper.readHexOctet();
- // If EF_phase is coded '03' or greater, an ME supporting STK shall
- // perform the PROFILE DOWNLOAD procedure.
- if (RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD &&
- phase >= ICC_PHASE_2_PROFILE_DOWNLOAD_REQUIRED) {
- this.context.RIL.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
- }
-
- Buf.readStringDelimiter(strLen);
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_PHASE,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read the MSISDN from the (U)SIM.
- */
- readMSISDN: function() {
- function callback(options) {
- let RIL = this.context.RIL;
-
- let contact =
- this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
- if (!contact ||
- (RIL.iccInfo.msisdn !== undefined &&
- RIL.iccInfo.msisdn === contact.number)) {
- return;
- }
- RIL.iccInfo.msisdn = contact.number;
- if (DEBUG) this.context.debug("MSISDN: " + RIL.iccInfo.msisdn);
- this.context.ICCUtilsHelper.handleICCInfoChange();
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_MSISDN,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read the AD (Administrative Data) from the (U)SIM.
- */
- readAD: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let ad = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) {
- let str = "";
- for (let i = 0; i < ad.length; i++) {
- str += ad[i] + ", ";
- }
- this.context.debug("AD: " + str);
- }
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- let RIL = this.context.RIL;
- // TS 31.102, clause 4.2.18 EFAD
- let mncLength = 0;
- if (ad && ad[3]) {
- mncLength = ad[3] & 0x0f;
- if (mncLength != 0x02 && mncLength != 0x03) {
- mncLength = 0;
- }
- }
- // The 4th byte of the response is the length of MNC.
- let mccMnc = ICCUtilsHelper.parseMccMncFromImsi(RIL.iccInfoPrivate.imsi,
- mncLength);
- if (mccMnc) {
- RIL.iccInfo.mcc = mccMnc.mcc;
- RIL.iccInfo.mnc = mccMnc.mnc;
- ICCUtilsHelper.handleICCInfoChange();
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_AD,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read the SPN (Service Provider Name) from the (U)SIM.
- */
- readSPN: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let spnDisplayCondition = this.context.GsmPDUHelper.readHexOctet();
- // Minus 1 because the first octet is used to store display condition.
- let spn = this.context.ICCPDUHelper.readAlphaIdentifier(octetLen - 1);
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) {
- this.context.debug("SPN: spn = " + spn +
- ", spnDisplayCondition = " + spnDisplayCondition);
- }
-
- let RIL = this.context.RIL;
- RIL.iccInfoPrivate.spnDisplayCondition = spnDisplayCondition;
- RIL.iccInfo.spn = spn;
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- ICCUtilsHelper.updateDisplayCondition();
- ICCUtilsHelper.handleICCInfoChange();
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_SPN,
- callback: callback.bind(this)
- });
- },
-
- readIMG: function(recordNumber, onsuccess, onerror) {
- function callback(options) {
- let RIL = this.context.RIL;
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
-
- let numInstances = GsmPDUHelper.readHexOctet();
-
- // Data length is defined as 9n+1 or 9n+2. See TS 31.102, sub-clause
- // 4.6.1.1. However, it's likely to have padding appended so we have a
- // rather loose check.
- if (octetLen < (9 * numInstances + 1)) {
- Buf.seekIncoming((octetLen - 1) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
- if (onerror) {
- onerror();
- }
- return;
- }
-
- let imgDescriptors = [];
- for (let i = 0; i < numInstances; i++) {
- imgDescriptors[i] = {
- width: GsmPDUHelper.readHexOctet(),
- height: GsmPDUHelper.readHexOctet(),
- codingScheme: GsmPDUHelper.readHexOctet(),
- fileId: (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet(),
- offset: (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet(),
- dataLen: (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet()
- };
- }
- Buf.seekIncoming((octetLen - 9 * numInstances - 1) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
-
- let instances = [];
- let currentInstance = 0;
- let readNextInstance = (function(img) {
- instances[currentInstance] = img;
- currentInstance++;
-
- if (currentInstance < numInstances) {
- let imgDescriptor = imgDescriptors[currentInstance];
- this.readIIDF(imgDescriptor.fileId,
- imgDescriptor.offset,
- imgDescriptor.dataLen,
- imgDescriptor.codingScheme,
- readNextInstance,
- onerror);
- } else {
- if (onsuccess) {
- onsuccess(instances);
- }
- }
- }).bind(this);
-
- this.readIIDF(imgDescriptors[0].fileId,
- imgDescriptors[0].offset,
- imgDescriptors[0].dataLen,
- imgDescriptors[0].codingScheme,
- readNextInstance,
- onerror);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_IMG,
- recordNumber: recordNumber,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- readIIDF: function(fileId, offset, dataLen, codingScheme, onsuccess, onerror) {
- // Valid fileId is '4FXX', see TS 31.102, clause 4.6.1.2.
- if ((fileId >> 8) != 0x4F) {
- if (onerror) {
- onerror();
- }
- return;
- }
-
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
-
- if (octetLen < offset + dataLen) {
- // Data length is not enough. See TS 31.102, clause 4.6.1.1, the
- // paragraph "Bytes 8 and 9: Length of Image Instance Data."
- Buf.seekIncoming(octetLen * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
- if (onerror) {
- onerror();
- }
- return;
- }
-
- Buf.seekIncoming(offset * Buf.PDU_HEX_OCTET_SIZE);
-
- let rawData = {
- width: GsmPDUHelper.readHexOctet(),
- height: GsmPDUHelper.readHexOctet(),
- codingScheme: codingScheme
- };
-
- switch (codingScheme) {
- case ICC_IMG_CODING_SCHEME_BASIC:
- rawData.body = GsmPDUHelper.readHexOctetArray(
- dataLen - ICC_IMG_HEADER_SIZE_BASIC);
- Buf.seekIncoming((octetLen - offset - dataLen) * Buf.PDU_HEX_OCTET_SIZE);
- break;
-
- case ICC_IMG_CODING_SCHEME_COLOR:
- case ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY:
- rawData.bitsPerImgPoint = GsmPDUHelper.readHexOctet();
- let num = GsmPDUHelper.readHexOctet();
- // The value 0 shall be interpreted as 256. See TS 31.102, Annex B.2.
- rawData.numOfClutEntries = (num === 0) ? 0x100 : num;
- rawData.clutOffset = (GsmPDUHelper.readHexOctet() << 8) |
- GsmPDUHelper.readHexOctet();
- rawData.body = GsmPDUHelper.readHexOctetArray(
- dataLen - ICC_IMG_HEADER_SIZE_COLOR);
-
- Buf.seekIncoming((rawData.clutOffset - offset - dataLen) *
- Buf.PDU_HEX_OCTET_SIZE);
- let clut = GsmPDUHelper.readHexOctetArray(rawData.numOfClutEntries *
- ICC_CLUT_ENTRY_SIZE);
-
- rawData.clut = clut;
- }
-
- Buf.readStringDelimiter(strLen);
-
- if (onsuccess) {
- onsuccess(rawData);
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: fileId,
- pathId: this.context.ICCFileHelper.getEFPath(ICC_EF_IMG),
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Read the (U)SIM Service Table from the (U)SIM.
- */
- readSST: function() {
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let sst = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
- RIL.iccInfoPrivate.sst = sst;
- if (DEBUG) {
- let str = "";
- for (let i = 0; i < sst.length; i++) {
- str += sst[i] + ", ";
- }
- this.context.debug("SST: " + str);
- }
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- if (ICCUtilsHelper.isICCServiceAvailable("MSISDN")) {
- if (DEBUG) this.context.debug("MSISDN: MSISDN is available");
- this.readMSISDN();
- } else {
- if (DEBUG) this.context.debug("MSISDN: MSISDN service is not available");
- }
-
- // Fetch SPN and PLMN list, if some of them are available.
- if (ICCUtilsHelper.isICCServiceAvailable("SPN")) {
- if (DEBUG) this.context.debug("SPN: SPN is available");
- this.readSPN();
- } else {
- if (DEBUG) this.context.debug("SPN: SPN service is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("MDN")) {
- if (DEBUG) this.context.debug("MDN: MDN available.");
- this.readMBDN();
- } else {
- if (DEBUG) this.context.debug("MDN: MDN service is not available");
-
- if (ICCUtilsHelper.isCphsServiceAvailable("MBN")) {
- // read CPHS_MBN in advance if MBDN is not available.
- this.readCphsMBN();
- } else {
- if (DEBUG) this.context.debug("CPHS_MBN: CPHS_MBN service is not available");
- }
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("MWIS")) {
- if (DEBUG) this.context.debug("MWIS: MWIS is available");
- this.readMWIS();
- } else {
- if (DEBUG) this.context.debug("MWIS: MWIS is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("SPDI")) {
- if (DEBUG) this.context.debug("SPDI: SPDI available.");
- this.readSPDI();
- } else {
- if (DEBUG) this.context.debug("SPDI: SPDI service is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("PNN")) {
- if (DEBUG) this.context.debug("PNN: PNN is available");
- this.readPNN();
- } else {
- if (DEBUG) this.context.debug("PNN: PNN is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("OPL")) {
- if (DEBUG) this.context.debug("OPL: OPL is available");
- this.readOPL();
- } else {
- if (DEBUG) this.context.debug("OPL: OPL is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("GID1")) {
- if (DEBUG) this.context.debug("GID1: GID1 is available");
- this.readGID1();
- } else {
- if (DEBUG) this.context.debug("GID1: GID1 is not available");
- }
-
- if (ICCUtilsHelper.isICCServiceAvailable("CBMI")) {
- this.readCBMI();
- } else {
- RIL.cellBroadcastConfigs.CBMI = null;
- }
- if (ICCUtilsHelper.isICCServiceAvailable("DATA_DOWNLOAD_SMS_CB")) {
- this.readCBMID();
- } else {
- RIL.cellBroadcastConfigs.CBMID = null;
- }
- if (ICCUtilsHelper.isICCServiceAvailable("CBMIR")) {
- this.readCBMIR();
- } else {
- RIL.cellBroadcastConfigs.CBMIR = null;
- }
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- // ICC_EF_UST has the same value with ICC_EF_SST.
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_SST,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read (U)SIM MBDN. (Mailbox Dialling Number)
- *
- * @see TS 131.102, clause 4.2.60
- */
- readMBDN: function() {
- function callback(options) {
- let RIL = this.context.RIL;
- let contact =
- this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
- if ((!contact ||
- ((!contact.alphaId || contact.alphaId == "") &&
- (!contact.number || contact.number == ""))) &&
- this.context.ICCUtilsHelper.isCphsServiceAvailable("MBN")) {
- // read CPHS_MBN in advance if MBDN is invalid or empty.
- this.readCphsMBN();
- return;
- }
-
- if (!contact ||
- (RIL.iccInfoPrivate.mbdn !== undefined &&
- RIL.iccInfoPrivate.mbdn === contact.number)) {
- return;
- }
- RIL.iccInfoPrivate.mbdn = contact.number;
- if (DEBUG) {
- this.context.debug("MBDN, alphaId=" + contact.alphaId +
- " number=" + contact.number);
- }
- contact.rilMessageType = "iccmbdn";
- RIL.sendChromeMessage(contact);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_MBDN,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read ICC MWIS. (Message Waiting Indication Status)
- *
- * @see TS 31.102, clause 4.2.63 for USIM and TS 51.011, clause 10.3.45 for SIM.
- */
- readMWIS: function() {
- function callback(options) {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let mwis = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
- if (!mwis) {
- return;
- }
- RIL.iccInfoPrivate.mwis = mwis; //Keep raw MWIS for updateMWIS()
-
- let mwi = {};
- // b8 b7 B6 b5 b4 b3 b2 b1 4.2.63, TS 31.102 version 11.6.0
- // | | | | | | | |__ Voicemail
- // | | | | | | |_____ Fax
- // | | | | | |________ Electronic Mail
- // | | | | |___________ Other
- // | | | |______________ Videomail
- // |__|__|_________________ RFU
- mwi.active = ((mwis[0] & 0x01) != 0);
-
- if (mwi.active) {
- // In TS 23.040 msgCount is in the range from 0 to 255.
- // The value 255 shall be taken to mean 255 or greater.
- //
- // However, There is no definition about 0 when MWI is active.
- //
- // Normally, when mwi is active, the msgCount must be larger than 0.
- // Refer to other reference phone,
- // 0 is usually treated as UNKNOWN for storing 2nd level MWI status (DCS).
- mwi.msgCount = (mwis[1] === 0) ? GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN
- : mwis[1];
- } else {
- mwi.msgCount = 0;
- }
-
- RIL.sendChromeMessage({ rilMessageType: "iccmwis",
- mwi: mwi });
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_MWIS,
- recordNumber: 1, // Get 1st Subscriber Profile.
- callback: callback.bind(this)
- });
- },
-
- /**
- * Update ICC MWIS. (Message Waiting Indication Status)
- *
- * @see TS 31.102, clause 4.2.63 for USIM and TS 51.011, clause 10.3.45 for SIM.
- */
- updateMWIS: function(mwi) {
- let RIL = this.context.RIL;
- if (!RIL.iccInfoPrivate.mwis) {
- return;
- }
-
- function dataWriter(recordSize) {
- let mwis = RIL.iccInfoPrivate.mwis;
-
- let msgCount =
- (mwi.msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : mwi.msgCount;
-
- [mwis[0], mwis[1]] = (mwi.active) ? [(mwis[0] | 0x01), msgCount]
- : [(mwis[0] & 0xFE), 0];
-
- let strLen = recordSize * 2;
- let Buf = this.context.Buf;
- Buf.writeInt32(strLen);
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- for (let i = 0; i < mwis.length; i++) {
- GsmPDUHelper.writeHexOctet(mwis[i]);
- }
-
- Buf.writeStringDelimiter(strLen);
- }
-
- this.context.ICCIOHelper.updateLinearFixedEF({
- fileId: ICC_EF_MWIS,
- recordNumber: 1, // Update 1st Subscriber Profile.
- dataWriter: dataWriter.bind(this)
- });
- },
-
- /**
- * Read the SPDI (Service Provider Display Information) from the (U)SIM.
- *
- * See TS 131.102 section 4.2.66 for USIM and TS 51.011 section 10.3.50
- * for SIM.
- */
- readSPDI: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- let readLen = 0;
- let endLoop = false;
-
- let RIL = this.context.RIL;
- RIL.iccInfoPrivate.SPDI = null;
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- while ((readLen < octetLen) && !endLoop) {
- let tlvTag = GsmPDUHelper.readHexOctet();
- let tlvLen = GsmPDUHelper.readHexOctet();
- readLen += 2; // For tag and length fields.
- switch (tlvTag) {
- case SPDI_TAG_SPDI:
- // The value part itself is a TLV.
- continue;
- case SPDI_TAG_PLMN_LIST:
- // This PLMN list is what we want.
- RIL.iccInfoPrivate.SPDI = this.readPLMNEntries(tlvLen / 3);
- readLen += tlvLen;
- endLoop = true;
- break;
- default:
- // We don't care about its content if its tag is not SPDI nor
- // PLMN_LIST.
- endLoop = true;
- break;
- }
- }
-
- // Consume unread octets.
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) {
- this.context.debug("SPDI: " + JSON.stringify(RIL.iccInfoPrivate.SPDI));
- }
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- if (ICCUtilsHelper.updateDisplayCondition()) {
- ICCUtilsHelper.handleICCInfoChange();
- }
- }
-
- // PLMN List is Servive 51 in USIM, EF_SPDI
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_SPDI,
- callback: callback.bind(this)
- });
- },
-
- _readCbmiHelper: function(which) {
- let RIL = this.context.RIL;
-
- function callback() {
- let Buf = this.context.Buf;
- let strLength = Buf.readInt32();
-
- // Each Message Identifier takes two octets and each octet is encoded
- // into two chars.
- let numIds = strLength / 4, list = null;
- if (numIds) {
- list = [];
- let GsmPDUHelper = this.context.GsmPDUHelper;
- for (let i = 0, id; i < numIds; i++) {
- id = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
- // `Unused entries shall be set to 'FF FF'.`
- if (id != 0xFFFF) {
- list.push(id);
- list.push(id + 1);
- }
- }
- }
- if (DEBUG) {
- this.context.debug(which + ": " + JSON.stringify(list));
- }
-
- Buf.readStringDelimiter(strLength);
-
- RIL.cellBroadcastConfigs[which] = list;
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- function onerror() {
- RIL.cellBroadcastConfigs[which] = null;
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- let fileId = GLOBAL["ICC_EF_" + which];
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: fileId,
- callback: callback.bind(this),
- onerror: onerror.bind(this)
- });
- },
-
- /**
- * Read EFcbmi (Cell Broadcast Message Identifier selection)
- *
- * @see 3GPP TS 31.102 v110.02.0 section 4.2.14 EFcbmi
- * @see 3GPP TS 51.011 v5.0.0 section 10.3.13 EFcbmi
- */
- readCBMI: function() {
- this._readCbmiHelper("CBMI");
- },
-
- /**
- * Read EFcbmid (Cell Broadcast Message Identifier for Data Download)
- *
- * @see 3GPP TS 31.102 v110.02.0 section 4.2.20 EFcbmid
- * @see 3GPP TS 51.011 v5.0.0 section 10.3.26 EFcbmid
- */
- readCBMID: function() {
- this._readCbmiHelper("CBMID");
- },
-
- /**
- * Read EFcbmir (Cell Broadcast Message Identifier Range selection)
- *
- * @see 3GPP TS 31.102 v110.02.0 section 4.2.22 EFcbmir
- * @see 3GPP TS 51.011 v5.0.0 section 10.3.28 EFcbmir
- */
- readCBMIR: function() {
- let RIL = this.context.RIL;
-
- function callback() {
- let Buf = this.context.Buf;
- let strLength = Buf.readInt32();
-
- // Each Message Identifier range takes four octets and each octet is
- // encoded into two chars.
- let numIds = strLength / 8, list = null;
- if (numIds) {
- list = [];
- let GsmPDUHelper = this.context.GsmPDUHelper;
- for (let i = 0, from, to; i < numIds; i++) {
- // `Bytes one and two of each range identifier equal the lower value
- // of a cell broadcast range, bytes three and four equal the upper
- // value of a cell broadcast range.`
- from = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
- to = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
- // `Unused entries shall be set to 'FF FF'.`
- if ((from != 0xFFFF) && (to != 0xFFFF)) {
- list.push(from);
- list.push(to + 1);
- }
- }
- }
- if (DEBUG) {
- this.context.debug("CBMIR: " + JSON.stringify(list));
- }
-
- Buf.readStringDelimiter(strLength);
-
- RIL.cellBroadcastConfigs.CBMIR = list;
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- function onerror() {
- RIL.cellBroadcastConfigs.CBMIR = null;
- RIL._mergeAllCellBroadcastConfigs();
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CBMIR,
- callback: callback.bind(this),
- onerror: onerror.bind(this)
- });
- },
-
- /**
- * Read OPL (Operator PLMN List) from (U)SIM.
- *
- * See 3GPP TS 31.102 Sec. 4.2.59 for USIM
- * 3GPP TS 51.011 Sec. 10.3.42 for SIM.
- */
- readOPL: function() {
- let ICCIOHelper = this.context.ICCIOHelper;
- let opl = [];
- function callback(options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let strLen = Buf.readInt32();
- // The first 7 bytes are LAI (for UMTS) and the format of LAI is defined
- // in 3GPP TS 23.003, Sec 4.1
- // +-------------+---------+
- // | Octet 1 - 3 | MCC/MNC |
- // +-------------+---------+
- // | Octet 4 - 7 | LAC |
- // +-------------+---------+
- let mccMnc = [GsmPDUHelper.readHexOctet(),
- GsmPDUHelper.readHexOctet(),
- GsmPDUHelper.readHexOctet()];
- if (mccMnc[0] != 0xFF || mccMnc[1] != 0xFF || mccMnc[2] != 0xFF) {
- let oplElement = {};
- let semiOctets = [];
- for (let i = 0; i < mccMnc.length; i++) {
- semiOctets.push((mccMnc[i] & 0xf0) >> 4);
- semiOctets.push(mccMnc[i] & 0x0f);
- }
- let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
- semiOctets[5], semiOctets[4], semiOctets[2]];
- let buf = "";
- for (let i = 0; i < reformat.length; i++) {
- if (reformat[i] != 0xF) {
- buf += GsmPDUHelper.semiOctetToExtendedBcdChar(reformat[i]);
- }
- if (i === 2) {
- // 0-2: MCC
- oplElement.mcc = buf;
- buf = "";
- } else if (i === 5) {
- // 3-5: MNC
- oplElement.mnc = buf;
- }
- }
- // LAC/TAC
- oplElement.lacTacStart =
- (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- oplElement.lacTacEnd =
- (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
- // PLMN Network Name Record Identifier
- oplElement.pnnRecordId = GsmPDUHelper.readHexOctet();
- if (DEBUG) {
- this.context.debug("OPL: [" + (opl.length + 1) + "]: " +
- JSON.stringify(oplElement));
- }
- opl.push(oplElement);
- } else {
- Buf.seekIncoming(5 * Buf.PDU_HEX_OCTET_SIZE);
- }
- Buf.readStringDelimiter(strLen);
-
- let RIL = this.context.RIL;
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- } else {
- RIL.iccInfoPrivate.OPL = opl;
- RIL.overrideICCNetworkName();
- }
- }
-
- ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_OPL,
- callback: callback.bind(this)});
- },
-
- /**
- * Read PNN (PLMN Network Name) from (U)SIM.
- *
- * See 3GPP TS 31.102 Sec. 4.2.58 for USIM
- * 3GPP TS 51.011 Sec. 10.3.41 for SIM.
- */
- readPNN: function() {
- let ICCIOHelper = this.context.ICCIOHelper;
- function callback(options) {
- let pnnElement;
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
- let readLen = 0;
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- while (readLen < octetLen) {
- let tlvTag = GsmPDUHelper.readHexOctet();
-
- if (tlvTag == 0xFF) {
- // Unused byte
- readLen++;
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- break;
- }
-
- // Needs this check to avoid initializing twice.
- pnnElement = pnnElement || {};
-
- let tlvLen = GsmPDUHelper.readHexOctet();
-
- switch (tlvTag) {
- case PNN_IEI_FULL_NETWORK_NAME:
- pnnElement.fullName = GsmPDUHelper.readNetworkName(tlvLen);
- break;
- case PNN_IEI_SHORT_NETWORK_NAME:
- pnnElement.shortName = GsmPDUHelper.readNetworkName(tlvLen);
- break;
- default:
- Buf.seekIncoming(tlvLen * Buf.PDU_HEX_OCTET_SIZE);
- break;
- }
-
- readLen += (tlvLen + 2); // +2 for tlvTag and tlvLen
- }
- Buf.readStringDelimiter(strLen);
-
- pnn.push(pnnElement);
-
- let RIL = this.context.RIL;
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- } else {
- if (DEBUG) {
- for (let i = 0; i < pnn.length; i++) {
- this.context.debug("PNN: [" + i + "]: " + JSON.stringify(pnn[i]));
- }
- }
- RIL.iccInfoPrivate.PNN = pnn;
- RIL.overrideICCNetworkName();
- }
- }
-
- let pnn = [];
- ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_PNN,
- callback: callback.bind(this)});
- },
-
- /**
- * Read the list of PLMN (Public Land Mobile Network) entries
- * We cannot directly rely on readSwappedNibbleBcdToString(),
- * since it will no correctly handle some corner-cases that are
- * not a problem in our case (0xFF 0xFF 0xFF).
- *
- * @param length The number of PLMN records.
- * @return An array of string corresponding to the PLMNs.
- */
- readPLMNEntries: function(length) {
- let plmnList = [];
- // Each PLMN entry has 3 bytes.
- if (DEBUG) {
- this.context.debug("PLMN entries length = " + length);
- }
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let index = 0;
- while (index < length) {
- // Unused entries will be 0xFFFFFF, according to EF_SPDI
- // specs (TS 131 102, section 4.2.66)
- try {
- let plmn = [GsmPDUHelper.readHexOctet(),
- GsmPDUHelper.readHexOctet(),
- GsmPDUHelper.readHexOctet()];
- if (DEBUG) {
- this.context.debug("Reading PLMN entry: [" + index + "]: '" + plmn + "'");
- }
- if (plmn[0] != 0xFF &&
- plmn[1] != 0xFF &&
- plmn[2] != 0xFF) {
- let semiOctets = [];
- for (let idx = 0; idx < plmn.length; idx++) {
- semiOctets.push((plmn[idx] & 0xF0) >> 4);
- semiOctets.push(plmn[idx] & 0x0F);
- }
-
- // According to TS 24.301, 9.9.3.12, the semi octets is arranged
- // in format:
- // Byte 1: MCC[2] | MCC[1]
- // Byte 2: MNC[3] | MCC[3]
- // Byte 3: MNC[2] | MNC[1]
- // Therefore, we need to rearrange them.
- let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
- semiOctets[5], semiOctets[4], semiOctets[2]];
- let buf = "";
- let plmnEntry = {};
- for (let i = 0; i < reformat.length; i++) {
- if (reformat[i] != 0xF) {
- buf += GsmPDUHelper.semiOctetToExtendedBcdChar(reformat[i]);
- }
- if (i === 2) {
- // 0-2: MCC
- plmnEntry.mcc = buf;
- buf = "";
- } else if (i === 5) {
- // 3-5: MNC
- plmnEntry.mnc = buf;
- }
- }
- if (DEBUG) {
- this.context.debug("PLMN = " + plmnEntry.mcc + ", " + plmnEntry.mnc);
- }
- plmnList.push(plmnEntry);
- }
- } catch (e) {
- if (DEBUG) {
- this.context.debug("PLMN entry " + index + " is invalid.");
- }
- break;
- }
- index ++;
- }
- return plmnList;
- },
-
- /**
- * Read the SMS from the ICC.
- *
- * @param recordNumber The number of the record shall be loaded.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readSMS: function(recordNumber, onsuccess, onerror) {
- function callback(options) {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
-
- // TS 51.011, 10.5.3 EF_SMS
- // b3 b2 b1
- // 0 0 1 message received by MS from network; message read
- // 0 1 1 message received by MS from network; message to be read
- // 1 1 1 MS originating message; message to be sent
- // 1 0 1 MS originating message; message sent to the network:
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let status = GsmPDUHelper.readHexOctet();
-
- let message = GsmPDUHelper.readMessage();
- message.simStatus = status;
-
- // Consumes the remaining buffer
- Buf.seekIncoming(Buf.getReadAvailable() - Buf.PDU_HEX_OCTET_SIZE);
-
- Buf.readStringDelimiter(strLen);
-
- if (message) {
- onsuccess(message);
- } else {
- onerror("Failed to decode SMS on SIM #" + recordNumber);
- }
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_SMS,
- recordNumber: recordNumber,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- readGID1: function() {
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- RIL.iccInfoPrivate.gid1 = Buf.readString();
- if (DEBUG) {
- this.context.debug("GID1: " + RIL.iccInfoPrivate.gid1);
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_GID1,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Read CPHS Phase & Service Table from CPHS Info.
- *
- * @See B.3.1.1 CPHS Information in CPHS Phase 2.
- *
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readCphsInfo: function(onsuccess, onerror) {
- function callback() {
- try {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- let octetLen = strLen / 2;
- let cphsInfo = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
- Buf.readStringDelimiter(strLen);
- if (DEBUG) {
- let str = "";
- for (let i = 0; i < cphsInfo.length; i++) {
- str += cphsInfo[i] + ", ";
- }
- this.context.debug("CPHS INFO: " + str);
- }
-
- /**
- * CPHS INFORMATION
- *
- * Byte 1: CPHS Phase
- * 01 phase 1
- * 02 phase 2
- * etc.
- *
- * Byte 2: CPHS Service Table
- * +----+----+----+----+----+----+----+----+
- * | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 |
- * +----+----+----+----+----+----+----+----+
- * | ONSF | MBN | SST | CSP |
- * | Phase 2 | ALL | Phase 1 | All |
- * +----+----+----+----+----+----+----+----+
- *
- * Byte 3: CPHS Service Table continued
- * +----+----+----+----+----+----+----+----+
- * | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 |
- * +----+----+----+----+----+----+----+----+
- * | RFU | RFU | RFU | INFO_NUM|
- * | | | | Phase 2 |
- * +----+----+----+----+----+----+----+----+
- */
- let cphsPhase = cphsInfo[0];
- if (cphsPhase == 1) {
- // Clear 'Phase 2 only' services.
- cphsInfo[1] &= 0x3F;
- // We don't know whether Byte 3 is available in CPHS phase 1 or not.
- // Add boundary check before accessing it.
- if (cphsInfo.length > 2) {
- cphsInfo[2] = 0x00;
- }
- } else if (cphsPhase == 2) {
- // Clear 'Phase 1 only' services.
- cphsInfo[1] &= 0xF3;
- } else {
- throw new Error("Unknown CPHS phase: " + cphsPhase);
- }
-
- RIL.iccInfoPrivate.cphsSt = cphsInfo.subarray(1);
- onsuccess();
- } catch(e) {
- onerror(e.toString());
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CPHS_INFO,
- callback: callback.bind(this),
- onerror: onerror
- });
- },
-
- /**
- * Read CPHS MBN. (Mailbox Numbers)
- *
- * @See B.4.2.2 Voice Message Retrieval and Indicator Clearing
- */
- readCphsMBN: function() {
- function callback(options) {
- let RIL = this.context.RIL;
- let contact =
- this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
- if (!contact ||
- (RIL.iccInfoPrivate.mbdn !== undefined &&
- RIL.iccInfoPrivate.mbdn === contact.number)) {
- return;
- }
- RIL.iccInfoPrivate.mbdn = contact.number;
- if (DEBUG) {
- this.context.debug("CPHS_MDN, alphaId=" + contact.alphaId +
- " number=" + contact.number);
- }
- contact.rilMessageType = "iccmbdn";
- RIL.sendChromeMessage(contact);
- }
-
- this.context.ICCIOHelper.loadLinearFixedEF({
- fileId: ICC_EF_CPHS_MBN,
- callback: callback.bind(this)
- });
- }
-};
-
-function RuimRecordHelperObject(aContext) {
- this.context = aContext;
-}
-RuimRecordHelperObject.prototype = {
- context: null,
-
- fetchRuimRecords: function() {
- this.getIMSI_M();
- this.readCST();
- this.readCDMAHome();
- this.context.RIL.getCdmaSubscription();
- },
-
- /**
- * Get IMSI_M from CSIM/RUIM.
- * See 3GPP2 C.S0065 Sec. 5.2.2
- */
- getIMSI_M: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let encodedImsi = this.context.GsmPDUHelper.readHexOctetArray(strLen / 2);
- Buf.readStringDelimiter(strLen);
-
- if ((encodedImsi[CSIM_IMSI_M_PROGRAMMED_BYTE] & 0x80)) { // IMSI_M programmed
- let RIL = this.context.RIL;
- RIL.iccInfoPrivate.imsi = this.decodeIMSI(encodedImsi);
- RIL.sendChromeMessage({rilMessageType: "iccimsi",
- imsi: RIL.iccInfoPrivate.imsi});
-
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- let mccMnc = ICCUtilsHelper.parseMccMncFromImsi(RIL.iccInfoPrivate.imsi);
- if (mccMnc) {
- RIL.iccInfo.mcc = mccMnc.mcc;
- RIL.iccInfo.mnc = mccMnc.mnc;
- ICCUtilsHelper.handleICCInfoChange();
- }
- }
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CSIM_IMSI_M,
- callback: callback.bind(this)
- });
- },
-
- /**
- * Decode IMSI from IMSI_M
- * See 3GPP2 C.S0005 Sec. 2.3.1
- * +---+---------+------------+---+--------+---------+---+---------+--------+
- * |RFU| MCC | programmed |RFU| MNC | MIN1 |RFU| MIN2 | CLASS |
- * +---+---------+------------+---+--------+---------+---+---------+--------+
- * | 6 | 10 bits | 8 bits | 1 | 7 bits | 24 bits | 6 | 10 bits | 8 bits |
- * +---+---------+------------+---+--------+---------+---+---------+--------+
- */
- decodeIMSI: function(encodedImsi) {
- // MCC: 10 bits, 3 digits
- let encodedMCC = ((encodedImsi[CSIM_IMSI_M_MCC_BYTE + 1] & 0x03) << 8) +
- (encodedImsi[CSIM_IMSI_M_MCC_BYTE] & 0xff);
- let mcc = this.decodeIMSIValue(encodedMCC, 3);
-
- // MNC: 7 bits, 2 digits
- let encodedMNC = encodedImsi[CSIM_IMSI_M_MNC_BYTE] & 0x7f;
- let mnc = this.decodeIMSIValue(encodedMNC, 2);
-
- // MIN2: 10 bits, 3 digits
- let encodedMIN2 = ((encodedImsi[CSIM_IMSI_M_MIN2_BYTE + 1] & 0x03) << 8) +
- (encodedImsi[CSIM_IMSI_M_MIN2_BYTE] & 0xff);
- let min2 = this.decodeIMSIValue(encodedMIN2, 3);
-
- // MIN1: 10+4+10 bits, 3+1+3 digits
- let encodedMIN1First3 = ((encodedImsi[CSIM_IMSI_M_MIN1_BYTE + 2] & 0xff) << 2) +
- ((encodedImsi[CSIM_IMSI_M_MIN1_BYTE + 1] & 0xc0) >> 6);
- let min1First3 = this.decodeIMSIValue(encodedMIN1First3, 3);
-
- let encodedFourthDigit = (encodedImsi[CSIM_IMSI_M_MIN1_BYTE + 1] & 0x3c) >> 2;
- if (encodedFourthDigit > 9) {
- encodedFourthDigit = 0;
- }
- let fourthDigit = encodedFourthDigit.toString();
-
- let encodedMIN1Last3 = ((encodedImsi[CSIM_IMSI_M_MIN1_BYTE + 1] & 0x03) << 8) +
- (encodedImsi[CSIM_IMSI_M_MIN1_BYTE] & 0xff);
- let min1Last3 = this.decodeIMSIValue(encodedMIN1Last3, 3);
-
- return mcc + mnc + min2 + min1First3 + fourthDigit + min1Last3;
- },
-
- /**
- * Decode IMSI Helper function
- * See 3GPP2 C.S0005 section 2.3.1.1
- */
- decodeIMSIValue: function(encoded, length) {
- let offset = length === 3 ? 111 : 11;
- let value = encoded + offset;
-
- for (let base = 10, temp = value, i = 0; i < length; i++) {
- if (temp % 10 === 0) {
- value -= base;
- }
- temp = Math.floor(value / base);
- base = base * 10;
- }
-
- let s = value.toString();
- while (s.length < length) {
- s = "0" + s;
- }
-
- return s;
- },
-
- /**
- * Read CDMAHOME for CSIM.
- * See 3GPP2 C.S0023 Sec. 3.4.8.
- */
- readCDMAHome: function() {
- let ICCIOHelper = this.context.ICCIOHelper;
-
- function callback(options) {
- let Buf = this.context.Buf;
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let strLen = Buf.readInt32();
- let tempOctet = GsmPDUHelper.readHexOctet();
- cdmaHomeSystemId.push(((GsmPDUHelper.readHexOctet() & 0x7f) << 8) | tempOctet);
- tempOctet = GsmPDUHelper.readHexOctet();
- cdmaHomeNetworkId.push(((GsmPDUHelper.readHexOctet() & 0xff) << 8) | tempOctet);
-
- // Consuming the last octet: band class.
- Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
-
- Buf.readStringDelimiter(strLen);
- if (options.p1 < options.totalRecords) {
- ICCIOHelper.loadNextRecord(options);
- } else {
- if (DEBUG) {
- this.context.debug("CDMAHome system id: " +
- JSON.stringify(cdmaHomeSystemId));
- this.context.debug("CDMAHome network id: " +
- JSON.stringify(cdmaHomeNetworkId));
- }
- this.context.RIL.cdmaHome = {
- systemId: cdmaHomeSystemId,
- networkId: cdmaHomeNetworkId
- };
- }
- }
-
- let cdmaHomeSystemId = [], cdmaHomeNetworkId = [];
- ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_CSIM_CDMAHOME,
- callback: callback.bind(this)});
- },
-
- /**
- * Read CDMA Service Table.
- * See 3GPP2 C.S0023 Sec. 3.4.18
- */
- readCST: function() {
- function callback() {
- let Buf = this.context.Buf;
- let RIL = this.context.RIL;
-
- let strLen = Buf.readInt32();
- // Each octet is encoded into two chars.
- RIL.iccInfoPrivate.cst =
- this.context.GsmPDUHelper.readHexOctetArray(strLen / 2);
- Buf.readStringDelimiter(strLen);
-
- if (DEBUG) {
- let str = "";
- for (let i = 0; i < RIL.iccInfoPrivate.cst.length; i++) {
- str += RIL.iccInfoPrivate.cst[i] + ", ";
- }
- this.context.debug("CST: " + str);
- }
-
- if (this.context.ICCUtilsHelper.isICCServiceAvailable("SPN")) {
- if (DEBUG) this.context.debug("SPN: SPN is available");
- this.readSPN();
- }
- }
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CSIM_CST,
- callback: callback.bind(this)
- });
- },
-
- readSPN: function() {
- function callback() {
- let Buf = this.context.Buf;
- let strLen = Buf.readInt32();
- let octetLen = strLen / 2;
-
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let displayCondition = GsmPDUHelper.readHexOctet();
- let codingScheme = GsmPDUHelper.readHexOctet();
- // Skip one octet: language indicator.
- Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
- let readLen = 3;
-
- // SPN String ends up with 0xff.
- let userDataBuffer = [];
-
- while (readLen < octetLen) {
- let octet = GsmPDUHelper.readHexOctet();
- readLen++;
- if (octet == 0xff) {
- break;
- }
- userDataBuffer.push(octet);
- }
-
- this.context.BitBufferHelper.startRead(userDataBuffer);
-
- let CdmaPDUHelper = this.context.CdmaPDUHelper;
- let msgLen;
- switch (CdmaPDUHelper.getCdmaMsgEncoding(codingScheme)) {
- case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
- msgLen = Math.floor(userDataBuffer.length * 8 / 7);
- break;
- case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
- msgLen = userDataBuffer.length;
- break;
- case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
- msgLen = Math.floor(userDataBuffer.length / 2);
- break;
- }
-
- let RIL = this.context.RIL;
- RIL.iccInfo.spn = CdmaPDUHelper.decodeCdmaPDUMsg(codingScheme, null, msgLen);
- if (DEBUG) {
- this.context.debug("CDMA SPN: " + RIL.iccInfo.spn +
- ", Display condition: " + displayCondition);
- }
- RIL.iccInfoPrivate.spnDisplayCondition = displayCondition;
- Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
- Buf.readStringDelimiter(strLen);
- }
-
- this.context.ICCIOHelper.loadTransparentEF({
- fileId: ICC_EF_CSIM_SPN,
- callback: callback.bind(this)
- });
- }
-};
-
-/**
- * Helper functions for ICC utilities.
- */
-function ICCUtilsHelperObject(aContext) {
- this.context = aContext;
-}
-ICCUtilsHelperObject.prototype = {
- context: null,
-
- /**
- * Get network names by using EF_OPL and EF_PNN
- *
- * @See 3GPP TS 31.102 sec. 4.2.58 and sec. 4.2.59 for USIM,
- * 3GPP TS 51.011 sec. 10.3.41 and sec. 10.3.42 for SIM.
- *
- * @param mcc The mobile country code of the network.
- * @param mnc The mobile network code of the network.
- * @param lac The location area code of the network.
- */
- getNetworkNameFromICC: function(mcc, mnc, lac) {
- let RIL = this.context.RIL;
- let iccInfoPriv = RIL.iccInfoPrivate;
- let iccInfo = RIL.iccInfo;
- let pnnEntry;
-
- if (!mcc || !mnc || lac == null || lac < 0) {
- return null;
- }
-
- // We won't get network name if there is no PNN file.
- if (!iccInfoPriv.PNN) {
- return null;
- }
-
- if (!this.isICCServiceAvailable("OPL")) {
- // When OPL is not present:
- // According to 3GPP TS 31.102 Sec. 4.2.58 and 3GPP TS 51.011 Sec. 10.3.41,
- // If EF_OPL is not present, the first record in this EF is used for the
- // default network name when registered to the HPLMN.
- // If we haven't get pnnEntry assigned, we should try to assign default
- // value to it.
- if (mcc == iccInfo.mcc && mnc == iccInfo.mnc) {
- pnnEntry = iccInfoPriv.PNN[0];
- }
- } else {
- let GsmPDUHelper = this.context.GsmPDUHelper;
- let wildChar = GsmPDUHelper.extendedBcdChars.charAt(0x0d);
- // According to 3GPP TS 31.102 Sec. 4.2.59 and 3GPP TS 51.011 Sec. 10.3.42,
- // the ME shall use this EF_OPL in association with the EF_PNN in place
- // of any network name stored within the ME's internal list and any network
- // name received when registered to the PLMN.
- let length = iccInfoPriv.OPL ? iccInfoPriv.OPL.length : 0;
- for (let i = 0; i < length; i++) {
- let unmatch = false;
- let opl = iccInfoPriv.OPL[i];
- // Try to match the MCC/MNC. Besides, A BCD value of 'D' in any of the
- // MCC and/or MNC digits shall be used to indicate a "wild" value for
- // that corresponding MCC/MNC digit.
- if (opl.mcc.indexOf(wildChar) !== -1) {
- for (let j = 0; j < opl.mcc.length; j++) {
- if (opl.mcc[j] !== wildChar && opl.mcc[j] !== mcc[j]) {
- unmatch = true;
- break;
- }
- }
- if (unmatch) {
- continue;
- }
- } else {
- if (mcc !== opl.mcc) {
- continue;
- }
- }
-
- if (mnc.length !== opl.mnc.length) {
- continue;
- }
-
- if (opl.mnc.indexOf(wildChar) !== -1) {
- for (let j = 0; j < opl.mnc.length; j++) {
- if (opl.mnc[j] !== wildChar && opl.mnc[j] !== mnc[j]) {
- unmatch = true;
- break;
- }
- }
- if (unmatch) {
- continue;
- }
- } else {
- if (mnc !== opl.mnc) {
- continue;
- }
- }
-
- // Try to match the location area code. If current local area code is
- // covered by lac range that specified in the OPL entry, use the PNN
- // that specified in the OPL entry.
- if ((opl.lacTacStart === 0x0 && opl.lacTacEnd == 0xFFFE) ||
- (opl.lacTacStart <= lac && opl.lacTacEnd >= lac)) {
- if (opl.pnnRecordId === 0) {
- // See 3GPP TS 31.102 Sec. 4.2.59 and 3GPP TS 51.011 Sec. 10.3.42,
- // A value of '00' indicates that the name is to be taken from other
- // sources.
- return null;
- }
- pnnEntry = iccInfoPriv.PNN[opl.pnnRecordId - 1];
- break;
- }
- }
- }
-
- if (!pnnEntry) {
- return null;
- }
-
- // Return a new object to avoid global variable, PNN, be modified by accident.
- return { fullName: pnnEntry.fullName || "",
- shortName: pnnEntry.shortName || "" };
- },
-
- /**
- * This will compute the spnDisplay field of the network.
- * See TS 22.101 Annex A and TS 51.011 10.3.11 for details.
- *
- * @return True if some of iccInfo is changed in by this function.
- */
- updateDisplayCondition: function() {
- let RIL = this.context.RIL;
-
- // If EFspn isn't existed in SIM or it haven't been read yet, we should
- // just set isDisplayNetworkNameRequired = true and
- // isDisplaySpnRequired = false
- let iccInfo = RIL.iccInfo;
- let iccInfoPriv = RIL.iccInfoPrivate;
- let displayCondition = iccInfoPriv.spnDisplayCondition;
- let origIsDisplayNetworkNameRequired = iccInfo.isDisplayNetworkNameRequired;
- let origIsDisplaySPNRequired = iccInfo.isDisplaySpnRequired;
-
- if (displayCondition === undefined) {
- iccInfo.isDisplayNetworkNameRequired = true;
- iccInfo.isDisplaySpnRequired = false;
- } else if (RIL._isCdma) {
- // CDMA family display rule.
- let cdmaHome = RIL.cdmaHome;
- let cell = RIL.voiceRegistrationState.cell;
- let sid = cell && cell.cdmaSystemId;
- let nid = cell && cell.cdmaNetworkId;
-
- iccInfo.isDisplayNetworkNameRequired = false;
-
- // If display condition is 0x0, we don't even need to check network id
- // or system id.
- if (displayCondition === 0x0) {
- iccInfo.isDisplaySpnRequired = false;
- } else {
- // CDMA SPN Display condition dosen't specify whenever network name is
- // reqired.
- if (!cdmaHome ||
- !cdmaHome.systemId ||
- cdmaHome.systemId.length === 0 ||
- cdmaHome.systemId.length != cdmaHome.networkId.length ||
- !sid || !nid) {
- // CDMA Home haven't been ready, or we haven't got the system id and
- // network id of the network we register to, assuming we are in home
- // network.
- iccInfo.isDisplaySpnRequired = true;
- } else {
- // Determine if we are registered in the home service area.
- // System ID and Network ID are described in 3GPP2 C.S0005 Sec. 2.6.5.2.
- let inHomeArea = false;
- for (let i = 0; i < cdmaHome.systemId.length; i++) {
- let homeSid = cdmaHome.systemId[i],
- homeNid = cdmaHome.networkId[i];
- if (homeSid === 0 || homeNid === 0 // Reserved system id/network id
- || homeSid != sid) {
- continue;
- }
- // According to 3GPP2 C.S0005 Sec. 2.6.5.2, NID number 65535 means
- // all networks in the system should be considered as home.
- if (homeNid == 65535 || homeNid == nid) {
- inHomeArea = true;
- break;
- }
- }
- iccInfo.isDisplaySpnRequired = inHomeArea;
- }
- }
- } else {
- // GSM family display rule.
- let operatorMnc = RIL.operator ? RIL.operator.mnc : -1;
- let operatorMcc = RIL.operator ? RIL.operator.mcc : -1;
-
- // First detect if we are on HPLMN or one of the PLMN
- // specified by the SIM card.
- let isOnMatchingPlmn = false;
-
- // If the current network is the one defined as mcc/mnc
- // in SIM card, it's okay.
- if (iccInfo.mcc == operatorMcc && iccInfo.mnc == operatorMnc) {
- isOnMatchingPlmn = true;
- }
-
- // Test to see if operator's mcc/mnc match mcc/mnc of PLMN.
- if (!isOnMatchingPlmn && iccInfoPriv.SPDI) {
- let iccSpdi = iccInfoPriv.SPDI; // PLMN list
- for (let plmn in iccSpdi) {
- let plmnMcc = iccSpdi[plmn].mcc;
- let plmnMnc = iccSpdi[plmn].mnc;
- isOnMatchingPlmn = (plmnMcc == operatorMcc) && (plmnMnc == operatorMnc);
- if (isOnMatchingPlmn) {
- break;
- }
- }
- }
-
- // See 3GPP TS 22.101 A.4 Service Provider Name indication, and TS 31.102
- // clause 4.2.12 EF_SPN for detail.
- if (isOnMatchingPlmn) {
- // The first bit of display condition tells us if we should display
- // registered PLMN.
- if (DEBUG) {
- this.context.debug("PLMN is HPLMN or PLMN " + "is in PLMN list");
- }
-
- // TS 31.102 Sec. 4.2.66 and TS 51.011 Sec. 10.3.50
- // EF_SPDI contains a list of PLMNs in which the Service Provider Name
- // shall be displayed.
- iccInfo.isDisplaySpnRequired = true;
- iccInfo.isDisplayNetworkNameRequired = (displayCondition & 0x01) !== 0;
- } else {
- // The second bit of display condition tells us if we should display
- // registered PLMN.
- if (DEBUG) {
- this.context.debug("PLMN isn't HPLMN and PLMN isn't in PLMN list");
- }
-
- iccInfo.isDisplayNetworkNameRequired = true;
- iccInfo.isDisplaySpnRequired = (displayCondition & 0x02) === 0;
- }
- }
-
- if (DEBUG) {
- this.context.debug("isDisplayNetworkNameRequired = " +
- iccInfo.isDisplayNetworkNameRequired);
- this.context.debug("isDisplaySpnRequired = " + iccInfo.isDisplaySpnRequired);
- }
-
- return ((origIsDisplayNetworkNameRequired !== iccInfo.isDisplayNetworkNameRequired) ||
- (origIsDisplaySPNRequired !== iccInfo.isDisplaySpnRequired));
- },
-
- decodeSimTlvs: function(tlvsLen) {
- let GsmPDUHelper = this.context.GsmPDUHelper;
-
- let index = 0;
- let tlvs = [];
- while (index < tlvsLen) {
- let simTlv = {
- tag : GsmPDUHelper.readHexOctet(),
- length : GsmPDUHelper.readHexOctet(),
- };
- simTlv.value = GsmPDUHelper.readHexOctetArray(simTlv.length);
- tlvs.push(simTlv);
- index += simTlv.length + 2; // The length of 'tag' and 'length' field.
- }
- return tlvs;
- },
-
- /**
- * Parse those TLVs and convert it to an object.
- */
- parsePbrTlvs: function(pbrTlvs) {
- let pbr = {};
- for (let i = 0; i < pbrTlvs.length; i++) {
- let pbrTlv = pbrTlvs[i];
- let anrIndex = 0;
- for (let j = 0; j < pbrTlv.value.length; j++) {
- let tlv = pbrTlv.value[j];
- let tagName = USIM_TAG_NAME[tlv.tag];
-
- // ANR could have multiple files. We save it as anr0, anr1,...etc.
- if (tlv.tag == ICC_USIM_EFANR_TAG) {
- tagName += anrIndex;
- anrIndex++;
- }
- pbr[tagName] = tlv;
- pbr[tagName].fileType = pbrTlv.tag;
- pbr[tagName].fileId = (tlv.value[0] << 8) | tlv.value[1];
- pbr[tagName].sfi = tlv.value[2];
-
- // For Type 2, the order of files is in the same order in IAP.
- if (pbrTlv.tag == ICC_USIM_TYPE2_TAG) {
- pbr[tagName].indexInIAP = j;
- }
- }
- }
-
- return pbr;
- },
-
- /**
- * Update the ICC information to RadioInterfaceLayer.
- */
- handleICCInfoChange: function() {
- let RIL = this.context.RIL;
- RIL.iccInfo.rilMessageType = "iccinfochange";
- RIL.sendChromeMessage(RIL.iccInfo);
- },
-
- /**
- * Get whether specificed (U)SIM service is available.
- *
- * @param geckoService
- * Service name like "ADN", "BDN", etc.
- *
- * @return true if the service is enabled, false otherwise.
- */
- isICCServiceAvailable: function(geckoService) {
- let RIL = this.context.RIL;
- let serviceTable = RIL._isCdma ? RIL.iccInfoPrivate.cst:
- RIL.iccInfoPrivate.sst;
- let index, bitmask;
- if (RIL.appType == CARD_APPTYPE_SIM || RIL.appType == CARD_APPTYPE_RUIM) {
- /**
- * Service id is valid in 1..N, and 2 bits are used to code each service.
- *
- * +----+-- --+----+----+
- * | b8 | ... | b2 | b1 |
- * +----+-- --+----+----+
- *
- * b1 = 0, service not allocated.
- * 1, service allocated.
- * b2 = 0, service not activated.
- * 1, service activated.
- *
- * @see 3GPP TS 51.011 10.3.7.
- */
- let simService;
- if (RIL.appType == CARD_APPTYPE_SIM) {
- simService = GECKO_ICC_SERVICES.sim[geckoService];
- } else {
- simService = GECKO_ICC_SERVICES.ruim[geckoService];
- }
- if (!simService) {
- return false;
- }
- simService -= 1;
- index = Math.floor(simService / 4);
- bitmask = 2 << ((simService % 4) << 1);
- } else if (RIL.appType == CARD_APPTYPE_USIM) {
- /**
- * Service id is valid in 1..N, and 1 bit is used to code each service.
- *
- * +----+-- --+----+----+
- * | b8 | ... | b2 | b1 |
- * +----+-- --+----+----+
- *
- * b1 = 0, service not avaiable.
- * 1, service available.
- *
- * @see 3GPP TS 31.102 4.2.8.
- */
- let usimService = GECKO_ICC_SERVICES.usim[geckoService];
- if (!usimService) {
- return false;
- }
- usimService -= 1;
- index = Math.floor(usimService / 8);
- bitmask = 1 << ((usimService % 8) << 0);
- }
-
- return (serviceTable !== null) &&
- (index < serviceTable.length) &&
- ((serviceTable[index] & bitmask) !== 0);
- },
-
- /**
- * Get whether specificed CPHS service is available.
- *
- * @param geckoService
- * Service name like "MDN", etc.
- *
- * @return true if the service is enabled, false otherwise.
- */
- isCphsServiceAvailable: function(geckoService) {
- let RIL = this.context.RIL;
- let serviceTable = RIL.iccInfoPrivate.cphsSt;
-
- if (!(serviceTable instanceof Uint8Array)) {
- return false;
- }
-
- /**
- * Service id is valid in 1..N, and 2 bits are used to code each service.
- *
- * +----+-- --+----+----+
- * | b8 | ... | b2 | b1 |
- * +----+-- --+----+----+
- *
- * b1 = 0, service not allocated.
- * 1, service allocated.
- * b2 = 0, service not activated.
- * 1, service activated.
- *
- * @See B.3.1.1 CPHS Information in CPHS Phase 2.
- */
- let cphsService = GECKO_ICC_SERVICES.cphs[geckoService];
-
- if (!cphsService) {
- return false;
- }
- cphsService -= 1;
- let index = Math.floor(cphsService / 4);
- let bitmask = 2 << ((cphsService % 4) << 1);
-
- return (index < serviceTable.length) &&
- ((serviceTable[index] & bitmask) !== 0);
- },
-
- /**
- * Check if the string is of GSM default 7-bit coded alphabets with bit 8
- * set to 0.
- *
- * @param str String to be checked.
- */
- isGsm8BitAlphabet: function(str) {
- if (!str) {
- return false;
- }
-
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- for (let i = 0; i < str.length; i++) {
- let c = str.charAt(i);
- let octet = langTable.indexOf(c);
- if (octet == -1) {
- octet = langShiftTable.indexOf(c);
- if (octet == -1) {
- return false;
- }
- }
- }
-
- return true;
- },
-
- /**
- * Parse MCC/MNC from IMSI. If there is no available value for the length of
- * mnc, it will use the data in MCC table to parse.
- *
- * @param imsi
- * The imsi of icc.
- * @param mncLength [optional]
- * The length of mnc.
- * Zero indicates we haven't got a valid mnc length.
- *
- * @return An object contains the parsing result of mcc and mnc.
- * Or null if any error occurred.
- */
- parseMccMncFromImsi: function(imsi, mncLength) {
- if (!imsi) {
- return null;
- }
-
- // MCC is the first 3 digits of IMSI.
- let mcc = imsi.substr(0,3);
- if (!mncLength) {
- // Check the MCC/MNC table for MNC length = 3 first for the case we don't
- // have the 4th byte data from EF_AD.
- if (PLMN_HAVING_3DIGITS_MNC[mcc] &&
- PLMN_HAVING_3DIGITS_MNC[mcc].indexOf(imsi.substr(3, 3)) !== -1) {
- mncLength = 3;
- } else {
- // Check the MCC table to decide the length of MNC.
- let index = MCC_TABLE_FOR_MNC_LENGTH_IS_3.indexOf(mcc);
- mncLength = (index !== -1) ? 3 : 2;
- }
- }
- let mnc = imsi.substr(3, mncLength);
- if (DEBUG) {
- this.context.debug("IMSI: " + imsi + " MCC: " + mcc + " MNC: " + mnc);
- }
-
- return { mcc: mcc, mnc: mnc};
- },
-};
-
-/**
- * Helper for ICC Contacts.
- */
-function ICCContactHelperObject(aContext) {
- this.context = aContext;
-}
-ICCContactHelperObject.prototype = {
- context: null,
-
- /**
- * Helper function to check DF_PHONEBOOK.
- */
- hasDfPhoneBook: function(appType) {
- switch (appType) {
- case CARD_APPTYPE_SIM:
- return false;
- case CARD_APPTYPE_USIM:
- return true;
- case CARD_APPTYPE_RUIM:
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
- return ICCUtilsHelper.isICCServiceAvailable("ENHANCED_PHONEBOOK");
- default:
- return false;
- }
- },
-
- /**
- * Helper function to read ICC contacts.
- *
- * @param appType One of CARD_APPTYPE_*.
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readICCContacts: function(appType, contactType, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
-
- switch (contactType) {
- case GECKO_CARDCONTACT_TYPE_ADN:
- if (!this.hasDfPhoneBook(appType)) {
- ICCRecordHelper.readADNLike(ICC_EF_ADN,
- (ICCUtilsHelper.isICCServiceAvailable("EXT1")) ? ICC_EF_EXT1 : null,
- onsuccess, onerror);
- } else {
- this.readUSimContacts(onsuccess, onerror);
- }
- break;
- case GECKO_CARDCONTACT_TYPE_FDN:
- if (!ICCUtilsHelper.isICCServiceAvailable("FDN")) {
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- ICCRecordHelper.readADNLike(ICC_EF_FDN,
- (ICCUtilsHelper.isICCServiceAvailable("EXT2")) ? ICC_EF_EXT2 : null,
- onsuccess, onerror);
- break;
- case GECKO_CARDCONTACT_TYPE_SDN:
- if (!ICCUtilsHelper.isICCServiceAvailable("SDN")) {
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
-
- ICCRecordHelper.readADNLike(ICC_EF_SDN,
- (ICCUtilsHelper.isICCServiceAvailable("EXT3")) ? ICC_EF_EXT3 : null,
- onsuccess, onerror);
- break;
- default:
- if (DEBUG) {
- this.context.debug("Unsupported contactType :" + contactType);
- }
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- },
-
- /**
- * Helper function to find free contact record.
- *
- * @param appType One of CARD_APPTYPE_*.
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- findFreeICCContact: function(appType, contactType, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- switch (contactType) {
- case GECKO_CARDCONTACT_TYPE_ADN:
- if (!this.hasDfPhoneBook(appType)) {
- ICCRecordHelper.findFreeRecordId(ICC_EF_ADN, onsuccess.bind(null, 0), onerror);
- } else {
- let gotPbrCb = function gotPbrCb(pbrs) {
- this.findUSimFreeADNRecordId(pbrs, onsuccess, onerror);
- }.bind(this);
-
- ICCRecordHelper.readPBR(gotPbrCb, onerror);
- }
- break;
- case GECKO_CARDCONTACT_TYPE_FDN:
- ICCRecordHelper.findFreeRecordId(ICC_EF_FDN, onsuccess.bind(null, 0), onerror);
- break;
- default:
- if (DEBUG) {
- this.context.debug("Unsupported contactType :" + contactType);
- }
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- },
-
- /**
- * Cache the pbr index of the possible free record.
- */
- _freePbrIndex: 0,
-
- /**
- * Find free ADN record id in USIM.
- *
- * @param pbrs All Phonebook Reference Files read.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- findUSimFreeADNRecordId: function(pbrs, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- function callback(pbrIndex, recordId) {
- // Assume other free records are probably in the same phonebook set.
- this._freePbrIndex = pbrIndex;
- onsuccess(pbrIndex, recordId);
- }
-
- let nextPbrIndex = -1;
- (function findFreeRecordId(pbrIndex) {
- if (nextPbrIndex === this._freePbrIndex) {
- // No free record found, reset the pbr index of free record.
- this._freePbrIndex = 0;
- if (DEBUG) {
- this.context.debug(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- }
- onerror(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- return;
- }
-
- let pbr = pbrs[pbrIndex];
- nextPbrIndex = (pbrIndex + 1) % pbrs.length;
- ICCRecordHelper.findFreeRecordId(
- pbr.adn.fileId,
- callback.bind(this, pbrIndex),
- findFreeRecordId.bind(this, nextPbrIndex));
- }).call(this, this._freePbrIndex);
- },
-
- /**
- * Helper function to add a new ICC contact.
- *
- * @param appType One of CARD_APPTYPE_*.
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param contact The contact will be added.
- * @param pin2 PIN2 is required for FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- addICCContact: function(appType, contactType, contact, pin2, onsuccess, onerror) {
- let foundFreeCb = (function foundFreeCb(pbrIndex, recordId) {
- contact.pbrIndex = pbrIndex;
- contact.recordId = recordId;
- this.updateICCContact(appType, contactType, contact, pin2, onsuccess, onerror);
- }).bind(this);
-
- // Find free record first.
- this.findFreeICCContact(appType, contactType, foundFreeCb, onerror);
- },
-
- /**
- * Helper function to update ICC contact.
- *
- * @param appType One of CARD_APPTYPE_*.
- * @param contactType One of GECKO_CARDCONTACT_TYPE_*.
- * @param contact The contact will be updated.
- * @param pin2 PIN2 is required for FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateICCContact: function(appType, contactType, contact, pin2, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let ICCUtilsHelper = this.context.ICCUtilsHelper;
-
- let updateContactCb = (updatedContact) => {
- updatedContact.pbrIndex = contact.pbrIndex;
- updatedContact.recordId = contact.recordId;
- onsuccess(updatedContact);
- }
-
- switch (contactType) {
- case GECKO_CARDCONTACT_TYPE_ADN:
- if (!this.hasDfPhoneBook(appType)) {
- if (ICCUtilsHelper.isICCServiceAvailable("EXT1")) {
- this.updateADNLikeWithExtension(ICC_EF_ADN, ICC_EF_EXT1,
- contact, null,
- updateContactCb, onerror);
- } else {
- ICCRecordHelper.updateADNLike(ICC_EF_ADN, 0xff,
- contact, null,
- updateContactCb, onerror);
- }
- } else {
- this.updateUSimContact(contact, updateContactCb, onerror);
- }
- break;
- case GECKO_CARDCONTACT_TYPE_FDN:
- if (!pin2) {
- onerror(GECKO_ERROR_SIM_PIN2);
- return;
- }
- if (!ICCUtilsHelper.isICCServiceAvailable("FDN")) {
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- if (ICCUtilsHelper.isICCServiceAvailable("EXT2")) {
- this.updateADNLikeWithExtension(ICC_EF_FDN, ICC_EF_EXT2,
- contact, pin2,
- updateContactCb, onerror);
- } else {
- ICCRecordHelper.updateADNLike(ICC_EF_FDN,
- 0xff,
- contact, pin2,
- updateContactCb, onerror);
- }
- break;
- default:
- if (DEBUG) {
- this.context.debug("Unsupported contactType :" + contactType);
- }
- onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
- break;
- }
- },
-
- /**
- * Read contacts from USIM.
- *
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readUSimContacts: function(onsuccess, onerror) {
- let gotPbrCb = function gotPbrCb(pbrs) {
- this.readAllPhonebookSets(pbrs, onsuccess, onerror);
- }.bind(this);
-
- this.context.ICCRecordHelper.readPBR(gotPbrCb, onerror);
- },
-
- /**
- * Read all Phonebook sets.
- *
- * @param pbrs All Phonebook Reference Files read.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readAllPhonebookSets: function(pbrs, onsuccess, onerror) {
- let allContacts = [], pbrIndex = 0;
- let readPhonebook = function(contacts) {
- if (contacts) {
- allContacts = allContacts.concat(contacts);
- }
-
- let cLen = contacts ? contacts.length : 0;
- for (let i = 0; i < cLen; i++) {
- contacts[i].pbrIndex = pbrIndex;
- }
-
- pbrIndex++;
- if (pbrIndex >= pbrs.length) {
- if (onsuccess) {
- onsuccess(allContacts);
- }
- return;
- }
-
- this.readPhonebookSet(pbrs[pbrIndex], readPhonebook, onerror);
- }.bind(this);
-
- this.readPhonebookSet(pbrs[pbrIndex], readPhonebook, onerror);
- },
-
- /**
- * Read from Phonebook Reference File.
- *
- * @param pbr Phonebook Reference File to be read.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readPhonebookSet: function(pbr, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let gotAdnCb = function gotAdnCb(contacts) {
- this.readSupportedPBRFields(pbr, contacts, onsuccess, onerror);
- }.bind(this);
-
- ICCRecordHelper.readADNLike(pbr.adn.fileId,
- (pbr.ext1) ? pbr.ext1.fileId : null, gotAdnCb, onerror);
- },
-
- /**
- * Read supported Phonebook fields.
- *
- * @param pbr Phone Book Reference file.
- * @param contacts Contacts stored on ICC.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readSupportedPBRFields: function(pbr, contacts, onsuccess, onerror) {
- let fieldIndex = 0;
- (function readField() {
- let field = USIM_PBR_FIELDS[fieldIndex];
- fieldIndex += 1;
- if (!field) {
- if (onsuccess) {
- onsuccess(contacts);
- }
- return;
- }
-
- this.readPhonebookField(pbr, contacts, field, readField.bind(this), onerror);
- }).call(this);
- },
-
- /**
- * Read Phonebook field.
- *
- * @param pbr The phonebook reference file.
- * @param contacts Contacts stored on ICC.
- * @param field Phonebook field to be retrieved.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readPhonebookField: function(pbr, contacts, field, onsuccess, onerror) {
- if (!pbr[field]) {
- if (onsuccess) {
- onsuccess(contacts);
- }
- return;
- }
-
- (function doReadContactField(n) {
- if (n >= contacts.length) {
- // All contact's fields are read.
- if (onsuccess) {
- onsuccess(contacts);
- }
- return;
- }
-
- // get n-th contact's field.
- this.readContactField(pbr, contacts[n], field,
- doReadContactField.bind(this, n + 1), onerror);
- }).call(this, 0);
- },
-
- /**
- * Read contact's field from USIM.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to get field.
- * @param field Phonebook field to be retrieved.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- readContactField: function(pbr, contact, field, onsuccess, onerror) {
- let gotRecordIdCb = function gotRecordIdCb(recordId) {
- if (recordId == 0xff) {
- if (onsuccess) {
- onsuccess();
- }
- return;
- }
-
- let fileId = pbr[field].fileId;
- let fileType = pbr[field].fileType;
- let gotFieldCb = function gotFieldCb(value) {
- if (value) {
- // Move anr0 anr1,.. into anr[].
- if (field.startsWith(USIM_PBR_ANR)) {
- if (!contact[USIM_PBR_ANR]) {
- contact[USIM_PBR_ANR] = [];
- }
- contact[USIM_PBR_ANR].push(value);
- } else {
- contact[field] = value;
- }
- }
-
- if (onsuccess) {
- onsuccess();
- }
- }.bind(this);
-
- let ICCRecordHelper = this.context.ICCRecordHelper;
- // Detect EF to be read, for anr, it could have anr0, anr1,...
- let ef = field.startsWith(USIM_PBR_ANR) ? USIM_PBR_ANR : field;
- switch (ef) {
- case USIM_PBR_EMAIL:
- ICCRecordHelper.readEmail(fileId, fileType, recordId, gotFieldCb, onerror);
- break;
- case USIM_PBR_ANR:
- ICCRecordHelper.readANR(fileId, fileType, recordId, gotFieldCb, onerror);
- break;
- default:
- if (DEBUG) {
- this.context.debug("Unsupported field :" + field);
- }
- onerror(CONTACT_ERR_FIELD_NOT_SUPPORTED);
- break;
- }
- }.bind(this);
-
- this.getContactFieldRecordId(pbr, contact, field, gotRecordIdCb, onerror);
- },
-
- /**
- * Get the recordId.
- *
- * If the fileType of field is ICC_USIM_TYPE1_TAG, use corresponding ADN recordId.
- * otherwise get the recordId from IAP.
- *
- * @see TS 131.102, clause 4.4.2.2
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact will be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- getContactFieldRecordId: function(pbr, contact, field, onsuccess, onerror) {
- if (pbr[field].fileType == ICC_USIM_TYPE1_TAG) {
- // If the file type is ICC_USIM_TYPE1_TAG, use corresponding ADN recordId.
- if (onsuccess) {
- onsuccess(contact.recordId);
- }
- } else if (pbr[field].fileType == ICC_USIM_TYPE2_TAG) {
- // If the file type is ICC_USIM_TYPE2_TAG, the recordId shall be got from IAP.
- let gotIapCb = function gotIapCb(iap) {
- let indexInIAP = pbr[field].indexInIAP;
- let recordId = iap[indexInIAP];
-
- if (onsuccess) {
- onsuccess(recordId);
- }
- }.bind(this);
-
- this.context.ICCRecordHelper.readIAP(pbr.iap.fileId, contact.recordId,
- gotIapCb, onerror);
- } else {
- if (DEBUG) {
- this.context.debug("USIM PBR files in Type 3 format are not supported.");
- }
- onerror(CONTACT_ERR_REQUEST_NOT_SUPPORTED);
- }
- },
-
- /**
- * Update USIM contact.
- *
- * @param contact The contact will be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateUSimContact: function(contact, onsuccess, onerror) {
- let gotPbrCb = function gotPbrCb(pbrs) {
- let pbr = pbrs[contact.pbrIndex];
- if (!pbr) {
- if (DEBUG) {
- this.context.debug(CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
- }
- onerror(CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
- return;
- }
- this.updatePhonebookSet(pbr, contact, onsuccess, onerror);
- }.bind(this);
-
- this.context.ICCRecordHelper.readPBR(gotPbrCb, onerror);
- },
-
- /**
- * Update fields in Phonebook Reference File.
- *
- * @param pbr Phonebook Reference File to be read.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updatePhonebookSet: function(pbr, contact, onsuccess, onerror) {
- let updateAdnCb = function(updatedContact) {
- this.updateSupportedPBRFields(pbr, contact, (updatedContactField) => {
- onsuccess(Object.assign(updatedContact, updatedContactField));
- }, onerror);
- }.bind(this);
-
- if (pbr.ext1) {
- this.updateADNLikeWithExtension(pbr.adn.fileId, pbr.ext1.fileId,
- contact, null, updateAdnCb, onerror);
- } else {
- this.context.ICCRecordHelper.updateADNLike(pbr.adn.fileId, 0xff, contact,
- null, updateAdnCb, onerror);
- }
- },
-
- /**
- * Update supported Phonebook fields.
- *
- * @param pbr Phone Book Reference file.
- * @param contact Contact to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateSupportedPBRFields: function(pbr, contact, onsuccess, onerror) {
- let fieldIndex = 0;
- let contactField = {};
-
- (function updateField() {
- let field = USIM_PBR_FIELDS[fieldIndex];
- fieldIndex += 1;
-
- if (!field) {
- if (onsuccess) {
- onsuccess(contactField);
- }
- return;
- }
-
- // Check if PBR has this field.
- if (!pbr[field]) {
- updateField.call(this);
- return;
- }
-
- this.updateContactField(pbr, contact, field, (fieldEntry) => {
- contactField = Object.assign(contactField, fieldEntry);
- updateField.call(this);
- }, (errorMsg) => {
- // Bug 1194149, there are some sim cards without sufficient
- // Type 2 USIM contact fields record. We allow user continue
- // importing contacts.
- if (errorMsg === CONTACT_ERR_NO_FREE_RECORD_FOUND) {
- updateField.call(this);
- return;
- }
- onerror(errorMsg);
- });
- }).call(this);
- },
-
- /**
- * Update contact's field from USIM.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to be updated.
- * @param field Phonebook field to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateContactField: function(pbr, contact, field, onsuccess, onerror) {
- if (pbr[field].fileType === ICC_USIM_TYPE1_TAG) {
- this.updateContactFieldType1(pbr, contact, field, onsuccess, onerror);
- } else if (pbr[field].fileType === ICC_USIM_TYPE2_TAG) {
- this.updateContactFieldType2(pbr, contact, field, onsuccess, onerror);
- } else {
- if (DEBUG) {
- this.context.debug("USIM PBR files in Type 3 format are not supported.");
- }
- onerror(CONTACT_ERR_REQUEST_NOT_SUPPORTED);
- }
- },
-
- /**
- * Update Type 1 USIM contact fields.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to be updated.
- * @param field Phonebook field to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateContactFieldType1: function(pbr, contact, field, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- if (field === USIM_PBR_EMAIL) {
- ICCRecordHelper.updateEmail(pbr, contact.recordId, contact.email, null,
- (updatedEmail) => {
- onsuccess({email: updatedEmail});
- }, onerror);
- } else if (field === USIM_PBR_ANR0) {
- let anr = Array.isArray(contact.anr) ? contact.anr[0] : null;
- ICCRecordHelper.updateANR(pbr, contact.recordId, anr, null,
- (updatedANR) => {
- // ANR could have multiple files. If we support more than one anr,
- // we will save it as anr0, anr1,...etc.
- onsuccess((updatedANR) ? {anr: [updatedANR]} : null);
- }, onerror);
- } else {
- if (DEBUG) {
- this.context.debug("Unsupported field :" + field);
- }
- onerror(CONTACT_ERR_FIELD_NOT_SUPPORTED);
- }
- },
-
- /**
- * Update Type 2 USIM contact fields.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to be updated.
- * @param field Phonebook field to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateContactFieldType2: function(pbr, contact, field, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- // Case 1 : EF_IAP[adnRecordId] doesn't have a value(0xff)
- // Find a free recordId for EF_field
- // Update field with that free recordId.
- // Update IAP.
- //
- // Case 2: EF_IAP[adnRecordId] has a value
- // update EF_field[iap[field.indexInIAP]]
-
- let gotIapCb = function gotIapCb(iap) {
- let recordId = iap[pbr[field].indexInIAP];
- if (recordId === 0xff) {
- // If the value in IAP[index] is 0xff, which means the contact stored on
- // the SIM doesn't have the additional attribute (email or anr).
- // So if the contact to be updated doesn't have the attribute either,
- // we don't have to update it.
- if ((field === USIM_PBR_EMAIL && contact.email) ||
- (field === USIM_PBR_ANR0 &&
- (Array.isArray(contact.anr) && contact.anr[0]))) {
- // Case 1.
- this.addContactFieldType2(pbr, contact, field, onsuccess, onerror);
- } else {
- if (onsuccess) {
- onsuccess();
- }
- }
- return;
- }
-
- // Case 2.
- if (field === USIM_PBR_EMAIL) {
- ICCRecordHelper.updateEmail(pbr, recordId, contact.email, contact.recordId,
- (updatedEmail) => {
- onsuccess({email: updatedEmail});
- }, onerror);
- } else if (field === USIM_PBR_ANR0) {
- let anr = Array.isArray(contact.anr) ? contact.anr[0] : null;
- ICCRecordHelper.updateANR(pbr, recordId, anr, contact.recordId,
- (updatedANR) => {
- // ANR could have multiple files. If we support more than one anr,
- // we will save it as anr0, anr1,...etc.
- onsuccess((updatedANR) ? {anr: [updatedANR]} : null);
- }, onerror);
- } else {
- if (DEBUG) {
- this.context.debug("Unsupported field :" + field);
- }
- onerror(CONTACT_ERR_FIELD_NOT_SUPPORTED);
- }
-
- }.bind(this);
-
- ICCRecordHelper.readIAP(pbr.iap.fileId, contact.recordId, gotIapCb, onerror);
- },
-
- /**
- * Add Type 2 USIM contact fields.
- *
- * @param pbr The phonebook reference file.
- * @param contact The contact needs to be updated.
- * @param field Phonebook field to be updated.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- addContactFieldType2: function(pbr, contact, field, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let successCb = function successCb(recordId) {
-
- let updateCb = function updateCb(contactField) {
- this.updateContactFieldIndexInIAP(pbr, contact.recordId, field, recordId, () => {
- onsuccess(contactField);
- }, onerror);
- }.bind(this);
-
- if (field === USIM_PBR_EMAIL) {
- ICCRecordHelper.updateEmail(pbr, recordId, contact.email, contact.recordId,
- (updatedEmail) => {
- updateCb({email: updatedEmail});
- }, onerror);
- } else if (field === USIM_PBR_ANR0) {
- ICCRecordHelper.updateANR(pbr, recordId, contact.anr[0], contact.recordId,
- (updatedANR) => {
- // ANR could have multiple files. If we support more than one anr,
- // we will save it as anr0, anr1,...etc.
- updateCb((updatedANR) ? {anr: [updatedANR]} : null);
- }, onerror);
- }
- }.bind(this);
-
- let errorCb = function errorCb(errorMsg) {
- if (DEBUG) {
- this.context.debug(errorMsg + " USIM field " + field);
- }
- onerror(errorMsg);
- }.bind(this);
-
- ICCRecordHelper.findFreeRecordId(pbr[field].fileId, successCb, errorCb);
- },
-
- /**
- * Update IAP value.
- *
- * @param pbr The phonebook reference file.
- * @param recordNumber The record identifier of EF_IAP.
- * @param field Phonebook field.
- * @param value The value of 'field' in IAP.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- *
- */
- updateContactFieldIndexInIAP: function(pbr, recordNumber, field, value, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
-
- let gotIAPCb = function gotIAPCb(iap) {
- iap[pbr[field].indexInIAP] = value;
- ICCRecordHelper.updateIAP(pbr.iap.fileId, recordNumber, iap, onsuccess, onerror);
- }.bind(this);
- ICCRecordHelper.readIAP(pbr.iap.fileId, recordNumber, gotIAPCb, onerror);
- },
-
- /**
- * Update ICC ADN like EFs with Extension, like EF_ADN, EF_FDN.
- *
- * @param fileId EF id of the ADN or FDN.
- * @param extFileId EF id of the EXT.
- * @param contact The contact will be updated. (Shall have recordId property)
- * @param pin2 PIN2 is required when updating ICC_EF_FDN.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- updateADNLikeWithExtension: function(fileId, extFileId, contact, pin2, onsuccess, onerror) {
- let ICCRecordHelper = this.context.ICCRecordHelper;
- let extNumber;
-
- if (contact.number) {
- let numStart = contact.number[0] == "+" ? 1 : 0;
- let number = contact.number.substring(0, numStart) +
- this.context.GsmPDUHelper.stringToExtendedBcd(
- contact.number.substring(numStart));
- extNumber = number.substr(numStart + ADN_MAX_NUMBER_DIGITS,
- EXT_MAX_NUMBER_DIGITS);
- }
-
- ICCRecordHelper.getADNLikeExtensionRecordNumber(fileId, contact.recordId,
- (extRecordNumber) => {
- let updateADNLike = (extRecordNumber) => {
- ICCRecordHelper.updateADNLike(fileId, extRecordNumber, contact,
- pin2, (updatedContact) => {
- if (extNumber && extRecordNumber != 0xff) {
- updatedContact.number = updatedContact.number.concat(extNumber);
- }
- onsuccess(updatedContact);
- }, onerror);
- };
-
- let updateExtension = (extRecordNumber) => {
- ICCRecordHelper.updateExtension(extFileId, extRecordNumber, extNumber,
- () => updateADNLike(extRecordNumber),
- () => updateADNLike(0xff));
- };
-
- if (extNumber) {
- if (extRecordNumber != 0xff) {
- updateExtension(extRecordNumber);
- return;
- }
-
- ICCRecordHelper.findFreeRecordId(extFileId,
- (extRecordNumber) => updateExtension(extRecordNumber),
- (errorMsg) => {
- if (DEBUG) {
- this.context.debug("Couldn't find free extension record Id for " + extFileId + ": " + errorMsg);
- }
- updateADNLike(0xff);
- });
- return;
- }
-
- if (extRecordNumber != 0xff) {
- ICCRecordHelper.cleanEFRecord(extFileId, extRecordNumber,
- () => updateADNLike(0xff), onerror);
- return;
- }
-
- updateADNLike(0xff);
- }, onerror);
- },
-};
-
-function IconLoaderObject(aContext) {
- this.context = aContext;
-}
-IconLoaderObject.prototype = {
- context: null,
-
- /**
- * Load icons.
- *
- * @param recordNumbers Array of the record identifiers of EF_IMG.
- * @param onsuccess Callback to be called when success.
- * @param onerror Callback to be called when error.
- */
- loadIcons: function(recordNumbers, onsuccess, onerror) {
- if (!recordNumbers || !recordNumbers.length) {
- if (onerror) {
- onerror();
- }
- return;
- }
-
- this._start({
- recordNumbers: recordNumbers,
- onsuccess: onsuccess,
- onerror: onerror});
- },
-
- _start: function(options) {
- let callback = (function(icons) {
- if (!options.icons) {
- options.icons = [];
- }
- for (let i = 0; i < icons.length; i++) {
- icons[i] = this._parseRawData(icons[i]);
- }
- options.icons[options.currentRecordIndex] = icons;
- options.currentRecordIndex++;
-
- let recordNumbers = options.recordNumbers;
- if (options.currentRecordIndex < recordNumbers.length) {
- let recordNumber = recordNumbers[options.currentRecordIndex];
- this.context.SimRecordHelper.readIMG(recordNumber,
- callback,
- options.onerror);
- } else {
- if (options.onsuccess) {
- options.onsuccess(options.icons);
- }
- }
- }).bind(this);
-
- options.currentRecordIndex = 0;
- this.context.SimRecordHelper.readIMG(options.recordNumbers[0],
- callback,
- options.onerror);
- },
-
- _parseRawData: function(rawData) {
- let codingScheme = rawData.codingScheme;
-
- switch (codingScheme) {
- case ICC_IMG_CODING_SCHEME_BASIC:
- return this._decodeBasicImage(rawData.width, rawData.height, rawData.body);
-
- case ICC_IMG_CODING_SCHEME_COLOR:
- case ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY:
- return this._decodeColorImage(codingScheme,
- rawData.width, rawData.height,
- rawData.bitsPerImgPoint,
- rawData.numOfClutEntries,
- rawData.clut, rawData.body);
- }
-
- return null;
- },
-
- _decodeBasicImage: function(width, height, body) {
- let numOfPixels = width * height;
- let pixelIndex = 0;
- let currentByteIndex = 0;
- let currentByte = 0x00;
-
- const BLACK = 0x000000FF;
- const WHITE = 0xFFFFFFFF;
-
- let pixels = [];
- while (pixelIndex < numOfPixels) {
- // Reassign data and index for every byte (8 bits).
- if (pixelIndex % 8 == 0) {
- currentByte = body[currentByteIndex++];
- }
- let bit = (currentByte >> (7 - (pixelIndex % 8))) & 0x01;
- pixels[pixelIndex++] = bit ? WHITE : BLACK;
- }
-
- return {pixels: pixels,
- codingScheme: GECKO_IMG_CODING_SCHEME_BASIC,
- width: width,
- height: height};
- },
-
- _decodeColorImage: function(codingScheme, width, height, bitsPerImgPoint,
- numOfClutEntries, clut, body) {
- let mask = 0xff >> (8 - bitsPerImgPoint);
- let bitsStartOffset = 8 - bitsPerImgPoint;
- let bitIndex = bitsStartOffset;
- let numOfPixels = width * height;
- let pixelIndex = 0;
- let currentByteIndex = 0;
- let currentByte = body[currentByteIndex++];
-
- let pixels = [];
- while (pixelIndex < numOfPixels) {
- // Reassign data and index for every byte (8 bits).
- if (bitIndex < 0) {
- currentByte = body[currentByteIndex++];
- bitIndex = bitsStartOffset;
- }
- let clutEntry = ((currentByte >> bitIndex) & mask);
- let clutIndex = clutEntry * ICC_CLUT_ENTRY_SIZE;
- let alpha = codingScheme == ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY &&
- clutEntry == numOfClutEntries - 1;
- pixels[pixelIndex++] = alpha ? 0x00
- : (clut[clutIndex] << 24 |
- clut[clutIndex + 1] << 16 |
- clut[clutIndex + 2] << 8 |
- 0xFF) >>> 0;
- bitIndex -= bitsPerImgPoint;
- }
-
- return {pixels: pixels,
- codingScheme: ICC_IMG_CODING_SCHEME_TO_GECKO[codingScheme],
- width: width,
- height: height};
- },
-};
-
-/**
- * Global stuff.
- */
-
-function Context(aClientId) {
- this.clientId = aClientId;
-
- this.Buf = new BufObject(this);
- this.RIL = new RilObject(this);
- this.RIL.initRILState();
-}
-Context.prototype = {
- clientId: null,
- Buf: null,
- RIL: null,
-
- debug: function(aMessage) {
- GLOBAL.debug("[" + this.clientId + "] " + aMessage);
- }
-};
-
-(function() {
- let lazySymbols = [
- "BerTlvHelper", "BitBufferHelper", "CdmaPDUHelper",
- "ComprehensionTlvHelper", "GsmPDUHelper", "ICCContactHelper",
- "ICCFileHelper", "ICCIOHelper", "ICCPDUHelper", "ICCRecordHelper",
- "ICCUtilsHelper", "RuimRecordHelper", "SimRecordHelper",
- "StkCommandParamsFactory", "StkProactiveCmdHelper", "IconLoader",
- ];
-
- for (let i = 0; i < lazySymbols.length; i++) {
- let symbol = lazySymbols[i];
- Object.defineProperty(Context.prototype, symbol, {
- get: function() {
- let real = new GLOBAL[symbol + "Object"](this);
- Object.defineProperty(this, symbol, {
- value: real,
- enumerable: true
- });
- return real;
- },
- configurable: true,
- enumerable: true
- });
- }
-})();
-
-var ContextPool = {
- _contexts: [],
-
- handleRilMessage: function(aClientId, aUint8Array) {
- let context = this._contexts[aClientId];
- context.Buf.processIncoming(aUint8Array);
- },
-
- handleChromeMessage: function(aMessage) {
- let clientId = aMessage.rilMessageClientId;
- if (clientId != null) {
- let context = this._contexts[clientId];
- context.RIL.handleChromeMessage(aMessage);
- return;
- }
-
- if (DEBUG) debug("Received global chrome message " + JSON.stringify(aMessage));
- let method = this[aMessage.rilMessageType];
- if (typeof method != "function") {
- if (DEBUG) {
- debug("Don't know what to do");
- }
- return;
- }
- method.call(this, aMessage);
- },
-
- setInitialOptions: function(aOptions) {
- DEBUG = DEBUG_WORKER || aOptions.debug;
-
- let quirks = aOptions.quirks;
- RILQUIRKS_CALLSTATE_EXTRA_UINT32 = quirks.callstateExtraUint32;
- RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = quirks.requestUseDialEmergencyCall;
- RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = quirks.simAppStateExtraFields;
- RILQUIRKS_EXTRA_UINT32_2ND_CALL = quirks.extraUint2ndCall;
- RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = quirks.haveQueryIccLockRetryCount;
- RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = quirks.sendStkProfileDownload;
- RILQUIRKS_DATA_REGISTRATION_ON_DEMAND = quirks.dataRegistrationOnDemand;
- RILQUIRKS_SUBSCRIPTION_CONTROL = quirks.subscriptionControl;
- RILQUIRKS_SIGNAL_EXTRA_INT32 = quirks.signalExtraInt;
- RILQUIRKS_AVAILABLE_NETWORKS_EXTRA_STRING = quirks.availableNetworkExtraStr;
- RILQUIRKS_SMSC_ADDRESS_FORMAT = quirks.smscAddressFormat;
- },
-
- setDebugFlag: function(aOptions) {
- DEBUG = DEBUG_WORKER || aOptions.debug;
- },
-
- registerClient: function(aOptions) {
- let clientId = aOptions.clientId;
- this._contexts[clientId] = new Context(clientId);
- },
-};
-
-function onRILMessage(aClientId, aUint8Array) {
- ContextPool.handleRilMessage(aClientId, aUint8Array);
-}
-
-onmessage = function onmessage(event) {
- ContextPool.handleChromeMessage(event.data);
-};
-
-onerror = function onerror(event) {
- if (DEBUG) debug("onerror" + event.message + "\n");
-};
diff --git a/dom/system/gonk/ril_worker_buf_object.js b/dom/system/gonk/ril_worker_buf_object.js
deleted file mode 100644
index 70018c5b2..000000000
--- a/dom/system/gonk/ril_worker_buf_object.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/* global require */
-/* global DEBUG, DEBUG_WORKER */
-/* global RESPONSE_TYPE_SOLICITED */
-/* global RESPONSE_TYPE_UNSOLICITED */
-
-"use strict";
-
-/**
- * This is a specialized worker buffer for the Parcel protocol.
- *
- * NOTE: To prevent including/importing twice, this file should be included
- * in a file which already includes 'ril_consts.js' and 'require.js'.
- */
-(function(exports) {
-
- // Set to true in ril_consts.js to see debug messages
- let DEBUG = DEBUG_WORKER;
- // Need to inherit it.
- let Buf = require("resource://gre/modules/workers/worker_buf.js").Buf;
-
- let BufObject = function(aContext) {
- this.context = aContext;
- // This gets incremented each time we send out a parcel.
- this.mToken = 1;
- // Maps tokens we send out with requests to the request type, so that
- // when we get a response parcel back, we know what request it was for.
- this.mTokenRequestMap = new Map();
- // This is because the underlying 'Buf' is still using the 'init' pattern, so
- // this derived one needs to invoke it.
- // Using 'apply' style to mark it's a parent method calling explicitly.
- Buf._init.apply(this);
-
- // Remapping the request type to different values based on RIL version.
- // We only have to do this for SUBSCRIPTION right now, so I just make it
- // simple. A generic logic or structure could be discussed if we have more
- // use cases, especially the cases from different partners.
- this._requestMap = {};
- // RIL version 8.
- // For the CAF's proprietary parcels. Please see
- // https://www.codeaurora.org/cgit/quic/la/platform/hardware/ril/tree/include/telephony/ril.h?h=b2g_jb_3.2
- let map = {};
- map[REQUEST_SET_UICC_SUBSCRIPTION] = 114;
- map[REQUEST_SET_DATA_SUBSCRIPTION] = 115;
- this._requestMap[8] = map;
- // RIL version 9.
- // For the CAF's proprietary parcels. Please see
- // https://www.codeaurora.org/cgit/quic/la/platform/hardware/ril/tree/include/telephony/ril.h?h=b2g_kk_3.5
- map = {};
- map[REQUEST_SET_UICC_SUBSCRIPTION] = 115;
- map[REQUEST_SET_DATA_SUBSCRIPTION] = 116;
- this._requestMap[9] = map;
- };
-
- /**
- * "inherit" the basic worker buffer.
- */
- BufObject.prototype = Object.create(Buf);
-
- /**
- * Process one parcel.
- */
- BufObject.prototype.processParcel = function() {
- let responseType = this.readInt32();
-
- let requestType, options;
- if (responseType == RESPONSE_TYPE_SOLICITED) {
- let token = this.readInt32();
- let error = this.readInt32();
-
- options = this.mTokenRequestMap.get(token);
- if (!options) {
- if (DEBUG) {
- this.context.debug("Suspicious uninvited request found: " +
- token + ". Ignored!");
- }
- return;
- }
-
- this.mTokenRequestMap.delete(token);
- requestType = options.rilRequestType;
-
- if (error !== ERROR_SUCCESS) {
- options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[error] ||
- GECKO_ERROR_UNSPECIFIED_ERROR;
- }
- if (DEBUG) {
- this.context.debug("Solicited response for request type " + requestType +
- ", token " + token + ", error " + error);
- }
- } else if (responseType == RESPONSE_TYPE_UNSOLICITED) {
- requestType = this.readInt32();
- if (DEBUG) {
- this.context.debug("Unsolicited response for request type " + requestType);
- }
- } else {
- if (DEBUG) {
- this.context.debug("Unknown response type: " + responseType);
- }
- return;
- }
-
- this.context.RIL.handleParcel(requestType, this.readAvailable, options);
- };
-
- /**
- * Start a new outgoing parcel.
- *
- * @param type
- * Integer specifying the request type.
- * @param options [optional]
- * Object containing information about the request, e.g. the
- * original main thread message object that led to the RIL request.
- */
- BufObject.prototype.newParcel = function(type, options) {
- if (DEBUG) {
- this.context.debug("New outgoing parcel of type " + type);
- }
-
- // We're going to leave room for the parcel size at the beginning.
- this.outgoingIndex = this.PARCEL_SIZE_SIZE;
- this.writeInt32(this._reMapRequestType(type));
- this.writeInt32(this.mToken);
-
- if (!options) {
- options = {};
- }
- options.rilRequestType = type;
- this.mTokenRequestMap.set(this.mToken, options);
- this.mToken++;
- return this.mToken;
- };
-
- BufObject.prototype.simpleRequest = function(type, options) {
- this.newParcel(type, options);
- this.sendParcel();
- };
-
- BufObject.prototype.onSendParcel = function(parcel) {
- self.postRILMessage(this.context.clientId, parcel);
- };
-
- /**
- * Remapping the request type to different values based on RIL version.
- * We only have to do this for SUBSCRIPTION right now, so I just make it
- * simple. A generic logic or structure could be discussed if we have more
- * use cases, especially the cases from different partners.
- */
- BufObject.prototype._reMapRequestType = function(type) {
- for (let version in this._requestMap) {
- if (this.context.RIL.version <= version) {
- let newType = this._requestMap[version][type];
- if (newType) {
- if (DEBUG) {
- this.context.debug("Remap request type to " + newType);
- }
- return newType;
- }
- }
- }
- return type;
- };
-
- // Before we make sure to form it as a module would not add extra
- // overhead of module loading, we need to define it in this way
- // rather than 'module.exports' it as a module component.
- exports.BufObject = BufObject;
-})(self); // in worker self is the global
-
diff --git a/dom/system/gonk/ril_worker_telephony_request_queue.js b/dom/system/gonk/ril_worker_telephony_request_queue.js
deleted file mode 100644
index 4dba7a42f..000000000
--- a/dom/system/gonk/ril_worker_telephony_request_queue.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/* global DEBUG, DEBUG_WORKER */
-/* global REQUEST_GET_CURRENT_CALLS */
-/* global REQUEST_ANSWER, REQUEST_CONFERENCE, REQUEST_DIAL */
-/* global REQUEST_DIAL_EMERGENCY_CALL, REQUEST_HANGUP */
-/* global REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND */
-/* global REQUEST_HANGUP_WAITING_OR_BACKGROUND */
-/* global REQUEST_SEPARATE_CONNECTION */
-/* global REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, REQUEST_UDUB */
-
-"use strict";
-
-(function(exports) {
-
- const TELEPHONY_REQUESTS = [
- REQUEST_GET_CURRENT_CALLS,
- REQUEST_ANSWER,
- REQUEST_CONFERENCE,
- REQUEST_DIAL,
- REQUEST_DIAL_EMERGENCY_CALL,
- REQUEST_HANGUP,
- REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
- REQUEST_HANGUP_WAITING_OR_BACKGROUND,
- REQUEST_SEPARATE_CONNECTION,
- REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
- REQUEST_UDUB
- ];
-
- // Set to true in ril_consts.js to see debug messages
- let DEBUG = DEBUG_WORKER;
-
- /**
- * Queue entry; only used in the queue.
- */
- let TelephonyRequestEntry = function(request, callback) {
- this.request = request;
- this.callback = callback;
- };
-
- let TelephonyRequestQueue = function(ril) {
- this.ril = ril;
- this.currentQueue = null; // Point to the current running queue.
-
- this.queryQueue = [];
- this.controlQueue = [];
- };
-
- TelephonyRequestQueue.prototype._getQueue = function(request) {
- return (request === REQUEST_GET_CURRENT_CALLS) ? this.queryQueue
- : this.controlQueue;
- };
-
- TelephonyRequestQueue.prototype._getAnotherQueue = function(queue) {
- return (this.queryQueue === queue) ? this.controlQueue : this.queryQueue;
- };
-
- TelephonyRequestQueue.prototype._find = function(queue, request) {
- for (let i = 0; i < queue.length; ++i) {
- if (queue[i].request === request) {
- return i;
- }
- }
- return -1;
- };
-
- TelephonyRequestQueue.prototype._startQueue = function(queue) {
- if (queue.length === 0) {
- return;
- }
-
- // We only need to keep one entry for queryQueue.
- if (queue === this.queryQueue) {
- queue.splice(1, queue.length - 1);
- }
-
- this.currentQueue = queue;
- for (let entry of queue) {
- this._executeEntry(entry);
- }
- };
-
- TelephonyRequestQueue.prototype._executeEntry = function(entry) {
- if (DEBUG) {
- this.debug("execute " + this._getRequestName(entry.request));
- }
- entry.callback();
- };
-
- TelephonyRequestQueue.prototype._getRequestName = function(request) {
- let method = this.ril[request];
- return (typeof method === 'function') ? method.name : "";
- };
-
- TelephonyRequestQueue.prototype.debug = function(msg) {
- this.ril.context.debug("[TeleQ] " + msg);
- };
-
- TelephonyRequestQueue.prototype.isValidRequest = function(request) {
- return TELEPHONY_REQUESTS.indexOf(request) !== -1;
- };
-
- TelephonyRequestQueue.prototype.push = function(request, callback) {
- if (!this.isValidRequest(request)) {
- if (DEBUG) {
- this.debug("Error: " + this._getRequestName(request) +
- " is not a telephony request");
- }
- return;
- }
-
- if (DEBUG) {
- this.debug("push " + this._getRequestName(request));
- }
- let entry = new TelephonyRequestEntry(request, callback);
- let queue = this._getQueue(request);
- queue.push(entry);
-
- // Try to run the request.
- if (this.currentQueue === queue) {
- this._executeEntry(entry);
- } else if (!this.currentQueue) {
- this._startQueue(queue);
- }
- };
-
- TelephonyRequestQueue.prototype.pop = function(request) {
- if (!this.isValidRequest(request)) {
- if (DEBUG) {
- this.debug("Error: " + this._getRequestName(request) +
- " is not a telephony request");
- }
- return;
- }
-
- if (DEBUG) {
- this.debug("pop " + this._getRequestName(request));
- }
- let queue = this._getQueue(request);
- let index = this._find(queue, request);
- if (index === -1) {
- throw new Error("Cannot find the request in telephonyRequestQueue.");
- } else {
- queue.splice(index, 1);
- }
-
- if (queue.length === 0) {
- this.currentQueue = null;
- this._startQueue(this._getAnotherQueue(queue));
- }
- };
-
-
- // Before we make sure to form it as a module would not add extra
- // overhead of module loading, we need to define it in this way
- // rather than 'module.exports' it as a module component.
- exports.TelephonyRequestQueue = TelephonyRequestQueue;
-})(self); // in worker self is the global
-
diff --git a/dom/system/gonk/systemlibs.js b/dom/system/gonk/systemlibs.js
deleted file mode 100644
index a27b30e20..000000000
--- a/dom/system/gonk/systemlibs.js
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-if (!this.ctypes) {
- // We're likely being loaded as a JSM.
- this.EXPORTED_SYMBOLS = [ "libcutils", "netHelpers" ];
- Components.utils.import("resource://gre/modules/ctypes.jsm");
-}
-
-const SYSTEM_PROPERTY_KEY_MAX = 32;
-const SYSTEM_PROPERTY_VALUE_MAX = 92;
-
-// We leave this as 'undefined' instead of setting it to 'false'. That
-// way a file that includes us can have it defined already without us
-// overriding the value here.
-var DEBUG;
-
-/**
- * Expose some system-level functions.
- */
-this.libcutils = (function() {
- let lib;
- try {
- lib = ctypes.open("libcutils.so");
- } catch(ex) {
- // Return a fallback option in case libcutils.so isn't present (e.g.
- // when building Firefox with MOZ_B2G_RIL.
- if (DEBUG) {
- dump("Could not load libcutils.so. Using fake propdb.\n");
- }
- let fake_propdb = Object.create(null);
- return {
- property_get: function(key, defaultValue) {
- if (key in fake_propdb) {
- return fake_propdb[key];
- }
- return defaultValue === undefined ? null : defaultValue;
- },
- property_set: function(key, value) {
- fake_propdb[key] = value;
- }
- };
- }
-
- let c_property_get = lib.declare("property_get", ctypes.default_abi,
- ctypes.int, // return value: length
- ctypes.char.ptr, // key
- ctypes.char.ptr, // value
- ctypes.char.ptr); // default
- let c_property_set = lib.declare("property_set", ctypes.default_abi,
- ctypes.int, // return value: success
- ctypes.char.ptr, // key
- ctypes.char.ptr); // value
- let c_value_buf = ctypes.char.array(SYSTEM_PROPERTY_VALUE_MAX)();
-
- return {
-
- /**
- * Get a system property.
- *
- * @param key
- * Name of the property
- * @param defaultValue [optional]
- * Default value to return if the property isn't set (default: null)
- */
- property_get: function(key, defaultValue) {
- if (defaultValue === undefined) {
- defaultValue = null;
- }
- c_property_get(key, c_value_buf, defaultValue);
- return c_value_buf.readString();
- },
-
- /**
- * Set a system property
- *
- * @param key
- * Name of the property
- * @param value
- * Value to set the property to.
- */
- property_set: function(key, value) {
- let rv = c_property_set(key, value);
- if (rv) {
- throw Error('libcutils.property_set("' + key + '", "' + value +
- '") failed with error ' + rv);
- }
- }
-
- };
-})();
-
-/**
- * Helpers for conversions.
- */
-this.netHelpers = {
-
- /**
- * Swap byte orders for 32-bit value
- */
- swap32: function(n) {
- return (((n >> 24) & 0xFF) << 0) |
- (((n >> 16) & 0xFF) << 8) |
- (((n >> 8) & 0xFF) << 16) |
- (((n >> 0) & 0xFF) << 24);
- },
-
- /**
- * Convert network byte order to host byte order
- * Note: Assume that the system is little endian
- */
- ntohl: function(n) {
- return this.swap32(n);
- },
-
- /**
- * Convert host byte order to network byte order
- * Note: Assume that the system is little endian
- */
- htonl: function(n) {
- return this.swap32(n);
- },
-
- /**
- * Convert integer representation of an IP address to the string
- * representation.
- *
- * @param ip
- * IP address in number format.
- */
- ipToString: function(ip) {
- return ((ip >> 0) & 0xFF) + "." +
- ((ip >> 8) & 0xFF) + "." +
- ((ip >> 16) & 0xFF) + "." +
- ((ip >> 24) & 0xFF);
- },
-
- /**
- * Convert string representation of an IP address to the integer
- * representation (network byte order).
- *
- * @param string
- * String containing the IP address.
- */
- stringToIP: function(string) {
- if (!string) {
- return null;
- }
- let ip = 0;
- let start, end = -1;
- for (let i = 0; i < 4; i++) {
- start = end + 1;
- end = string.indexOf(".", start);
- if (end == -1) {
- end = string.length;
- }
- let num = parseInt(string.slice(start, end), 10);
- if (isNaN(num)) {
- return null;
- }
- ip |= num << (i * 8);
- }
- return ip;
- },
-
- /**
- * Make a subnet mask.
- */
- makeMask: function(len) {
- let mask = 0;
- for (let i = 0; i < len; ++i) {
- mask |= (0x80000000 >> i);
- }
- return this.ntohl(mask);
- },
-
- /**
- * Get Mask length from given mask address
- */
- getMaskLength: function(mask) {
- let len = 0;
- let netmask = this.ntohl(mask);
- while (netmask & 0x80000000) {
- len++;
- netmask = netmask << 1;
- }
- return len;
- }
-};
diff --git a/dom/system/gonk/tests/header_helpers.js b/dom/system/gonk/tests/header_helpers.js
deleted file mode 100644
index 8d1144f75..000000000
--- a/dom/system/gonk/tests/header_helpers.js
+++ /dev/null
@@ -1,217 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-
-var subscriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Ci.mozIJSSubScriptLoader);
-
-/**
- * Start a new RIL worker.
- *
- * @param custom_ns
- * Namespace with symbols to be injected into the new worker
- * namespace.
- *
- * @return an object that represents the worker's namespace.
- *
- * @note that this does not start an actual worker thread. The worker
- * is executed on the main thread, within a separate namespace object.
- */
-function newWorker(custom_ns) {
- let worker_ns = {
- importScripts: function() {
- Array.slice(arguments).forEach(function(script) {
- if (!script.startsWith("resource:")) {
- script = "resource://gre/modules/" + script;
- }
- subscriptLoader.loadSubScript(script, this);
- }, this);
- },
-
- postRILMessage: function(message) {
- },
-
- postMessage: function(message) {
- },
-
- // Define these variables inside the worker scope so ES5 strict mode
- // doesn't flip out.
- onmessage: undefined,
- onerror: undefined,
-
- DEBUG: true
- };
- // The 'self' variable in a worker points to the worker's own namespace.
- worker_ns.self = worker_ns;
-
- // Copy the custom definitions over.
- for (let key in custom_ns) {
- worker_ns[key] = custom_ns[key];
- }
-
- // fake require() for toolkit/components/workerloader/require.js
- let require = (function() {
- return function require(script) {
- worker_ns.module = {};
- worker_ns.importScripts(script);
- return worker_ns;
- }
- })();
-
- Object.freeze(require);
- Object.defineProperty(worker_ns, "require", {
- value: require,
- enumerable: true,
- configurable: false
- });
-
- // Load the RIL worker itself.
- worker_ns.importScripts("ril_worker.js");
-
- // Register at least one client.
- worker_ns.ContextPool.registerClient({ clientId: 0 });
-
- return worker_ns;
-}
-
-/**
- * Create a buffered RIL worker.
- *
- * @return A worker object that stores sending octets in a internal buffer.
- */
-function newUint8Worker() {
- let worker = newWorker();
- let index = 0; // index for read
- let buf = [];
-
- let context = worker.ContextPool._contexts[0];
- context.Buf.writeUint8 = function(value) {
- buf.push(value);
- };
-
- context.Buf.readUint8 = function() {
- return buf[index++];
- };
-
- context.Buf.seekIncoming = function(offset) {
- index += offset;
- };
-
- context.Buf.getReadAvailable = function() {
- return buf.length - index;
- };
-
- worker.debug = do_print;
-
- return worker;
-}
-
-/**
- * Create a worker that keeps posted chrome message.
- */
-function newInterceptWorker() {
- let postedMessage;
- let worker = newWorker({
- postRILMessage: function(data) {
- },
- postMessage: function(message) {
- postedMessage = message;
- }
- });
- return {
- get postedMessage() {
- return postedMessage;
- },
- get worker() {
- return worker;
- }
- };
-}
-
-/**
- * Create a parcel suitable for postRILMessage().
- *
- * @param fakeParcelSize
- * Value to be written to parcel size field for testing
- * incorrect/incomplete parcel reading. Replaced with correct
- * one determined length of data if negative.
- * @param response
- * Response code of the incoming parcel.
- * @param request
- * Request code of the incoming parcel.
- * @param data
- * Extra data to be appended.
- *
- * @return an Uint8Array carrying all parcel data.
- */
-function newIncomingParcel(fakeParcelSize, response, request, data) {
- const UINT32_SIZE = 4;
- const PARCEL_SIZE_SIZE = 4;
-
- let realParcelSize = data.length + 2 * UINT32_SIZE;
- let buffer = new ArrayBuffer(realParcelSize + PARCEL_SIZE_SIZE);
- let bytes = new Uint8Array(buffer);
-
- let writeIndex = 0;
- function writeUint8(value) {
- bytes[writeIndex] = value;
- ++writeIndex;
- }
-
- function writeInt32(value) {
- writeUint8(value & 0xff);
- writeUint8((value >> 8) & 0xff);
- writeUint8((value >> 16) & 0xff);
- writeUint8((value >> 24) & 0xff);
- }
-
- function writeParcelSize(value) {
- writeUint8((value >> 24) & 0xff);
- writeUint8((value >> 16) & 0xff);
- writeUint8((value >> 8) & 0xff);
- writeUint8(value & 0xff);
- }
-
- if (fakeParcelSize < 0) {
- fakeParcelSize = realParcelSize;
- }
- writeParcelSize(fakeParcelSize);
-
- writeInt32(response);
- writeInt32(request);
-
- // write parcel data
- for (let ii = 0; ii < data.length; ++ii) {
- writeUint8(data[ii]);
- }
-
- return bytes;
-}
-
-/**
- * Create a parcel buffer which represents the hex string.
- *
- * @param hexString
- * The HEX string to be converted.
- *
- * @return an Uint8Array carrying all parcel data.
- */
-function hexStringToParcelByteArrayData(hexString) {
- let length = Math.ceil((hexString.length / 2));
- let bytes = new Uint8Array(4 + length);
-
- bytes[0] = length & 0xFF;
- bytes[1] = (length >> 8) & 0xFF;
- bytes[2] = (length >> 16) & 0xFF;
- bytes[3] = (length >> 24) & 0xFF;
-
- for (let i = 0; i < length; i ++) {
- bytes[i + 4] = Number.parseInt(hexString.substr(i * 2, 2), 16);
- }
-
- return bytes;
-}
diff --git a/dom/system/gonk/tests/marionette/head.js b/dom/system/gonk/tests/marionette/head.js
deleted file mode 100644
index 5a6ee1272..000000000
--- a/dom/system/gonk/tests/marionette/head.js
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_CONTEXT = "chrome";
-
-const SETTINGS_KEY_DATA_ENABLED = "ril.data.enabled";
-const SETTINGS_KEY_DATA_APN_SETTINGS = "ril.data.apnSettings";
-const SETTINGS_KEY_WIFI_ENABLED = "wifi.enabled";
-
-const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
-const TOPIC_NETWORK_ACTIVE_CHANGED = "network-active-changed";
-
-const NETWORK_STATE_UNKNOWN = Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN;
-const NETWORK_STATE_CONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTING;
-const NETWORK_STATE_CONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
-const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTING;
-const NETWORK_STATE_DISCONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
-
-const NETWORK_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
-const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS;
-const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL;
-const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS;
-const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN;
-const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA;
-
-const networkTypes = [
- NETWORK_TYPE_MOBILE,
- NETWORK_TYPE_MOBILE_MMS,
- NETWORK_TYPE_MOBILE_SUPL,
- NETWORK_TYPE_MOBILE_IMS,
- NETWORK_TYPE_MOBILE_DUN,
- NETWORK_TYPE_MOBILE_FOTA
-];
-
-var Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise;
-
-var ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
-ok(ril, "ril.constructor is " + ril.constructor);
-
-var radioInterface = ril.getRadioInterface(0);
-ok(radioInterface, "radioInterface.constructor is " + radioInterface.constrctor);
-
-var _pendingEmulatorShellCmdCount = 0;
-var _pendingEmulatorCmdCount = 0;
-
-/**
- * Send emulator shell command with safe guard.
- *
- * We should only call |finish()| after all emulator shell command transactions
- * end, so here comes with the pending counter. Resolve when the emulator
- * shell gives response. Never reject.
- *
- * Fulfill params:
- * result -- an array of emulator shell response lines.
- *
- * @param aCommands
- * A string array commands to be passed to emulator through adb shell.
- *
- * @return A deferred promise.
- */
-function runEmulatorShellCmdSafe(aCommands) {
- return new Promise(function(aResolve, aReject) {
- ++_pendingEmulatorShellCmdCount;
- runEmulatorShell(aCommands, function(aResult) {
- --_pendingEmulatorShellCmdCount;
-
- log("Emulator shell response: " + JSON.stringify(aResult));
- aResolve(aResult);
- });
- });
-}
-
-/**
- * Send emulator command with safe guard.
- *
- * We should only call |finish()| after all emulator command transactions
- * end, so here comes with the pending counter. Resolve when the emulator
- * gives positive response, and reject otherwise.
- *
- * Fulfill params:
- * result -- an array of emulator response lines.
- * Reject params:
- * result -- an array of emulator response lines.
- *
- * @param aCommand
- * A string command to be passed to emulator through its telnet console.
- *
- * @return A deferred promise.
- */
-function runEmulatorCmdSafe(aCommand) {
- log(aCommand);
- return new Promise(function(aResolve, aReject) {
- ++_pendingEmulatorCmdCount;
- runEmulatorCmd(aCommand, function(aResult) {
- --_pendingEmulatorCmdCount;
-
- log("Emulator console response: " + JSON.stringify(aResult));
- if (Array.isArray(aResult) &&
- aResult[aResult.length - 1] === "OK") {
- aResolve(aResult);
- } else {
- aReject(aResult);
- }
- });
- });
-}
-
-/**
- * Get mozSettings value specified by @aKey.
- *
- * Resolve if that mozSettings value is retrieved successfully, reject
- * otherwise.
- *
- * Fulfill params: The corresponding mozSettings value of the key.
- * Reject params: (none)
- *
- * @param aKey
- * A string.
- * @param aAllowError [optional]
- * A boolean value. If set to true, an error response won't be treated
- * as test failure. Default: false.
- *
- * @return A deferred promise.
- */
-function getSettings(aKey, aAllowError) {
- let request = window.navigator.mozSettings.createLock().get(aKey);
- return request.then(function resolve(aValue) {
- log("getSettings(" + aKey + ") - success");
- return aValue[aKey];
- }, function reject(aError) {
- ok(aAllowError, "getSettings(" + aKey + ") - error");
- });
-}
-
-/**
- * Set mozSettings values.
- *
- * Resolve if that mozSettings value is set successfully, reject otherwise.
- *
- * Fulfill params: (none)
- * Reject params: (none)
- *
- * @param aKey
- * A string key.
- * @param aValue
- * An object value.
- * @param aAllowError [optional]
- * A boolean value. If set to true, an error response won't be treated
- * as test failure. Default: false.
- *
- * @return A deferred promise.
- */
-function setSettings(aKey, aValue, aAllowError) {
- let settings = {};
- settings[aKey] = aValue;
- let lock = window.navigator.mozSettings.createLock();
- let request = lock.set(settings);
- let deferred = Promise.defer();
- lock.onsettingstransactionsuccess = function () {
- log("setSettings(" + JSON.stringify(settings) + ") - success");
- deferred.resolve();
- };
- lock.onsettingstransactionfailure = function () {
- ok(aAllowError, "setSettings(" + JSON.stringify(settings) + ") - error");
- // We resolve even though we've thrown an error, since the ok()
- // will do that.
- deferred.resolve();
- };
- return deferred.promise;
-}
-
-/**
- * Wait for observer event.
- *
- * Resolve if that topic event occurs. Never reject.
- *
- * Fulfill params: the subject passed.
- *
- * @param aTopic
- * A string topic name.
- *
- * @return A deferred promise.
- */
-function waitForObserverEvent(aTopic) {
- let obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
- let deferred = Promise.defer();
-
- obs.addObserver(function observer(subject, topic, data) {
- if (topic === aTopic) {
- obs.removeObserver(observer, aTopic);
- deferred.resolve(subject);
- }
- }, aTopic, false);
-
- return deferred.promise;
-}
-
-/**
- * Wait for one named event.
- *
- * Resolve if that named event occurs. Never reject.
- *
- * Fulfill params: the DOMEvent passed.
- *
- * @param aEventTarget
- * An EventTarget object.
- * @param aEventName
- * A string event name.
- * @param aMatchFun [optional]
- * A matching function returns true or false to filter the event.
- *
- * @return A deferred promise.
- */
-function waitForTargetEvent(aEventTarget, aEventName, aMatchFun) {
- return new Promise(function(aResolve, aReject) {
- aEventTarget.addEventListener(aEventName, function onevent(aEvent) {
- if (!aMatchFun || aMatchFun(aEvent)) {
- aEventTarget.removeEventListener(aEventName, onevent);
- ok(true, "Event '" + aEventName + "' got.");
- aResolve(aEvent);
- }
- });
- });
-}
-
-/**
- * Set the default data connection enabling state, wait for
- * "network-connection-state-changed" event and verify state.
- *
- * Fulfill params: instance of nsIRilNetworkInfo of the network connected.
- *
- * @param aEnabled
- * A boolean state.
- *
- * @return A deferred promise.
- */
-function setDataEnabledAndWait(aEnabled) {
- let promises = [];
- promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
- .then(function(aSubject) {
- ok(aSubject instanceof Ci.nsIRilNetworkInfo,
- "subject should be an instance of nsIRilNetworkInfo");
- is(aSubject.type, NETWORK_TYPE_MOBILE,
- "subject.type should be " + NETWORK_TYPE_MOBILE);
- is(aSubject.state,
- aEnabled ? Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED
- : Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
- "subject.state should be " + aEnabled ? "CONNECTED" : "DISCONNECTED");
-
- return aSubject;
- }));
- promises.push(setSettings(SETTINGS_KEY_DATA_ENABLED, aEnabled));
-
- return Promise.all(promises).then(aValues => aValues[0]);
-}
-
-/**
- * Setup a certain type of data connection, wait for
- * "network-connection-state-changed" event and verify state.
- *
- * Fulfill params: instance of nsIRilNetworkInfo of the network connected.
- *
- * @param aNetworkType
- * The mobile network type to setup.
- *
- * @return A deferred promise.
- */
-function setupDataCallAndWait(aNetworkType) {
- log("setupDataCallAndWait: " + aNetworkType);
-
- let promises = [];
- promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
- .then(function(aSubject) {
- ok(aSubject instanceof Ci.nsIRilNetworkInfo,
- "subject should be an instance of nsIRilNetworkInfo");
- is(aSubject.type, aNetworkType,
- "subject.type should be " + aNetworkType);
- is(aSubject.state, Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED,
- "subject.state should be CONNECTED");
-
- return aSubject;
- }));
- promises.push(radioInterface.setupDataCallByType(aNetworkType));
-
- return Promise.all(promises).then(aValues => aValues[0]);
-}
-
-/**
- * Deactivate a certain type of data connection, wait for
- * "network-connection-state-changed" event and verify state.
- *
- * Fulfill params: (none)
- *
- * @param aNetworkType
- * The mobile network type to deactivate.
- *
- * @return A deferred promise.
- */
-function deactivateDataCallAndWait(aNetworkType) {
- log("deactivateDataCallAndWait: " + aNetworkType);
-
- let promises = [];
- promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
- .then(function(aSubject) {
- ok(aSubject instanceof Ci.nsIRilNetworkInfo,
- "subject should be an instance of nsIRilNetworkInfo");
- is(aSubject.type, aNetworkType,
- "subject.type should be " + aNetworkType);
- is(aSubject.state, Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
- "subject.state should be DISCONNECTED");
- }));
- promises.push(radioInterface.deactivateDataCallByType(aNetworkType));
-
- return Promise.all(promises);
-}
-
-/**
- * Wait for pending emulator transactions and call |finish()|.
- */
-function cleanUp() {
- // Use ok here so that we have at least one test run.
- ok(true, ":: CLEANING UP ::");
-
- waitFor(finish, function() {
- return _pendingEmulatorShellCmdCount === 0 &&
- _pendingEmulatorCmdCount === 0;
- });
-}
-
-/**
- * Basic test routine helper.
- *
- * This helper does nothing but clean-ups.
- *
- * @param aTestCaseMain
- * A function that takes no parameter.
- */
-function startTestBase(aTestCaseMain) {
- Promise.resolve()
- .then(aTestCaseMain)
- .then(cleanUp, function(aException) {
- ok(false, "promise rejects during test: " + aException);
- cleanUp();
- });
-}
diff --git a/dom/system/gonk/tests/marionette/manifest.ini b/dom/system/gonk/tests/marionette/manifest.ini
deleted file mode 100644
index 528fe3baf..000000000
--- a/dom/system/gonk/tests/marionette/manifest.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[DEFAULT]
-run-if = buildapp == 'b2g'
-
-[test_geolocation.js]
-skip-if = true # Bug 808783
-[test_fakevolume.js]
-[test_ril_code_quality.py]
-[test_screen_state.js]
-[test_dsds_numRadioInterfaces.js]
-[test_data_connection.js]
-[test_network_active_changed.js]
-[test_multiple_data_connection.js]
-[test_data_connection_proxy.js]
-[test_network_interface_list_service.js]
-[test_all_network_info.js]
-[test_network_interface_mtu.js]
-skip-if = android_version < '19'
-[test_timezone_changes.js]
-skip-if = android_version < '19'
diff --git a/dom/system/gonk/tests/marionette/ril_jshint/README.md b/dom/system/gonk/tests/marionette/ril_jshint/README.md
deleted file mode 100644
index a63967d63..000000000
--- a/dom/system/gonk/tests/marionette/ril_jshint/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-Test RIL Code Quality
-=====================
-
-For more information, please refer to
-
-* Bug 880643 - B2G RIL: Add a code quality test on try server for RIL javascript code in gecko
-* Slide: https://speakerdeck.com/aknow/improve-code-quality-of-ril-code-by-jshint
-* Document: https://hackpad.com/Code-Quality-Test-For-RIL-Javascript-Code-In-Gecko-cz5j7YIGiw8
-
diff --git a/dom/system/gonk/tests/marionette/ril_jshint/jshint.js b/dom/system/gonk/tests/marionette/ril_jshint/jshint.js
deleted file mode 100644
index ec5263a5b..000000000
--- a/dom/system/gonk/tests/marionette/ril_jshint/jshint.js
+++ /dev/null
@@ -1,11096 +0,0 @@
-//2.1.3
-var JSHINT;
-(function () {
-var require;
-require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
-// shim for using process in browser
-
-var process = module.exports = {};
-
-process.nextTick = (function () {
- var canSetImmediate = typeof window !== 'undefined'
- && window.setImmediate;
- var canPost = typeof window !== 'undefined'
- && window.postMessage && window.addEventListener
- ;
-
- if (canSetImmediate) {
- return function (f) { return window.setImmediate(f) };
- }
-
- if (canPost) {
- var queue = [];
- window.addEventListener('message', function (ev) {
- if (ev.source === window && ev.data === 'process-tick') {
- ev.stopPropagation();
- if (queue.length > 0) {
- var fn = queue.shift();
- fn();
- }
- }
- }, true);
-
- return function nextTick(fn) {
- queue.push(fn);
- window.postMessage('process-tick', '*');
- };
- }
-
- return function nextTick(fn) {
- setTimeout(fn, 0);
- };
-})();
-
-process.title = 'browser';
-process.browser = true;
-process.env = {};
-process.argv = [];
-
-process.binding = function (name) {
- throw new Error('process.binding is not supported');
-}
-
-// TODO(shtylman)
-process.cwd = function () { return '/' };
-process.chdir = function (dir) {
- throw new Error('process.chdir is not supported');
-};
-
-},{}],2:[function(require,module,exports){
-(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
-
-var EventEmitter = exports.EventEmitter = process.EventEmitter;
-var isArray = typeof Array.isArray === 'function'
- ? Array.isArray
- : function (xs) {
- return Object.prototype.toString.call(xs) === '[object Array]'
- }
-;
-function indexOf (xs, x) {
- if (xs.indexOf) return xs.indexOf(x);
- for (var i = 0; i < xs.length; i++) {
- if (x === xs[i]) return i;
- }
- return -1;
-}
-
-// By default EventEmitters will print a warning if more than
-// 10 listeners are added to it. This is a useful default which
-// helps finding memory leaks.
-//
-// Obviously not all Emitters should be limited to 10. This function allows
-// that to be increased. Set to zero for unlimited.
-var defaultMaxListeners = 10;
-EventEmitter.prototype.setMaxListeners = function(n) {
- if (!this._events) this._events = {};
- this._events.maxListeners = n;
-};
-
-
-EventEmitter.prototype.emit = function(type) {
- // If there is no 'error' event listener then throw.
- if (type === 'error') {
- if (!this._events || !this._events.error ||
- (isArray(this._events.error) && !this._events.error.length))
- {
- if (arguments[1] instanceof Error) {
- throw arguments[1]; // Unhandled 'error' event
- } else {
- throw new Error("Uncaught, unspecified 'error' event.");
- }
- return false;
- }
- }
-
- if (!this._events) return false;
- var handler = this._events[type];
- if (!handler) return false;
-
- if (typeof handler == 'function') {
- switch (arguments.length) {
- // fast cases
- case 1:
- handler.call(this);
- break;
- case 2:
- handler.call(this, arguments[1]);
- break;
- case 3:
- handler.call(this, arguments[1], arguments[2]);
- break;
- // slower
- default:
- var args = Array.prototype.slice.call(arguments, 1);
- handler.apply(this, args);
- }
- return true;
-
- } else if (isArray(handler)) {
- var args = Array.prototype.slice.call(arguments, 1);
-
- var listeners = handler.slice();
- for (var i = 0, l = listeners.length; i < l; i++) {
- listeners[i].apply(this, args);
- }
- return true;
-
- } else {
- return false;
- }
-};
-
-// EventEmitter is defined in src/node_events.cc
-// EventEmitter.prototype.emit() is also defined there.
-EventEmitter.prototype.addListener = function(type, listener) {
- if ('function' !== typeof listener) {
- throw new Error('addListener only takes instances of Function');
- }
-
- if (!this._events) this._events = {};
-
- // To avoid recursion in the case that type == "newListeners"! Before
- // adding it to the listeners, first emit "newListeners".
- this.emit('newListener', type, listener);
-
- if (!this._events[type]) {
- // Optimize the case of one listener. Don't need the extra array object.
- this._events[type] = listener;
- } else if (isArray(this._events[type])) {
-
- // Check for listener leak
- if (!this._events[type].warned) {
- var m;
- if (this._events.maxListeners !== undefined) {
- m = this._events.maxListeners;
- } else {
- m = defaultMaxListeners;
- }
-
- if (m && m > 0 && this._events[type].length > m) {
- this._events[type].warned = true;
- console.error('(node) warning: possible EventEmitter memory ' +
- 'leak detected. %d listeners added. ' +
- 'Use emitter.setMaxListeners() to increase limit.',
- this._events[type].length);
- console.trace();
- }
- }
-
- // If we've already got an array, just append.
- this._events[type].push(listener);
- } else {
- // Adding the second element, need to change to array.
- this._events[type] = [this._events[type], listener];
- }
-
- return this;
-};
-
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
-
-EventEmitter.prototype.once = function(type, listener) {
- var self = this;
- self.on(type, function g() {
- self.removeListener(type, g);
- listener.apply(this, arguments);
- });
-
- return this;
-};
-
-EventEmitter.prototype.removeListener = function(type, listener) {
- if ('function' !== typeof listener) {
- throw new Error('removeListener only takes instances of Function');
- }
-
- // does not use listeners(), so no side effect of creating _events[type]
- if (!this._events || !this._events[type]) return this;
-
- var list = this._events[type];
-
- if (isArray(list)) {
- var i = indexOf(list, listener);
- if (i < 0) return this;
- list.splice(i, 1);
- if (list.length == 0)
- delete this._events[type];
- } else if (this._events[type] === listener) {
- delete this._events[type];
- }
-
- return this;
-};
-
-EventEmitter.prototype.removeAllListeners = function(type) {
- if (arguments.length === 0) {
- this._events = {};
- return this;
- }
-
- // does not use listeners(), so no side effect of creating _events[type]
- if (type && this._events && this._events[type]) this._events[type] = null;
- return this;
-};
-
-EventEmitter.prototype.listeners = function(type) {
- if (!this._events) this._events = {};
- if (!this._events[type]) this._events[type] = [];
- if (!isArray(this._events[type])) {
- this._events[type] = [this._events[type]];
- }
- return this._events[type];
-};
-
-})(require("__browserify_process"))
-},{"__browserify_process":1}],3:[function(require,module,exports){
-(function(){// jshint -W001
-
-"use strict";
-
-// Identifiers provided by the ECMAScript standard.
-
-exports.reservedVars = {
- arguments : false,
- NaN : false
-};
-
-exports.ecmaIdentifiers = {
- Array : false,
- Boolean : false,
- Date : false,
- decodeURI : false,
- decodeURIComponent : false,
- encodeURI : false,
- encodeURIComponent : false,
- Error : false,
- "eval" : false,
- EvalError : false,
- Function : false,
- hasOwnProperty : false,
- isFinite : false,
- isNaN : false,
- JSON : false,
- Math : false,
- Map : false,
- Number : false,
- Object : false,
- parseInt : false,
- parseFloat : false,
- RangeError : false,
- ReferenceError : false,
- RegExp : false,
- Set : false,
- String : false,
- SyntaxError : false,
- TypeError : false,
- URIError : false,
- WeakMap : false
-};
-
-// Global variables commonly provided by a web browser environment.
-
-exports.browser = {
- ArrayBuffer : false,
- ArrayBufferView : false,
- Audio : false,
- Blob : false,
- addEventListener : false,
- applicationCache : false,
- atob : false,
- blur : false,
- btoa : false,
- clearInterval : false,
- clearTimeout : false,
- close : false,
- closed : false,
- DataView : false,
- DOMParser : false,
- defaultStatus : false,
- document : false,
- Element : false,
- ElementTimeControl : false,
- event : false,
- FileReader : false,
- Float32Array : false,
- Float64Array : false,
- FormData : false,
- focus : false,
- frames : false,
- getComputedStyle : false,
- HTMLElement : false,
- HTMLAnchorElement : false,
- HTMLBaseElement : false,
- HTMLBlockquoteElement: false,
- HTMLBodyElement : false,
- HTMLBRElement : false,
- HTMLButtonElement : false,
- HTMLCanvasElement : false,
- HTMLDirectoryElement : false,
- HTMLDivElement : false,
- HTMLDListElement : false,
- HTMLFieldSetElement : false,
- HTMLFontElement : false,
- HTMLFormElement : false,
- HTMLFrameElement : false,
- HTMLFrameSetElement : false,
- HTMLHeadElement : false,
- HTMLHeadingElement : false,
- HTMLHRElement : false,
- HTMLHtmlElement : false,
- HTMLIFrameElement : false,
- HTMLImageElement : false,
- HTMLInputElement : false,
- HTMLIsIndexElement : false,
- HTMLLabelElement : false,
- HTMLLayerElement : false,
- HTMLLegendElement : false,
- HTMLLIElement : false,
- HTMLLinkElement : false,
- HTMLMapElement : false,
- HTMLMenuElement : false,
- HTMLMetaElement : false,
- HTMLModElement : false,
- HTMLObjectElement : false,
- HTMLOListElement : false,
- HTMLOptGroupElement : false,
- HTMLOptionElement : false,
- HTMLParagraphElement : false,
- HTMLParamElement : false,
- HTMLPreElement : false,
- HTMLQuoteElement : false,
- HTMLScriptElement : false,
- HTMLSelectElement : false,
- HTMLStyleElement : false,
- HTMLTableCaptionElement: false,
- HTMLTableCellElement : false,
- HTMLTableColElement : false,
- HTMLTableElement : false,
- HTMLTableRowElement : false,
- HTMLTableSectionElement: false,
- HTMLTextAreaElement : false,
- HTMLTitleElement : false,
- HTMLUListElement : false,
- HTMLVideoElement : false,
- history : false,
- Int16Array : false,
- Int32Array : false,
- Int8Array : false,
- Image : false,
- length : false,
- localStorage : false,
- location : false,
- MessageChannel : false,
- MessageEvent : false,
- MessagePort : false,
- moveBy : false,
- moveTo : false,
- MutationObserver : false,
- name : false,
- Node : false,
- NodeFilter : false,
- navigator : false,
- onbeforeunload : true,
- onblur : true,
- onerror : true,
- onfocus : true,
- onload : true,
- onresize : true,
- onunload : true,
- open : false,
- openDatabase : false,
- opener : false,
- Option : false,
- parent : false,
- print : false,
- removeEventListener : false,
- resizeBy : false,
- resizeTo : false,
- screen : false,
- scroll : false,
- scrollBy : false,
- scrollTo : false,
- sessionStorage : false,
- setInterval : false,
- setTimeout : false,
- SharedWorker : false,
- status : false,
- SVGAElement : false,
- SVGAltGlyphDefElement: false,
- SVGAltGlyphElement : false,
- SVGAltGlyphItemElement: false,
- SVGAngle : false,
- SVGAnimateColorElement: false,
- SVGAnimateElement : false,
- SVGAnimateMotionElement: false,
- SVGAnimateTransformElement: false,
- SVGAnimatedAngle : false,
- SVGAnimatedBoolean : false,
- SVGAnimatedEnumeration: false,
- SVGAnimatedInteger : false,
- SVGAnimatedLength : false,
- SVGAnimatedLengthList: false,
- SVGAnimatedNumber : false,
- SVGAnimatedNumberList: false,
- SVGAnimatedPathData : false,
- SVGAnimatedPoints : false,
- SVGAnimatedPreserveAspectRatio: false,
- SVGAnimatedRect : false,
- SVGAnimatedString : false,
- SVGAnimatedTransformList: false,
- SVGAnimationElement : false,
- SVGCSSRule : false,
- SVGCircleElement : false,
- SVGClipPathElement : false,
- SVGColor : false,
- SVGColorProfileElement: false,
- SVGColorProfileRule : false,
- SVGComponentTransferFunctionElement: false,
- SVGCursorElement : false,
- SVGDefsElement : false,
- SVGDescElement : false,
- SVGDocument : false,
- SVGElement : false,
- SVGElementInstance : false,
- SVGElementInstanceList: false,
- SVGEllipseElement : false,
- SVGExternalResourcesRequired: false,
- SVGFEBlendElement : false,
- SVGFEColorMatrixElement: false,
- SVGFEComponentTransferElement: false,
- SVGFECompositeElement: false,
- SVGFEConvolveMatrixElement: false,
- SVGFEDiffuseLightingElement: false,
- SVGFEDisplacementMapElement: false,
- SVGFEDistantLightElement: false,
- SVGFEDropShadowElement: false,
- SVGFEFloodElement : false,
- SVGFEFuncAElement : false,
- SVGFEFuncBElement : false,
- SVGFEFuncGElement : false,
- SVGFEFuncRElement : false,
- SVGFEGaussianBlurElement: false,
- SVGFEImageElement : false,
- SVGFEMergeElement : false,
- SVGFEMergeNodeElement: false,
- SVGFEMorphologyElement: false,
- SVGFEOffsetElement : false,
- SVGFEPointLightElement: false,
- SVGFESpecularLightingElement: false,
- SVGFESpotLightElement: false,
- SVGFETileElement : false,
- SVGFETurbulenceElement: false,
- SVGFilterElement : false,
- SVGFilterPrimitiveStandardAttributes: false,
- SVGFitToViewBox : false,
- SVGFontElement : false,
- SVGFontFaceElement : false,
- SVGFontFaceFormatElement: false,
- SVGFontFaceNameElement: false,
- SVGFontFaceSrcElement: false,
- SVGFontFaceUriElement: false,
- SVGForeignObjectElement: false,
- SVGGElement : false,
- SVGGlyphElement : false,
- SVGGlyphRefElement : false,
- SVGGradientElement : false,
- SVGHKernElement : false,
- SVGICCColor : false,
- SVGImageElement : false,
- SVGLangSpace : false,
- SVGLength : false,
- SVGLengthList : false,
- SVGLineElement : false,
- SVGLinearGradientElement: false,
- SVGLocatable : false,
- SVGMPathElement : false,
- SVGMarkerElement : false,
- SVGMaskElement : false,
- SVGMatrix : false,
- SVGMetadataElement : false,
- SVGMissingGlyphElement: false,
- SVGNumber : false,
- SVGNumberList : false,
- SVGPaint : false,
- SVGPathElement : false,
- SVGPathSeg : false,
- SVGPathSegArcAbs : false,
- SVGPathSegArcRel : false,
- SVGPathSegClosePath : false,
- SVGPathSegCurvetoCubicAbs: false,
- SVGPathSegCurvetoCubicRel: false,
- SVGPathSegCurvetoCubicSmoothAbs: false,
- SVGPathSegCurvetoCubicSmoothRel: false,
- SVGPathSegCurvetoQuadraticAbs: false,
- SVGPathSegCurvetoQuadraticRel: false,
- SVGPathSegCurvetoQuadraticSmoothAbs: false,
- SVGPathSegCurvetoQuadraticSmoothRel: false,
- SVGPathSegLinetoAbs : false,
- SVGPathSegLinetoHorizontalAbs: false,
- SVGPathSegLinetoHorizontalRel: false,
- SVGPathSegLinetoRel : false,
- SVGPathSegLinetoVerticalAbs: false,
- SVGPathSegLinetoVerticalRel: false,
- SVGPathSegList : false,
- SVGPathSegMovetoAbs : false,
- SVGPathSegMovetoRel : false,
- SVGPatternElement : false,
- SVGPoint : false,
- SVGPointList : false,
- SVGPolygonElement : false,
- SVGPolylineElement : false,
- SVGPreserveAspectRatio: false,
- SVGRadialGradientElement: false,
- SVGRect : false,
- SVGRectElement : false,
- SVGRenderingIntent : false,
- SVGSVGElement : false,
- SVGScriptElement : false,
- SVGSetElement : false,
- SVGStopElement : false,
- SVGStringList : false,
- SVGStylable : false,
- SVGStyleElement : false,
- SVGSwitchElement : false,
- SVGSymbolElement : false,
- SVGTRefElement : false,
- SVGTSpanElement : false,
- SVGTests : false,
- SVGTextContentElement: false,
- SVGTextElement : false,
- SVGTextPathElement : false,
- SVGTextPositioningElement: false,
- SVGTitleElement : false,
- SVGTransform : false,
- SVGTransformList : false,
- SVGTransformable : false,
- SVGURIReference : false,
- SVGUnitTypes : false,
- SVGUseElement : false,
- SVGVKernElement : false,
- SVGViewElement : false,
- SVGViewSpec : false,
- SVGZoomAndPan : false,
- TimeEvent : false,
- top : false,
- Uint16Array : false,
- Uint32Array : false,
- Uint8Array : false,
- Uint8ClampedArray : false,
- WebSocket : false,
- window : false,
- Worker : false,
- XMLHttpRequest : false,
- XMLSerializer : false,
- XPathEvaluator : false,
- XPathException : false,
- XPathExpression : false,
- XPathNSResolver : false,
- XPathResult : false
-};
-
-exports.devel = {
- alert : false,
- confirm: false,
- console: false,
- Debug : false,
- opera : false,
- prompt : false
-};
-
-exports.worker = {
- importScripts: true,
- postMessage : true,
- self : true
-};
-
-// Widely adopted global names that are not part of ECMAScript standard
-exports.nonstandard = {
- escape : false,
- unescape: false
-};
-
-// Globals provided by popular JavaScript environments.
-
-exports.couch = {
- "require" : false,
- respond : false,
- getRow : false,
- emit : false,
- send : false,
- start : false,
- sum : false,
- log : false,
- exports : false,
- module : false,
- provides : false
-};
-
-exports.node = {
- __filename : false,
- __dirname : false,
- Buffer : false,
- DataView : false,
- console : false,
- exports : true, // In Node it is ok to exports = module.exports = foo();
- GLOBAL : false,
- global : false,
- module : false,
- process : false,
- require : false,
- setTimeout : false,
- clearTimeout : false,
- setInterval : false,
- clearInterval : false,
- setImmediate : false, // v0.9.1+
- clearImmediate: false // v0.9.1+
-};
-
-exports.phantom = {
- phantom : true,
- require : true,
- WebPage : true
-};
-
-exports.rhino = {
- defineClass : false,
- deserialize : false,
- gc : false,
- help : false,
- importPackage: false,
- "java" : false,
- load : false,
- loadClass : false,
- print : false,
- quit : false,
- readFile : false,
- readUrl : false,
- runCommand : false,
- seal : false,
- serialize : false,
- spawn : false,
- sync : false,
- toint32 : false,
- version : false
-};
-
-exports.wsh = {
- ActiveXObject : true,
- Enumerator : true,
- GetObject : true,
- ScriptEngine : true,
- ScriptEngineBuildVersion : true,
- ScriptEngineMajorVersion : true,
- ScriptEngineMinorVersion : true,
- VBArray : true,
- WSH : true,
- WScript : true,
- XDomainRequest : true
-};
-
-// Globals provided by popular JavaScript libraries.
-
-exports.dojo = {
- dojo : false,
- dijit : false,
- dojox : false,
- define : false,
- "require": false
-};
-
-exports.jquery = {
- "$" : false,
- jQuery : false
-};
-
-exports.mootools = {
- "$" : false,
- "$$" : false,
- Asset : false,
- Browser : false,
- Chain : false,
- Class : false,
- Color : false,
- Cookie : false,
- Core : false,
- Document : false,
- DomReady : false,
- DOMEvent : false,
- DOMReady : false,
- Drag : false,
- Element : false,
- Elements : false,
- Event : false,
- Events : false,
- Fx : false,
- Group : false,
- Hash : false,
- HtmlTable : false,
- Iframe : false,
- IframeShim : false,
- InputValidator: false,
- instanceOf : false,
- Keyboard : false,
- Locale : false,
- Mask : false,
- MooTools : false,
- Native : false,
- Options : false,
- OverText : false,
- Request : false,
- Scroller : false,
- Slick : false,
- Slider : false,
- Sortables : false,
- Spinner : false,
- Swiff : false,
- Tips : false,
- Type : false,
- typeOf : false,
- URI : false,
- Window : false
-};
-
-exports.prototypejs = {
- "$" : false,
- "$$" : false,
- "$A" : false,
- "$F" : false,
- "$H" : false,
- "$R" : false,
- "$break" : false,
- "$continue" : false,
- "$w" : false,
- Abstract : false,
- Ajax : false,
- Class : false,
- Enumerable : false,
- Element : false,
- Event : false,
- Field : false,
- Form : false,
- Hash : false,
- Insertion : false,
- ObjectRange : false,
- PeriodicalExecuter: false,
- Position : false,
- Prototype : false,
- Selector : false,
- Template : false,
- Toggle : false,
- Try : false,
- Autocompleter : false,
- Builder : false,
- Control : false,
- Draggable : false,
- Draggables : false,
- Droppables : false,
- Effect : false,
- Sortable : false,
- SortableObserver : false,
- Sound : false,
- Scriptaculous : false
-};
-
-exports.yui = {
- YUI : false,
- Y : false,
- YUI_config: false
-};
-
-
-})()
-},{}],4:[function(require,module,exports){
-"use strict";
-
-var state = {
- syntax: {},
-
- reset: function () {
- this.tokens = {
- prev: null,
- next: null,
- curr: null
- };
-
- this.option = {};
- this.ignored = {};
- this.directive = {};
- this.jsonMode = false;
- this.jsonWarnings = [];
- this.lines = [];
- this.tab = "";
- this.cache = {}; // Node.JS doesn't have Map. Sniff.
- }
-};
-
-exports.state = state;
-
-},{}],5:[function(require,module,exports){
-(function(){"use strict";
-
-exports.register = function (linter) {
- // Check for properties named __proto__. This special property was
- // deprecated and then re-introduced for ES6.
-
- linter.on("Identifier", function style_scanProto(data) {
- if (linter.getOption("proto")) {
- return;
- }
-
- if (data.name === "__proto__") {
- linter.warn("W103", {
- line: data.line,
- char: data.char,
- data: [ data.name ]
- });
- }
- });
-
- // Check for properties named __iterator__. This is a special property
- // available only in browsers with JavaScript 1.7 implementation.
-
- linter.on("Identifier", function style_scanIterator(data) {
- if (linter.getOption("iterator")) {
- return;
- }
-
- if (data.name === "__iterator__") {
- linter.warn("W104", {
- line: data.line,
- char: data.char,
- data: [ data.name ]
- });
- }
- });
-
- // Check for dangling underscores.
-
- linter.on("Identifier", function style_scanDangling(data) {
- if (!linter.getOption("nomen")) {
- return;
- }
-
- // Underscore.js
- if (data.name === "_") {
- return;
- }
-
- // In Node, __dirname and __filename should be ignored.
- if (linter.getOption("node")) {
- if (/^(__dirname|__filename)$/.test(data.name) && !data.isProperty) {
- return;
- }
- }
-
- if (/^(_+.*|.*_+)$/.test(data.name)) {
- linter.warn("W105", {
- line: data.line,
- char: data.from,
- data: [ "dangling '_'", data.name ]
- });
- }
- });
-
- // Check that all identifiers are using camelCase notation.
- // Exceptions: names like MY_VAR and _myVar.
-
- linter.on("Identifier", function style_scanCamelCase(data) {
- if (!linter.getOption("camelcase")) {
- return;
- }
-
- if (data.name.replace(/^_+/, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
- linter.warn("W106", {
- line: data.line,
- char: data.from,
- data: [ data.name ]
- });
- }
- });
-
- // Enforce consistency in style of quoting.
-
- linter.on("String", function style_scanQuotes(data) {
- var quotmark = linter.getOption("quotmark");
- var code;
-
- if (!quotmark) {
- return;
- }
-
- // If quotmark is set to 'single' warn about all double-quotes.
-
- if (quotmark === "single" && data.quote !== "'") {
- code = "W109";
- }
-
- // If quotmark is set to 'double' warn about all single-quotes.
-
- if (quotmark === "double" && data.quote !== "\"") {
- code = "W108";
- }
-
- // If quotmark is set to true, remember the first quotation style
- // and then warn about all others.
-
- if (quotmark === true) {
- if (!linter.getCache("quotmark")) {
- linter.setCache("quotmark", data.quote);
- }
-
- if (linter.getCache("quotmark") !== data.quote) {
- code = "W110";
- }
- }
-
- if (code) {
- linter.warn(code, {
- line: data.line,
- char: data.char,
- });
- }
- });
-
- linter.on("Number", function style_scanNumbers(data) {
- if (data.value.charAt(0) === ".") {
- // Warn about a leading decimal point.
- linter.warn("W008", {
- line: data.line,
- char: data.char,
- data: [ data.value ]
- });
- }
-
- if (data.value.substr(data.value.length - 1) === ".") {
- // Warn about a trailing decimal point.
- linter.warn("W047", {
- line: data.line,
- char: data.char,
- data: [ data.value ]
- });
- }
-
- if (/^00+/.test(data.value)) {
- // Multiple leading zeroes.
- linter.warn("W046", {
- line: data.line,
- char: data.char,
- data: [ data.value ]
- });
- }
- });
-
- // Warn about script URLs.
-
- linter.on("String", function style_scanJavaScriptURLs(data) {
- var re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
-
- if (linter.getOption("scripturl")) {
- return;
- }
-
- if (re.test(data.value)) {
- linter.warn("W107", {
- line: data.line,
- char: data.char
- });
- }
- });
-};
-})()
-},{}],6:[function(require,module,exports){
-/*
- * Regular expressions. Some of these are stupidly long.
- */
-
-/*jshint maxlen:1000 */
-
-"use string";
-
-// Unsafe comment or string (ax)
-exports.unsafeString =
- /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
-
-// Unsafe characters that are silently deleted by one or more browsers (cx)
-exports.unsafeChars =
- /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
-
-// Characters in strings that need escaping (nx and nxg)
-exports.needEsc =
- /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
-
-exports.needEscGlobal =
- /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
-
-// Star slash (lx)
-exports.starSlash = /\*\//;
-
-// Identifier (ix)
-exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
-
-// JavaScript URL (jx)
-exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
-
-// Catches /* falls through */ comments (ft)
-//exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
-exports.fallsThrough = /^\s*\/\/\s*Falls?\sthrough.*\s*$/;
-
-},{}],7:[function(require,module,exports){
-(function(global){/*global window, global*/
-var util = require("util")
-var assert = require("assert")
-
-var slice = Array.prototype.slice
-var console
-var times = {}
-
-if (typeof global !== "undefined" && global.console) {
- console = global.console
-} else if (typeof window !== "undefined" && window.console) {
- console = window.console
-} else {
- console = window.console = {}
-}
-
-var functions = [
- [log, "log"]
- , [info, "info"]
- , [warn, "warn"]
- , [error, "error"]
- , [time, "time"]
- , [timeEnd, "timeEnd"]
- , [trace, "trace"]
- , [dir, "dir"]
- , [assert, "assert"]
-]
-
-for (var i = 0; i < functions.length; i++) {
- var tuple = functions[i]
- var f = tuple[0]
- var name = tuple[1]
-
- if (!console[name]) {
- console[name] = f
- }
-}
-
-module.exports = console
-
-function log() {}
-
-function info() {
- console.log.apply(console, arguments)
-}
-
-function warn() {
- console.log.apply(console, arguments)
-}
-
-function error() {
- console.warn.apply(console, arguments)
-}
-
-function time(label) {
- times[label] = Date.now()
-}
-
-function timeEnd(label) {
- var time = times[label]
- if (!time) {
- throw new Error("No such label: " + label)
- }
-
- var duration = Date.now() - time
- console.log(label + ": " + duration + "ms")
-}
-
-function trace() {
- var err = new Error()
- err.name = "Trace"
- err.message = util.format.apply(null, arguments)
- console.error(err.stack)
-}
-
-function dir(object) {
- console.log(util.inspect(object) + "\n")
-}
-
-function assert(expression) {
- if (!expression) {
- var arr = slice.call(arguments, 1)
- assert.ok(false, util.format.apply(null, arr))
- }
-}
-
-})(window)
-},{"util":8,"assert":9}],10:[function(require,module,exports){
-(function(){/*
- * Lexical analysis and token construction.
- */
-
-"use strict";
-
-var _ = require("underscore");
-var events = require("events");
-var reg = require("./reg.js");
-var state = require("./state.js").state;
-
-// Some of these token types are from JavaScript Parser API
-// while others are specific to JSHint parser.
-// JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
-
-var Token = {
- Identifier: 1,
- Punctuator: 2,
- NumericLiteral: 3,
- StringLiteral: 4,
- Comment: 5,
- Keyword: 6,
- NullLiteral: 7,
- BooleanLiteral: 8,
- RegExp: 9
-};
-
-// This is auto generated from the unicode tables.
-// The tables are at:
-// http://www.fileformat.info/info/unicode/category/Lu/list.htm
-// http://www.fileformat.info/info/unicode/category/Ll/list.htm
-// http://www.fileformat.info/info/unicode/category/Lt/list.htm
-// http://www.fileformat.info/info/unicode/category/Lm/list.htm
-// http://www.fileformat.info/info/unicode/category/Lo/list.htm
-// http://www.fileformat.info/info/unicode/category/Nl/list.htm
-
-var unicodeLetterTable = [
- 170, 170, 181, 181, 186, 186, 192, 214,
- 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750,
- 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908,
- 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366,
- 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610,
- 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775,
- 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,
- 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069,
- 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361,
- 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431,
- 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482,
- 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,
- 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608,
- 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654,
- 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,
- 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785,
- 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,
- 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,
- 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970,
- 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001,
- 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123,
- 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,
- 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261,
- 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344,
- 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455,
- 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526,
- 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716,
- 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,
- 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760,
- 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805,
- 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138,
- 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,
- 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346,
- 4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696,
- 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789,
- 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,
- 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,
- 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900,
- 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000,
- 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,
- 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516,
- 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823,
- 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141,
- 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409,
- 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013,
- 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061,
- 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140,
- 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188,
- 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455,
- 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486,
- 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,
- 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358,
- 11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621,
- 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,
- 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,
- 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,
- 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438,
- 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589,
- 12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312,
- 19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124,
- 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539,
- 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783,
- 42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921,
- 43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042,
- 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259,
- 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442,
- 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595,
- 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697,
- 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714,
- 43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798,
- 43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032,
- 55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045,
- 64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279,
- 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316,
- 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,
- 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,
- 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370,
- 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,
- 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594,
- 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786,
- 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334,
- 66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511,
- 66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592,
- 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669,
- 67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115,
- 68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405,
- 68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687,
- 69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894,
- 92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964,
- 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,
- 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069,
- 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121,
- 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144,
- 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570,
- 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,
- 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779,
- 131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972,
- 177984, 177984, 178205, 178205, 194560, 195101
-];
-
-var identifierStartTable = [];
-
-for (var i = 0; i < 128; i++) {
- identifierStartTable[i] =
- i === 36 || // $
- i >= 65 && i <= 90 || // A-Z
- i === 95 || // _
- i >= 97 && i <= 122; // a-z
-}
-
-var identifierPartTable = [];
-
-for (var i = 0; i < 128; i++) {
- identifierPartTable[i] =
- identifierStartTable[i] || // $, _, A-Z, a-z
- i >= 48 && i <= 57; // 0-9
-}
-
-// Object that handles postponed lexing verifications that checks the parsed
-// environment state.
-
-function asyncTrigger() {
- var _checks = [];
-
- return {
- push: function (fn) {
- _checks.push(fn);
- },
-
- check: function () {
- for (var check in _checks) {
- _checks[check]();
- }
-
- _checks.splice(0, _checks.length);
- }
- };
-}
-
-/*
- * Lexer for JSHint.
- *
- * This object does a char-by-char scan of the provided source code
- * and produces a sequence of tokens.
- *
- * var lex = new Lexer("var i = 0;");
- * lex.start();
- * lex.token(); // returns the next token
- *
- * You have to use the token() method to move the lexer forward
- * but you don't have to use its return value to get tokens. In addition
- * to token() method returning the next token, the Lexer object also
- * emits events.
- *
- * lex.on("Identifier", function (data) {
- * if (data.name.indexOf("_") >= 0) {
- * // Produce a warning.
- * }
- * });
- *
- * Note that the token() method returns tokens in a JSLint-compatible
- * format while the event emitter uses a slightly modified version of
- * Mozilla's JavaScript Parser API. Eventually, we will move away from
- * JSLint format.
- */
-function Lexer(source) {
- var lines = source;
-
- if (typeof lines === "string") {
- lines = lines
- .replace(/\r\n/g, "\n")
- .replace(/\r/g, "\n")
- .split("\n");
- }
-
- // If the first line is a shebang (#!), make it a blank and move on.
- // Shebangs are used by Node scripts.
-
- if (lines[0] && lines[0].substr(0, 2) === "#!") {
- lines[0] = "";
- }
-
- this.emitter = new events.EventEmitter();
- this.source = source;
- this.lines = lines;
- this.prereg = true;
-
- this.line = 0;
- this.char = 1;
- this.from = 1;
- this.input = "";
-
- for (var i = 0; i < state.option.indent; i += 1) {
- state.tab += " ";
- }
-}
-
-Lexer.prototype = {
- _lines: [],
-
- get lines() {
- this._lines = state.lines;
- return this._lines;
- },
-
- set lines(val) {
- this._lines = val;
- state.lines = this._lines;
- },
-
- /*
- * Return the next i character without actually moving the
- * char pointer.
- */
- peek: function (i) {
- return this.input.charAt(i || 0);
- },
-
- /*
- * Move the char pointer forward i times.
- */
- skip: function (i) {
- i = i || 1;
- this.char += i;
- this.input = this.input.slice(i);
- },
-
- /*
- * Subscribe to a token event. The API for this method is similar
- * Underscore.js i.e. you can subscribe to multiple events with
- * one call:
- *
- * lex.on("Identifier Number", function (data) {
- * // ...
- * });
- */
- on: function (names, listener) {
- names.split(" ").forEach(function (name) {
- this.emitter.on(name, listener);
- }.bind(this));
- },
-
- /*
- * Trigger a token event. All arguments will be passed to each
- * listener.
- */
- trigger: function () {
- this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
- },
-
- /*
- * Postpone a token event. the checking condition is set as
- * last parameter, and the trigger function is called in a
- * stored callback. To be later called using the check() function
- * by the parser. This avoids parser's peek() to give the lexer
- * a false context.
- */
- triggerAsync: function (type, args, checks, fn) {
- checks.push(function () {
- if (fn()) {
- this.trigger(type, args);
- }
- }.bind(this));
- },
-
- /*
- * Extract a punctuator out of the next sequence of characters
- * or return 'null' if its not possible.
- *
- * This method's implementation was heavily influenced by the
- * scanPunctuator function in the Esprima parser's source code.
- */
- scanPunctuator: function () {
- var ch1 = this.peek();
- var ch2, ch3, ch4;
-
- switch (ch1) {
- // Most common single-character punctuators
- case ".":
- if ((/^[0-9]$/).test(this.peek(1))) {
- return null;
- }
- if (this.peek(1) === "." && this.peek(2) === ".") {
- return {
- type: Token.Punctuator,
- value: "..."
- };
- }
- /* falls through */
- case "(":
- case ")":
- case ";":
- case ",":
- case "{":
- case "}":
- case "[":
- case "]":
- case ":":
- case "~":
- case "?":
- return {
- type: Token.Punctuator,
- value: ch1
- };
-
- // A pound sign (for Node shebangs)
- case "#":
- return {
- type: Token.Punctuator,
- value: ch1
- };
-
- // We're at the end of input
- case "":
- return null;
- }
-
- // Peek more characters
-
- ch2 = this.peek(1);
- ch3 = this.peek(2);
- ch4 = this.peek(3);
-
- // 4-character punctuator: >>>=
-
- if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
- return {
- type: Token.Punctuator,
- value: ">>>="
- };
- }
-
- // 3-character punctuators: === !== >>> <<= >>=
-
- if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: "==="
- };
- }
-
- if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: "!=="
- };
- }
-
- if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
- return {
- type: Token.Punctuator,
- value: ">>>"
- };
- }
-
- if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: "<<="
- };
- }
-
- if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: ">>="
- };
- }
-
- // Fat arrow punctuator
- if (ch1 === "=" && ch2 === ">") {
- return {
- type: Token.Punctuator,
- value: ch1 + ch2
- };
- }
-
- // 2-character punctuators: <= >= == != ++ -- << >> && ||
- // += -= *= %= &= |= ^= (but not /=, see below)
- if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
- return {
- type: Token.Punctuator,
- value: ch1 + ch2
- };
- }
-
- if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
- if (ch2 === "=") {
- return {
- type: Token.Punctuator,
- value: ch1 + ch2
- };
- }
-
- return {
- type: Token.Punctuator,
- value: ch1
- };
- }
-
- // Special case: /=. We need to make sure that this is an
- // operator and not a regular expression.
-
- if (ch1 === "/") {
- if (ch2 === "=" && /\/=(?!(\S*\/[gim]?))/.test(this.input)) {
- // /= is not a part of a regular expression, return it as a
- // punctuator.
- return {
- type: Token.Punctuator,
- value: "/="
- };
- }
-
- return {
- type: Token.Punctuator,
- value: "/"
- };
- }
-
- return null;
- },
-
- /*
- * Extract a comment out of the next sequence of characters and/or
- * lines or return 'null' if its not possible. Since comments can
- * span across multiple lines this method has to move the char
- * pointer.
- *
- * In addition to normal JavaScript comments (// and /*) this method
- * also recognizes JSHint- and JSLint-specific comments such as
- * /*jshint, /*jslint, /*globals and so on.
- */
- scanComments: function () {
- var ch1 = this.peek();
- var ch2 = this.peek(1);
- var rest = this.input.substr(2);
- var startLine = this.line;
- var startChar = this.char;
-
- // Create a comment token object and make sure it
- // has all the data JSHint needs to work with special
- // comments.
-
- function commentToken(label, body, opt) {
- var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
- var isSpecial = false;
- var value = label + body;
- var commentType = "plain";
- opt = opt || {};
-
- if (opt.isMultiline) {
- value += "*/";
- }
-
- special.forEach(function (str) {
- if (isSpecial) {
- return;
- }
-
- // Don't recognize any special comments other than jshint for single-line
- // comments. This introduced many problems with legit comments.
- if (label === "//" && str !== "jshint") {
- return;
- }
-
- if (body.substr(0, str.length) === str) {
- isSpecial = true;
- label = label + str;
- body = body.substr(str.length);
- }
-
- if (!isSpecial && body.charAt(0) === " " && body.substr(1, str.length) === str) {
- isSpecial = true;
- label = label + " " + str;
- body = body.substr(str.length + 1);
- }
-
- if (!isSpecial) {
- return;
- }
-
- switch (str) {
- case "member":
- commentType = "members";
- break;
- case "global":
- commentType = "globals";
- break;
- default:
- commentType = str;
- }
- });
-
- return {
- type: Token.Comment,
- commentType: commentType,
- value: value,
- body: body,
- isSpecial: isSpecial,
- isMultiline: opt.isMultiline || false,
- isMalformed: opt.isMalformed || false
- };
- }
-
- // End of unbegun comment. Raise an error and skip that input.
- if (ch1 === "*" && ch2 === "/") {
- this.trigger("error", {
- code: "E018",
- line: startLine,
- character: startChar
- });
-
- this.skip(2);
- return null;
- }
-
- // Comments must start either with // or /*
- if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
- return null;
- }
-
- // One-line comment
- if (ch2 === "/") {
- this.skip(this.input.length); // Skip to the EOL.
- return commentToken("//", rest);
- }
-
- var body = "";
-
- /* Multi-line comment */
- if (ch2 === "*") {
- this.skip(2);
-
- while (this.peek() !== "*" || this.peek(1) !== "/") {
- if (this.peek() === "") { // End of Line
- body += "\n";
-
- // If we hit EOF and our comment is still unclosed,
- // trigger an error and end the comment implicitly.
- if (!this.nextLine()) {
- this.trigger("error", {
- code: "E017",
- line: startLine,
- character: startChar
- });
-
- return commentToken("/*", body, {
- isMultiline: true,
- isMalformed: true
- });
- }
- } else {
- body += this.peek();
- this.skip();
- }
- }
-
- this.skip(2);
- return commentToken("/*", body, { isMultiline: true });
- }
- },
-
- /*
- * Extract a keyword out of the next sequence of characters or
- * return 'null' if its not possible.
- */
- scanKeyword: function () {
- var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);
- var keywords = [
- "if", "in", "do", "var", "for", "new",
- "try", "let", "this", "else", "case",
- "void", "with", "enum", "while", "break",
- "catch", "throw", "const", "yield", "class",
- "super", "return", "typeof", "delete",
- "switch", "export", "import", "default",
- "finally", "extends", "function", "continue",
- "debugger", "instanceof"
- ];
-
- if (result && keywords.indexOf(result[0]) >= 0) {
- return {
- type: Token.Keyword,
- value: result[0]
- };
- }
-
- return null;
- },
-
- /*
- * Extract a JavaScript identifier out of the next sequence of
- * characters or return 'null' if its not possible. In addition,
- * to Identifier this method can also produce BooleanLiteral
- * (true/false) and NullLiteral (null).
- */
- scanIdentifier: function () {
- var id = "";
- var index = 0;
- var type, char;
-
- // Detects any character in the Unicode categories "Uppercase
- // letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter
- // (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or
- // "Letter number (Nl)".
- //
- // Both approach and unicodeLetterTable were borrowed from
- // Google's Traceur.
-
- function isUnicodeLetter(code) {
- for (var i = 0; i < unicodeLetterTable.length;) {
- if (code < unicodeLetterTable[i++]) {
- return false;
- }
-
- if (code <= unicodeLetterTable[i++]) {
- return true;
- }
- }
-
- return false;
- }
-
- function isHexDigit(str) {
- return (/^[0-9a-fA-F]$/).test(str);
- }
-
- var readUnicodeEscapeSequence = function () {
- /*jshint validthis:true */
- index += 1;
-
- if (this.peek(index) !== "u") {
- return null;
- }
-
- var ch1 = this.peek(index + 1);
- var ch2 = this.peek(index + 2);
- var ch3 = this.peek(index + 3);
- var ch4 = this.peek(index + 4);
- var code;
-
- if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {
- code = parseInt(ch1 + ch2 + ch3 + ch4, 16);
-
- if (isUnicodeLetter(code)) {
- index += 5;
- return "\\u" + ch1 + ch2 + ch3 + ch4;
- }
-
- return null;
- }
-
- return null;
- }.bind(this);
-
- var getIdentifierStart = function () {
- /*jshint validthis:true */
- var chr = this.peek(index);
- var code = chr.charCodeAt(0);
-
- if (code === 92) {
- return readUnicodeEscapeSequence();
- }
-
- if (code < 128) {
- if (identifierStartTable[code]) {
- index += 1;
- return chr;
- }
-
- return null;
- }
-
- if (isUnicodeLetter(code)) {
- index += 1;
- return chr;
- }
-
- return null;
- }.bind(this);
-
- var getIdentifierPart = function () {
- /*jshint validthis:true */
- var chr = this.peek(index);
- var code = chr.charCodeAt(0);
-
- if (code === 92) {
- return readUnicodeEscapeSequence();
- }
-
- if (code < 128) {
- if (identifierPartTable[code]) {
- index += 1;
- return chr;
- }
-
- return null;
- }
-
- if (isUnicodeLetter(code)) {
- index += 1;
- return chr;
- }
-
- return null;
- }.bind(this);
-
- char = getIdentifierStart();
- if (char === null) {
- return null;
- }
-
- id = char;
- for (;;) {
- char = getIdentifierPart();
-
- if (char === null) {
- break;
- }
-
- id += char;
- }
-
- switch (id) {
- case "true":
- case "false":
- type = Token.BooleanLiteral;
- break;
- case "null":
- type = Token.NullLiteral;
- break;
- default:
- type = Token.Identifier;
- }
-
- return {
- type: type,
- value: id
- };
- },
-
- /*
- * Extract a numeric literal out of the next sequence of
- * characters or return 'null' if its not possible. This method
- * supports all numeric literals described in section 7.8.3
- * of the EcmaScript 5 specification.
- *
- * This method's implementation was heavily influenced by the
- * scanNumericLiteral function in the Esprima parser's source code.
- */
- scanNumericLiteral: function () {
- var index = 0;
- var value = "";
- var length = this.input.length;
- var char = this.peek(index);
- var bad;
-
- function isDecimalDigit(str) {
- return (/^[0-9]$/).test(str);
- }
-
- function isOctalDigit(str) {
- return (/^[0-7]$/).test(str);
- }
-
- function isHexDigit(str) {
- return (/^[0-9a-fA-F]$/).test(str);
- }
-
- function isIdentifierStart(ch) {
- return (ch === "$") || (ch === "_") || (ch === "\\") ||
- (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
- }
-
- // Numbers must start either with a decimal digit or a point.
-
- if (char !== "." && !isDecimalDigit(char)) {
- return null;
- }
-
- if (char !== ".") {
- value = this.peek(index);
- index += 1;
- char = this.peek(index);
-
- if (value === "0") {
- // Base-16 numbers.
- if (char === "x" || char === "X") {
- index += 1;
- value += char;
-
- while (index < length) {
- char = this.peek(index);
- if (!isHexDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
-
- if (value.length <= 2) { // 0x
- return {
- type: Token.NumericLiteral,
- value: value,
- isMalformed: true
- };
- }
-
- if (index < length) {
- char = this.peek(index);
- if (isIdentifierStart(char)) {
- return null;
- }
- }
-
- return {
- type: Token.NumericLiteral,
- value: value,
- base: 16,
- isMalformed: false
- };
- }
-
- // Base-8 numbers.
- if (isOctalDigit(char)) {
- index += 1;
- value += char;
- bad = false;
-
- while (index < length) {
- char = this.peek(index);
-
- // Numbers like '019' (note the 9) are not valid octals
- // but we still parse them and mark as malformed.
-
- if (isDecimalDigit(char)) {
- bad = true;
- } else if (!isOctalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
-
- if (index < length) {
- char = this.peek(index);
- if (isIdentifierStart(char)) {
- return null;
- }
- }
-
- return {
- type: Token.NumericLiteral,
- value: value,
- base: 8,
- isMalformed: false
- };
- }
-
- // Decimal numbers that start with '0' such as '09' are illegal
- // but we still parse them and return as malformed.
-
- if (isDecimalDigit(char)) {
- index += 1;
- value += char;
- }
- }
-
- while (index < length) {
- char = this.peek(index);
- if (!isDecimalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- }
-
- // Decimal digits.
-
- if (char === ".") {
- value += char;
- index += 1;
-
- while (index < length) {
- char = this.peek(index);
- if (!isDecimalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- }
-
- // Exponent part.
-
- if (char === "e" || char === "E") {
- value += char;
- index += 1;
- char = this.peek(index);
-
- if (char === "+" || char === "-") {
- value += this.peek(index);
- index += 1;
- }
-
- char = this.peek(index);
- if (isDecimalDigit(char)) {
- value += char;
- index += 1;
-
- while (index < length) {
- char = this.peek(index);
- if (!isDecimalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- } else {
- return null;
- }
- }
-
- if (index < length) {
- char = this.peek(index);
- if (isIdentifierStart(char)) {
- return null;
- }
- }
-
- return {
- type: Token.NumericLiteral,
- value: value,
- base: 10,
- isMalformed: !isFinite(value)
- };
- },
-
- /*
- * Extract a string out of the next sequence of characters and/or
- * lines or return 'null' if its not possible. Since strings can
- * span across multiple lines this method has to move the char
- * pointer.
- *
- * This method recognizes pseudo-multiline JavaScript strings:
- *
- * var str = "hello\
- * world";
- */
- scanStringLiteral: function (checks) {
- /*jshint loopfunc:true */
- var quote = this.peek();
-
- // String must start with a quote.
- if (quote !== "\"" && quote !== "'") {
- return null;
- }
-
- // In JSON strings must always use double quotes.
- this.triggerAsync("warning", {
- code: "W108",
- line: this.line,
- character: this.char // +1?
- }, checks, function () { return state.jsonMode && quote !== "\""; });
-
- var value = "";
- var startLine = this.line;
- var startChar = this.char;
- var allowNewLine = false;
-
- this.skip();
-
- while (this.peek() !== quote) {
- while (this.peek() === "") { // End Of Line
-
- // If an EOL is not preceded by a backslash, show a warning
- // and proceed like it was a legit multi-line string where
- // author simply forgot to escape the newline symbol.
- //
- // Another approach is to implicitly close a string on EOL
- // but it generates too many false positives.
-
- if (!allowNewLine) {
- this.trigger("warning", {
- code: "W112",
- line: this.line,
- character: this.char
- });
- } else {
- allowNewLine = false;
-
- // Otherwise show a warning if multistr option was not set.
- // For JSON, show warning no matter what.
-
- this.triggerAsync("warning", {
- code: "W043",
- line: this.line,
- character: this.char
- }, checks, function () { return !state.option.multistr; });
-
- this.triggerAsync("warning", {
- code: "W042",
- line: this.line,
- character: this.char
- }, checks, function () { return state.jsonMode && state.option.multistr; });
- }
-
- // If we get an EOF inside of an unclosed string, show an
- // error and implicitly close it at the EOF point.
-
- if (!this.nextLine()) {
- this.trigger("error", {
- code: "E029",
- line: startLine,
- character: startChar
- });
-
- return {
- type: Token.StringLiteral,
- value: value,
- isUnclosed: true,
- quote: quote
- };
- }
- }
-
- allowNewLine = false;
- var char = this.peek();
- var jump = 1; // A length of a jump, after we're done
- // parsing this character.
-
- if (char < " ") {
- // Warn about a control character in a string.
- this.trigger("warning", {
- code: "W113",
- line: this.line,
- character: this.char,
- data: [ "<non-printable>" ]
- });
- }
-
- // Special treatment for some escaped characters.
-
- if (char === "\\") {
- this.skip();
- char = this.peek();
-
- switch (char) {
- case "'":
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "\\'" ]
- }, checks, function () {return state.jsonMode; });
- break;
- case "b":
- char = "\b";
- break;
- case "f":
- char = "\f";
- break;
- case "n":
- char = "\n";
- break;
- case "r":
- char = "\r";
- break;
- case "t":
- char = "\t";
- break;
- case "0":
- char = "\0";
-
- // Octal literals fail in strict mode.
- // Check if the number is between 00 and 07.
- var n = parseInt(this.peek(1), 10);
- this.triggerAsync("warning", {
- code: "W115",
- line: this.line,
- character: this.char
- }, checks,
- function () { return n >= 0 && n <= 7 && state.directive["use strict"]; });
- break;
- case "u":
- char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16));
- jump = 5;
- break;
- case "v":
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "\\v" ]
- }, checks, function () { return state.jsonMode; });
-
- char = "\v";
- break;
- case "x":
- var x = parseInt(this.input.substr(1, 2), 16);
-
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "\\x-" ]
- }, checks, function () { return state.jsonMode; });
-
- char = String.fromCharCode(x);
- jump = 3;
- break;
- case "\\":
- case "\"":
- case "/":
- break;
- case "":
- allowNewLine = true;
- char = "";
- break;
- case "!":
- if (value.slice(value.length - 2) === "<") {
- break;
- }
-
- /*falls through */
- default:
- // Weird escaping.
- this.trigger("warning", {
- code: "W044",
- line: this.line,
- character: this.char
- });
- }
- }
-
- value += char;
- this.skip(jump);
- }
-
- this.skip();
- return {
- type: Token.StringLiteral,
- value: value,
- isUnclosed: false,
- quote: quote
- };
- },
-
- /*
- * Extract a regular expression out of the next sequence of
- * characters and/or lines or return 'null' if its not possible.
- *
- * This method is platform dependent: it accepts almost any
- * regular expression values but then tries to compile and run
- * them using system's RegExp object. This means that there are
- * rare edge cases where one JavaScript engine complains about
- * your regular expression while others don't.
- */
- scanRegExp: function () {
- var index = 0;
- var length = this.input.length;
- var char = this.peek();
- var value = char;
- var body = "";
- var flags = [];
- var malformed = false;
- var isCharSet = false;
- var terminated;
-
- var scanUnexpectedChars = function () {
- // Unexpected control character
- if (char < " ") {
- malformed = true;
- this.trigger("warning", {
- code: "W048",
- line: this.line,
- character: this.char
- });
- }
-
- // Unexpected escaped character
- if (char === "<") {
- malformed = true;
- this.trigger("warning", {
- code: "W049",
- line: this.line,
- character: this.char,
- data: [ char ]
- });
- }
- }.bind(this);
-
- // Regular expressions must start with '/'
- if (!this.prereg || char !== "/") {
- return null;
- }
-
- index += 1;
- terminated = false;
-
- // Try to get everything in between slashes. A couple of
- // cases aside (see scanUnexpectedChars) we don't really
- // care whether the resulting expression is valid or not.
- // We will check that later using the RegExp object.
-
- while (index < length) {
- char = this.peek(index);
- value += char;
- body += char;
-
- if (isCharSet) {
- if (char === "]") {
- if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
- isCharSet = false;
- }
- }
-
- if (char === "\\") {
- index += 1;
- char = this.peek(index);
- body += char;
- value += char;
-
- scanUnexpectedChars();
- }
-
- index += 1;
- continue;
- }
-
- if (char === "\\") {
- index += 1;
- char = this.peek(index);
- body += char;
- value += char;
-
- scanUnexpectedChars();
-
- if (char === "/") {
- index += 1;
- continue;
- }
-
- if (char === "[") {
- index += 1;
- continue;
- }
- }
-
- if (char === "[") {
- isCharSet = true;
- index += 1;
- continue;
- }
-
- if (char === "/") {
- body = body.substr(0, body.length - 1);
- terminated = true;
- index += 1;
- break;
- }
-
- index += 1;
- }
-
- // A regular expression that was never closed is an
- // error from which we cannot recover.
-
- if (!terminated) {
- this.trigger("error", {
- code: "E015",
- line: this.line,
- character: this.from
- });
-
- return void this.trigger("fatal", {
- line: this.line,
- from: this.from
- });
- }
-
- // Parse flags (if any).
-
- while (index < length) {
- char = this.peek(index);
- if (!/[gim]/.test(char)) {
- break;
- }
- flags.push(char);
- value += char;
- index += 1;
- }
-
- // Check regular expression for correctness.
-
- try {
- new RegExp(body, flags.join(""));
- } catch (err) {
- malformed = true;
- this.trigger("error", {
- code: "E016",
- line: this.line,
- character: this.char,
- data: [ err.message ] // Platform dependent!
- });
- }
-
- return {
- type: Token.RegExp,
- value: value,
- flags: flags,
- isMalformed: malformed
- };
- },
-
- /*
- * Scan for any occurence of mixed tabs and spaces. If smarttabs option
- * is on, ignore tabs followed by spaces.
- *
- * Tabs followed by one space followed by a block comment are allowed.
- */
- scanMixedSpacesAndTabs: function () {
- var at, match;
-
- if (state.option.smarttabs) {
- // Negative look-behind for "//"
- match = this.input.match(/(\/\/|^\s?\*)? \t/);
- at = match && !match[1] ? 0 : -1;
- } else {
- at = this.input.search(/ \t|\t [^\*]/);
- }
-
- return at;
- },
-
- /*
- * Scan for characters that get silently deleted by one or more browsers.
- */
- scanUnsafeChars: function () {
- return this.input.search(reg.unsafeChars);
- },
-
- /*
- * Produce the next raw token or return 'null' if no tokens can be matched.
- * This method skips over all space characters.
- */
- next: function (checks) {
- this.from = this.char;
-
- // Move to the next non-space character.
- var start;
- if (/\s/.test(this.peek())) {
- start = this.char;
-
- while (/\s/.test(this.peek())) {
- this.from += 1;
- this.skip();
- }
-
- if (this.peek() === "") { // EOL
- if (!/^\s*$/.test(this.lines[this.line - 1]) && state.option.trailing) {
- this.trigger("warning", { code: "W102", line: this.line, character: start });
- }
- }
- }
-
- // Methods that work with multi-line structures and move the
- // character pointer.
-
- var match = this.scanComments() ||
- this.scanStringLiteral(checks);
-
- if (match) {
- return match;
- }
-
- // Methods that don't move the character pointer.
-
- match =
- this.scanRegExp() ||
- this.scanPunctuator() ||
- this.scanKeyword() ||
- this.scanIdentifier() ||
- this.scanNumericLiteral();
-
- if (match) {
- this.skip(match.value.length);
- return match;
- }
-
- // No token could be matched, give up.
-
- return null;
- },
-
- /*
- * Switch to the next line and reset all char pointers. Once
- * switched, this method also checks for mixed spaces and tabs
- * and other minor warnings.
- */
- nextLine: function () {
- var char;
-
- if (this.line >= this.lines.length) {
- return false;
- }
-
- this.input = this.lines[this.line];
- this.line += 1;
- this.char = 1;
- this.from = 1;
-
- char = this.scanMixedSpacesAndTabs();
- if (char >= 0) {
- this.trigger("warning", { code: "W099", line: this.line, character: char + 1 });
- }
-
- this.input = this.input.replace(/\t/g, state.tab);
- char = this.scanUnsafeChars();
-
- if (char >= 0) {
- this.trigger("warning", { code: "W100", line: this.line, character: char });
- }
-
- // If there is a limit on line length, warn when lines get too
- // long.
-
- if (state.option.maxlen && state.option.maxlen < this.input.length) {
- this.trigger("warning", { code: "W101", line: this.line, character: this.input.length });
- }
-
- return true;
- },
-
- /*
- * This is simply a synonym for nextLine() method with a friendlier
- * public name.
- */
- start: function () {
- this.nextLine();
- },
-
- /*
- * Produce the next token. This function is called by advance() to get
- * the next token. It retuns a token in a JSLint-compatible format.
- */
- token: function () {
- /*jshint loopfunc:true */
- var checks = asyncTrigger();
- var token;
-
-
- function isReserved(token, isProperty) {
- if (!token.reserved) {
- return false;
- }
-
- if (token.meta && token.meta.isFutureReservedWord) {
- // ES3 FutureReservedWord in an ES5 environment.
- if (state.option.inES5(true) && !token.meta.es5) {
- return false;
- }
-
- // Some ES5 FutureReservedWord identifiers are active only
- // within a strict mode environment.
- if (token.meta.strictOnly) {
- if (!state.option.strict && !state.directive["use strict"]) {
- return false;
- }
- }
-
- if (isProperty) {
- return false;
- }
- }
-
- return true;
- }
-
- // Produce a token object.
- var create = function (type, value, isProperty) {
- /*jshint validthis:true */
- var obj;
-
- if (type !== "(endline)" && type !== "(end)") {
- this.prereg = false;
- }
-
- if (type === "(punctuator)") {
- switch (value) {
- case ".":
- case ")":
- case "~":
- case "#":
- case "]":
- this.prereg = false;
- break;
- default:
- this.prereg = true;
- }
-
- obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
- }
-
- if (type === "(identifier)") {
- if (value === "return" || value === "case" || value === "typeof") {
- this.prereg = true;
- }
-
- if (_.has(state.syntax, value)) {
- obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
-
- // If this can't be a reserved keyword, reset the object.
- if (!isReserved(obj, isProperty && type === "(identifier)")) {
- obj = null;
- }
- }
- }
-
- if (!obj) {
- obj = Object.create(state.syntax[type]);
- }
-
- obj.identifier = (type === "(identifier)");
- obj.type = obj.type || type;
- obj.value = value;
- obj.line = this.line;
- obj.character = this.char;
- obj.from = this.from;
-
- if (isProperty && obj.identifier) {
- obj.isProperty = isProperty;
- }
-
- obj.check = checks.check;
-
- return obj;
- }.bind(this);
-
- for (;;) {
- if (!this.input.length) {
- return create(this.nextLine() ? "(endline)" : "(end)", "");
- }
-
- token = this.next(checks);
-
- if (!token) {
- if (this.input.length) {
- // Unexpected character.
- this.trigger("error", {
- code: "E024",
- line: this.line,
- character: this.char,
- data: [ this.peek() ]
- });
-
- this.input = "";
- }
-
- continue;
- }
-
- switch (token.type) {
- case Token.StringLiteral:
- this.triggerAsync("String", {
- line: this.line,
- char: this.char,
- from: this.from,
- value: token.value,
- quote: token.quote
- }, checks, function () { return true; });
-
- return create("(string)", token.value);
- case Token.Identifier:
- this.trigger("Identifier", {
- line: this.line,
- char: this.char,
- from: this.form,
- name: token.value,
- isProperty: state.tokens.curr.id === "."
- });
-
- /* falls through */
- case Token.Keyword:
- case Token.NullLiteral:
- case Token.BooleanLiteral:
- return create("(identifier)", token.value, state.tokens.curr.id === ".");
-
- case Token.NumericLiteral:
- if (token.isMalformed) {
- this.trigger("warning", {
- code: "W045",
- line: this.line,
- character: this.char,
- data: [ token.value ]
- });
- }
-
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "0x-" ]
- }, checks, function () { return token.base === 16 && state.jsonMode; });
-
- this.triggerAsync("warning", {
- code: "W115",
- line: this.line,
- character: this.char
- }, checks, function () {
- return state.directive["use strict"] && token.base === 8;
- });
-
- this.trigger("Number", {
- line: this.line,
- char: this.char,
- from: this.from,
- value: token.value,
- base: token.base,
- isMalformed: token.malformed
- });
-
- return create("(number)", token.value);
-
- case Token.RegExp:
- return create("(regexp)", token.value);
-
- case Token.Comment:
- state.tokens.curr.comment = true;
-
- if (token.isSpecial) {
- return {
- value: token.value,
- body: token.body,
- type: token.commentType,
- isSpecial: token.isSpecial,
- line: this.line,
- character: this.char,
- from: this.from
- };
- }
-
- break;
-
- case "":
- break;
-
- default:
- return create("(punctuator)", token.value);
- }
- }
- }
-};
-
-exports.Lexer = Lexer;
-
-})()
-},{"events":2,"./reg.js":6,"./state.js":4,"underscore":11}],"jshint":[function(require,module,exports){
-module.exports=require('E/GbHF');
-},{}],"E/GbHF":[function(require,module,exports){
-(function(){/*!
- * JSHint, by JSHint Community.
- *
- * This file (and this file only) is licensed under the same slightly modified
- * MIT license that JSLint is. It stops evil-doers everywhere:
- *
- * Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * The Software shall be used for Good, not Evil.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-/*jshint quotmark:double */
-/*global console:true */
-/*exported console */
-
-var _ = require("underscore");
-var events = require("events");
-var vars = require("../shared/vars.js");
-var messages = require("../shared/messages.js");
-var Lexer = require("./lex.js").Lexer;
-var reg = require("./reg.js");
-var state = require("./state.js").state;
-var style = require("./style.js");
-
-// We need this module here because environments such as IE and Rhino
-// don't necessarilly expose the 'console' API and browserify uses
-// it to log things. It's a sad state of affair, really.
-var console = require("console-browserify");
-
-// We build the application inside a function so that we produce only a singleton
-// variable. That function will be invoked immediately, and its return value is
-// the JSHINT function itself.
-
-var JSHINT = (function () {
- "use strict";
-
- var anonname, // The guessed name for anonymous functions.
- api, // Extension API
-
- // These are operators that should not be used with the ! operator.
- bang = {
- "<" : true,
- "<=" : true,
- "==" : true,
- "===": true,
- "!==": true,
- "!=" : true,
- ">" : true,
- ">=" : true,
- "+" : true,
- "-" : true,
- "*" : true,
- "/" : true,
- "%" : true
- },
-
- // These are the JSHint boolean options.
- boolOptions = {
- asi : true, // if automatic semicolon insertion should be tolerated
- bitwise : true, // if bitwise operators should not be allowed
- boss : true, // if advanced usage of assignments should be allowed
- browser : true, // if the standard browser globals should be predefined
- camelcase : true, // if identifiers should be required in camel case
- couch : true, // if CouchDB globals should be predefined
- curly : true, // if curly braces around all blocks should be required
- debug : true, // if debugger statements should be allowed
- devel : true, // if logging globals should be predefined (console, alert, etc.)
- dojo : true, // if Dojo Toolkit globals should be predefined
- eqeqeq : true, // if === should be required
- eqnull : true, // if == null comparisons should be tolerated
- es3 : true, // if ES3 syntax should be allowed
- es5 : true, // if ES5 syntax should be allowed (is now set per default)
- esnext : true, // if es.next specific syntax should be allowed
- moz : true, // if mozilla specific syntax should be allowed
- evil : true, // if eval should be allowed
- expr : true, // if ExpressionStatement should be allowed as Programs
- forin : true, // if for in statements must filter
- funcscope : true, // if only function scope should be used for scope tests
- gcl : true, // if JSHint should be compatible with Google Closure Linter
- globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
- immed : true, // if immediate invocations must be wrapped in parens
- iterator : true, // if the `__iterator__` property should be allowed
- jquery : true, // if jQuery globals should be predefined
- lastsemic : true, // if semicolons may be ommitted for the trailing
- // statements inside of a one-line blocks.
- laxbreak : true, // if line breaks should not be checked
- laxcomma : true, // if line breaks should not be checked around commas
- loopfunc : true, // if functions should be allowed to be defined within
- // loops
- mootools : true, // if MooTools globals should be predefined
- multistr : true, // allow multiline strings
- newcap : true, // if constructor names must be capitalized
- noarg : true, // if arguments.caller and arguments.callee should be
- // disallowed
- node : true, // if the Node.js environment globals should be
- // predefined
- noempty : true, // if empty blocks should be disallowed
- nonew : true, // if using `new` for side-effects should be disallowed
- nonstandard : true, // if non-standard (but widely adopted) globals should
- // be predefined
- nomen : true, // if names should be checked
- onevar : true, // if only one var statement per function should be
- // allowed
- passfail : true, // if the scan should stop on first error
- phantom : true, // if PhantomJS symbols should be allowed
- plusplus : true, // if increment/decrement should not be allowed
- proto : true, // if the `__proto__` property should be allowed
- prototypejs : true, // if Prototype and Scriptaculous globals should be
- // predefined
- rhino : true, // if the Rhino environment globals should be predefined
- undef : true, // if variables should be declared before used
- scripturl : true, // if script-targeted URLs should be tolerated
- shadow : true, // if variable shadowing should be tolerated
- smarttabs : true, // if smarttabs should be tolerated
- // (http://www.emacswiki.org/emacs/SmartTabs)
- strict : true, // require the "use strict"; pragma
- sub : true, // if all forms of subscript notation are tolerated
- supernew : true, // if `new function () { ... };` and `new Object;`
- // should be tolerated
- trailing : true, // if trailing whitespace rules apply
- validthis : true, // if 'this' inside a non-constructor function is valid.
- // This is a function scoped option only.
- withstmt : true, // if with statements should be allowed
- white : true, // if strict whitespace rules apply
- worker : true, // if Web Worker script symbols should be allowed
- wsh : true, // if the Windows Scripting Host environment globals
- // should be predefined
- yui : true, // YUI variables should be predefined
-
- // Obsolete options
- onecase : true, // if one case switch statements should be allowed
- regexp : true, // if the . should not be allowed in regexp literals
- regexdash : true // if unescaped first/last dash (-) inside brackets
- // should be tolerated
- },
-
- // These are the JSHint options that can take any value
- // (we use this object to detect invalid options)
- valOptions = {
- maxlen : false,
- indent : false,
- maxerr : false,
- predef : false,
- quotmark : false, //'single'|'double'|true
- scope : false,
- maxstatements: false, // {int} max statements per function
- maxdepth : false, // {int} max nested block depth per function
- maxparams : false, // {int} max params per function
- maxcomplexity: false, // {int} max cyclomatic complexity per function
- unused : true, // warn if variables are unused. Available options:
- // false - don't check for unused variables
- // true - "vars" + check last function param
- // "vars" - skip checking unused function params
- // "strict" - "vars" + check all function params
- latedef : false // warn if the variable is used before its definition
- // false - don't emit any warnings
- // true - warn if any variable is used before its definition
- // "nofunc" - warn for any variable but function declarations
- },
-
- // These are JSHint boolean options which are shared with JSLint
- // where the definition in JSHint is opposite JSLint
- invertedOptions = {
- bitwise : true,
- forin : true,
- newcap : true,
- nomen : true,
- plusplus: true,
- regexp : true,
- undef : true,
- white : true,
-
- // Inverted and renamed, use JSHint name here
- eqeqeq : true,
- onevar : true,
- strict : true
- },
-
- // These are JSHint boolean options which are shared with JSLint
- // where the name has been changed but the effect is unchanged
- renamedOptions = {
- eqeq : "eqeqeq",
- vars : "onevar",
- windows: "wsh",
- sloppy : "strict"
- },
-
- declared, // Globals that were declared using /*global ... */ syntax.
- exported, // Variables that are used outside of the current file.
-
- functionicity = [
- "closure", "exception", "global", "label",
- "outer", "unused", "var"
- ],
-
- funct, // The current function
- functions, // All of the functions
-
- global, // The global scope
- implied, // Implied globals
- inblock,
- indent,
- lookahead,
- lex,
- member,
- membersOnly,
- noreach,
- predefined, // Global variables defined by option
-
- scope, // The current scope
- stack,
- unuseds,
- urls,
- warnings,
-
- extraModules = [],
- emitter = new events.EventEmitter();
-
- function checkOption(name, t) {
- name = name.trim();
-
- if (/^[+-]W\d{3}$/g.test(name)) {
- return true;
- }
-
- if (valOptions[name] === undefined && boolOptions[name] === undefined) {
- if (t.type !== "jslint") {
- error("E001", t, name);
- return false;
- }
- }
-
- return true;
- }
-
- function isString(obj) {
- return Object.prototype.toString.call(obj) === "[object String]";
- }
-
- function isIdentifier(tkn, value) {
- if (!tkn)
- return false;
-
- if (!tkn.identifier || tkn.value !== value)
- return false;
-
- return true;
- }
-
- function isReserved(token) {
- if (!token.reserved) {
- return false;
- }
-
- if (token.meta && token.meta.isFutureReservedWord) {
- // ES3 FutureReservedWord in an ES5 environment.
- if (state.option.inES5(true) && !token.meta.es5) {
- return false;
- }
-
- // Some ES5 FutureReservedWord identifiers are active only
- // within a strict mode environment.
- if (token.meta.strictOnly) {
- if (!state.option.strict && !state.directive["use strict"]) {
- return false;
- }
- }
-
- if (token.isProperty) {
- return false;
- }
- }
-
- return true;
- }
-
- function supplant(str, data) {
- return str.replace(/\{([^{}]*)\}/g, function (a, b) {
- var r = data[b];
- return typeof r === "string" || typeof r === "number" ? r : a;
- });
- }
-
- function combine(t, o) {
- var n;
- for (n in o) {
- if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) {
- t[n] = o[n];
- }
- }
- }
-
- function updatePredefined() {
- Object.keys(JSHINT.blacklist).forEach(function (key) {
- delete predefined[key];
- });
- }
-
- function assume() {
- if (state.option.es5) {
- warning("I003");
- }
- if (state.option.couch) {
- combine(predefined, vars.couch);
- }
-
- if (state.option.rhino) {
- combine(predefined, vars.rhino);
- }
-
- if (state.option.phantom) {
- combine(predefined, vars.phantom);
- }
-
- if (state.option.prototypejs) {
- combine(predefined, vars.prototypejs);
- }
-
- if (state.option.node) {
- combine(predefined, vars.node);
- }
-
- if (state.option.devel) {
- combine(predefined, vars.devel);
- }
-
- if (state.option.dojo) {
- combine(predefined, vars.dojo);
- }
-
- if (state.option.browser) {
- combine(predefined, vars.browser);
- }
-
- if (state.option.nonstandard) {
- combine(predefined, vars.nonstandard);
- }
-
- if (state.option.jquery) {
- combine(predefined, vars.jquery);
- }
-
- if (state.option.mootools) {
- combine(predefined, vars.mootools);
- }
-
- if (state.option.worker) {
- combine(predefined, vars.worker);
- }
-
- if (state.option.wsh) {
- combine(predefined, vars.wsh);
- }
-
- if (state.option.globalstrict && state.option.strict !== false) {
- state.option.strict = true;
- }
-
- if (state.option.yui) {
- combine(predefined, vars.yui);
- }
-
- // Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz
-
- state.option.inMoz = function (strict) {
- if (strict) {
- return state.option.moz && !state.option.esnext;
- }
- return state.option.moz;
- };
-
- state.option.inESNext = function (strict) {
- if (strict) {
- return !state.option.moz && state.option.esnext;
- }
- return state.option.moz || state.option.esnext;
- };
-
- state.option.inES5 = function (/* strict */) {
- return !state.option.es3;
- };
-
- state.option.inES3 = function (strict) {
- if (strict) {
- return !state.option.moz && !state.option.esnext && state.option.es3;
- }
- return state.option.es3;
- };
- }
-
- // Produce an error warning.
- function quit(code, line, chr) {
- var percentage = Math.floor((line / state.lines.length) * 100);
- var message = messages.errors[code].desc;
-
- throw {
- name: "JSHintError",
- line: line,
- character: chr,
- message: message + " (" + percentage + "% scanned).",
- raw: message
- };
- }
-
- function isundef(scope, code, token, a) {
- return JSHINT.undefs.push([scope, code, token, a]);
- }
-
- function warning(code, t, a, b, c, d) {
- var ch, l, w, msg;
-
- if (/^W\d{3}$/.test(code)) {
- if (state.ignored[code])
- return;
-
- msg = messages.warnings[code];
- } else if (/E\d{3}/.test(code)) {
- msg = messages.errors[code];
- } else if (/I\d{3}/.test(code)) {
- msg = messages.info[code];
- }
-
- t = t || state.tokens.next;
- if (t.id === "(end)") { // `~
- t = state.tokens.curr;
- }
-
- l = t.line || 0;
- ch = t.from || 0;
-
- w = {
- id: "(error)",
- raw: msg.desc,
- code: msg.code,
- evidence: state.lines[l - 1] || "",
- line: l,
- character: ch,
- scope: JSHINT.scope,
- a: a,
- b: b,
- c: c,
- d: d
- };
-
- w.reason = supplant(msg.desc, w);
- JSHINT.errors.push(w);
-
- if (state.option.passfail) {
- quit("E042", l, ch);
- }
-
- warnings += 1;
- if (warnings >= state.option.maxerr) {
- quit("E043", l, ch);
- }
-
- return w;
- }
-
- function warningAt(m, l, ch, a, b, c, d) {
- return warning(m, {
- line: l,
- from: ch
- }, a, b, c, d);
- }
-
- function error(m, t, a, b, c, d) {
- warning(m, t, a, b, c, d);
- }
-
- function errorAt(m, l, ch, a, b, c, d) {
- return error(m, {
- line: l,
- from: ch
- }, a, b, c, d);
- }
-
- // Tracking of "internal" scripts, like eval containing a static string
- function addInternalSrc(elem, src) {
- var i;
- i = {
- id: "(internal)",
- elem: elem,
- value: src
- };
- JSHINT.internals.push(i);
- return i;
- }
-
- function addlabel(t, type, tkn, islet) {
- // Define t in the current function in the current scope.
- if (type === "exception") {
- if (_.has(funct["(context)"], t)) {
- if (funct[t] !== true && !state.option.node) {
- warning("W002", state.tokens.next, t);
- }
- }
- }
-
- if (_.has(funct, t) && !funct["(global)"]) {
- if (funct[t] === true) {
- if (state.option.latedef) {
- if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
- !_.contains([funct[t], type], "unction")) {
- warning("W003", state.tokens.next, t);
- }
- }
- } else {
- if (!state.option.shadow && type !== "exception" ||
- (funct["(blockscope)"].getlabel(t))) {
- warning("W004", state.tokens.next, t);
- }
- }
- }
-
- // a double definition of a let variable in same block throws a TypeError
- //if (funct["(blockscope)"] && funct["(blockscope)"].current.has(t)) {
- // error("E044", state.tokens.next, t);
- //}
-
- // if the identifier is from a let, adds it only to the current blockscope
- if (islet) {
- funct["(blockscope)"].current.add(t, type, state.tokens.curr);
- } else {
-
- funct[t] = type;
-
- if (tkn) {
- funct["(tokens)"][t] = tkn;
- }
-
- if (funct["(global)"]) {
- global[t] = funct;
- if (_.has(implied, t)) {
- if (state.option.latedef) {
- if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
- !_.contains([funct[t], type], "unction")) {
- warning("W003", state.tokens.next, t);
- }
- }
-
- delete implied[t];
- }
- } else {
- scope[t] = funct;
- }
- }
- }
-
- function doOption() {
- var nt = state.tokens.next;
- var body = nt.body.split(",").map(function (s) { return s.trim(); });
- var predef = {};
-
- if (nt.type === "globals") {
- body.forEach(function (g) {
- g = g.split(":");
- var key = g[0];
- var val = g[1];
-
- if (key.charAt(0) === "-") {
- key = key.slice(1);
- val = false;
-
- JSHINT.blacklist[key] = key;
- updatePredefined();
- } else {
- predef[key] = (val === "true");
- }
- });
-
- combine(predefined, predef);
-
- for (var key in predef) {
- if (_.has(predef, key)) {
- declared[key] = nt;
- }
- }
- }
-
- if (nt.type === "exported") {
- body.forEach(function (e) {
- exported[e] = true;
- });
- }
-
- if (nt.type === "members") {
- membersOnly = membersOnly || {};
-
- body.forEach(function (m) {
- var ch1 = m.charAt(0);
- var ch2 = m.charAt(m.length - 1);
-
- if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
- m = m
- .substr(1, m.length - 2)
- .replace("\\b", "\b")
- .replace("\\t", "\t")
- .replace("\\n", "\n")
- .replace("\\v", "\v")
- .replace("\\f", "\f")
- .replace("\\r", "\r")
- .replace("\\\\", "\\")
- .replace("\\\"", "\"");
- }
-
- membersOnly[m] = false;
- });
- }
-
- var numvals = [
- "maxstatements",
- "maxparams",
- "maxdepth",
- "maxcomplexity",
- "maxerr",
- "maxlen",
- "indent"
- ];
-
- if (nt.type === "jshint" || nt.type === "jslint") {
- body.forEach(function (g) {
- g = g.split(":");
- var key = (g[0] || "").trim();
- var val = (g[1] || "").trim();
-
- if (!checkOption(key, nt)) {
- return;
- }
-
- if (numvals.indexOf(key) >= 0) {
-
- // GH988 - numeric options can be disabled by setting them to `false`
- if (val !== "false") {
- val = +val;
-
- if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
- error("E032", nt, g[1].trim());
- return;
- }
-
- if (key === "indent") {
- state.option["(explicitIndent)"] = true;
- }
- state.option[key] = val;
- } else {
- if (key === "indent") {
- state.option["(explicitIndent)"] = false;
- } else {
- state.option[key] = false;
- }
- }
-
- return;
- }
-
- if (key === "validthis") {
- // `validthis` is valid only within a function scope.
- if (funct["(global)"]) {
- error("E009");
- } else {
- if (val === "true" || val === "false") {
- state.option.validthis = (val === "true");
- } else {
- error("E002", nt);
- }
- }
- return;
- }
-
- if (key === "quotmark") {
- switch (val) {
- case "true":
- case "false":
- state.option.quotmark = (val === "true");
- break;
- case "double":
- case "single":
- state.option.quotmark = val;
- break;
- default:
- error("E002", nt);
- }
- return;
- }
-
- if (key === "unused") {
- switch (val) {
- case "true":
- state.option.unused = true;
- break;
- case "false":
- state.option.unused = false;
- break;
- case "vars":
- case "strict":
- state.option.unused = val;
- break;
- default:
- error("E002", nt);
- }
- return;
- }
-
- if (key === "latedef") {
- switch (val) {
- case "true":
- state.option.latedef = true;
- break;
- case "false":
- state.option.latedef = false;
- break;
- case "nofunc":
- state.option.latedef = "nofunc";
- break;
- default:
- error("E002", nt);
- }
- return;
- }
-
- var match = /^([+-])(W\d{3})$/g.exec(key);
- if (match) {
- // ignore for -W..., unignore for +W...
- state.ignored[match[2]] = (match[1] === "-");
- return;
- }
-
- var tn;
- if (val === "true" || val === "false") {
- if (nt.type === "jslint") {
- tn = renamedOptions[key] || key;
- state.option[tn] = (val === "true");
-
- if (invertedOptions[tn] !== undefined) {
- state.option[tn] = !state.option[tn];
- }
- } else {
- state.option[key] = (val === "true");
- }
-
- if (key === "newcap") {
- state.option["(explicitNewcap)"] = true;
- }
- return;
- }
-
- error("E002", nt);
- });
-
- assume();
- }
- }
-
- // We need a peek function. If it has an argument, it peeks that much farther
- // ahead. It is used to distinguish
- // for ( var i in ...
- // from
- // for ( var i = ...
-
- function peek(p) {
- var i = p || 0, j = 0, t;
-
- while (j <= i) {
- t = lookahead[j];
- if (!t) {
- t = lookahead[j] = lex.token();
- }
- j += 1;
- }
- return t;
- }
-
- // Produce the next token. It looks for programming errors.
-
- function advance(id, t) {
- switch (state.tokens.curr.id) {
- case "(number)":
- if (state.tokens.next.id === ".") {
- warning("W005", state.tokens.curr);
- }
- break;
- case "-":
- if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
- warning("W006");
- }
- break;
- case "+":
- if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
- warning("W007");
- }
- break;
- }
-
- if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
- anonname = state.tokens.curr.value;
- }
-
- if (id && state.tokens.next.id !== id) {
- if (t) {
- if (state.tokens.next.id === "(end)") {
- error("E019", t, t.id);
- } else {
- error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
- }
- } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
- warning("W116", state.tokens.next, id, state.tokens.next.value);
- }
- }
-
- state.tokens.prev = state.tokens.curr;
- state.tokens.curr = state.tokens.next;
- for (;;) {
- state.tokens.next = lookahead.shift() || lex.token();
-
- if (!state.tokens.next) { // No more tokens left, give up
- quit("E041", state.tokens.curr.line);
- }
-
- if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
- return;
- }
-
- if (state.tokens.next.check) {
- state.tokens.next.check();
- }
-
- if (state.tokens.next.isSpecial) {
- doOption();
- } else {
- if (state.tokens.next.id !== "(endline)") {
- break;
- }
- }
- }
- }
-
- // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
- // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
- // like .nud except that it is only used on the first token of a statement.
- // Having .fud makes it much easier to define statement-oriented languages like
- // JavaScript. I retained Pratt's nomenclature.
-
- // .nud Null denotation
- // .fud First null denotation
- // .led Left denotation
- // lbp Left binding power
- // rbp Right binding power
-
- // They are elements of the parsing method called Top Down Operator Precedence.
-
- function expression(rbp, initial) {
- var left, isArray = false, isObject = false, isLetExpr = false;
-
- // if current expression is a let expression
- if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.next, "let expressions");
- }
- isLetExpr = true;
- // create a new block scope we use only for the current expression
- funct["(blockscope)"].stack();
- advance("let");
- advance("(");
- state.syntax["let"].fud.call(state.syntax["let"].fud, false);
- advance(")");
- }
-
- if (state.tokens.next.id === "(end)")
- error("E006", state.tokens.curr);
-
- advance();
-
- if (initial) {
- anonname = "anonymous";
- funct["(verb)"] = state.tokens.curr.value;
- }
-
- if (initial === true && state.tokens.curr.fud) {
- left = state.tokens.curr.fud();
- } else {
- if (state.tokens.curr.nud) {
- left = state.tokens.curr.nud();
- } else {
- error("E030", state.tokens.curr, state.tokens.curr.id);
- }
-
- var end_of_expr = state.tokens.next.identifier &&
- !state.tokens.curr.led &&
- state.tokens.curr.line !== state.tokens.next.line;
- while (rbp < state.tokens.next.lbp && !end_of_expr) {
- isArray = state.tokens.curr.value === "Array";
- isObject = state.tokens.curr.value === "Object";
-
- // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
- // Line breaks in IfStatement heads exist to satisfy the checkJSHint
- // "Line too long." error.
- if (left && (left.value || (left.first && left.first.value))) {
- // If the left.value is not "new", or the left.first.value is a "."
- // then safely assume that this is not "new Array()" and possibly
- // not "new Object()"...
- if (left.value !== "new" ||
- (left.first && left.first.value && left.first.value === ".")) {
- isArray = false;
- // ...In the case of Object, if the left.value and state.tokens.curr.value
- // are not equal, then safely assume that this not "new Object()"
- if (left.value !== state.tokens.curr.value) {
- isObject = false;
- }
- }
- }
-
- advance();
-
- if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
- warning("W009", state.tokens.curr);
- }
-
- if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
- warning("W010", state.tokens.curr);
- }
-
- if (left && state.tokens.curr.led) {
- left = state.tokens.curr.led(left);
- } else {
- error("E033", state.tokens.curr, state.tokens.curr.id);
- }
- }
- }
- if (isLetExpr) {
- funct["(blockscope)"].unstack();
- }
- return left;
- }
-
-
-// Functions for conformance of style.
-
- function adjacent(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (state.option.white) {
- if (left.character !== right.from && left.line === right.line) {
- left.from += (left.character - left.from);
- warning("W011", left, left.value);
- }
- }
- }
-
- function nobreak(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (state.option.white && (left.character !== right.from || left.line !== right.line)) {
- warning("W012", right, right.value);
- }
- }
-
- function nospace(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (state.option.white && !left.comment) {
- if (left.line === right.line) {
- adjacent(left, right);
- }
- }
- }
-
- function nonadjacent(left, right) {
- if (state.option.white) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
-
- if (left.value === ";" && right.value === ";") {
- return;
- }
-
- if (left.line === right.line && left.character === right.from) {
- left.from += (left.character - left.from);
- warning("W013", left, left.value);
- }
- }
- }
-
- function nobreaknonadjacent(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (!state.option.laxbreak && left.line !== right.line) {
- warning("W014", right, right.id);
- } else if (state.option.white) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (left.character === right.from) {
- left.from += (left.character - left.from);
- warning("W013", left, left.value);
- }
- }
- }
-
- function indentation(bias) {
- if (!state.option.white && !state.option["(explicitIndent)"]) {
- return;
- }
-
- if (state.tokens.next.id === "(end)") {
- return;
- }
-
- var i = indent + (bias || 0);
- if (state.tokens.next.from !== i) {
- warning("W015", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from);
- }
- }
-
- function nolinebreak(t) {
- t = t || state.tokens.curr;
- if (t.line !== state.tokens.next.line) {
- warning("E022", t, t.value);
- }
- }
-
-
- function comma(opts) {
- opts = opts || {};
-
- if (!opts.peek) {
- if (state.tokens.curr.line !== state.tokens.next.line) {
- if (!state.option.laxcomma) {
- if (comma.first) {
- warning("I001");
- comma.first = false;
- }
- warning("W014", state.tokens.curr, state.tokens.next.value);
- }
- } else if (!state.tokens.curr.comment &&
- state.tokens.curr.character !== state.tokens.next.from && state.option.white) {
- state.tokens.curr.from += (state.tokens.curr.character - state.tokens.curr.from);
- warning("W011", state.tokens.curr, state.tokens.curr.value);
- }
-
- advance(",");
- }
-
- // TODO: This is a temporary solution to fight against false-positives in
- // arrays and objects with trailing commas (see GH-363). The best solution
- // would be to extract all whitespace rules out of parser.
-
- if (state.tokens.next.value !== "]" && state.tokens.next.value !== "}") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
-
- if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) {
- // Keywords that cannot follow a comma operator.
- switch (state.tokens.next.value) {
- case "break":
- case "case":
- case "catch":
- case "continue":
- case "default":
- case "do":
- case "else":
- case "finally":
- case "for":
- case "if":
- case "in":
- case "instanceof":
- case "return":
- case "yield":
- case "switch":
- case "throw":
- case "try":
- case "var":
- case "let":
- case "while":
- case "with":
- error("E024", state.tokens.next, state.tokens.next.value);
- return false;
- }
- }
-
- if (state.tokens.next.type === "(punctuator)") {
- switch (state.tokens.next.value) {
- case "}":
- case "]":
- case ",":
- if (opts.allowTrailing) {
- return true;
- }
-
- /* falls through */
- case ")":
- error("E024", state.tokens.next, state.tokens.next.value);
- return false;
- }
- }
- return true;
- }
-
- // Functional constructors for making the symbols that will be inherited by
- // tokens.
-
- function symbol(s, p) {
- var x = state.syntax[s];
- if (!x || typeof x !== "object") {
- state.syntax[s] = x = {
- id: s,
- lbp: p,
- value: s
- };
- }
- return x;
- }
-
- function delim(s) {
- return symbol(s, 0);
- }
-
- function stmt(s, f) {
- var x = delim(s);
- x.identifier = x.reserved = true;
- x.fud = f;
- return x;
- }
-
- function blockstmt(s, f) {
- var x = stmt(s, f);
- x.block = true;
- return x;
- }
-
- function reserveName(x) {
- var c = x.id.charAt(0);
- if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
- x.identifier = x.reserved = true;
- }
- return x;
- }
-
- function prefix(s, f) {
- var x = symbol(s, 150);
- reserveName(x);
- x.nud = (typeof f === "function") ? f : function () {
- this.right = expression(150);
- this.arity = "unary";
- if (this.id === "++" || this.id === "--") {
- if (state.option.plusplus) {
- warning("W016", this, this.id);
- } else if ((!this.right.identifier || isReserved(this.right)) &&
- this.right.id !== "." && this.right.id !== "[") {
- warning("W017", this);
- }
- }
- return this;
- };
- return x;
- }
-
- function type(s, f) {
- var x = delim(s);
- x.type = s;
- x.nud = f;
- return x;
- }
-
- function reserve(name, func) {
- var x = type(name, func);
- x.identifier = true;
- x.reserved = true;
- return x;
- }
-
- function FutureReservedWord(name, meta) {
- var x = type(name, (meta && meta.nud) || function () {
- return this;
- });
-
- meta = meta || {};
- meta.isFutureReservedWord = true;
-
- x.value = name;
- x.identifier = true;
- x.reserved = true;
- x.meta = meta;
-
- return x;
- }
-
- function reservevar(s, v) {
- return reserve(s, function () {
- if (typeof v === "function") {
- v(this);
- }
- return this;
- });
- }
-
- function infix(s, f, p, w) {
- var x = symbol(s, p);
- reserveName(x);
- x.led = function (left) {
- if (!w) {
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- if (s === "in" && left.id === "!") {
- warning("W018", left, "!");
- }
- if (typeof f === "function") {
- return f(left, this);
- } else {
- this.left = left;
- this.right = expression(p);
- return this;
- }
- };
- return x;
- }
-
-
- function application(s) {
- var x = symbol(s, 42);
-
- x.led = function (left) {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "arrow function syntax (=>)");
- }
-
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
-
- this.left = left;
- this.right = doFunction(undefined, undefined, false, left);
- return this;
- };
- return x;
- }
-
- function relation(s, f) {
- var x = symbol(s, 100);
-
- x.led = function (left) {
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- var right = expression(100);
-
- if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
- warning("W019", this);
- } else if (f) {
- f.apply(this, [left, right]);
- }
-
- if (!left || !right) {
- quit("E041", state.tokens.curr.line);
- }
-
- if (left.id === "!") {
- warning("W018", left, "!");
- }
-
- if (right.id === "!") {
- warning("W018", right, "!");
- }
-
- this.left = left;
- this.right = right;
- return this;
- };
- return x;
- }
-
- function isPoorRelation(node) {
- return node &&
- ((node.type === "(number)" && +node.value === 0) ||
- (node.type === "(string)" && node.value === "") ||
- (node.type === "null" && !state.option.eqnull) ||
- node.type === "true" ||
- node.type === "false" ||
- node.type === "undefined");
- }
-
- function assignop(s) {
- symbol(s, 20).exps = true;
-
- return infix(s, function (left, that) {
- that.left = left;
-
- if (left) {
- if (predefined[left.value] === false &&
- scope[left.value]["(global)"] === true) {
- warning("W020", left);
- } else if (left["function"]) {
- warning("W021", left, left.value);
- }
-
- if (funct[left.value] === "const") {
- error("E013", left, left.value);
- }
-
- if (left.id === ".") {
- if (!left.left) {
- warning("E031", that);
- } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
- warning("E031", that);
- }
-
- that.right = expression(19);
- return that;
- } else if (left.id === "[") {
- if (state.tokens.curr.left.first) {
- state.tokens.curr.left.first.forEach(function (t) {
- if (funct[t.value] === "const") {
- error("E013", t, t.value);
- }
- });
- } else if (!left.left) {
- warning("E031", that);
- } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
- warning("E031", that);
- }
- that.right = expression(19);
- return that;
- } else if (left.identifier && !isReserved(left)) {
- if (funct[left.value] === "exception") {
- warning("W022", left);
- }
- that.right = expression(19);
- return that;
- }
-
- if (left === state.syntax["function"]) {
- warning("W023", state.tokens.curr);
- }
- }
-
- error("E031", that);
- }, 20);
- }
-
-
- function bitwise(s, f, p) {
- var x = symbol(s, p);
- reserveName(x);
- x.led = (typeof f === "function") ? f : function (left) {
- if (state.option.bitwise) {
- warning("W016", this, this.id);
- }
- this.left = left;
- this.right = expression(p);
- return this;
- };
- return x;
- }
-
-
- function bitwiseassignop(s) {
- symbol(s, 20).exps = true;
- return infix(s, function (left, that) {
- if (state.option.bitwise) {
- warning("W016", that, that.id);
- }
- nonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (left) {
- if (left.id === "." || left.id === "[" ||
- (left.identifier && !isReserved(left))) {
- expression(19);
- return that;
- }
- if (left === state.syntax["function"]) {
- warning("W023", state.tokens.curr);
- }
- return that;
- }
- error("E031", that);
- }, 20);
- }
-
-
- function suffix(s) {
- var x = symbol(s, 150);
-
- x.led = function (left) {
- if (state.option.plusplus) {
- warning("W016", this, this.id);
- } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
- warning("W017", this);
- }
-
- this.left = left;
- return this;
- };
- return x;
- }
-
- // fnparam means that this identifier is being defined as a function
- // argument (see identifier())
- // prop means that this identifier is that of an object property
-
- function optionalidentifier(fnparam, prop) {
- if (!state.tokens.next.identifier) {
- return;
- }
-
- advance();
-
- var curr = state.tokens.curr;
- var meta = curr.meta || {};
- var val = state.tokens.curr.value;
-
- if (!isReserved(curr)) {
- return val;
- }
-
- if (prop) {
- if (state.option.inES5() || meta.isFutureReservedWord) {
- return val;
- }
- }
-
- if (fnparam && val === "undefined") {
- return val;
- }
-
- // Display an info message about reserved words as properties
- // and ES5 but do it only once.
- if (prop && !api.getCache("displayed:I002")) {
- api.setCache("displayed:I002", true);
- warning("I002");
- }
-
- warning("W024", state.tokens.curr, state.tokens.curr.id);
- return val;
- }
-
- // fnparam means that this identifier is being defined as a function
- // argument
- // prop means that this identifier is that of an object property
- function identifier(fnparam, prop) {
- var i = optionalidentifier(fnparam, prop);
- if (i) {
- return i;
- }
- if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") {
- warning("W025");
- } else {
- error("E030", state.tokens.next, state.tokens.next.value);
- }
- }
-
-
- function reachable(s) {
- var i = 0, t;
- if (state.tokens.next.id !== ";" || noreach) {
- return;
- }
- for (;;) {
- t = peek(i);
- if (t.reach) {
- return;
- }
- if (t.id !== "(endline)") {
- if (t.id === "function") {
- if (!state.option.latedef) {
- break;
- }
-
- warning("W026", t);
- break;
- }
-
- warning("W027", t, t.value, s);
- break;
- }
- i += 1;
- }
- }
-
-
- function statement(noindent) {
- var values;
- var i = indent, r, s = scope, t = state.tokens.next;
-
- if (t.id === ";") {
- advance(";");
- return;
- }
-
- // Is this a labelled statement?
- var res = isReserved(t);
-
- // We're being more tolerant here: if someone uses
- // a FutureReservedWord as a label, we warn but proceed
- // anyway.
-
- if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
- warning("W024", t, t.id);
- res = false;
- }
-
- // detect a destructuring assignment
- if (_.has(["[", "{"], t.value)) {
- if (lookupBlockType().isDestAssign) {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring expression");
- }
- values = destructuringExpression();
- values.forEach(function (tok) {
- isundef(funct, "W117", tok.token, tok.id);
- });
- advance("=");
- destructuringExpressionMatch(values, expression(5, true));
- advance(";");
- return;
- }
- }
- if (t.identifier && !res && peek().id === ":") {
- advance();
- advance(":");
- scope = Object.create(s);
- addlabel(t.value, "label");
-
- if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
- warning("W028", state.tokens.next, t.value, state.tokens.next.value);
- }
-
- state.tokens.next.label = t.value;
- t = state.tokens.next;
- }
-
- // Is it a lonely block?
-
- if (t.id === "{") {
- // Is it a switch case block?
- //
- // switch (foo) {
- // case bar: { <= here.
- // ...
- // }
- // }
- var iscase = (funct["(verb)"] === "case" && state.tokens.curr.value === ":");
- block(true, true, false, false, iscase);
- return;
- }
-
- // Parse the statement.
-
- if (!noindent) {
- indentation();
- }
- r = expression(0, true);
-
- // Look for the final semicolon.
-
- if (!t.block) {
- if (!state.option.expr && (!r || !r.exps)) {
- warning("W030", state.tokens.curr);
- } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
- warning("W031", t);
- }
-
- if (state.tokens.next.id !== ";") {
- if (!state.option.asi) {
- // If this is the last statement in a block that ends on
- // the same line *and* option lastsemic is on, ignore the warning.
- // Otherwise, complain about missing semicolon.
- if (!state.option.lastsemic || state.tokens.next.id !== "}" ||
- state.tokens.next.line !== state.tokens.curr.line) {
- warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
- }
- }
- } else {
- adjacent(state.tokens.curr, state.tokens.next);
- advance(";");
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- }
-
- // Restore the indentation.
-
- indent = i;
- scope = s;
- return r;
- }
-
-
- function statements(startLine) {
- var a = [], p;
-
- while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
- if (state.tokens.next.id === ";") {
- p = peek();
-
- if (!p || (p.id !== "(" && p.id !== "[")) {
- warning("W032");
- }
-
- advance(";");
- } else {
- a.push(statement(startLine === state.tokens.next.line));
- }
- }
- return a;
- }
-
-
- /*
- * read all directives
- * recognizes a simple form of asi, but always
- * warns, if it is used
- */
- function directives() {
- var i, p, pn;
-
- for (;;) {
- if (state.tokens.next.id === "(string)") {
- p = peek(0);
- if (p.id === "(endline)") {
- i = 1;
- do {
- pn = peek(i);
- i = i + 1;
- } while (pn.id === "(endline)");
-
- if (pn.id !== ";") {
- if (pn.id !== "(string)" && pn.id !== "(number)" &&
- pn.id !== "(regexp)" && pn.identifier !== true &&
- pn.id !== "}") {
- break;
- }
- warning("W033", state.tokens.next);
- } else {
- p = pn;
- }
- } else if (p.id === "}") {
- // Directive with no other statements, warn about missing semicolon
- warning("W033", p);
- } else if (p.id !== ";") {
- break;
- }
-
- indentation();
- advance();
- if (state.directive[state.tokens.curr.value]) {
- warning("W034", state.tokens.curr, state.tokens.curr.value);
- }
-
- if (state.tokens.curr.value === "use strict") {
- if (!state.option["(explicitNewcap)"])
- state.option.newcap = true;
- state.option.undef = true;
- }
-
- // there's no directive negation, so always set to true
- state.directive[state.tokens.curr.value] = true;
-
- if (p.id === ";") {
- advance(";");
- }
- continue;
- }
- break;
- }
- }
-
-
- /*
- * Parses a single block. A block is a sequence of statements wrapped in
- * braces.
- *
- * ordinary - true for everything but function bodies and try blocks.
- * stmt - true if block can be a single statement (e.g. in if/for/while).
- * isfunc - true if block is a function body
- * isfatarrow -
- * iscase - true if block is a switch case block
- */
- function block(ordinary, stmt, isfunc, isfatarrow, iscase) {
- var a,
- b = inblock,
- old_indent = indent,
- m,
- s = scope,
- t,
- line,
- d;
-
- inblock = ordinary;
-
- if (!ordinary || !state.option.funcscope)
- scope = Object.create(scope);
-
- nonadjacent(state.tokens.curr, state.tokens.next);
- t = state.tokens.next;
-
- var metrics = funct["(metrics)"];
- metrics.nestedBlockDepth += 1;
- metrics.verifyMaxNestedBlockDepthPerFunction();
-
- if (state.tokens.next.id === "{") {
- advance("{");
-
- // create a new block scope
- funct["(blockscope)"].stack();
-
- line = state.tokens.curr.line;
- if (state.tokens.next.id !== "}") {
- indent += state.option.indent;
- while (!ordinary && state.tokens.next.from > indent) {
- indent += state.option.indent;
- }
-
- if (isfunc) {
- m = {};
- for (d in state.directive) {
- if (_.has(state.directive, d)) {
- m[d] = state.directive[d];
- }
- }
- directives();
-
- if (state.option.strict && funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !state.directive["use strict"]) {
- warning("E007");
- }
- }
- }
-
- a = statements(line);
-
- metrics.statementCount += a.length;
-
- if (isfunc) {
- state.directive = m;
- }
-
- indent -= state.option.indent;
- if (line !== state.tokens.next.line) {
- indentation();
- }
- } else if (line !== state.tokens.next.line) {
- indentation();
- }
- advance("}", t);
-
- funct["(blockscope)"].unstack();
-
- indent = old_indent;
- } else if (!ordinary) {
- if (isfunc) {
- m = {};
- if (stmt && !isfatarrow && !state.option.inMoz(true)) {
- error("W118", state.tokens.curr, "function closure expressions");
- }
-
- if (!stmt) {
- for (d in state.directive) {
- if (_.has(state.directive, d)) {
- m[d] = state.directive[d];
- }
- }
- }
- expression(5);
-
- if (state.option.strict && funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !state.directive["use strict"]) {
- warning("E007");
- }
- }
- } else {
- error("E021", state.tokens.next, "{", state.tokens.next.value);
- }
- } else {
-
- // check to avoid let declaration not within a block
- funct["(nolet)"] = true;
-
- if (!stmt || state.option.curly) {
- warning("W116", state.tokens.next, "{", state.tokens.next.value);
- }
-
- noreach = true;
- indent += state.option.indent;
- // test indentation only if statement is in new line
- a = [statement(state.tokens.next.line === state.tokens.curr.line)];
- indent -= state.option.indent;
- noreach = false;
-
- delete funct["(nolet)"];
- }
- // If it is a "break" in switch case, don't clear and let it propagate out.
- if (!(iscase && funct["(verb)"] === "break")) funct["(verb)"] = null;
-
- if (!ordinary || !state.option.funcscope) scope = s;
- inblock = b;
- if (ordinary && state.option.noempty && (!a || a.length === 0)) {
- warning("W035");
- }
- metrics.nestedBlockDepth -= 1;
- return a;
- }
-
-
- function countMember(m) {
- if (membersOnly && typeof membersOnly[m] !== "boolean") {
- warning("W036", state.tokens.curr, m);
- }
- if (typeof member[m] === "number") {
- member[m] += 1;
- } else {
- member[m] = 1;
- }
- }
-
-
- function note_implied(tkn) {
- var name = tkn.value, line = tkn.line, a = implied[name];
- if (typeof a === "function") {
- a = false;
- }
-
- if (!a) {
- a = [line];
- implied[name] = a;
- } else if (a[a.length - 1] !== line) {
- a.push(line);
- }
- }
-
-
- // Build the syntax table by declaring the syntactic elements of the language.
-
- type("(number)", function () {
- return this;
- });
-
- type("(string)", function () {
- return this;
- });
-
- state.syntax["(identifier)"] = {
- type: "(identifier)",
- lbp: 0,
- identifier: true,
- nud: function () {
- var v = this.value,
- s = scope[v],
- f;
-
- if (typeof s === "function") {
- // Protection against accidental inheritance.
- s = undefined;
- } else if (typeof s === "boolean") {
- f = funct;
- funct = functions[0];
- addlabel(v, "var");
- s = funct;
- funct = f;
- }
- var block;
- if (_.has(funct, "(blockscope)")) {
- block = funct["(blockscope)"].getlabel(v);
- }
-
- // The name is in scope and defined in the current function.
- if (funct === s || block) {
- // Change 'unused' to 'var', and reject labels.
- // the name is in a block scope
- switch (block ? block[v]["(type)"] : funct[v]) {
- case "unused":
- if (block) block[v]["(type)"] = "var";
- else funct[v] = "var";
- break;
- case "unction":
- if (block) block[v]["(type)"] = "function";
- else funct[v] = "function";
- this["function"] = true;
- break;
- case "function":
- this["function"] = true;
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- break;
- }
- } else if (funct["(global)"]) {
- // The name is not defined in the function. If we are in the global
- // scope, then we have an undefined variable.
- //
- // Operators typeof and delete do not raise runtime errors even if
- // the base object of a reference is null so no need to display warning
- // if we're inside of typeof or delete.
-
- if (typeof predefined[v] !== "boolean") {
- // Attempting to subscript a null reference will throw an
- // error, even within the typeof and delete operators
- if (!(anonname === "typeof" || anonname === "delete") ||
- (state.tokens.next && (state.tokens.next.value === "." ||
- state.tokens.next.value === "["))) {
-
- // if we're in a list comprehension, variables are declared
- // locally and used before being defined. So we check
- // the presence of the given variable in the comp array
- // before declaring it undefined.
-
- if (!funct["(comparray)"].check(v)) {
- isundef(funct, "W117", state.tokens.curr, v);
- }
- }
- }
-
- note_implied(state.tokens.curr);
- } else {
- // If the name is already defined in the current
- // function, but not as outer, then there is a scope error.
-
- switch (funct[v]) {
- case "closure":
- case "function":
- case "var":
- case "unused":
- warning("W038", state.tokens.curr, v);
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- break;
- case "outer":
- case "global":
- break;
- default:
- // If the name is defined in an outer function, make an outer entry,
- // and if it was unused, make it var.
- if (s === true) {
- funct[v] = true;
- } else if (s === null) {
- warning("W039", state.tokens.curr, v);
- note_implied(state.tokens.curr);
- } else if (typeof s !== "object") {
- // Operators typeof and delete do not raise runtime errors even
- // if the base object of a reference is null so no need to
- //
- // display warning if we're inside of typeof or delete.
- // Attempting to subscript a null reference will throw an
- // error, even within the typeof and delete operators
- if (!(anonname === "typeof" || anonname === "delete") ||
- (state.tokens.next &&
- (state.tokens.next.value === "." || state.tokens.next.value === "["))) {
-
- isundef(funct, "W117", state.tokens.curr, v);
- }
- funct[v] = true;
- note_implied(state.tokens.curr);
- } else {
- switch (s[v]) {
- case "function":
- case "unction":
- this["function"] = true;
- s[v] = "closure";
- funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "var":
- case "unused":
- s[v] = "closure";
- funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "closure":
- funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- }
- }
- }
- }
- return this;
- },
- led: function () {
- error("E033", state.tokens.next, state.tokens.next.value);
- }
- };
-
- type("(regexp)", function () {
- return this;
- });
-
- // ECMAScript parser
-
- delim("(endline)");
- delim("(begin)");
- delim("(end)").reach = true;
- delim("(error)").reach = true;
- delim("}").reach = true;
- delim(")");
- delim("]");
- delim("\"").reach = true;
- delim("'").reach = true;
- delim(";");
- delim(":").reach = true;
- delim("#");
-
- reserve("else");
- reserve("case").reach = true;
- reserve("catch");
- reserve("default").reach = true;
- reserve("finally");
- reservevar("arguments", function (x) {
- if (state.directive["use strict"] && funct["(global)"]) {
- warning("E008", x);
- }
- });
- reservevar("eval");
- reservevar("false");
- reservevar("Infinity");
- reservevar("null");
- reservevar("this", function (x) {
- if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] &&
- funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
- warning("W040", x);
- }
- });
- reservevar("true");
- reservevar("undefined");
-
- assignop("=", "assign", 20);
- assignop("+=", "assignadd", 20);
- assignop("-=", "assignsub", 20);
- assignop("*=", "assignmult", 20);
- assignop("/=", "assigndiv", 20).nud = function () {
- error("E014");
- };
- assignop("%=", "assignmod", 20);
-
- bitwiseassignop("&=", "assignbitand", 20);
- bitwiseassignop("|=", "assignbitor", 20);
- bitwiseassignop("^=", "assignbitxor", 20);
- bitwiseassignop("<<=", "assignshiftleft", 20);
- bitwiseassignop(">>=", "assignshiftright", 20);
- bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
- infix(",", function (left, that) {
- var expr;
- that.exprs = [left];
- if (!comma({peek: true})) {
- return that;
- }
- while (true) {
- if (!(expr = expression(5))) {
- break;
- }
- that.exprs.push(expr);
- if (state.tokens.next.value !== "," || !comma()) {
- break;
- }
- }
- return that;
- }, 5, true);
- infix("?", function (left, that) {
- that.left = left;
- that.right = expression(10);
- advance(":");
- that["else"] = expression(10);
- return that;
- }, 30);
-
- infix("||", "or", 40);
- infix("&&", "and", 50);
- bitwise("|", "bitor", 70);
- bitwise("^", "bitxor", 80);
- bitwise("&", "bitand", 90);
- relation("==", function (left, right) {
- var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null");
-
- if (!eqnull && state.option.eqeqeq)
- warning("W116", this, "===", "==");
- else if (isPoorRelation(left))
- warning("W041", this, "===", left.value);
- else if (isPoorRelation(right))
- warning("W041", this, "===", right.value);
-
- return this;
- });
- relation("===");
- relation("!=", function (left, right) {
- var eqnull = state.option.eqnull &&
- (left.value === "null" || right.value === "null");
-
- if (!eqnull && state.option.eqeqeq) {
- warning("W116", this, "!==", "!=");
- } else if (isPoorRelation(left)) {
- warning("W041", this, "!==", left.value);
- } else if (isPoorRelation(right)) {
- warning("W041", this, "!==", right.value);
- }
- return this;
- });
- relation("!==");
- relation("<");
- relation(">");
- relation("<=");
- relation(">=");
- bitwise("<<", "shiftleft", 120);
- bitwise(">>", "shiftright", 120);
- bitwise(">>>", "shiftrightunsigned", 120);
- infix("in", "in", 120);
- infix("instanceof", "instanceof", 120);
- infix("+", function (left, that) {
- var right = expression(130);
- if (left && right && left.id === "(string)" && right.id === "(string)") {
- left.value += right.value;
- left.character = right.character;
- if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
- warning("W050", left);
- }
- return left;
- }
- that.left = left;
- that.right = right;
- return that;
- }, 130);
- prefix("+", "num");
- prefix("+++", function () {
- warning("W007");
- this.right = expression(150);
- this.arity = "unary";
- return this;
- });
- infix("+++", function (left) {
- warning("W007");
- this.left = left;
- this.right = expression(130);
- return this;
- }, 130);
- infix("-", "sub", 130);
- prefix("-", "neg");
- prefix("---", function () {
- warning("W006");
- this.right = expression(150);
- this.arity = "unary";
- return this;
- });
- infix("---", function (left) {
- warning("W006");
- this.left = left;
- this.right = expression(130);
- return this;
- }, 130);
- infix("*", "mult", 140);
- infix("/", "div", 140);
- infix("%", "mod", 140);
-
- suffix("++", "postinc");
- prefix("++", "preinc");
- state.syntax["++"].exps = true;
-
- suffix("--", "postdec");
- prefix("--", "predec");
- state.syntax["--"].exps = true;
- prefix("delete", function () {
- var p = expression(5);
- if (!p || (p.id !== "." && p.id !== "[")) {
- warning("W051");
- }
- this.first = p;
- return this;
- }).exps = true;
-
- prefix("~", function () {
- if (state.option.bitwise) {
- warning("W052", this, "~");
- }
- expression(150);
- return this;
- });
-
- prefix("...", function () {
- if (!state.option.inESNext()) {
- warning("W104", this, "spread/rest operator");
- }
- if (!state.tokens.next.identifier) {
- error("E030", state.tokens.next, state.tokens.next.value);
- }
- expression(150);
- return this;
- });
-
- prefix("!", function () {
- this.right = expression(150);
- this.arity = "unary";
-
- if (!this.right) { // '!' followed by nothing? Give up.
- quit("E041", this.line || 0);
- }
-
- if (bang[this.right.id] === true) {
- warning("W018", this, "!");
- }
- return this;
- });
-
- prefix("typeof", "typeof");
- prefix("new", function () {
- var c = expression(155), i;
- if (c && c.id !== "function") {
- if (c.identifier) {
- c["new"] = true;
- switch (c.value) {
- case "Number":
- case "String":
- case "Boolean":
- case "Math":
- case "JSON":
- warning("W053", state.tokens.prev, c.value);
- break;
- case "Function":
- if (!state.option.evil) {
- warning("W054");
- }
- break;
- case "Date":
- case "RegExp":
- break;
- default:
- if (c.id !== "function") {
- i = c.value.substr(0, 1);
- if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) {
- warning("W055", state.tokens.curr);
- }
- }
- }
- } else {
- if (c.id !== "." && c.id !== "[" && c.id !== "(") {
- warning("W056", state.tokens.curr);
- }
- }
- } else {
- if (!state.option.supernew)
- warning("W057", this);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id !== "(" && !state.option.supernew) {
- warning("W058", state.tokens.curr, state.tokens.curr.value);
- }
- this.first = c;
- return this;
- });
- state.syntax["new"].exps = true;
-
- prefix("void").exps = true;
-
- infix(".", function (left, that) {
- adjacent(state.tokens.prev, state.tokens.curr);
- nobreak();
- var m = identifier(false, true);
-
- if (typeof m === "string") {
- countMember(m);
- }
-
- that.left = left;
- that.right = m;
-
- if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
- warning("W001");
- }
-
- if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
- if (state.option.noarg)
- warning("W059", left, m);
- else if (state.directive["use strict"])
- error("E008");
- } else if (!state.option.evil && left && left.value === "document" &&
- (m === "write" || m === "writeln")) {
- warning("W060", left);
- }
-
- if (!state.option.evil && (m === "eval" || m === "execScript")) {
- warning("W061");
- }
-
- return that;
- }, 160, true);
-
- infix("(", function (left, that) {
- if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") {
- nobreak(state.tokens.prev, state.tokens.curr);
- }
-
- nospace();
- if (state.option.immed && left && !left.immed && left.id === "function") {
- warning("W062");
- }
-
- var n = 0;
- var p = [];
-
- if (left) {
- if (left.type === "(identifier)") {
- if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
- if ("Number String Boolean Date Object".indexOf(left.value) === -1) {
- if (left.value === "Math") {
- warning("W063", left);
- } else if (state.option.newcap) {
- warning("W064", left);
- }
- }
- }
- }
- }
-
- if (state.tokens.next.id !== ")") {
- for (;;) {
- p[p.length] = expression(10);
- n += 1;
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
-
- advance(")");
- nospace(state.tokens.prev, state.tokens.curr);
-
- if (typeof left === "object") {
- if (left.value === "parseInt" && n === 1) {
- warning("W065", state.tokens.curr);
- }
- if (!state.option.evil) {
- if (left.value === "eval" || left.value === "Function" ||
- left.value === "execScript") {
- warning("W061", left);
-
- if (p[0] && [0].id === "(string)") {
- addInternalSrc(left, p[0].value);
- }
- } else if (p[0] && p[0].id === "(string)" &&
- (left.value === "setTimeout" ||
- left.value === "setInterval")) {
- warning("W066", left);
- addInternalSrc(left, p[0].value);
-
- // window.setTimeout/setInterval
- } else if (p[0] && p[0].id === "(string)" &&
- left.value === "." &&
- left.left.value === "window" &&
- (left.right === "setTimeout" ||
- left.right === "setInterval")) {
- warning("W066", left);
- addInternalSrc(left, p[0].value);
- }
- }
- if (!left.identifier && left.id !== "." && left.id !== "[" &&
- left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
- left.id !== "?") {
- warning("W067", left);
- }
- }
-
- that.left = left;
- return that;
- }, 155, true).exps = true;
-
- prefix("(", function () {
- nospace();
- var bracket, brackets = [];
- var pn, pn1, i = 0;
-
- do {
- pn = peek(i);
- i += 1;
- pn1 = peek(i);
- i += 1;
- } while (pn.value !== ")" && pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)");
-
- if (state.tokens.next.id === "function") {
- state.tokens.next.immed = true;
- }
-
- var exprs = [];
-
- if (state.tokens.next.id !== ")") {
- for (;;) {
- if (pn1.value === "=>" && state.tokens.next.value === "{") {
- bracket = state.tokens.next;
- bracket.left = destructuringExpression();
- brackets.push(bracket);
- for (var t in bracket.left) {
- exprs.push(bracket.left[t].token);
- }
- } else {
- exprs.push(expression(5));
- }
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
-
- advance(")", this);
- nospace(state.tokens.prev, state.tokens.curr);
- if (state.option.immed && exprs[0] && exprs[0].id === "function") {
- if (state.tokens.next.id !== "(" &&
- (state.tokens.next.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
- warning("W068", this);
- }
- }
-
- if (state.tokens.next.value === "=>") {
- return exprs;
- }
- if (!exprs.length) {
- return;
- }
- exprs[exprs.length - 1].paren = true;
- if (exprs.length > 1) {
- return Object.create(state.syntax[","], { exprs: { value: exprs } });
- }
- return exprs[0];
- });
-
- application("=>");
-
- infix("[", function (left, that) {
- nobreak(state.tokens.prev, state.tokens.curr);
- nospace();
- var e = expression(5), s;
- if (e && e.type === "(string)") {
- if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
- warning("W061", that);
- }
-
- countMember(e.value);
- if (!state.option.sub && reg.identifier.test(e.value)) {
- s = state.syntax[e.value];
- if (!s || !isReserved(s)) {
- warning("W069", state.tokens.prev, e.value);
- }
- }
- }
- advance("]", that);
-
- if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
- warning("W001");
- }
-
- nospace(state.tokens.prev, state.tokens.curr);
- that.left = left;
- that.right = e;
- return that;
- }, 160, true);
-
- function comprehensiveArrayExpression() {
- var res = {};
- res.exps = true;
- funct["(comparray)"].stack();
-
- res.right = expression(5);
- advance("for");
- if (state.tokens.next.value === "each") {
- advance("each");
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "for each");
- }
- }
- advance("(");
- funct["(comparray)"].setState("define");
- res.left = expression(5);
- advance(")");
- if (state.tokens.next.value === "if") {
- advance("if");
- advance("(");
- funct["(comparray)"].setState("filter");
- res.filter = expression(5);
- advance(")");
- }
- advance("]");
- funct["(comparray)"].unstack();
- return res;
- }
-
- prefix("[", function () {
- var blocktype = lookupBlockType(true);
- if (blocktype.isCompArray) {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "array comprehension");
- }
- return comprehensiveArrayExpression();
- } else if (blocktype.isDestAssign && !state.option.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring assignment");
- }
- var b = state.tokens.curr.line !== state.tokens.next.line;
- this.first = [];
- if (b) {
- indent += state.option.indent;
- if (state.tokens.next.from === indent + state.option.indent) {
- indent += state.option.indent;
- }
- }
- while (state.tokens.next.id !== "(end)") {
- while (state.tokens.next.id === ",") {
- if (!state.option.inES5())
- warning("W070");
- advance(",");
- }
- if (state.tokens.next.id === "]") {
- break;
- }
- if (b && state.tokens.curr.line !== state.tokens.next.line) {
- indentation();
- }
- this.first.push(expression(10));
- if (state.tokens.next.id === ",") {
- comma({ allowTrailing: true });
- if (state.tokens.next.id === "]" && !state.option.inES5(true)) {
- warning("W070", state.tokens.curr);
- break;
- }
- } else {
- break;
- }
- }
- if (b) {
- indent -= state.option.indent;
- indentation();
- }
- advance("]", this);
- return this;
- }, 160);
-
-
- function property_name() {
- var id = optionalidentifier(false, true);
-
- if (!id) {
- if (state.tokens.next.id === "(string)") {
- id = state.tokens.next.value;
- advance();
- } else if (state.tokens.next.id === "(number)") {
- id = state.tokens.next.value.toString();
- advance();
- }
- }
-
- if (id === "hasOwnProperty") {
- warning("W001");
- }
-
- return id;
- }
-
-
- function functionparams(parsed) {
- var curr, next;
- var params = [];
- var ident;
- var tokens = [];
- var t;
-
- if (parsed) {
- if (parsed instanceof Array) {
- for (var i in parsed) {
- curr = parsed[i];
- if (_.contains(["{", "["], curr.id)) {
- for (t in curr.left) {
- t = tokens[t];
- if (t.id) {
- params.push(t.id);
- addlabel(t.id, "unused", t.token);
- }
- }
- } else if (curr.value === "...") {
- if (!state.option.inESNext()) {
- warning("W104", curr, "spread/rest operator");
- }
- continue;
- } else {
- addlabel(curr.value, "unused", curr);
- }
- }
- return params;
- } else {
- if (parsed.identifier === true) {
- addlabel(parsed.value, "unused", parsed);
- return [parsed];
- }
- }
- }
-
- next = state.tokens.next;
-
- advance("(");
- nospace();
-
- if (state.tokens.next.id === ")") {
- advance(")");
- return;
- }
-
- for (;;) {
- if (_.contains(["{", "["], state.tokens.next.id)) {
- tokens = destructuringExpression();
- for (t in tokens) {
- t = tokens[t];
- if (t.id) {
- params.push(t.id);
- addlabel(t.id, "unused", t.token);
- }
- }
- } else if (state.tokens.next.value === "...") {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.next, "spread/rest operator");
- }
- advance("...");
- nospace();
- ident = identifier(true);
- params.push(ident);
- addlabel(ident, "unused", state.tokens.curr);
- } else {
- ident = identifier(true);
- params.push(ident);
- addlabel(ident, "unused", state.tokens.curr);
- }
- if (state.tokens.next.id === ",") {
- comma();
- } else {
- advance(")", next);
- nospace(state.tokens.prev, state.tokens.curr);
- return params;
- }
- }
- }
-
-
- function doFunction(name, statement, generator, fatarrowparams) {
- var f;
- var oldOption = state.option;
- var oldIgnored = state.ignored;
- var oldScope = scope;
-
- state.option = Object.create(state.option);
- state.ignored = Object.create(state.ignored);
- scope = Object.create(scope);
-
- funct = {
- "(name)" : name || "\"" + anonname + "\"",
- "(line)" : state.tokens.next.line,
- "(character)" : state.tokens.next.character,
- "(context)" : funct,
- "(breakage)" : 0,
- "(loopage)" : 0,
- "(metrics)" : createMetrics(state.tokens.next),
- "(scope)" : scope,
- "(statement)" : statement,
- "(tokens)" : {},
- "(blockscope)": funct["(blockscope)"],
- "(comparray)" : funct["(comparray)"]
- };
-
- if (generator) {
- funct["(generator)"] = true;
- }
-
- f = funct;
- state.tokens.curr.funct = funct;
-
- functions.push(funct);
-
- if (name) {
- addlabel(name, "function");
- }
-
- funct["(params)"] = functionparams(fatarrowparams);
-
- funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
-
- block(false, true, true, fatarrowparams ? true:false);
-
- if (generator && funct["(generator)"] !== "yielded") {
- error("E047", state.tokens.curr);
- }
-
- funct["(metrics)"].verifyMaxStatementsPerFunction();
- funct["(metrics)"].verifyMaxComplexityPerFunction();
- funct["(unusedOption)"] = state.option.unused;
-
- scope = oldScope;
- state.option = oldOption;
- state.ignored = oldIgnored;
- funct["(last)"] = state.tokens.curr.line;
- funct["(lastcharacter)"] = state.tokens.curr.character;
- funct = funct["(context)"];
-
- return f;
- }
-
- function createMetrics(functionStartToken) {
- return {
- statementCount: 0,
- nestedBlockDepth: -1,
- ComplexityCount: 1,
- verifyMaxStatementsPerFunction: function () {
- if (state.option.maxstatements &&
- this.statementCount > state.option.maxstatements) {
- warning("W071", functionStartToken, this.statementCount);
- }
- },
-
- verifyMaxParametersPerFunction: function (params) {
- params = params || [];
-
- if (state.option.maxparams && params.length > state.option.maxparams) {
- warning("W072", functionStartToken, params.length);
- }
- },
-
- verifyMaxNestedBlockDepthPerFunction: function () {
- if (state.option.maxdepth &&
- this.nestedBlockDepth > 0 &&
- this.nestedBlockDepth === state.option.maxdepth + 1) {
- warning("W073", null, this.nestedBlockDepth);
- }
- },
-
- verifyMaxComplexityPerFunction: function () {
- var max = state.option.maxcomplexity;
- var cc = this.ComplexityCount;
- if (max && cc > max) {
- warning("W074", functionStartToken, cc);
- }
- }
- };
- }
-
- function increaseComplexityCount() {
- funct["(metrics)"].ComplexityCount += 1;
- }
-
- // Parse assignments that were found instead of conditionals.
- // For example: if (a = 1) { ... }
-
- function checkCondAssignment(expr) {
- var id = expr.id;
- if (id === ",") {
- expr = expr.exprs[expr.exprs.length - 1];
- id = expr.id;
- }
- switch (id) {
- case "=":
- case "+=":
- case "-=":
- case "*=":
- case "%=":
- case "&=":
- case "|=":
- case "^=":
- case "/=":
- if (!expr.paren && !state.option.boss) {
- warning("W084");
- }
- }
- }
-
-
- (function (x) {
- x.nud = function (isclassdef) {
- var b, f, i, p, t, g;
- var props = {}; // All properties, including accessors
- var tag = "";
-
- function saveProperty(name, tkn) {
- if (props[name] && _.has(props, name))
- warning("W075", state.tokens.next, i);
- else
- props[name] = {};
-
- props[name].basic = true;
- props[name].basictkn = tkn;
- }
-
- function saveSetter(name, tkn) {
- if (props[name] && _.has(props, name)) {
- if (props[name].basic || props[name].setter)
- warning("W075", state.tokens.next, i);
- } else {
- props[name] = {};
- }
-
- props[name].setter = true;
- props[name].setterToken = tkn;
- }
-
- function saveGetter(name) {
- if (props[name] && _.has(props, name)) {
- if (props[name].basic || props[name].getter)
- warning("W075", state.tokens.next, i);
- } else {
- props[name] = {};
- }
-
- props[name].getter = true;
- props[name].getterToken = state.tokens.curr;
- }
-
- b = state.tokens.curr.line !== state.tokens.next.line;
- if (b) {
- indent += state.option.indent;
- if (state.tokens.next.from === indent + state.option.indent) {
- indent += state.option.indent;
- }
- }
-
- for (;;) {
- if (state.tokens.next.id === "}") {
- break;
- }
-
- if (b) {
- indentation();
- }
-
- if (isclassdef && state.tokens.next.value === "static") {
- advance("static");
- tag = "static ";
- }
-
- if (state.tokens.next.value === "get" && peek().id !== ":") {
- advance("get");
-
- if (!state.option.inES5(!isclassdef)) {
- error("E034");
- }
-
- i = property_name();
- if (!i) {
- error("E035");
- }
-
- // It is a Syntax Error if PropName of MethodDefinition is
- // "constructor" and SpecialMethod of MethodDefinition is true.
- if (isclassdef && i === "constructor") {
- error("E049", state.tokens.next, "class getter method", i);
- }
-
- saveGetter(tag + i);
- t = state.tokens.next;
- adjacent(state.tokens.curr, state.tokens.next);
- f = doFunction();
- p = f["(params)"];
-
- if (p) {
- warning("W076", t, p[0], i);
- }
-
- adjacent(state.tokens.curr, state.tokens.next);
- } else if (state.tokens.next.value === "set" && peek().id !== ":") {
- advance("set");
-
- if (!state.option.inES5(!isclassdef)) {
- error("E034");
- }
-
- i = property_name();
- if (!i) {
- error("E035");
- }
-
- // It is a Syntax Error if PropName of MethodDefinition is
- // "constructor" and SpecialMethod of MethodDefinition is true.
- if (isclassdef && i === "constructor") {
- error("E049", state.tokens.next, "class setter method", i);
- }
-
- saveSetter(tag + i, state.tokens.next);
- t = state.tokens.next;
- adjacent(state.tokens.curr, state.tokens.next);
- f = doFunction();
- p = f["(params)"];
-
- if (!p || p.length !== 1) {
- warning("W077", t, i);
- }
- } else {
- g = false;
- if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.next, "generator functions");
- }
- advance("*");
- g = true;
- }
- i = property_name();
- saveProperty(tag + i, state.tokens.next);
-
- if (typeof i !== "string") {
- break;
- }
-
- if (state.tokens.next.value === "(") {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "concise methods");
- }
- doFunction(i, undefined, g);
- } else if (!isclassdef) {
- advance(":");
- nonadjacent(state.tokens.curr, state.tokens.next);
- expression(10);
- }
- }
- // It is a Syntax Error if PropName of MethodDefinition is "prototype".
- if (isclassdef && i === "prototype") {
- error("E049", state.tokens.next, "class method", i);
- }
-
- countMember(i);
- if (isclassdef) {
- tag = "";
- continue;
- }
- if (state.tokens.next.id === ",") {
- comma({ allowTrailing: true, property: true });
- if (state.tokens.next.id === ",") {
- warning("W070", state.tokens.curr);
- } else if (state.tokens.next.id === "}" && !state.option.inES5(true)) {
- warning("W070", state.tokens.curr);
- }
- } else {
- break;
- }
- }
- if (b) {
- indent -= state.option.indent;
- indentation();
- }
- advance("}", this);
-
- // Check for lonely setters if in the ES5 mode.
- if (state.option.inES5()) {
- for (var name in props) {
- if (_.has(props, name) && props[name].setter && !props[name].getter) {
- warning("W078", props[name].setterToken);
- }
- }
- }
- return this;
- };
- x.fud = function () {
- error("E036", state.tokens.curr);
- };
- }(delim("{")));
-
- function destructuringExpression() {
- var id, ids;
- var identifiers = [];
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring expression");
- }
- var nextInnerDE = function () {
- var ident;
- if (_.contains(["[", "{"], state.tokens.next.value)) {
- ids = destructuringExpression();
- for (var id in ids) {
- id = ids[id];
- identifiers.push({ id: id.id, token: id.token });
- }
- } else if (state.tokens.next.value === ",") {
- identifiers.push({ id: null, token: state.tokens.curr });
- } else {
- ident = identifier();
- if (ident)
- identifiers.push({ id: ident, token: state.tokens.curr });
- }
- };
- if (state.tokens.next.value === "[") {
- advance("[");
- nextInnerDE();
- while (state.tokens.next.value !== "]") {
- advance(",");
- nextInnerDE();
- }
- advance("]");
- } else if (state.tokens.next.value === "{") {
- advance("{");
- id = identifier();
- if (state.tokens.next.value === ":") {
- advance(":");
- nextInnerDE();
- } else {
- identifiers.push({ id: id, token: state.tokens.curr });
- }
- while (state.tokens.next.value !== "}") {
- advance(",");
- id = identifier();
- if (state.tokens.next.value === ":") {
- advance(":");
- nextInnerDE();
- } else {
- identifiers.push({ id: id, token: state.tokens.curr });
- }
- }
- advance("}");
- }
- return identifiers;
- }
- function destructuringExpressionMatch(tokens, value) {
- if (value.first) {
- _.zip(tokens, value.first).forEach(function (val) {
- var token = val[0];
- var value = val[1];
- if (token && value) {
- token.first = value;
- } else if (token && token.first && !value) {
- warning("W080", token.first, token.first.value);
- } /* else {
- XXX value is discarded: wouldn't it need a warning ?
- } */
- });
- }
- }
-
- var conststatement = stmt("const", function (prefix) {
- var tokens, value;
- // state variable to know if it is a lone identifier, or a destructuring statement.
- var lone;
-
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "const");
- }
-
- this.first = [];
- for (;;) {
- var names = [];
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr } ];
- lone = true;
- }
- for (var t in tokens) {
- t = tokens[t];
- if (funct[t.id] === "const") {
- warning("E011", null, t.id);
- }
- if (funct["(global)"] && predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- if (t.id) {
- addlabel(t.id, "const");
- names.push(t.token);
- }
- }
- if (prefix) {
- break;
- }
-
- this.first = this.first.concat(names);
-
- if (state.tokens.next.id !== "=") {
- warning("E012", state.tokens.curr, state.tokens.curr.value);
- }
-
- if (state.tokens.next.id === "=") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("=");
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- error("E037", state.tokens.next, state.tokens.next.value);
- }
- value = expression(5);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
-
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- return this;
- });
- conststatement.exps = true;
- var varstatement = stmt("var", function (prefix) {
- // JavaScript does not have block scope. It only has function scope. So,
- // declaring a variable in a block can have unexpected consequences.
- var tokens, lone, value;
-
- if (funct["(onevar)"] && state.option.onevar) {
- warning("W081");
- } else if (!funct["(global)"]) {
- funct["(onevar)"] = true;
- }
-
- this.first = [];
- for (;;) {
- var names = [];
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr } ];
- lone = true;
- }
- for (var t in tokens) {
- t = tokens[t];
- if (state.option.inESNext() && funct[t.id] === "const") {
- warning("E011", null, t.id);
- }
- if (funct["(global)"] && predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- if (t.id) {
- addlabel(t.id, "unused", t.token);
- names.push(t.token);
- }
- }
- if (prefix) {
- break;
- }
-
- this.first = this.first.concat(names);
-
- if (state.tokens.next.id === "=") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("=");
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- error("E038", state.tokens.next, state.tokens.next.value);
- }
- value = expression(5);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
-
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- return this;
- });
- varstatement.exps = true;
- var letstatement = stmt("let", function (prefix) {
- var tokens, lone, value, letblock;
-
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "let");
- }
-
- if (state.tokens.next.value === "(") {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.next, "let block");
- }
- advance("(");
- funct["(blockscope)"].stack();
- letblock = true;
- } else if (funct["(nolet)"]) {
- error("E048", state.tokens.curr);
- }
-
- if (funct["(onevar)"] && state.option.onevar) {
- warning("W081");
- } else if (!funct["(global)"]) {
- funct["(onevar)"] = true;
- }
-
- this.first = [];
- for (;;) {
- var names = [];
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr.value } ];
- lone = true;
- }
- for (var t in tokens) {
- t = tokens[t];
- if (state.option.inESNext() && funct[t.id] === "const") {
- warning("E011", null, t.id);
- }
- if (funct["(global)"] && predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- if (t.id && !funct["(nolet)"]) {
- addlabel(t.id, "unused", t.token, true);
- names.push(t.token);
- }
- }
- if (prefix) {
- break;
- }
-
- this.first = this.first.concat(names);
-
- if (state.tokens.next.id === "=") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("=");
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- error("E037", state.tokens.next, state.tokens.next.value);
- }
- value = expression(5);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
-
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- if (letblock) {
- advance(")");
- block(true, true);
- this.block = true;
- funct["(blockscope)"].unstack();
- }
-
- return this;
- });
- letstatement.exps = true;
-
- blockstmt("class", function () {
- return classdef.call(this, true);
- });
-
- function classdef(stmt) {
- /*jshint validthis:true */
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "class");
- }
- if (stmt) {
- // BindingIdentifier
- this.name = identifier();
- addlabel(this.name, "unused", state.tokens.curr);
- } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
- // BindingIdentifier(opt)
- this.name = identifier();
- }
- classtail(this);
- return this;
- }
-
- function classtail(c) {
- var strictness = state.directive["use strict"];
-
- // ClassHeritage(opt)
- if (state.tokens.next.value === "extends") {
- advance("extends");
- c.heritage = expression(10);
- }
-
- // A ClassBody is always strict code.
- state.directive["use strict"] = true;
- advance("{");
- // ClassBody(opt)
- c.body = state.syntax["{"].nud(true);
- state.directive["use strict"] = strictness;
- }
-
- blockstmt("function", function () {
- var generator = false;
- if (state.tokens.next.value === "*") {
- advance("*");
- if (state.option.inESNext(true)) {
- generator = true;
- } else {
- warning("W119", state.tokens.curr, "function*");
- }
- }
- if (inblock) {
- warning("W082", state.tokens.curr);
-
- }
- var i = identifier();
- if (funct[i] === "const") {
- warning("E011", null, i);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- addlabel(i, "unction", state.tokens.curr);
-
- doFunction(i, { statement: true }, generator);
- if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) {
- error("E039");
- }
- return this;
- });
-
- prefix("function", function () {
- var generator = false;
- if (state.tokens.next.value === "*") {
- if (!state.option.inESNext()) {
- warning("W119", state.tokens.curr, "function*");
- }
- advance("*");
- generator = true;
- }
- var i = optionalidentifier();
- if (i || state.option.gcl) {
- adjacent(state.tokens.curr, state.tokens.next);
- } else {
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- doFunction(i, undefined, generator);
- if (!state.option.loopfunc && funct["(loopage)"]) {
- warning("W083");
- }
- return this;
- });
-
- blockstmt("if", function () {
- var t = state.tokens.next;
- increaseComplexityCount();
- state.condition = true;
- advance("(");
- nonadjacent(this, t);
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- state.condition = false;
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- if (state.tokens.next.id === "else") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("else");
- if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
- statement(true);
- } else {
- block(true, true);
- }
- }
- return this;
- });
-
- blockstmt("try", function () {
- var b;
-
- function doCatch() {
- var oldScope = scope;
- var e;
-
- advance("catch");
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("(");
-
- scope = Object.create(oldScope);
-
- e = state.tokens.next.value;
- if (state.tokens.next.type !== "(identifier)") {
- e = null;
- warning("E030", state.tokens.next, e);
- }
-
- advance();
-
- funct = {
- "(name)" : "(catch)",
- "(line)" : state.tokens.next.line,
- "(character)": state.tokens.next.character,
- "(context)" : funct,
- "(breakage)" : funct["(breakage)"],
- "(loopage)" : funct["(loopage)"],
- "(scope)" : scope,
- "(statement)": false,
- "(metrics)" : createMetrics(state.tokens.next),
- "(catch)" : true,
- "(tokens)" : {},
- "(blockscope)": funct["(blockscope)"],
- "(comparray)": funct["(comparray)"]
- };
-
- if (e) {
- addlabel(e, "exception");
- }
-
- if (state.tokens.next.value === "if") {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "catch filter");
- }
- advance("if");
- expression(0);
- }
-
- advance(")");
-
- state.tokens.curr.funct = funct;
- functions.push(funct);
-
- block(false);
-
- scope = oldScope;
-
- funct["(last)"] = state.tokens.curr.line;
- funct["(lastcharacter)"] = state.tokens.curr.character;
- funct = funct["(context)"];
- }
-
- block(false);
-
- while (state.tokens.next.id === "catch") {
- increaseComplexityCount();
- if (b && (!state.option.inMoz(true))) {
- warning("W118", state.tokens.next, "multiple catch blocks");
- }
- doCatch();
- b = true;
- }
-
- if (state.tokens.next.id === "finally") {
- advance("finally");
- block(false);
- return;
- }
-
- if (!b) {
- error("E021", state.tokens.next, "catch", state.tokens.next.value);
- }
-
- return this;
- });
-
- blockstmt("while", function () {
- var t = state.tokens.next;
- funct["(breakage)"] += 1;
- funct["(loopage)"] += 1;
- increaseComplexityCount();
- advance("(");
- nonadjacent(this, t);
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- return this;
- }).labelled = true;
-
- blockstmt("with", function () {
- var t = state.tokens.next;
- if (state.directive["use strict"]) {
- error("E010", state.tokens.curr);
- } else if (!state.option.withstmt) {
- warning("W085", state.tokens.curr);
- }
-
- advance("(");
- nonadjacent(this, t);
- nospace();
- expression(0);
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
-
- return this;
- });
-
- blockstmt("switch", function () {
- var t = state.tokens.next,
- g = false;
- funct["(breakage)"] += 1;
- advance("(");
- nonadjacent(this, t);
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- t = state.tokens.next;
- advance("{");
- nonadjacent(state.tokens.curr, state.tokens.next);
- indent += state.option.indent;
- this.cases = [];
-
- for (;;) {
- switch (state.tokens.next.id) {
- case "case":
- switch (funct["(verb)"]) {
- case "yield":
- case "break":
- case "case":
- case "continue":
- case "return":
- case "switch":
- case "throw":
- break;
- default:
- // You can tell JSHint that you don't use break intentionally by
- // adding a comment /* falls through */ on a line just before
- // the next `case`.
- if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
- warning("W086", state.tokens.curr, "case");
- }
- }
- indentation(-state.option.indent);
- advance("case");
- this.cases.push(expression(20));
- increaseComplexityCount();
- g = true;
- advance(":");
- funct["(verb)"] = "case";
- break;
- case "default":
- switch (funct["(verb)"]) {
- case "yield":
- case "break":
- case "continue":
- case "return":
- case "throw":
- break;
- default:
- // Do not display a warning if 'default' is the first statement or if
- // there is a special /* falls through */ comment.
- if (this.cases.length) {
- if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
- warning("W086", state.tokens.curr, "default");
- }
- }
- }
- indentation(-state.option.indent);
- advance("default");
- g = true;
- advance(":");
- break;
- case "}":
- indent -= state.option.indent;
- indentation();
- advance("}", t);
- funct["(breakage)"] -= 1;
- funct["(verb)"] = undefined;
- return;
- case "(end)":
- error("E023", state.tokens.next, "}");
- return;
- default:
- if (g) {
- switch (state.tokens.curr.id) {
- case ",":
- error("E040");
- return;
- case ":":
- g = false;
- statements();
- break;
- default:
- error("E025", state.tokens.curr);
- return;
- }
- } else {
- if (state.tokens.curr.id === ":") {
- advance(":");
- error("E024", state.tokens.curr, ":");
- statements();
- } else {
- error("E021", state.tokens.next, "case", state.tokens.next.value);
- return;
- }
- }
- }
- }
- }).labelled = true;
-
- stmt("debugger", function () {
- if (!state.option.debug) {
- warning("W087");
- }
- return this;
- }).exps = true;
-
- (function () {
- var x = stmt("do", function () {
- funct["(breakage)"] += 1;
- funct["(loopage)"] += 1;
- increaseComplexityCount();
-
- this.first = block(true, true);
- advance("while");
- var t = state.tokens.next;
- nonadjacent(state.tokens.curr, t);
- advance("(");
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- return this;
- });
- x.labelled = true;
- x.exps = true;
- }());
-
- blockstmt("for", function () {
- var s, t = state.tokens.next;
- var letscope = false;
- var foreachtok = null;
-
- if (t.value === "each") {
- foreachtok = t;
- advance("each");
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "for each");
- }
- }
-
- funct["(breakage)"] += 1;
- funct["(loopage)"] += 1;
- increaseComplexityCount();
- advance("(");
- nonadjacent(this, t);
- nospace();
-
- // what kind of for(…) statement it is? for(…of…)? for(…in…)? for(…;…;…)?
- var nextop; // contains the token of the "in" or "of" operator
- var i = 0;
- var inof = ["in", "of"];
- do {
- nextop = peek(i);
- ++i;
- } while (!_.contains(inof, nextop.value) && nextop.value !== ";" &&
- nextop.type !== "(end)");
-
- // if we're in a for (… in|of …) statement
- if (_.contains(inof, nextop.value)) {
- if (!state.option.inESNext() && nextop.value === "of") {
- error("W104", nextop, "for of");
- }
- if (state.tokens.next.id === "var") {
- advance("var");
- state.syntax["var"].fud.call(state.syntax["var"].fud, true);
- } else if (state.tokens.next.id === "let") {
- advance("let");
- // create a new block scope
- letscope = true;
- funct["(blockscope)"].stack();
- state.syntax["let"].fud.call(state.syntax["let"].fud, true);
- } else {
- switch (funct[state.tokens.next.value]) {
- case "unused":
- funct[state.tokens.next.value] = "var";
- break;
- case "var":
- break;
- default:
- if (!funct["(blockscope)"].getlabel(state.tokens.next.value))
- warning("W088", state.tokens.next, state.tokens.next.value);
- }
- advance();
- }
- advance(nextop.value);
- expression(20);
- advance(")", t);
- s = block(true, true);
- if (state.option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
- s[0].value !== "if")) {
- warning("W089", this);
- }
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- } else {
- if (foreachtok) {
- error("E045", foreachtok);
- }
- if (state.tokens.next.id !== ";") {
- if (state.tokens.next.id === "var") {
- advance("var");
- state.syntax["var"].fud.call(state.syntax["var"].fud);
- } else if (state.tokens.next.id === "let") {
- advance("let");
- // create a new block scope
- letscope = true;
- funct["(blockscope)"].stack();
- state.syntax["let"].fud.call(state.syntax["let"].fud);
- } else {
- for (;;) {
- expression(0, "for");
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
- }
- nolinebreak(state.tokens.curr);
- advance(";");
- if (state.tokens.next.id !== ";") {
- checkCondAssignment(expression(0));
- }
- nolinebreak(state.tokens.curr);
- advance(";");
- if (state.tokens.next.id === ";") {
- error("E021", state.tokens.next, ")", ";");
- }
- if (state.tokens.next.id !== ")") {
- for (;;) {
- expression(0, "for");
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
-
- }
- // unstack loop blockscope
- if (letscope) {
- funct["(blockscope)"].unstack();
- }
- return this;
- }).labelled = true;
-
-
- stmt("break", function () {
- var v = state.tokens.next.value;
-
- if (funct["(breakage)"] === 0)
- warning("W052", state.tokens.next, this.value);
-
- if (!state.option.asi)
- nolinebreak(this);
-
- if (state.tokens.next.id !== ";") {
- if (state.tokens.curr.line === state.tokens.next.line) {
- if (funct[v] !== "label") {
- warning("W090", state.tokens.next, v);
- } else if (scope[v] !== funct) {
- warning("W091", state.tokens.next, v);
- }
- this.first = state.tokens.next;
- advance();
- }
- }
- reachable("break");
- return this;
- }).exps = true;
-
-
- stmt("continue", function () {
- var v = state.tokens.next.value;
-
- if (funct["(breakage)"] === 0)
- warning("W052", state.tokens.next, this.value);
-
- if (!state.option.asi)
- nolinebreak(this);
-
- if (state.tokens.next.id !== ";") {
- if (state.tokens.curr.line === state.tokens.next.line) {
- if (funct[v] !== "label") {
- warning("W090", state.tokens.next, v);
- } else if (scope[v] !== funct) {
- warning("W091", state.tokens.next, v);
- }
- this.first = state.tokens.next;
- advance();
- }
- } else if (!funct["(loopage)"]) {
- warning("W052", state.tokens.next, this.value);
- }
- reachable("continue");
- return this;
- }).exps = true;
-
-
- stmt("return", function () {
- if (this.line === state.tokens.next.line) {
- if (state.tokens.next.id === "(regexp)")
- warning("W092");
-
- if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
- nonadjacent(state.tokens.curr, state.tokens.next);
- this.first = expression(0);
-
- if (this.first &&
- this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
- warningAt("W093", this.first.line, this.first.character);
- }
- }
- } else {
- if (state.tokens.next.type === "(punctuator)" &&
- ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) {
- nolinebreak(this); // always warn (Line breaking error)
- }
- }
- reachable("return");
- return this;
- }).exps = true;
-
- stmt("yield", function () {
- if (state.option.inESNext(true) && funct["(generator)"] !== true) {
- error("E046", state.tokens.curr, "yield");
- } else if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "yield");
- }
- funct["(generator)"] = "yielded";
- if (this.line === state.tokens.next.line) {
- if (state.tokens.next.id === "(regexp)")
- warning("W092");
-
- if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
- nonadjacent(state.tokens.curr, state.tokens.next);
- this.first = expression(0);
-
- if (this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
- warningAt("W093", this.first.line, this.first.character);
- }
- }
- } else if (!state.option.asi) {
- nolinebreak(this); // always warn (Line breaking error)
- }
- return this;
- }).exps = true;
-
-
- stmt("throw", function () {
- nolinebreak(this);
- nonadjacent(state.tokens.curr, state.tokens.next);
- this.first = expression(20);
- reachable("throw");
- return this;
- }).exps = true;
-
- // Future Reserved Words
-
- FutureReservedWord("abstract");
- FutureReservedWord("boolean");
- FutureReservedWord("byte");
- FutureReservedWord("char");
- FutureReservedWord("class", { es5: true, nud: classdef });
- FutureReservedWord("double");
- FutureReservedWord("enum", { es5: true });
- FutureReservedWord("export", { es5: true });
- FutureReservedWord("extends", { es5: true });
- FutureReservedWord("final");
- FutureReservedWord("float");
- FutureReservedWord("goto");
- FutureReservedWord("implements", { es5: true, strictOnly: true });
- FutureReservedWord("import", { es5: true });
- FutureReservedWord("int");
- FutureReservedWord("interface", { es5: true, strictOnly: true });
- FutureReservedWord("long");
- FutureReservedWord("native");
- FutureReservedWord("package", { es5: true, strictOnly: true });
- FutureReservedWord("private", { es5: true, strictOnly: true });
- FutureReservedWord("protected", { es5: true, strictOnly: true });
- FutureReservedWord("public", { es5: true, strictOnly: true });
- FutureReservedWord("short");
- FutureReservedWord("static", { es5: true, strictOnly: true });
- FutureReservedWord("super", { es5: true });
- FutureReservedWord("synchronized");
- FutureReservedWord("throws");
- FutureReservedWord("transient");
- FutureReservedWord("volatile");
-
- // this function is used to determine wether a squarebracket or a curlybracket
- // expression is a comprehension array, destructuring assignment or a json value.
-
- var lookupBlockType = function () {
- var pn, pn1;
- var i = 0;
- var bracketStack = 0;
- var ret = {};
- if (_.contains(["[", "{"], state.tokens.curr.value))
- bracketStack += 1;
- if (_.contains(["[", "{"], state.tokens.next.value))
- bracketStack += 1;
- if (_.contains(["]", "}"], state.tokens.next.value))
- bracketStack -= 1;
- do {
- pn = peek(i);
- pn1 = peek(i + 1);
- i = i + 1;
- if (_.contains(["[", "{"], pn.value)) {
- bracketStack += 1;
- } else if (_.contains(["]", "}"], pn.value)) {
- bracketStack -= 1;
- }
- if (pn.identifier && pn.value === "for" && bracketStack === 1) {
- ret.isCompArray = true;
- ret.notJson = true;
- break;
- }
- if (_.contains(["}", "]"], pn.value) && pn1.value === "=") {
- ret.isDestAssign = true;
- ret.notJson = true;
- break;
- }
- if (pn.value === ";") {
- ret.isBlock = true;
- ret.notJson = true;
- }
- } while (bracketStack > 0 && pn.id !== "(end)" && i < 15);
- return ret;
- };
-
- // Check whether this function has been reached for a destructuring assign with undeclared values
- function destructuringAssignOrJsonValue() {
- // lookup for the assignment (esnext only)
- // if it has semicolons, it is a block, so go parse it as a block
- // or it's not a block, but there are assignments, check for undeclared variables
-
- var block = lookupBlockType();
- if (block.notJson) {
- if (!state.option.inESNext() && block.isDestAssign) {
- warning("W104", state.tokens.curr, "destructuring assignment");
- }
- statements();
- // otherwise parse json value
- } else {
- state.option.laxbreak = true;
- state.jsonMode = true;
- jsonValue();
- }
- }
-
- // array comprehension parsing function
- // parses and defines the three states of the list comprehension in order
- // to avoid defining global variables, but keeping them to the list comprehension scope
- // only. The order of the states are as follows:
- // * "use" which will be the returned iterative part of the list comprehension
- // * "define" which will define the variables local to the list comprehension
- // * "filter" which will help filter out values
-
- var arrayComprehension = function () {
- var CompArray = function () {
- this.mode = "use";
- this.variables = [];
- };
- var _carrays = [];
- var _current;
- function declare(v) {
- var l = _current.variables.filter(function (elt) {
- // if it has, change its undef state
- if (elt.value === v) {
- elt.undef = false;
- return v;
- }
- }).length;
- return l !== 0;
- }
- function use(v) {
- var l = _current.variables.filter(function (elt) {
- // and if it has been defined
- if (elt.value === v && !elt.undef) {
- if (elt.unused === true) {
- elt.unused = false;
- }
- return v;
- }
- }).length;
- // otherwise we warn about it
- return (l === 0);
- }
- return {stack: function () {
- _current = new CompArray();
- _carrays.push(_current);
- },
- unstack: function () {
- _current.variables.filter(function (v) {
- if (v.unused)
- warning("W098", v.token, v.value);
- if (v.undef)
- isundef(v.funct, "W117", v.token, v.value);
- });
- _carrays.splice(_carrays[_carrays.length - 1], 1);
- _current = _carrays[_carrays.length - 1];
- },
- setState: function (s) {
- if (_.contains(["use", "define", "filter"], s))
- _current.mode = s;
- },
- check: function (v) {
- // When we are in "use" state of the list comp, we enqueue that var
- if (_current && _current.mode === "use") {
- _current.variables.push({funct: funct,
- token: state.tokens.curr,
- value: v,
- undef: true,
- unused: false});
- return true;
- // When we are in "define" state of the list comp,
- } else if (_current && _current.mode === "define") {
- // check if the variable has been used previously
- if (!declare(v)) {
- _current.variables.push({funct: funct,
- token: state.tokens.curr,
- value: v,
- undef: false,
- unused: true});
- }
- return true;
- // When we are in "filter" state,
- } else if (_current && _current.mode === "filter") {
- // we check whether current variable has been declared
- if (use(v)) {
- // if not we warn about it
- isundef(funct, "W117", state.tokens.curr, v);
- }
- return true;
- }
- return false;
- }
- };
- };
-
-
- // Parse JSON
-
- function jsonValue() {
-
- function jsonObject() {
- var o = {}, t = state.tokens.next;
- advance("{");
- if (state.tokens.next.id !== "}") {
- for (;;) {
- if (state.tokens.next.id === "(end)") {
- error("E026", state.tokens.next, t.line);
- } else if (state.tokens.next.id === "}") {
- warning("W094", state.tokens.curr);
- break;
- } else if (state.tokens.next.id === ",") {
- error("E028", state.tokens.next);
- } else if (state.tokens.next.id !== "(string)") {
- warning("W095", state.tokens.next, state.tokens.next.value);
- }
- if (o[state.tokens.next.value] === true) {
- warning("W075", state.tokens.next, state.tokens.next.value);
- } else if ((state.tokens.next.value === "__proto__" &&
- !state.option.proto) || (state.tokens.next.value === "__iterator__" &&
- !state.option.iterator)) {
- warning("W096", state.tokens.next, state.tokens.next.value);
- } else {
- o[state.tokens.next.value] = true;
- }
- advance();
- advance(":");
- jsonValue();
- if (state.tokens.next.id !== ",") {
- break;
- }
- advance(",");
- }
- }
- advance("}");
- }
-
- function jsonArray() {
- var t = state.tokens.next;
- advance("[");
- if (state.tokens.next.id !== "]") {
- for (;;) {
- if (state.tokens.next.id === "(end)") {
- error("E027", state.tokens.next, t.line);
- } else if (state.tokens.next.id === "]") {
- warning("W094", state.tokens.curr);
- break;
- } else if (state.tokens.next.id === ",") {
- error("E028", state.tokens.next);
- }
- jsonValue();
- if (state.tokens.next.id !== ",") {
- break;
- }
- advance(",");
- }
- }
- advance("]");
- }
-
- switch (state.tokens.next.id) {
- case "{":
- jsonObject();
- break;
- case "[":
- jsonArray();
- break;
- case "true":
- case "false":
- case "null":
- case "(number)":
- case "(string)":
- advance();
- break;
- case "-":
- advance("-");
- if (state.tokens.curr.character !== state.tokens.next.from) {
- warning("W011", state.tokens.curr);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- advance("(number)");
- break;
- default:
- error("E003", state.tokens.next);
- }
- }
-
- var blockScope = function () {
- var _current = {};
- var _variables = [_current];
-
- function _checkBlockLabels() {
- for (var t in _current) {
- if (_current[t]["(type)"] === "unused") {
- if (state.option.unused) {
- var tkn = _current[t]["(token)"];
- var line = tkn.line;
- var chr = tkn.character;
- warningAt("W098", line, chr, t);
- }
- }
- }
- }
-
- return {
- stack: function () {
- _current = {};
- _variables.push(_current);
- },
-
- unstack: function () {
- _checkBlockLabels();
- _variables.splice(_variables.length - 1, 1);
- _current = _.last(_variables);
- },
-
- getlabel: function (l) {
- for (var i = _variables.length - 1 ; i >= 0; --i) {
- if (_.has(_variables[i], l)) {
- return _variables[i];
- }
- }
- },
-
- current: {
- has: function (t) {
- return _.has(_current, t);
- },
- add: function (t, type, tok) {
- _current[t] = { "(type)" : type,
- "(token)": tok };
- }
- }
- };
- };
-
- // The actual JSHINT function itself.
- var itself = function (s, o, g) {
- var a, i, k, x;
- var optionKeys;
- var newOptionObj = {};
- var newIgnoredObj = {};
-
- state.reset();
-
- if (o && o.scope) {
- JSHINT.scope = o.scope;
- } else {
- JSHINT.errors = [];
- JSHINT.undefs = [];
- JSHINT.internals = [];
- JSHINT.blacklist = {};
- JSHINT.scope = "(main)";
- }
-
- predefined = Object.create(null);
- combine(predefined, vars.ecmaIdentifiers);
- combine(predefined, vars.reservedVars);
-
- combine(predefined, g || {});
-
- declared = Object.create(null);
- exported = Object.create(null);
-
- if (o) {
- a = o.predef;
- if (a) {
- if (!Array.isArray(a) && typeof a === "object") {
- a = Object.keys(a);
- }
-
- a.forEach(function (item) {
- var slice, prop;
-
- if (item[0] === "-") {
- slice = item.slice(1);
- JSHINT.blacklist[slice] = slice;
- } else {
- prop = Object.getOwnPropertyDescriptor(o.predef, item);
- predefined[item] = prop ? prop.value : false;
- }
- });
- }
-
- optionKeys = Object.keys(o);
- for (x = 0; x < optionKeys.length; x++) {
- if (/^-W\d{3}$/g.test(optionKeys[x])) {
- newIgnoredObj[optionKeys[x].slice(1)] = true;
- } else {
- newOptionObj[optionKeys[x]] = o[optionKeys[x]];
-
- if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
- newOptionObj["(explicitNewcap)"] = true;
-
- if (optionKeys[x] === "indent")
- newOptionObj["(explicitIndent)"] = o[optionKeys[x]] === false ? false : true;
- }
- }
- }
-
- state.option = newOptionObj;
- state.ignored = newIgnoredObj;
-
- state.option.indent = state.option.indent || 4;
- state.option.maxerr = state.option.maxerr || 50;
-
- indent = 1;
- global = Object.create(predefined);
- scope = global;
- funct = {
- "(global)": true,
- "(name)": "(global)",
- "(scope)": scope,
- "(breakage)": 0,
- "(loopage)": 0,
- "(tokens)": {},
- "(metrics)": createMetrics(state.tokens.next),
- "(blockscope)": blockScope(),
- "(comparray)": arrayComprehension()
- };
- functions = [funct];
- urls = [];
- stack = null;
- member = {};
- membersOnly = null;
- implied = {};
- inblock = false;
- lookahead = [];
- warnings = 0;
- unuseds = [];
-
- if (!isString(s) && !Array.isArray(s)) {
- errorAt("E004", 0);
- return false;
- }
-
- api = {
- get isJSON() {
- return state.jsonMode;
- },
-
- getOption: function (name) {
- return state.option[name] || null;
- },
-
- getCache: function (name) {
- return state.cache[name];
- },
-
- setCache: function (name, value) {
- state.cache[name] = value;
- },
-
- warn: function (code, data) {
- warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));
- },
-
- on: function (names, listener) {
- names.split(" ").forEach(function (name) {
- emitter.on(name, listener);
- }.bind(this));
- }
- };
-
- emitter.removeAllListeners();
- (extraModules || []).forEach(function (func) {
- func(api);
- });
-
- state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];
-
- lex = new Lexer(s);
-
- lex.on("warning", function (ev) {
- warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));
- });
-
- lex.on("error", function (ev) {
- errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));
- });
-
- lex.on("fatal", function (ev) {
- quit("E041", ev.line, ev.from);
- });
-
- lex.on("Identifier", function (ev) {
- emitter.emit("Identifier", ev);
- });
-
- lex.on("String", function (ev) {
- emitter.emit("String", ev);
- });
-
- lex.on("Number", function (ev) {
- emitter.emit("Number", ev);
- });
-
- lex.start();
-
- // Check options
- for (var name in o) {
- if (_.has(o, name)) {
- checkOption(name, state.tokens.curr);
- }
- }
-
- assume();
-
- // combine the passed globals after we've assumed all our options
- combine(predefined, g || {});
-
- //reset values
- comma.first = true;
-
- try {
- advance();
- switch (state.tokens.next.id) {
- case "{":
- case "[":
- destructuringAssignOrJsonValue();
- break;
- default:
- directives();
-
- if (state.directive["use strict"]) {
- if (!state.option.globalstrict && !state.option.node) {
- warning("W097", state.tokens.prev);
- }
- }
-
- statements();
- }
- advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined);
- funct["(blockscope)"].unstack();
-
- var markDefined = function (name, context) {
- do {
- if (typeof context[name] === "string") {
- // JSHINT marks unused variables as 'unused' and
- // unused function declaration as 'unction'. This
- // code changes such instances back 'var' and
- // 'closure' so that the code in JSHINT.data()
- // doesn't think they're unused.
-
- if (context[name] === "unused")
- context[name] = "var";
- else if (context[name] === "unction")
- context[name] = "closure";
-
- return true;
- }
-
- context = context["(context)"];
- } while (context);
-
- return false;
- };
-
- var clearImplied = function (name, line) {
- if (!implied[name])
- return;
-
- var newImplied = [];
- for (var i = 0; i < implied[name].length; i += 1) {
- if (implied[name][i] !== line)
- newImplied.push(implied[name][i]);
- }
-
- if (newImplied.length === 0)
- delete implied[name];
- else
- implied[name] = newImplied;
- };
-
- var warnUnused = function (name, tkn, type, unused_opt) {
- var line = tkn.line;
- var chr = tkn.character;
-
- if (unused_opt === undefined) {
- unused_opt = state.option.unused;
- }
-
- if (unused_opt === true) {
- unused_opt = "last-param";
- }
-
- var warnable_types = {
- "vars": ["var"],
- "last-param": ["var", "param"],
- "strict": ["var", "param", "last-param"]
- };
-
- if (unused_opt) {
- if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
- warningAt("W098", line, chr, name);
- }
- }
-
- unuseds.push({
- name: name,
- line: line,
- character: chr
- });
- };
-
- var checkUnused = function (func, key) {
- var type = func[key];
- var tkn = func["(tokens)"][key];
-
- if (key.charAt(0) === "(")
- return;
-
- if (type !== "unused" && type !== "unction")
- return;
-
- // Params are checked separately from other variables.
- if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
- return;
-
- // Variable is in global scope and defined as exported.
- if (func["(global)"] && _.has(exported, key)) {
- return;
- }
-
- warnUnused(key, tkn, "var");
- };
-
- // Check queued 'x is not defined' instances to see if they're still undefined.
- for (i = 0; i < JSHINT.undefs.length; i += 1) {
- k = JSHINT.undefs[i].slice(0);
-
- if (markDefined(k[2].value, k[0])) {
- clearImplied(k[2].value, k[2].line);
- } else if (state.option.undef) {
- warning.apply(warning, k.slice(1));
- }
- }
-
- functions.forEach(function (func) {
- if (func["(unusedOption)"] === false) {
- return;
- }
-
- for (var key in func) {
- if (_.has(func, key)) {
- checkUnused(func, key);
- }
- }
-
- if (!func["(params)"])
- return;
-
- var params = func["(params)"].slice();
- var param = params.pop();
- var type, unused_opt;
-
- while (param) {
- type = func[param];
- unused_opt = func["(unusedOption)"] || state.option.unused;
- unused_opt = unused_opt === true ? "last-param" : unused_opt;
-
- // 'undefined' is a special case for (function (window, undefined) { ... })();
- // patterns.
-
- if (param === "undefined")
- return;
-
- if (type === "unused" || type === "unction") {
- warnUnused(param, func["(tokens)"][param], "param", func["(unusedOption)"]);
- } else if (unused_opt === "last-param") {
- return;
- }
-
- param = params.pop();
- }
- });
-
- for (var key in declared) {
- if (_.has(declared, key) && !_.has(global, key)) {
- warnUnused(key, declared[key], "var");
- }
- }
-
- } catch (err) {
- if (err && err.name === "JSHintError") {
- var nt = state.tokens.next || {};
- JSHINT.errors.push({
- scope : "(main)",
- raw : err.raw,
- reason : err.message,
- line : err.line || nt.line,
- character : err.character || nt.from
- }, null);
- } else {
- throw err;
- }
- }
-
- // Loop over the listed "internals", and check them as well.
-
- if (JSHINT.scope === "(main)") {
- o = o || {};
-
- for (i = 0; i < JSHINT.internals.length; i += 1) {
- k = JSHINT.internals[i];
- o.scope = k.elem;
- itself(k.value, o, g);
- }
- }
-
- return JSHINT.errors.length === 0;
- };
-
- // Modules.
- itself.addModule = function (func) {
- extraModules.push(func);
- };
-
- itself.addModule(style.register);
-
- // Data summary.
- itself.data = function () {
- var data = {
- functions: [],
- options: state.option
- };
- var implieds = [];
- var members = [];
- var fu, f, i, j, n, globals;
-
- if (itself.errors.length) {
- data.errors = itself.errors;
- }
-
- if (state.jsonMode) {
- data.json = true;
- }
-
- for (n in implied) {
- if (_.has(implied, n)) {
- implieds.push({
- name: n,
- line: implied[n]
- });
- }
- }
-
- if (implieds.length > 0) {
- data.implieds = implieds;
- }
-
- if (urls.length > 0) {
- data.urls = urls;
- }
-
- globals = Object.keys(scope);
- if (globals.length > 0) {
- data.globals = globals;
- }
-
- for (i = 1; i < functions.length; i += 1) {
- f = functions[i];
- fu = {};
-
- for (j = 0; j < functionicity.length; j += 1) {
- fu[functionicity[j]] = [];
- }
-
- for (j = 0; j < functionicity.length; j += 1) {
- if (fu[functionicity[j]].length === 0) {
- delete fu[functionicity[j]];
- }
- }
-
- fu.name = f["(name)"];
- fu.param = f["(params)"];
- fu.line = f["(line)"];
- fu.character = f["(character)"];
- fu.last = f["(last)"];
- fu.lastcharacter = f["(lastcharacter)"];
- data.functions.push(fu);
- }
-
- if (unuseds.length > 0) {
- data.unused = unuseds;
- }
-
- members = [];
- for (n in member) {
- if (typeof member[n] === "number") {
- data.member = member;
- break;
- }
- }
-
- return data;
- };
-
- itself.jshint = itself;
-
- return itself;
-}());
-
-// Make JSHINT a Node module, if possible.
-if (typeof exports === "object" && exports) {
- exports.JSHINT = JSHINT;
-}
-
-})()
-},{"events":2,"../shared/vars.js":3,"./lex.js":10,"./reg.js":6,"./state.js":4,"../shared/messages.js":12,"./style.js":5,"console-browserify":7,"underscore":11}],12:[function(require,module,exports){
-(function(){"use strict";
-
-var _ = require("underscore");
-
-var errors = {
- // JSHint options
- E001: "Bad option: '{a}'.",
- E002: "Bad option value.",
-
- // JSHint input
- E003: "Expected a JSON value.",
- E004: "Input is neither a string nor an array of strings.",
- E005: "Input is empty.",
- E006: "Unexpected early end of program.",
-
- // Strict mode
- E007: "Missing \"use strict\" statement.",
- E008: "Strict violation.",
- E009: "Option 'validthis' can't be used in a global scope.",
- E010: "'with' is not allowed in strict mode.",
-
- // Constants
- E011: "const '{a}' has already been declared.",
- E012: "const '{a}' is initialized to 'undefined'.",
- E013: "Attempting to override '{a}' which is a constant.",
-
- // Regular expressions
- E014: "A regular expression literal can be confused with '/='.",
- E015: "Unclosed regular expression.",
- E016: "Invalid regular expression.",
-
- // Tokens
- E017: "Unclosed comment.",
- E018: "Unbegun comment.",
- E019: "Unmatched '{a}'.",
- E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
- E021: "Expected '{a}' and instead saw '{b}'.",
- E022: "Line breaking error '{a}'.",
- E023: "Missing '{a}'.",
- E024: "Unexpected '{a}'.",
- E025: "Missing ':' on a case clause.",
- E026: "Missing '}' to match '{' from line {a}.",
- E027: "Missing ']' to match '[' form line {a}.",
- E028: "Illegal comma.",
- E029: "Unclosed string.",
-
- // Everything else
- E030: "Expected an identifier and instead saw '{a}'.",
- E031: "Bad assignment.", // FIXME: Rephrase
- E032: "Expected a small integer or 'false' and instead saw '{a}'.",
- E033: "Expected an operator and instead saw '{a}'.",
- E034: "get/set are ES5 features.",
- E035: "Missing property name.",
- E036: "Expected to see a statement and instead saw a block.",
- E037: "Constant {a} was not declared correctly.",
- E038: "Variable {a} was not declared correctly.",
- E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.",
- E040: "Each value should have its own case label.",
- E041: "Unrecoverable syntax error.",
- E042: "Stopping.",
- E043: "Too many errors.",
- E044: "'{a}' is already defined and can't be redefined.",
- E045: "Invalid for each loop.",
- E046: "A yield statement shall be within a generator function (with syntax: `function*`)",
- E047: "A generator function shall contain a yield statement.",
- E048: "Let declaration not directly within block.",
- E049: "A {a} cannot be named '{b}'."
-};
-
-var warnings = {
- W001: "'hasOwnProperty' is a really bad name.",
- W002: "Value of '{a}' may be overwritten in IE.",
- W003: "'{a}' was used before it was defined.",
- W004: "'{a}' is already defined.",
- W005: "A dot following a number can be confused with a decimal point.",
- W006: "Confusing minuses.",
- W007: "Confusing pluses.",
- W008: "A leading decimal point can be confused with a dot: '{a}'.",
- W009: "The array literal notation [] is preferrable.",
- W010: "The object literal notation {} is preferrable.",
- W011: "Unexpected space after '{a}'.",
- W012: "Unexpected space before '{a}'.",
- W013: "Missing space after '{a}'.",
- W014: "Bad line breaking before '{a}'.",
- W015: "Expected '{a}' to have an indentation at {b} instead at {c}.",
- W016: "Unexpected use of '{a}'.",
- W017: "Bad operand.",
- W018: "Confusing use of '{a}'.",
- W019: "Use the isNaN function to compare with NaN.",
- W020: "Read only.",
- W021: "'{a}' is a function.",
- W022: "Do not assign to the exception parameter.",
- W023: "Expected an identifier in an assignment and instead saw a function invocation.",
- W024: "Expected an identifier and instead saw '{a}' (a reserved word).",
- W025: "Missing name in function declaration.",
- W026: "Inner functions should be listed at the top of the outer function.",
- W027: "Unreachable '{a}' after '{b}'.",
- W028: "Label '{a}' on {b} statement.",
- W030: "Expected an assignment or function call and instead saw an expression.",
- W031: "Do not use 'new' for side effects.",
- W032: "Unnecessary semicolon.",
- W033: "Missing semicolon.",
- W034: "Unnecessary directive \"{a}\".",
- W035: "Empty block.",
- W036: "Unexpected /*member '{a}'.",
- W037: "'{a}' is a statement label.",
- W038: "'{a}' used out of scope.",
- W039: "'{a}' is not allowed.",
- W040: "Possible strict violation.",
- W041: "Use '{a}' to compare with '{b}'.",
- W042: "Avoid EOL escaping.",
- W043: "Bad escaping of EOL. Use option multistr if needed.",
- W044: "Bad or unnecessary escaping.",
- W045: "Bad number '{a}'.",
- W046: "Don't use extra leading zeros '{a}'.",
- W047: "A trailing decimal point can be confused with a dot: '{a}'.",
- W048: "Unexpected control character in regular expression.",
- W049: "Unexpected escaped character '{a}' in regular expression.",
- W050: "JavaScript URL.",
- W051: "Variables should not be deleted.",
- W052: "Unexpected '{a}'.",
- W053: "Do not use {a} as a constructor.",
- W054: "The Function constructor is a form of eval.",
- W055: "A constructor name should start with an uppercase letter.",
- W056: "Bad constructor.",
- W057: "Weird construction. Is 'new' unnecessary?",
- W058: "Missing '()' invoking a constructor.",
- W059: "Avoid arguments.{a}.",
- W060: "document.write can be a form of eval.",
- W061: "eval can be harmful.",
- W062: "Wrap an immediate function invocation in parens " +
- "to assist the reader in understanding that the expression " +
- "is the result of a function, and not the function itself.",
- W063: "Math is not a function.",
- W064: "Missing 'new' prefix when invoking a constructor.",
- W065: "Missing radix parameter.",
- W066: "Implied eval. Consider passing a function instead of a string.",
- W067: "Bad invocation.",
- W068: "Wrapping non-IIFE function literals in parens is unnecessary.",
- W069: "['{a}'] is better written in dot notation.",
- W070: "Extra comma. (it breaks older versions of IE)",
- W071: "This function has too many statements. ({a})",
- W072: "This function has too many parameters. ({a})",
- W073: "Blocks are nested too deeply. ({a})",
- W074: "This function's cyclomatic complexity is too high. ({a})",
- W075: "Duplicate key '{a}'.",
- W076: "Unexpected parameter '{a}' in get {b} function.",
- W077: "Expected a single parameter in set {a} function.",
- W078: "Setter is defined without getter.",
- W079: "Redefinition of '{a}'.",
- W080: "It's not necessary to initialize '{a}' to 'undefined'.",
- W081: "Too many var statements.",
- W082: "Function declarations should not be placed in blocks. " +
- "Use a function expression or move the statement to the top of " +
- "the outer function.",
- W083: "Don't make functions within a loop.",
- W084: "Expected a conditional expression and instead saw an assignment.",
- W085: "Don't use 'with'.",
- W086: "Expected a 'break' statement before '{a}'.",
- W087: "Forgotten 'debugger' statement?",
- W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.",
- W089: "The body of a for in should be wrapped in an if statement to filter " +
- "unwanted properties from the prototype.",
- W090: "'{a}' is not a statement label.",
- W091: "'{a}' is out of scope.",
- W092: "Wrap the /regexp/ literal in parens to disambiguate the slash operator.",
- W093: "Did you mean to return a conditional instead of an assignment?",
- W094: "Unexpected comma.",
- W095: "Expected a string and instead saw {a}.",
- W096: "The '{a}' key may produce unexpected results.",
- W097: "Use the function form of \"use strict\".",
- W098: "'{a}' is defined but never used.",
- W099: "Mixed spaces and tabs.",
- W100: "This character may get silently deleted by one or more browsers.",
- W101: "Line is too long.",
- W102: "Trailing whitespace.",
- W103: "The '{a}' property is deprecated.",
- W104: "'{a}' is only available in JavaScript 1.7.",
- W105: "Unexpected {a} in '{b}'.",
- W106: "Identifier '{a}' is not in camel case.",
- W107: "Script URL.",
- W108: "Strings must use doublequote.",
- W109: "Strings must use singlequote.",
- W110: "Mixed double and single quotes.",
- W112: "Unclosed string.",
- W113: "Control character in string: {a}.",
- W114: "Avoid {a}.",
- W115: "Octal literals are not allowed in strict mode.",
- W116: "Expected '{a}' and instead saw '{b}'.",
- W117: "'{a}' is not defined.",
- W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
- W119: "'{a}' is only available in ES6 (use esnext option)."
-};
-
-var info = {
- I001: "Comma warnings can be turned off with 'laxcomma'.",
- I002: "Reserved words as properties can be used under the 'es5' option.",
- I003: "ES5 option is now set per default"
-};
-
-exports.errors = {};
-exports.warnings = {};
-exports.info = {};
-
-_.each(errors, function (desc, code) {
- exports.errors[code] = { code: code, desc: desc };
-});
-
-_.each(warnings, function (desc, code) {
- exports.warnings[code] = { code: code, desc: desc };
-});
-
-_.each(info, function (desc, code) {
- exports.info[code] = { code: code, desc: desc };
-});
-
-})()
-},{"underscore":11}],8:[function(require,module,exports){
-var events = require('events');
-
-exports.isArray = isArray;
-exports.isDate = function(obj){return Object.prototype.toString.call(obj) === '[object Date]'};
-exports.isRegExp = function(obj){return Object.prototype.toString.call(obj) === '[object RegExp]'};
-
-
-exports.print = function () {};
-exports.puts = function () {};
-exports.debug = function() {};
-
-exports.inspect = function(obj, showHidden, depth, colors) {
- var seen = [];
-
- var stylize = function(str, styleType) {
- // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
- var styles =
- { 'bold' : [1, 22],
- 'italic' : [3, 23],
- 'underline' : [4, 24],
- 'inverse' : [7, 27],
- 'white' : [37, 39],
- 'grey' : [90, 39],
- 'black' : [30, 39],
- 'blue' : [34, 39],
- 'cyan' : [36, 39],
- 'green' : [32, 39],
- 'magenta' : [35, 39],
- 'red' : [31, 39],
- 'yellow' : [33, 39] };
-
- var style =
- { 'special': 'cyan',
- 'number': 'blue',
- 'boolean': 'yellow',
- 'undefined': 'grey',
- 'null': 'bold',
- 'string': 'green',
- 'date': 'magenta',
- // "name": intentionally not styling
- 'regexp': 'red' }[styleType];
-
- if (style) {
- return '\033[' + styles[style][0] + 'm' + str +
- '\033[' + styles[style][1] + 'm';
- } else {
- return str;
- }
- };
- if (! colors) {
- stylize = function(str, styleType) { return str; };
- }
-
- function format(value, recurseTimes) {
- // Provide a hook for user-specified inspect functions.
- // Check that value is an object with an inspect function on it
- if (value && typeof value.inspect === 'function' &&
- // Filter out the util module, it's inspect function is special
- value !== exports &&
- // Also filter out any prototype objects using the circular check.
- !(value.constructor && value.constructor.prototype === value)) {
- return value.inspect(recurseTimes);
- }
-
- // Primitive types cannot have properties
- switch (typeof value) {
- case 'undefined':
- return stylize('undefined', 'undefined');
-
- case 'string':
- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
- .replace(/'/g, "\\'")
- .replace(/\\"/g, '"') + '\'';
- return stylize(simple, 'string');
-
- case 'number':
- return stylize('' + value, 'number');
-
- case 'boolean':
- return stylize('' + value, 'boolean');
- }
- // For some reason typeof null is "object", so special case here.
- if (value === null) {
- return stylize('null', 'null');
- }
-
- // Look up the keys of the object.
- var visible_keys = Object_keys(value);
- var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys;
-
- // Functions without properties can be shortcutted.
- if (typeof value === 'function' && keys.length === 0) {
- if (isRegExp(value)) {
- return stylize('' + value, 'regexp');
- } else {
- var name = value.name ? ': ' + value.name : '';
- return stylize('[Function' + name + ']', 'special');
- }
- }
-
- // Dates without properties can be shortcutted
- if (isDate(value) && keys.length === 0) {
- return stylize(value.toUTCString(), 'date');
- }
-
- var base, type, braces;
- // Determine the object type
- if (isArray(value)) {
- type = 'Array';
- braces = ['[', ']'];
- } else {
- type = 'Object';
- braces = ['{', '}'];
- }
-
- // Make functions say that they are functions
- if (typeof value === 'function') {
- var n = value.name ? ': ' + value.name : '';
- base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';
- } else {
- base = '';
- }
-
- // Make dates with properties first say the date
- if (isDate(value)) {
- base = ' ' + value.toUTCString();
- }
-
- if (keys.length === 0) {
- return braces[0] + base + braces[1];
- }
-
- if (recurseTimes < 0) {
- if (isRegExp(value)) {
- return stylize('' + value, 'regexp');
- } else {
- return stylize('[Object]', 'special');
- }
- }
-
- seen.push(value);
-
- var output = keys.map(function(key) {
- var name, str;
- if (value.__lookupGetter__) {
- if (value.__lookupGetter__(key)) {
- if (value.__lookupSetter__(key)) {
- str = stylize('[Getter/Setter]', 'special');
- } else {
- str = stylize('[Getter]', 'special');
- }
- } else {
- if (value.__lookupSetter__(key)) {
- str = stylize('[Setter]', 'special');
- }
- }
- }
- if (visible_keys.indexOf(key) < 0) {
- name = '[' + key + ']';
- }
- if (!str) {
- if (seen.indexOf(value[key]) < 0) {
- if (recurseTimes === null) {
- str = format(value[key]);
- } else {
- str = format(value[key], recurseTimes - 1);
- }
- if (str.indexOf('\n') > -1) {
- if (isArray(value)) {
- str = str.split('\n').map(function(line) {
- return ' ' + line;
- }).join('\n').substr(2);
- } else {
- str = '\n' + str.split('\n').map(function(line) {
- return ' ' + line;
- }).join('\n');
- }
- }
- } else {
- str = stylize('[Circular]', 'special');
- }
- }
- if (typeof name === 'undefined') {
- if (type === 'Array' && key.match(/^\d+$/)) {
- return str;
- }
- name = JSON.stringify('' + key);
- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
- name = name.substr(1, name.length - 2);
- name = stylize(name, 'name');
- } else {
- name = name.replace(/'/g, "\\'")
- .replace(/\\"/g, '"')
- .replace(/(^"|"$)/g, "'");
- name = stylize(name, 'string');
- }
- }
-
- return name + ': ' + str;
- });
-
- seen.pop();
-
- var numLinesEst = 0;
- var length = output.reduce(function(prev, cur) {
- numLinesEst++;
- if (cur.indexOf('\n') >= 0) numLinesEst++;
- return prev + cur.length + 1;
- }, 0);
-
- if (length > 50) {
- output = braces[0] +
- (base === '' ? '' : base + '\n ') +
- ' ' +
- output.join(',\n ') +
- ' ' +
- braces[1];
-
- } else {
- output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
- }
-
- return output;
- }
- return format(obj, (typeof depth === 'undefined' ? 2 : depth));
-};
-
-
-function isArray(ar) {
- return ar instanceof Array ||
- Array.isArray(ar) ||
- (ar && ar !== Object.prototype && isArray(ar.__proto__));
-}
-
-
-function isRegExp(re) {
- return re instanceof RegExp ||
- (typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]');
-}
-
-
-function isDate(d) {
- if (d instanceof Date) return true;
- if (typeof d !== 'object') return false;
- var properties = Date.prototype && Object_getOwnPropertyNames(Date.prototype);
- var proto = d.__proto__ && Object_getOwnPropertyNames(d.__proto__);
- return JSON.stringify(proto) === JSON.stringify(properties);
-}
-
-function pad(n) {
- return n < 10 ? '0' + n.toString(10) : n.toString(10);
-}
-
-var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
- 'Oct', 'Nov', 'Dec'];
-
-// 26 Feb 16:19:34
-function timestamp() {
- var d = new Date();
- var time = [pad(d.getHours()),
- pad(d.getMinutes()),
- pad(d.getSeconds())].join(':');
- return [d.getDate(), months[d.getMonth()], time].join(' ');
-}
-
-exports.log = function (msg) {};
-
-exports.pump = null;
-
-var Object_keys = Object.keys || function (obj) {
- var res = [];
- for (var key in obj) res.push(key);
- return res;
-};
-
-var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) {
- var res = [];
- for (var key in obj) {
- if (Object.hasOwnProperty.call(obj, key)) res.push(key);
- }
- return res;
-};
-
-var Object_create = Object.create || function (prototype, properties) {
- // from es5-shim
- var object;
- if (prototype === null) {
- object = { '__proto__' : null };
- }
- else {
- if (typeof prototype !== 'object') {
- throw new TypeError(
- 'typeof prototype[' + (typeof prototype) + '] != \'object\''
- );
- }
- var Type = function () {};
- Type.prototype = prototype;
- object = new Type();
- object.__proto__ = prototype;
- }
- if (typeof properties !== 'undefined' && Object.defineProperties) {
- Object.defineProperties(object, properties);
- }
- return object;
-};
-
-exports.inherits = function(ctor, superCtor) {
- ctor.super_ = superCtor;
- ctor.prototype = Object_create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
-};
-
-var formatRegExp = /%[sdj%]/g;
-exports.format = function(f) {
- if (typeof f !== 'string') {
- var objects = [];
- for (var i = 0; i < arguments.length; i++) {
- objects.push(exports.inspect(arguments[i]));
- }
- return objects.join(' ');
- }
-
- var i = 1;
- var args = arguments;
- var len = args.length;
- var str = String(f).replace(formatRegExp, function(x) {
- if (x === '%%') return '%';
- if (i >= len) return x;
- switch (x) {
- case '%s': return String(args[i++]);
- case '%d': return Number(args[i++]);
- case '%j': return JSON.stringify(args[i++]);
- default:
- return x;
- }
- });
- for(var x = args[i]; i < len; x = args[++i]){
- if (x === null || typeof x !== 'object') {
- str += ' ' + x;
- } else {
- str += ' ' + exports.inspect(x);
- }
- }
- return str;
-};
-
-},{"events":2}],9:[function(require,module,exports){
-(function(){// UTILITY
-var util = require('util');
-var Buffer = require("buffer").Buffer;
-var pSlice = Array.prototype.slice;
-
-function objectKeys(object) {
- if (Object.keys) return Object.keys(object);
- var result = [];
- for (var name in object) {
- if (Object.prototype.hasOwnProperty.call(object, name)) {
- result.push(name);
- }
- }
- return result;
-}
-
-// 1. The assert module provides functions that throw
-// AssertionError's when particular conditions are not met. The
-// assert module must conform to the following interface.
-
-var assert = module.exports = ok;
-
-// 2. The AssertionError is defined in assert.
-// new assert.AssertionError({ message: message,
-// actual: actual,
-// expected: expected })
-
-assert.AssertionError = function AssertionError(options) {
- this.name = 'AssertionError';
- this.message = options.message;
- this.actual = options.actual;
- this.expected = options.expected;
- this.operator = options.operator;
- var stackStartFunction = options.stackStartFunction || fail;
-
- if (Error.captureStackTrace) {
- Error.captureStackTrace(this, stackStartFunction);
- }
-};
-util.inherits(assert.AssertionError, Error);
-
-function replacer(key, value) {
- if (value === undefined) {
- return '' + value;
- }
- if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {
- return value.toString();
- }
- if (typeof value === 'function' || value instanceof RegExp) {
- return value.toString();
- }
- return value;
-}
-
-function truncate(s, n) {
- if (typeof s == 'string') {
- return s.length < n ? s : s.slice(0, n);
- } else {
- return s;
- }
-}
-
-assert.AssertionError.prototype.toString = function() {
- if (this.message) {
- return [this.name + ':', this.message].join(' ');
- } else {
- return [
- this.name + ':',
- truncate(JSON.stringify(this.actual, replacer), 128),
- this.operator,
- truncate(JSON.stringify(this.expected, replacer), 128)
- ].join(' ');
- }
-};
-
-// assert.AssertionError instanceof Error
-
-assert.AssertionError.__proto__ = Error.prototype;
-
-// At present only the three keys mentioned above are used and
-// understood by the spec. Implementations or sub modules can pass
-// other keys to the AssertionError's constructor - they will be
-// ignored.
-
-// 3. All of the following functions must throw an AssertionError
-// when a corresponding condition is not met, with a message that
-// may be undefined if not provided. All assertion methods provide
-// both the actual and expected values to the assertion error for
-// display purposes.
-
-function fail(actual, expected, message, operator, stackStartFunction) {
- throw new assert.AssertionError({
- message: message,
- actual: actual,
- expected: expected,
- operator: operator,
- stackStartFunction: stackStartFunction
- });
-}
-
-// EXTENSION! allows for well behaved errors defined elsewhere.
-assert.fail = fail;
-
-// 4. Pure assertion tests whether a value is truthy, as determined
-// by !!guard.
-// assert.ok(guard, message_opt);
-// This statement is equivalent to assert.equal(true, guard,
-// message_opt);. To test strictly for the value true, use
-// assert.strictEqual(true, guard, message_opt);.
-
-function ok(value, message) {
- if (!!!value) fail(value, true, message, '==', assert.ok);
-}
-assert.ok = ok;
-
-// 5. The equality assertion tests shallow, coercive equality with
-// ==.
-// assert.equal(actual, expected, message_opt);
-
-assert.equal = function equal(actual, expected, message) {
- if (actual != expected) fail(actual, expected, message, '==', assert.equal);
-};
-
-// 6. The non-equality assertion tests for whether two objects are not equal
-// with != assert.notEqual(actual, expected, message_opt);
-
-assert.notEqual = function notEqual(actual, expected, message) {
- if (actual == expected) {
- fail(actual, expected, message, '!=', assert.notEqual);
- }
-};
-
-// 7. The equivalence assertion tests a deep equality relation.
-// assert.deepEqual(actual, expected, message_opt);
-
-assert.deepEqual = function deepEqual(actual, expected, message) {
- if (!_deepEqual(actual, expected)) {
- fail(actual, expected, message, 'deepEqual', assert.deepEqual);
- }
-};
-
-function _deepEqual(actual, expected) {
- // 7.1. All identical values are equivalent, as determined by ===.
- if (actual === expected) {
- return true;
-
- } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
- if (actual.length != expected.length) return false;
-
- for (var i = 0; i < actual.length; i++) {
- if (actual[i] !== expected[i]) return false;
- }
-
- return true;
-
- // 7.2. If the expected value is a Date object, the actual value is
- // equivalent if it is also a Date object that refers to the same time.
- } else if (actual instanceof Date && expected instanceof Date) {
- return actual.getTime() === expected.getTime();
-
- // 7.3. Other pairs that do not both pass typeof value == 'object',
- // equivalence is determined by ==.
- } else if (typeof actual != 'object' && typeof expected != 'object') {
- return actual == expected;
-
- // 7.4. For all other Object pairs, including Array objects, equivalence is
- // determined by having the same number of owned properties (as verified
- // with Object.prototype.hasOwnProperty.call), the same set of keys
- // (although not necessarily the same order), equivalent values for every
- // corresponding key, and an identical 'prototype' property. Note: this
- // accounts for both named and indexed properties on Arrays.
- } else {
- return objEquiv(actual, expected);
- }
-}
-
-function isUndefinedOrNull(value) {
- return value === null || value === undefined;
-}
-
-function isArguments(object) {
- return Object.prototype.toString.call(object) == '[object Arguments]';
-}
-
-function objEquiv(a, b) {
- if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
- return false;
- // an identical 'prototype' property.
- if (a.prototype !== b.prototype) return false;
- //~~~I've managed to break Object.keys through screwy arguments passing.
- // Converting to array solves the problem.
- if (isArguments(a)) {
- if (!isArguments(b)) {
- return false;
- }
- a = pSlice.call(a);
- b = pSlice.call(b);
- return _deepEqual(a, b);
- }
- try {
- var ka = objectKeys(a),
- kb = objectKeys(b),
- key, i;
- } catch (e) {//happens when one is a string literal and the other isn't
- return false;
- }
- // having the same number of owned properties (keys incorporates
- // hasOwnProperty)
- if (ka.length != kb.length)
- return false;
- //the same set of keys (although not necessarily the same order),
- ka.sort();
- kb.sort();
- //~~~cheap key test
- for (i = ka.length - 1; i >= 0; i--) {
- if (ka[i] != kb[i])
- return false;
- }
- //equivalent values for every corresponding key, and
- //~~~possibly expensive deep test
- for (i = ka.length - 1; i >= 0; i--) {
- key = ka[i];
- if (!_deepEqual(a[key], b[key])) return false;
- }
- return true;
-}
-
-// 8. The non-equivalence assertion tests for any deep inequality.
-// assert.notDeepEqual(actual, expected, message_opt);
-
-assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
- if (_deepEqual(actual, expected)) {
- fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
- }
-};
-
-// 9. The strict equality assertion tests strict equality, as determined by ===.
-// assert.strictEqual(actual, expected, message_opt);
-
-assert.strictEqual = function strictEqual(actual, expected, message) {
- if (actual !== expected) {
- fail(actual, expected, message, '===', assert.strictEqual);
- }
-};
-
-// 10. The strict non-equality assertion tests for strict inequality, as
-// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
-
-assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
- if (actual === expected) {
- fail(actual, expected, message, '!==', assert.notStrictEqual);
- }
-};
-
-function expectedException(actual, expected) {
- if (!actual || !expected) {
- return false;
- }
-
- if (expected instanceof RegExp) {
- return expected.test(actual);
- } else if (actual instanceof expected) {
- return true;
- } else if (expected.call({}, actual) === true) {
- return true;
- }
-
- return false;
-}
-
-function _throws(shouldThrow, block, expected, message) {
- var actual;
-
- if (typeof expected === 'string') {
- message = expected;
- expected = null;
- }
-
- try {
- block();
- } catch (e) {
- actual = e;
- }
-
- message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
- (message ? ' ' + message : '.');
-
- if (shouldThrow && !actual) {
- fail('Missing expected exception' + message);
- }
-
- if (!shouldThrow && expectedException(actual, expected)) {
- fail('Got unwanted exception' + message);
- }
-
- if ((shouldThrow && actual && expected &&
- !expectedException(actual, expected)) || (!shouldThrow && actual)) {
- throw actual;
- }
-}
-
-// 11. Expected to throw an error:
-// assert.throws(block, Error_opt, message_opt);
-
-assert.throws = function(block, /*optional*/error, /*optional*/message) {
- _throws.apply(this, [true].concat(pSlice.call(arguments)));
-};
-
-// EXTENSION! This is annoying to write outside this module.
-assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
- _throws.apply(this, [false].concat(pSlice.call(arguments)));
-};
-
-assert.ifError = function(err) { if (err) {throw err;}};
-
-})()
-},{"util":8,"buffer":13}],11:[function(require,module,exports){
-(function(){// Underscore.js 1.4.4
-// http://underscorejs.org
-// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore may be freely distributed under the MIT license.
-
-(function() {
-
- // Baseline setup
- // --------------
-
- // Establish the root object, `window` in the browser, or `global` on the server.
- var root = this;
-
- // Save the previous value of the `_` variable.
- var previousUnderscore = root._;
-
- // Establish the object that gets returned to break out of a loop iteration.
- var breaker = {};
-
- // Save bytes in the minified (but not gzipped) version:
- var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
-
- // Create quick reference variables for speed access to core prototypes.
- var push = ArrayProto.push,
- slice = ArrayProto.slice,
- concat = ArrayProto.concat,
- toString = ObjProto.toString,
- hasOwnProperty = ObjProto.hasOwnProperty;
-
- // All **ECMAScript 5** native function implementations that we hope to use
- // are declared here.
- var
- nativeForEach = ArrayProto.forEach,
- nativeMap = ArrayProto.map,
- nativeReduce = ArrayProto.reduce,
- nativeReduceRight = ArrayProto.reduceRight,
- nativeFilter = ArrayProto.filter,
- nativeEvery = ArrayProto.every,
- nativeSome = ArrayProto.some,
- nativeIndexOf = ArrayProto.indexOf,
- nativeLastIndexOf = ArrayProto.lastIndexOf,
- nativeIsArray = Array.isArray,
- nativeKeys = Object.keys,
- nativeBind = FuncProto.bind;
-
- // Create a safe reference to the Underscore object for use below.
- var _ = function(obj) {
- if (obj instanceof _) return obj;
- if (!(this instanceof _)) return new _(obj);
- this._wrapped = obj;
- };
-
- // Export the Underscore object for **Node.js**, with
- // backwards-compatibility for the old `require()` API. If we're in
- // the browser, add `_` as a global object via a string identifier,
- // for Closure Compiler "advanced" mode.
- if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
- exports = module.exports = _;
- }
- exports._ = _;
- } else {
- root._ = _;
- }
-
- // Current version.
- _.VERSION = '1.4.4';
-
- // Collection Functions
- // --------------------
-
- // The cornerstone, an `each` implementation, aka `forEach`.
- // Handles objects with the built-in `forEach`, arrays, and raw objects.
- // Delegates to **ECMAScript 5**'s native `forEach` if available.
- var each = _.each = _.forEach = function(obj, iterator, context) {
- if (obj == null) return;
- if (nativeForEach && obj.forEach === nativeForEach) {
- obj.forEach(iterator, context);
- } else if (obj.length === +obj.length) {
- for (var i = 0, l = obj.length; i < l; i++) {
- if (iterator.call(context, obj[i], i, obj) === breaker) return;
- }
- } else {
- for (var key in obj) {
- if (_.has(obj, key)) {
- if (iterator.call(context, obj[key], key, obj) === breaker) return;
- }
- }
- }
- };
-
- // Return the results of applying the iterator to each element.
- // Delegates to **ECMAScript 5**'s native `map` if available.
- _.map = _.collect = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
- each(obj, function(value, index, list) {
- results[results.length] = iterator.call(context, value, index, list);
- });
- return results;
- };
-
- var reduceError = 'Reduce of empty array with no initial value';
-
- // **Reduce** builds up a single result from a list of values, aka `inject`,
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduce && obj.reduce === nativeReduce) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
- }
- each(obj, function(value, index, list) {
- if (!initial) {
- memo = value;
- initial = true;
- } else {
- memo = iterator.call(context, memo, value, index, list);
- }
- });
- if (!initial) throw new TypeError(reduceError);
- return memo;
- };
-
- // The right-associative version of reduce, also known as `foldr`.
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
- }
- var length = obj.length;
- if (length !== +length) {
- var keys = _.keys(obj);
- length = keys.length;
- }
- each(obj, function(value, index, list) {
- index = keys ? keys[--length] : --length;
- if (!initial) {
- memo = obj[index];
- initial = true;
- } else {
- memo = iterator.call(context, memo, obj[index], index, list);
- }
- });
- if (!initial) throw new TypeError(reduceError);
- return memo;
- };
-
- // Return the first value which passes a truth test. Aliased as `detect`.
- _.find = _.detect = function(obj, iterator, context) {
- var result;
- any(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) {
- result = value;
- return true;
- }
- });
- return result;
- };
-
- // Return all the elements that pass a truth test.
- // Delegates to **ECMAScript 5**'s native `filter` if available.
- // Aliased as `select`.
- _.filter = _.select = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
- each(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- };
-
- // Return all the elements for which a truth test fails.
- _.reject = function(obj, iterator, context) {
- return _.filter(obj, function(value, index, list) {
- return !iterator.call(context, value, index, list);
- }, context);
- };
-
- // Determine whether all of the elements match a truth test.
- // Delegates to **ECMAScript 5**'s native `every` if available.
- // Aliased as `all`.
- _.every = _.all = function(obj, iterator, context) {
- iterator || (iterator = _.identity);
- var result = true;
- if (obj == null) return result;
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
- each(obj, function(value, index, list) {
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- };
-
- // Determine if at least one element in the object matches a truth test.
- // Delegates to **ECMAScript 5**'s native `some` if available.
- // Aliased as `any`.
- var any = _.some = _.any = function(obj, iterator, context) {
- iterator || (iterator = _.identity);
- var result = false;
- if (obj == null) return result;
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
- each(obj, function(value, index, list) {
- if (result || (result = iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- };
-
- // Determine if the array or object contains a given value (using `===`).
- // Aliased as `include`.
- _.contains = _.include = function(obj, target) {
- if (obj == null) return false;
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
- return any(obj, function(value) {
- return value === target;
- });
- };
-
- // Invoke a method (with arguments) on every item in a collection.
- _.invoke = function(obj, method) {
- var args = slice.call(arguments, 2);
- var isFunc = _.isFunction(method);
- return _.map(obj, function(value) {
- return (isFunc ? method : value[method]).apply(value, args);
- });
- };
-
- // Convenience version of a common use case of `map`: fetching a property.
- _.pluck = function(obj, key) {
- return _.map(obj, function(value){ return value[key]; });
- };
-
- // Convenience version of a common use case of `filter`: selecting only objects
- // containing specific `key:value` pairs.
- _.where = function(obj, attrs, first) {
- if (_.isEmpty(attrs)) return first ? null : [];
- return _[first ? 'find' : 'filter'](obj, function(value) {
- for (var key in attrs) {
- if (attrs[key] !== value[key]) return false;
- }
- return true;
- });
- };
-
- // Convenience version of a common use case of `find`: getting the first object
- // containing specific `key:value` pairs.
- _.findWhere = function(obj, attrs) {
- return _.where(obj, attrs, true);
- };
-
- // Return the maximum element or (element-based computation).
- // Can't optimize arrays of integers longer than 65,535 elements.
- // See: https://bugs.webkit.org/show_bug.cgi?id=80797
- _.max = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.max.apply(Math, obj);
- }
- if (!iterator && _.isEmpty(obj)) return -Infinity;
- var result = {computed : -Infinity, value: -Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed >= result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Return the minimum element (or element-based computation).
- _.min = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.min.apply(Math, obj);
- }
- if (!iterator && _.isEmpty(obj)) return Infinity;
- var result = {computed : Infinity, value: Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed < result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Shuffle an array.
- _.shuffle = function(obj) {
- var rand;
- var index = 0;
- var shuffled = [];
- each(obj, function(value) {
- rand = _.random(index++);
- shuffled[index - 1] = shuffled[rand];
- shuffled[rand] = value;
- });
- return shuffled;
- };
-
- // An internal function to generate lookup iterators.
- var lookupIterator = function(value) {
- return _.isFunction(value) ? value : function(obj){ return obj[value]; };
- };
-
- // Sort the object's values by a criterion produced by an iterator.
- _.sortBy = function(obj, value, context) {
- var iterator = lookupIterator(value);
- return _.pluck(_.map(obj, function(value, index, list) {
- return {
- value : value,
- index : index,
- criteria : iterator.call(context, value, index, list)
- };
- }).sort(function(left, right) {
- var a = left.criteria;
- var b = right.criteria;
- if (a !== b) {
- if (a > b || a === void 0) return 1;
- if (a < b || b === void 0) return -1;
- }
- return left.index < right.index ? -1 : 1;
- }), 'value');
- };
-
- // An internal function used for aggregate "group by" operations.
- var group = function(obj, value, context, behavior) {
- var result = {};
- var iterator = lookupIterator(value || _.identity);
- each(obj, function(value, index) {
- var key = iterator.call(context, value, index, obj);
- behavior(result, key, value);
- });
- return result;
- };
-
- // Groups the object's values by a criterion. Pass either a string attribute
- // to group by, or a function that returns the criterion.
- _.groupBy = function(obj, value, context) {
- return group(obj, value, context, function(result, key, value) {
- (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
- });
- };
-
- // Counts instances of an object that group by a certain criterion. Pass
- // either a string attribute to count by, or a function that returns the
- // criterion.
- _.countBy = function(obj, value, context) {
- return group(obj, value, context, function(result, key) {
- if (!_.has(result, key)) result[key] = 0;
- result[key]++;
- });
- };
-
- // Use a comparator function to figure out the smallest index at which
- // an object should be inserted so as to maintain order. Uses binary search.
- _.sortedIndex = function(array, obj, iterator, context) {
- iterator = iterator == null ? _.identity : lookupIterator(iterator);
- var value = iterator.call(context, obj);
- var low = 0, high = array.length;
- while (low < high) {
- var mid = (low + high) >>> 1;
- iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
- }
- return low;
- };
-
- // Safely convert anything iterable into a real, live array.
- _.toArray = function(obj) {
- if (!obj) return [];
- if (_.isArray(obj)) return slice.call(obj);
- if (obj.length === +obj.length) return _.map(obj, _.identity);
- return _.values(obj);
- };
-
- // Return the number of elements in an object.
- _.size = function(obj) {
- if (obj == null) return 0;
- return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
- };
-
- // Array Functions
- // ---------------
-
- // Get the first element of an array. Passing **n** will return the first N
- // values in the array. Aliased as `head` and `take`. The **guard** check
- // allows it to work with `_.map`.
- _.first = _.head = _.take = function(array, n, guard) {
- if (array == null) return void 0;
- return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
- };
-
- // Returns everything but the last entry of the array. Especially useful on
- // the arguments object. Passing **n** will return all the values in
- // the array, excluding the last N. The **guard** check allows it to work with
- // `_.map`.
- _.initial = function(array, n, guard) {
- return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
- };
-
- // Get the last element of an array. Passing **n** will return the last N
- // values in the array. The **guard** check allows it to work with `_.map`.
- _.last = function(array, n, guard) {
- if (array == null) return void 0;
- if ((n != null) && !guard) {
- return slice.call(array, Math.max(array.length - n, 0));
- } else {
- return array[array.length - 1];
- }
- };
-
- // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
- // Especially useful on the arguments object. Passing an **n** will return
- // the rest N values in the array. The **guard**
- // check allows it to work with `_.map`.
- _.rest = _.tail = _.drop = function(array, n, guard) {
- return slice.call(array, (n == null) || guard ? 1 : n);
- };
-
- // Trim out all falsy values from an array.
- _.compact = function(array) {
- return _.filter(array, _.identity);
- };
-
- // Internal implementation of a recursive `flatten` function.
- var flatten = function(input, shallow, output) {
- each(input, function(value) {
- if (_.isArray(value)) {
- shallow ? push.apply(output, value) : flatten(value, shallow, output);
- } else {
- output.push(value);
- }
- });
- return output;
- };
-
- // Return a completely flattened version of an array.
- _.flatten = function(array, shallow) {
- return flatten(array, shallow, []);
- };
-
- // Return a version of the array that does not contain the specified value(s).
- _.without = function(array) {
- return _.difference(array, slice.call(arguments, 1));
- };
-
- // Produce a duplicate-free version of the array. If the array has already
- // been sorted, you have the option of using a faster algorithm.
- // Aliased as `unique`.
- _.uniq = _.unique = function(array, isSorted, iterator, context) {
- if (_.isFunction(isSorted)) {
- context = iterator;
- iterator = isSorted;
- isSorted = false;
- }
- var initial = iterator ? _.map(array, iterator, context) : array;
- var results = [];
- var seen = [];
- each(initial, function(value, index) {
- if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
- seen.push(value);
- results.push(array[index]);
- }
- });
- return results;
- };
-
- // Produce an array that contains the union: each distinct element from all of
- // the passed-in arrays.
- _.union = function() {
- return _.uniq(concat.apply(ArrayProto, arguments));
- };
-
- // Produce an array that contains every item shared between all the
- // passed-in arrays.
- _.intersection = function(array) {
- var rest = slice.call(arguments, 1);
- return _.filter(_.uniq(array), function(item) {
- return _.every(rest, function(other) {
- return _.indexOf(other, item) >= 0;
- });
- });
- };
-
- // Take the difference between one array and a number of other arrays.
- // Only the elements present in just the first array will remain.
- _.difference = function(array) {
- var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
- return _.filter(array, function(value){ return !_.contains(rest, value); });
- };
-
- // Zip together multiple lists into a single array -- elements that share
- // an index go together.
- _.zip = function() {
- var args = slice.call(arguments);
- var length = _.max(_.pluck(args, 'length'));
- var results = new Array(length);
- for (var i = 0; i < length; i++) {
- results[i] = _.pluck(args, "" + i);
- }
- return results;
- };
-
- // Converts lists into objects. Pass either a single array of `[key, value]`
- // pairs, or two parallel arrays of the same length -- one of keys, and one of
- // the corresponding values.
- _.object = function(list, values) {
- if (list == null) return {};
- var result = {};
- for (var i = 0, l = list.length; i < l; i++) {
- if (values) {
- result[list[i]] = values[i];
- } else {
- result[list[i][0]] = list[i][1];
- }
- }
- return result;
- };
-
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
- // we need this function. Return the position of the first occurrence of an
- // item in an array, or -1 if the item is not included in the array.
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
- // If the array is large and already in sort order, pass `true`
- // for **isSorted** to use binary search.
- _.indexOf = function(array, item, isSorted) {
- if (array == null) return -1;
- var i = 0, l = array.length;
- if (isSorted) {
- if (typeof isSorted == 'number') {
- i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
- } else {
- i = _.sortedIndex(array, item);
- return array[i] === item ? i : -1;
- }
- }
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
- for (; i < l; i++) if (array[i] === item) return i;
- return -1;
- };
-
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
- _.lastIndexOf = function(array, item, from) {
- if (array == null) return -1;
- var hasIndex = from != null;
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
- return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
- }
- var i = (hasIndex ? from : array.length);
- while (i--) if (array[i] === item) return i;
- return -1;
- };
-
- // Generate an integer Array containing an arithmetic progression. A port of
- // the native Python `range()` function. See
- // [the Python documentation](http://docs.python.org/library/functions.html#range).
- _.range = function(start, stop, step) {
- if (arguments.length <= 1) {
- stop = start || 0;
- start = 0;
- }
- step = arguments[2] || 1;
-
- var len = Math.max(Math.ceil((stop - start) / step), 0);
- var idx = 0;
- var range = new Array(len);
-
- while(idx < len) {
- range[idx++] = start;
- start += step;
- }
-
- return range;
- };
-
- // Function (ahem) Functions
- // ------------------
-
- // Create a function bound to a given object (assigning `this`, and arguments,
- // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
- // available.
- _.bind = function(func, context) {
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- var args = slice.call(arguments, 2);
- return function() {
- return func.apply(context, args.concat(slice.call(arguments)));
- };
- };
-
- // Partially apply a function by creating a version that has had some of its
- // arguments pre-filled, without changing its dynamic `this` context.
- _.partial = function(func) {
- var args = slice.call(arguments, 1);
- return function() {
- return func.apply(this, args.concat(slice.call(arguments)));
- };
- };
-
- // Bind all of an object's methods to that object. Useful for ensuring that
- // all callbacks defined on an object belong to it.
- _.bindAll = function(obj) {
- var funcs = slice.call(arguments, 1);
- if (funcs.length === 0) funcs = _.functions(obj);
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
- return obj;
- };
-
- // Memoize an expensive function by storing its results.
- _.memoize = function(func, hasher) {
- var memo = {};
- hasher || (hasher = _.identity);
- return function() {
- var key = hasher.apply(this, arguments);
- return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
- };
- };
-
- // Delays a function for the given number of milliseconds, and then calls
- // it with the arguments supplied.
- _.delay = function(func, wait) {
- var args = slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(null, args); }, wait);
- };
-
- // Defers a function, scheduling it to run after the current call stack has
- // cleared.
- _.defer = function(func) {
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
- };
-
- // Returns a function, that, when invoked, will only be triggered at most once
- // during a given window of time.
- _.throttle = function(func, wait) {
- var context, args, timeout, result;
- var previous = 0;
- var later = function() {
- previous = new Date;
- timeout = null;
- result = func.apply(context, args);
- };
- return function() {
- var now = new Date;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0) {
- clearTimeout(timeout);
- timeout = null;
- previous = now;
- result = func.apply(context, args);
- } else if (!timeout) {
- timeout = setTimeout(later, remaining);
- }
- return result;
- };
- };
-
- // Returns a function, that, as long as it continues to be invoked, will not
- // be triggered. The function will be called after it stops being called for
- // N milliseconds. If `immediate` is passed, trigger the function on the
- // leading edge, instead of the trailing.
- _.debounce = function(func, wait, immediate) {
- var timeout, result;
- return function() {
- var context = this, args = arguments;
- var later = function() {
- timeout = null;
- if (!immediate) result = func.apply(context, args);
- };
- var callNow = immediate && !timeout;
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- if (callNow) result = func.apply(context, args);
- return result;
- };
- };
-
- // Returns a function that will be executed at most one time, no matter how
- // often you call it. Useful for lazy initialization.
- _.once = function(func) {
- var ran = false, memo;
- return function() {
- if (ran) return memo;
- ran = true;
- memo = func.apply(this, arguments);
- func = null;
- return memo;
- };
- };
-
- // Returns the first function passed as an argument to the second,
- // allowing you to adjust arguments, run code before and after, and
- // conditionally execute the original function.
- _.wrap = function(func, wrapper) {
- return function() {
- var args = [func];
- push.apply(args, arguments);
- return wrapper.apply(this, args);
- };
- };
-
- // Returns a function that is the composition of a list of functions, each
- // consuming the return value of the function that follows.
- _.compose = function() {
- var funcs = arguments;
- return function() {
- var args = arguments;
- for (var i = funcs.length - 1; i >= 0; i--) {
- args = [funcs[i].apply(this, args)];
- }
- return args[0];
- };
- };
-
- // Returns a function that will only be executed after being called N times.
- _.after = function(times, func) {
- if (times <= 0) return func();
- return function() {
- if (--times < 1) {
- return func.apply(this, arguments);
- }
- };
- };
-
- // Object Functions
- // ----------------
-
- // Retrieve the names of an object's properties.
- // Delegates to **ECMAScript 5**'s native `Object.keys`
- _.keys = nativeKeys || function(obj) {
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
- var keys = [];
- for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
- return keys;
- };
-
- // Retrieve the values of an object's properties.
- _.values = function(obj) {
- var values = [];
- for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
- return values;
- };
-
- // Convert an object into a list of `[key, value]` pairs.
- _.pairs = function(obj) {
- var pairs = [];
- for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
- return pairs;
- };
-
- // Invert the keys and values of an object. The values must be serializable.
- _.invert = function(obj) {
- var result = {};
- for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
- return result;
- };
-
- // Return a sorted list of the function names available on the object.
- // Aliased as `methods`
- _.functions = _.methods = function(obj) {
- var names = [];
- for (var key in obj) {
- if (_.isFunction(obj[key])) names.push(key);
- }
- return names.sort();
- };
-
- // Extend a given object with all the properties in passed-in object(s).
- _.extend = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- if (source) {
- for (var prop in source) {
- obj[prop] = source[prop];
- }
- }
- });
- return obj;
- };
-
- // Return a copy of the object only containing the whitelisted properties.
- _.pick = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- each(keys, function(key) {
- if (key in obj) copy[key] = obj[key];
- });
- return copy;
- };
-
- // Return a copy of the object without the blacklisted properties.
- _.omit = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- for (var key in obj) {
- if (!_.contains(keys, key)) copy[key] = obj[key];
- }
- return copy;
- };
-
- // Fill in a given object with default properties.
- _.defaults = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- if (source) {
- for (var prop in source) {
- if (obj[prop] == null) obj[prop] = source[prop];
- }
- }
- });
- return obj;
- };
-
- // Create a (shallow-cloned) duplicate of an object.
- _.clone = function(obj) {
- if (!_.isObject(obj)) return obj;
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
- };
-
- // Invokes interceptor with the obj, and then returns obj.
- // The primary purpose of this method is to "tap into" a method chain, in
- // order to perform operations on intermediate results within the chain.
- _.tap = function(obj, interceptor) {
- interceptor(obj);
- return obj;
- };
-
- // Internal recursive comparison function for `isEqual`.
- var eq = function(a, b, aStack, bStack) {
- // Identical objects are equal. `0 === -0`, but they aren't identical.
- // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
- if (a === b) return a !== 0 || 1 / a == 1 / b;
- // A strict comparison is necessary because `null == undefined`.
- if (a == null || b == null) return a === b;
- // Unwrap any wrapped objects.
- if (a instanceof _) a = a._wrapped;
- if (b instanceof _) b = b._wrapped;
- // Compare `[[Class]]` names.
- var className = toString.call(a);
- if (className != toString.call(b)) return false;
- switch (className) {
- // Strings, numbers, dates, and booleans are compared by value.
- case '[object String]':
- // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
- // equivalent to `new String("5")`.
- return a == String(b);
- case '[object Number]':
- // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
- // other numeric values.
- return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
- case '[object Date]':
- case '[object Boolean]':
- // Coerce dates and booleans to numeric primitive values. Dates are compared by their
- // millisecond representations. Note that invalid dates with millisecond representations
- // of `NaN` are not equivalent.
- return +a == +b;
- // RegExps are compared by their source patterns and flags.
- case '[object RegExp]':
- return a.source == b.source &&
- a.global == b.global &&
- a.multiline == b.multiline &&
- a.ignoreCase == b.ignoreCase;
- }
- if (typeof a != 'object' || typeof b != 'object') return false;
- // Assume equality for cyclic structures. The algorithm for detecting cyclic
- // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
- var length = aStack.length;
- while (length--) {
- // Linear search. Performance is inversely proportional to the number of
- // unique nested structures.
- if (aStack[length] == a) return bStack[length] == b;
- }
- // Add the first object to the stack of traversed objects.
- aStack.push(a);
- bStack.push(b);
- var size = 0, result = true;
- // Recursively compare objects and arrays.
- if (className == '[object Array]') {
- // Compare array lengths to determine if a deep comparison is necessary.
- size = a.length;
- result = size == b.length;
- if (result) {
- // Deep compare the contents, ignoring non-numeric properties.
- while (size--) {
- if (!(result = eq(a[size], b[size], aStack, bStack))) break;
- }
- }
- } else {
- // Objects with different constructors are not equivalent, but `Object`s
- // from different frames are.
- var aCtor = a.constructor, bCtor = b.constructor;
- if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
- _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
- return false;
- }
- // Deep compare objects.
- for (var key in a) {
- if (_.has(a, key)) {
- // Count the expected number of properties.
- size++;
- // Deep compare each member.
- if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
- }
- }
- // Ensure that both objects contain the same number of properties.
- if (result) {
- for (key in b) {
- if (_.has(b, key) && !(size--)) break;
- }
- result = !size;
- }
- }
- // Remove the first object from the stack of traversed objects.
- aStack.pop();
- bStack.pop();
- return result;
- };
-
- // Perform a deep comparison to check if two objects are equal.
- _.isEqual = function(a, b) {
- return eq(a, b, [], []);
- };
-
- // Is a given array, string, or object empty?
- // An "empty" object has no enumerable own-properties.
- _.isEmpty = function(obj) {
- if (obj == null) return true;
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
- for (var key in obj) if (_.has(obj, key)) return false;
- return true;
- };
-
- // Is a given value a DOM element?
- _.isElement = function(obj) {
- return !!(obj && obj.nodeType === 1);
- };
-
- // Is a given value an array?
- // Delegates to ECMA5's native Array.isArray
- _.isArray = nativeIsArray || function(obj) {
- return toString.call(obj) == '[object Array]';
- };
-
- // Is a given variable an object?
- _.isObject = function(obj) {
- return obj === Object(obj);
- };
-
- // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
- each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
- _['is' + name] = function(obj) {
- return toString.call(obj) == '[object ' + name + ']';
- };
- });
-
- // Define a fallback version of the method in browsers (ahem, IE), where
- // there isn't any inspectable "Arguments" type.
- if (!_.isArguments(arguments)) {
- _.isArguments = function(obj) {
- return !!(obj && _.has(obj, 'callee'));
- };
- }
-
- // Optimize `isFunction` if appropriate.
- if (typeof (/./) !== 'function') {
- _.isFunction = function(obj) {
- return typeof obj === 'function';
- };
- }
-
- // Is a given object a finite number?
- _.isFinite = function(obj) {
- return isFinite(obj) && !isNaN(parseFloat(obj));
- };
-
- // Is the given value `NaN`? (NaN is the only number which does not equal itself).
- _.isNaN = function(obj) {
- return _.isNumber(obj) && obj != +obj;
- };
-
- // Is a given value a boolean?
- _.isBoolean = function(obj) {
- return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
- };
-
- // Is a given value equal to null?
- _.isNull = function(obj) {
- return obj === null;
- };
-
- // Is a given variable undefined?
- _.isUndefined = function(obj) {
- return obj === void 0;
- };
-
- // Shortcut function for checking if an object has a given property directly
- // on itself (in other words, not on a prototype).
- _.has = function(obj, key) {
- return hasOwnProperty.call(obj, key);
- };
-
- // Utility Functions
- // -----------------
-
- // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
- // previous owner. Returns a reference to the Underscore object.
- _.noConflict = function() {
- root._ = previousUnderscore;
- return this;
- };
-
- // Keep the identity function around for default iterators.
- _.identity = function(value) {
- return value;
- };
-
- // Run a function **n** times.
- _.times = function(n, iterator, context) {
- var accum = Array(n);
- for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
- return accum;
- };
-
- // Return a random integer between min and max (inclusive).
- _.random = function(min, max) {
- if (max == null) {
- max = min;
- min = 0;
- }
- return min + Math.floor(Math.random() * (max - min + 1));
- };
-
- // List of HTML entities for escaping.
- var entityMap = {
- escape: {
- '&': '&amp;',
- '<': '&lt;',
- '>': '&gt;',
- '"': '&quot;',
- "'": '&#x27;',
- '/': '&#x2F;'
- }
- };
- entityMap.unescape = _.invert(entityMap.escape);
-
- // Regexes containing the keys and values listed immediately above.
- var entityRegexes = {
- escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
- unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
- };
-
- // Functions for escaping and unescaping strings to/from HTML interpolation.
- _.each(['escape', 'unescape'], function(method) {
- _[method] = function(string) {
- if (string == null) return '';
- return ('' + string).replace(entityRegexes[method], function(match) {
- return entityMap[method][match];
- });
- };
- });
-
- // If the value of the named property is a function then invoke it;
- // otherwise, return it.
- _.result = function(object, property) {
- if (object == null) return null;
- var value = object[property];
- return _.isFunction(value) ? value.call(object) : value;
- };
-
- // Add your own custom functions to the Underscore object.
- _.mixin = function(obj) {
- each(_.functions(obj), function(name){
- var func = _[name] = obj[name];
- _.prototype[name] = function() {
- var args = [this._wrapped];
- push.apply(args, arguments);
- return result.call(this, func.apply(_, args));
- };
- });
- };
-
- // Generate a unique integer id (unique within the entire client session).
- // Useful for temporary DOM ids.
- var idCounter = 0;
- _.uniqueId = function(prefix) {
- var id = ++idCounter + '';
- return prefix ? prefix + id : id;
- };
-
- // By default, Underscore uses ERB-style template delimiters, change the
- // following template settings to use alternative delimiters.
- _.templateSettings = {
- evaluate : /<%([\s\S]+?)%>/g,
- interpolate : /<%=([\s\S]+?)%>/g,
- escape : /<%-([\s\S]+?)%>/g
- };
-
- // When customizing `templateSettings`, if you don't want to define an
- // interpolation, evaluation or escaping regex, we need one that is
- // guaranteed not to match.
- var noMatch = /(.)^/;
-
- // Certain characters need to be escaped so that they can be put into a
- // string literal.
- var escapes = {
- "'": "'",
- '\\': '\\',
- '\r': 'r',
- '\n': 'n',
- '\t': 't',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
- };
-
- var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
-
- // JavaScript micro-templating, similar to John Resig's implementation.
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
- // and correctly escapes quotes within interpolated code.
- _.template = function(text, data, settings) {
- var render;
- settings = _.defaults({}, settings, _.templateSettings);
-
- // Combine delimiters into one regular expression via alternation.
- var matcher = new RegExp([
- (settings.escape || noMatch).source,
- (settings.interpolate || noMatch).source,
- (settings.evaluate || noMatch).source
- ].join('|') + '|$', 'g');
-
- // Compile the template source, escaping string literals appropriately.
- var index = 0;
- var source = "__p+='";
- text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
- source += text.slice(index, offset)
- .replace(escaper, function(match) { return '\\' + escapes[match]; });
-
- if (escape) {
- source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
- }
- if (interpolate) {
- source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
- }
- if (evaluate) {
- source += "';\n" + evaluate + "\n__p+='";
- }
- index = offset + match.length;
- return match;
- });
- source += "';\n";
-
- // If a variable is not specified, place data values in local scope.
- if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
-
- source = "var __t,__p='',__j=Array.prototype.join," +
- "print=function(){__p+=__j.call(arguments,'');};\n" +
- source + "return __p;\n";
-
- try {
- render = new Function(settings.variable || 'obj', '_', source);
- } catch (e) {
- e.source = source;
- throw e;
- }
-
- if (data) return render(data, _);
- var template = function(data) {
- return render.call(this, data, _);
- };
-
- // Provide the compiled function source as a convenience for precompilation.
- template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
-
- return template;
- };
-
- // Add a "chain" function, which will delegate to the wrapper.
- _.chain = function(obj) {
- return _(obj).chain();
- };
-
- // OOP
- // ---------------
- // If Underscore is called as a function, it returns a wrapped object that
- // can be used OO-style. This wrapper holds altered versions of all the
- // underscore functions. Wrapped objects may be chained.
-
- // Helper function to continue chaining intermediate results.
- var result = function(obj) {
- return this._chain ? _(obj).chain() : obj;
- };
-
- // Add all of the Underscore functions to the wrapper object.
- _.mixin(_);
-
- // Add all mutator Array functions to the wrapper.
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
- var method = ArrayProto[name];
- _.prototype[name] = function() {
- var obj = this._wrapped;
- method.apply(obj, arguments);
- if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
- return result.call(this, obj);
- };
- });
-
- // Add all accessor Array functions to the wrapper.
- each(['concat', 'join', 'slice'], function(name) {
- var method = ArrayProto[name];
- _.prototype[name] = function() {
- return result.call(this, method.apply(this._wrapped, arguments));
- };
- });
-
- _.extend(_.prototype, {
-
- // Start chaining a wrapped Underscore object.
- chain: function() {
- this._chain = true;
- return this;
- },
-
- // Extracts the result from a wrapped and chained object.
- value: function() {
- return this._wrapped;
- }
-
- });
-
-}).call(this);
-
-})()
-},{}],14:[function(require,module,exports){
-exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
- var e, m,
- eLen = nBytes * 8 - mLen - 1,
- eMax = (1 << eLen) - 1,
- eBias = eMax >> 1,
- nBits = -7,
- i = isBE ? 0 : (nBytes - 1),
- d = isBE ? 1 : -1,
- s = buffer[offset + i];
-
- i += d;
-
- e = s & ((1 << (-nBits)) - 1);
- s >>= (-nBits);
- nBits += eLen;
- for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
-
- m = e & ((1 << (-nBits)) - 1);
- e >>= (-nBits);
- nBits += mLen;
- for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
-
- if (e === 0) {
- e = 1 - eBias;
- } else if (e === eMax) {
- return m ? NaN : ((s ? -1 : 1) * Infinity);
- } else {
- m = m + Math.pow(2, mLen);
- e = e - eBias;
- }
- return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
-};
-
-exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
- var e, m, c,
- eLen = nBytes * 8 - mLen - 1,
- eMax = (1 << eLen) - 1,
- eBias = eMax >> 1,
- rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
- i = isBE ? (nBytes - 1) : 0,
- d = isBE ? -1 : 1,
- s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
-
- value = Math.abs(value);
-
- if (isNaN(value) || value === Infinity) {
- m = isNaN(value) ? 1 : 0;
- e = eMax;
- } else {
- e = Math.floor(Math.log(value) / Math.LN2);
- if (value * (c = Math.pow(2, -e)) < 1) {
- e--;
- c *= 2;
- }
- if (e + eBias >= 1) {
- value += rt / c;
- } else {
- value += rt * Math.pow(2, 1 - eBias);
- }
- if (value * c >= 2) {
- e++;
- c /= 2;
- }
-
- if (e + eBias >= eMax) {
- m = 0;
- e = eMax;
- } else if (e + eBias >= 1) {
- m = (value * c - 1) * Math.pow(2, mLen);
- e = e + eBias;
- } else {
- m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
- e = 0;
- }
- }
-
- for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
-
- e = (e << mLen) | m;
- eLen += mLen;
- for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
-
- buffer[offset + i - d] |= s * 128;
-};
-
-},{}],13:[function(require,module,exports){
-(function(){function SlowBuffer (size) {
- this.length = size;
-};
-
-var assert = require('assert');
-
-exports.INSPECT_MAX_BYTES = 50;
-
-
-function toHex(n) {
- if (n < 16) return '0' + n.toString(16);
- return n.toString(16);
-}
-
-function utf8ToBytes(str) {
- var byteArray = [];
- for (var i = 0; i < str.length; i++)
- if (str.charCodeAt(i) <= 0x7F)
- byteArray.push(str.charCodeAt(i));
- else {
- var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
- for (var j = 0; j < h.length; j++)
- byteArray.push(parseInt(h[j], 16));
- }
-
- return byteArray;
-}
-
-function asciiToBytes(str) {
- var byteArray = []
- for (var i = 0; i < str.length; i++ )
- // Node's code seems to be doing this and not & 0x7F..
- byteArray.push( str.charCodeAt(i) & 0xFF );
-
- return byteArray;
-}
-
-function base64ToBytes(str) {
- return require("base64-js").toByteArray(str);
-}
-
-SlowBuffer.byteLength = function (str, encoding) {
- switch (encoding || "utf8") {
- case 'hex':
- return str.length / 2;
-
- case 'utf8':
- case 'utf-8':
- return utf8ToBytes(str).length;
-
- case 'ascii':
- case 'binary':
- return str.length;
-
- case 'base64':
- return base64ToBytes(str).length;
-
- default:
- throw new Error('Unknown encoding');
- }
-};
-
-function blitBuffer(src, dst, offset, length) {
- var pos, i = 0;
- while (i < length) {
- if ((i+offset >= dst.length) || (i >= src.length))
- break;
-
- dst[i + offset] = src[i];
- i++;
- }
- return i;
-}
-
-SlowBuffer.prototype.utf8Write = function (string, offset, length) {
- var bytes, pos;
- return SlowBuffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
-};
-
-SlowBuffer.prototype.asciiWrite = function (string, offset, length) {
- var bytes, pos;
- return SlowBuffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
-};
-
-SlowBuffer.prototype.binaryWrite = SlowBuffer.prototype.asciiWrite;
-
-SlowBuffer.prototype.base64Write = function (string, offset, length) {
- var bytes, pos;
- return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
-};
-
-SlowBuffer.prototype.base64Slice = function (start, end) {
- var bytes = Array.prototype.slice.apply(this, arguments)
- return require("base64-js").fromByteArray(bytes);
-}
-
-function decodeUtf8Char(str) {
- try {
- return decodeURIComponent(str);
- } catch (err) {
- return String.fromCharCode(0xFFFD); // UTF 8 invalid char
- }
-}
-
-SlowBuffer.prototype.utf8Slice = function () {
- var bytes = Array.prototype.slice.apply(this, arguments);
- var res = "";
- var tmp = "";
- var i = 0;
- while (i < bytes.length) {
- if (bytes[i] <= 0x7F) {
- res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
- tmp = "";
- } else
- tmp += "%" + bytes[i].toString(16);
-
- i++;
- }
-
- return res + decodeUtf8Char(tmp);
-}
-
-SlowBuffer.prototype.asciiSlice = function () {
- var bytes = Array.prototype.slice.apply(this, arguments);
- var ret = "";
- for (var i = 0; i < bytes.length; i++)
- ret += String.fromCharCode(bytes[i]);
- return ret;
-}
-
-SlowBuffer.prototype.binarySlice = SlowBuffer.prototype.asciiSlice;
-
-SlowBuffer.prototype.inspect = function() {
- var out = [],
- len = this.length;
- for (var i = 0; i < len; i++) {
- out[i] = toHex(this[i]);
- if (i == exports.INSPECT_MAX_BYTES) {
- out[i + 1] = '...';
- break;
- }
- }
- return '<SlowBuffer ' + out.join(' ') + '>';
-};
-
-
-SlowBuffer.prototype.hexSlice = function(start, end) {
- var len = this.length;
-
- if (!start || start < 0) start = 0;
- if (!end || end < 0 || end > len) end = len;
-
- var out = '';
- for (var i = start; i < end; i++) {
- out += toHex(this[i]);
- }
- return out;
-};
-
-
-SlowBuffer.prototype.toString = function(encoding, start, end) {
- encoding = String(encoding || 'utf8').toLowerCase();
- start = +start || 0;
- if (typeof end == 'undefined') end = this.length;
-
- // Fastpath empty strings
- if (+end == start) {
- return '';
- }
-
- switch (encoding) {
- case 'hex':
- return this.hexSlice(start, end);
-
- case 'utf8':
- case 'utf-8':
- return this.utf8Slice(start, end);
-
- case 'ascii':
- return this.asciiSlice(start, end);
-
- case 'binary':
- return this.binarySlice(start, end);
-
- case 'base64':
- return this.base64Slice(start, end);
-
- case 'ucs2':
- case 'ucs-2':
- return this.ucs2Slice(start, end);
-
- default:
- throw new Error('Unknown encoding');
- }
-};
-
-
-SlowBuffer.prototype.hexWrite = function(string, offset, length) {
- offset = +offset || 0;
- var remaining = this.length - offset;
- if (!length) {
- length = remaining;
- } else {
- length = +length;
- if (length > remaining) {
- length = remaining;
- }
- }
-
- // must be an even number of digits
- var strLen = string.length;
- if (strLen % 2) {
- throw new Error('Invalid hex string');
- }
- if (length > strLen / 2) {
- length = strLen / 2;
- }
- for (var i = 0; i < length; i++) {
- var byte = parseInt(string.substr(i * 2, 2), 16);
- if (isNaN(byte)) throw new Error('Invalid hex string');
- this[offset + i] = byte;
- }
- SlowBuffer._charsWritten = i * 2;
- return i;
-};
-
-
-SlowBuffer.prototype.write = function(string, offset, length, encoding) {
- // Support both (string, offset, length, encoding)
- // and the legacy (string, encoding, offset, length)
- if (isFinite(offset)) {
- if (!isFinite(length)) {
- encoding = length;
- length = undefined;
- }
- } else { // legacy
- var swap = encoding;
- encoding = offset;
- offset = length;
- length = swap;
- }
-
- offset = +offset || 0;
- var remaining = this.length - offset;
- if (!length) {
- length = remaining;
- } else {
- length = +length;
- if (length > remaining) {
- length = remaining;
- }
- }
- encoding = String(encoding || 'utf8').toLowerCase();
-
- switch (encoding) {
- case 'hex':
- return this.hexWrite(string, offset, length);
-
- case 'utf8':
- case 'utf-8':
- return this.utf8Write(string, offset, length);
-
- case 'ascii':
- return this.asciiWrite(string, offset, length);
-
- case 'binary':
- return this.binaryWrite(string, offset, length);
-
- case 'base64':
- return this.base64Write(string, offset, length);
-
- case 'ucs2':
- case 'ucs-2':
- return this.ucs2Write(string, offset, length);
-
- default:
- throw new Error('Unknown encoding');
- }
-};
-
-
-// slice(start, end)
-SlowBuffer.prototype.slice = function(start, end) {
- if (end === undefined) end = this.length;
-
- if (end > this.length) {
- throw new Error('oob');
- }
- if (start > end) {
- throw new Error('oob');
- }
-
- return new Buffer(this, end - start, +start);
-};
-
-SlowBuffer.prototype.copy = function(target, targetstart, sourcestart, sourceend) {
- var temp = [];
- for (var i=sourcestart; i<sourceend; i++) {
- assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
- temp.push(this[i]);
- }
-
- for (var i=targetstart; i<targetstart+temp.length; i++) {
- target[i] = temp[i-targetstart];
- }
-};
-
-SlowBuffer.prototype.fill = function(value, start, end) {
- if (end > this.length) {
- throw new Error('oob');
- }
- if (start > end) {
- throw new Error('oob');
- }
-
- for (var i = start; i < end; i++) {
- this[i] = value;
- }
-}
-
-function coerce(length) {
- // Coerce length to a number (possibly NaN), round up
- // in case it's fractional (e.g. 123.456) then do a
- // double negate to coerce a NaN to 0. Easy, right?
- length = ~~Math.ceil(+length);
- return length < 0 ? 0 : length;
-}
-
-
-// Buffer
-
-function Buffer(subject, encoding, offset) {
- if (!(this instanceof Buffer)) {
- return new Buffer(subject, encoding, offset);
- }
-
- var type;
-
- // Are we slicing?
- if (typeof offset === 'number') {
- this.length = coerce(encoding);
- this.parent = subject;
- this.offset = offset;
- } else {
- // Find the length
- switch (type = typeof subject) {
- case 'number':
- this.length = coerce(subject);
- break;
-
- case 'string':
- this.length = Buffer.byteLength(subject, encoding);
- break;
-
- case 'object': // Assume object is an array
- this.length = coerce(subject.length);
- break;
-
- default:
- throw new Error('First argument needs to be a number, ' +
- 'array or string.');
- }
-
- if (this.length > Buffer.poolSize) {
- // Big buffer, just alloc one.
- this.parent = new SlowBuffer(this.length);
- this.offset = 0;
-
- } else {
- // Small buffer.
- if (!pool || pool.length - pool.used < this.length) allocPool();
- this.parent = pool;
- this.offset = pool.used;
- pool.used += this.length;
- }
-
- // Treat array-ish objects as a byte array.
- if (isArrayIsh(subject)) {
- for (var i = 0; i < this.length; i++) {
- if (subject instanceof Buffer) {
- this.parent[i + this.offset] = subject.readUInt8(i);
- }
- else {
- this.parent[i + this.offset] = subject[i];
- }
- }
- } else if (type == 'string') {
- // We are a string
- this.length = this.write(subject, 0, encoding);
- }
- }
-
-}
-
-function isArrayIsh(subject) {
- return Array.isArray(subject) || Buffer.isBuffer(subject) ||
- subject && typeof subject === 'object' &&
- typeof subject.length === 'number';
-}
-
-exports.SlowBuffer = SlowBuffer;
-exports.Buffer = Buffer;
-
-Buffer.poolSize = 8 * 1024;
-var pool;
-
-function allocPool() {
- pool = new SlowBuffer(Buffer.poolSize);
- pool.used = 0;
-}
-
-
-// Static methods
-Buffer.isBuffer = function isBuffer(b) {
- return b instanceof Buffer || b instanceof SlowBuffer;
-};
-
-Buffer.concat = function (list, totalLength) {
- if (!Array.isArray(list)) {
- throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
- list should be an Array.");
- }
-
- if (list.length === 0) {
- return new Buffer(0);
- } else if (list.length === 1) {
- return list[0];
- }
-
- if (typeof totalLength !== 'number') {
- totalLength = 0;
- for (var i = 0; i < list.length; i++) {
- var buf = list[i];
- totalLength += buf.length;
- }
- }
-
- var buffer = new Buffer(totalLength);
- var pos = 0;
- for (var i = 0; i < list.length; i++) {
- var buf = list[i];
- buf.copy(buffer, pos);
- pos += buf.length;
- }
- return buffer;
-};
-
-// Inspect
-Buffer.prototype.inspect = function inspect() {
- var out = [],
- len = this.length;
-
- for (var i = 0; i < len; i++) {
- out[i] = toHex(this.parent[i + this.offset]);
- if (i == exports.INSPECT_MAX_BYTES) {
- out[i + 1] = '...';
- break;
- }
- }
-
- return '<Buffer ' + out.join(' ') + '>';
-};
-
-
-Buffer.prototype.get = function get(i) {
- if (i < 0 || i >= this.length) throw new Error('oob');
- return this.parent[this.offset + i];
-};
-
-
-Buffer.prototype.set = function set(i, v) {
- if (i < 0 || i >= this.length) throw new Error('oob');
- return this.parent[this.offset + i] = v;
-};
-
-
-// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
-Buffer.prototype.write = function(string, offset, length, encoding) {
- // Support both (string, offset, length, encoding)
- // and the legacy (string, encoding, offset, length)
- if (isFinite(offset)) {
- if (!isFinite(length)) {
- encoding = length;
- length = undefined;
- }
- } else { // legacy
- var swap = encoding;
- encoding = offset;
- offset = length;
- length = swap;
- }
-
- offset = +offset || 0;
- var remaining = this.length - offset;
- if (!length) {
- length = remaining;
- } else {
- length = +length;
- if (length > remaining) {
- length = remaining;
- }
- }
- encoding = String(encoding || 'utf8').toLowerCase();
-
- var ret;
- switch (encoding) {
- case 'hex':
- ret = this.parent.hexWrite(string, this.offset + offset, length);
- break;
-
- case 'utf8':
- case 'utf-8':
- ret = this.parent.utf8Write(string, this.offset + offset, length);
- break;
-
- case 'ascii':
- ret = this.parent.asciiWrite(string, this.offset + offset, length);
- break;
-
- case 'binary':
- ret = this.parent.binaryWrite(string, this.offset + offset, length);
- break;
-
- case 'base64':
- // Warning: maxLength not taken into account in base64Write
- ret = this.parent.base64Write(string, this.offset + offset, length);
- break;
-
- case 'ucs2':
- case 'ucs-2':
- ret = this.parent.ucs2Write(string, this.offset + offset, length);
- break;
-
- default:
- throw new Error('Unknown encoding');
- }
-
- Buffer._charsWritten = SlowBuffer._charsWritten;
-
- return ret;
-};
-
-
-// toString(encoding, start=0, end=buffer.length)
-Buffer.prototype.toString = function(encoding, start, end) {
- encoding = String(encoding || 'utf8').toLowerCase();
-
- if (typeof start == 'undefined' || start < 0) {
- start = 0;
- } else if (start > this.length) {
- start = this.length;
- }
-
- if (typeof end == 'undefined' || end > this.length) {
- end = this.length;
- } else if (end < 0) {
- end = 0;
- }
-
- start = start + this.offset;
- end = end + this.offset;
-
- switch (encoding) {
- case 'hex':
- return this.parent.hexSlice(start, end);
-
- case 'utf8':
- case 'utf-8':
- return this.parent.utf8Slice(start, end);
-
- case 'ascii':
- return this.parent.asciiSlice(start, end);
-
- case 'binary':
- return this.parent.binarySlice(start, end);
-
- case 'base64':
- return this.parent.base64Slice(start, end);
-
- case 'ucs2':
- case 'ucs-2':
- return this.parent.ucs2Slice(start, end);
-
- default:
- throw new Error('Unknown encoding');
- }
-};
-
-
-// byteLength
-Buffer.byteLength = SlowBuffer.byteLength;
-
-
-// fill(value, start=0, end=buffer.length)
-Buffer.prototype.fill = function fill(value, start, end) {
- value || (value = 0);
- start || (start = 0);
- end || (end = this.length);
-
- if (typeof value === 'string') {
- value = value.charCodeAt(0);
- }
- if (!(typeof value === 'number') || isNaN(value)) {
- throw new Error('value is not a number');
- }
-
- if (end < start) throw new Error('end < start');
-
- // Fill 0 bytes; we're done
- if (end === start) return 0;
- if (this.length == 0) return 0;
-
- if (start < 0 || start >= this.length) {
- throw new Error('start out of bounds');
- }
-
- if (end < 0 || end > this.length) {
- throw new Error('end out of bounds');
- }
-
- return this.parent.fill(value,
- start + this.offset,
- end + this.offset);
-};
-
-
-// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
-Buffer.prototype.copy = function(target, target_start, start, end) {
- var source = this;
- start || (start = 0);
- end || (end = this.length);
- target_start || (target_start = 0);
-
- if (end < start) throw new Error('sourceEnd < sourceStart');
-
- // Copy 0 bytes; we're done
- if (end === start) return 0;
- if (target.length == 0 || source.length == 0) return 0;
-
- if (target_start < 0 || target_start >= target.length) {
- throw new Error('targetStart out of bounds');
- }
-
- if (start < 0 || start >= source.length) {
- throw new Error('sourceStart out of bounds');
- }
-
- if (end < 0 || end > source.length) {
- throw new Error('sourceEnd out of bounds');
- }
-
- // Are we oob?
- if (end > this.length) {
- end = this.length;
- }
-
- if (target.length - target_start < end - start) {
- end = target.length - target_start + start;
- }
-
- return this.parent.copy(target.parent,
- target_start + target.offset,
- start + this.offset,
- end + this.offset);
-};
-
-
-// slice(start, end)
-Buffer.prototype.slice = function(start, end) {
- if (end === undefined) end = this.length;
- if (end > this.length) throw new Error('oob');
- if (start > end) throw new Error('oob');
-
- return new Buffer(this.parent, end - start, +start + this.offset);
-};
-
-
-// Legacy methods for backwards compatibility.
-
-Buffer.prototype.utf8Slice = function(start, end) {
- return this.toString('utf8', start, end);
-};
-
-Buffer.prototype.binarySlice = function(start, end) {
- return this.toString('binary', start, end);
-};
-
-Buffer.prototype.asciiSlice = function(start, end) {
- return this.toString('ascii', start, end);
-};
-
-Buffer.prototype.utf8Write = function(string, offset) {
- return this.write(string, offset, 'utf8');
-};
-
-Buffer.prototype.binaryWrite = function(string, offset) {
- return this.write(string, offset, 'binary');
-};
-
-Buffer.prototype.asciiWrite = function(string, offset) {
- return this.write(string, offset, 'ascii');
-};
-
-Buffer.prototype.readUInt8 = function(offset, noAssert) {
- var buffer = this;
-
- if (!noAssert) {
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- if (offset >= buffer.length) return;
-
- return buffer.parent[buffer.offset + offset];
-};
-
-function readUInt16(buffer, offset, isBigEndian, noAssert) {
- var val = 0;
-
-
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 1 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- if (offset >= buffer.length) return 0;
-
- if (isBigEndian) {
- val = buffer.parent[buffer.offset + offset] << 8;
- if (offset + 1 < buffer.length) {
- val |= buffer.parent[buffer.offset + offset + 1];
- }
- } else {
- val = buffer.parent[buffer.offset + offset];
- if (offset + 1 < buffer.length) {
- val |= buffer.parent[buffer.offset + offset + 1] << 8;
- }
- }
-
- return val;
-}
-
-Buffer.prototype.readUInt16LE = function(offset, noAssert) {
- return readUInt16(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readUInt16BE = function(offset, noAssert) {
- return readUInt16(this, offset, true, noAssert);
-};
-
-function readUInt32(buffer, offset, isBigEndian, noAssert) {
- var val = 0;
-
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- if (offset >= buffer.length) return 0;
-
- if (isBigEndian) {
- if (offset + 1 < buffer.length)
- val = buffer.parent[buffer.offset + offset + 1] << 16;
- if (offset + 2 < buffer.length)
- val |= buffer.parent[buffer.offset + offset + 2] << 8;
- if (offset + 3 < buffer.length)
- val |= buffer.parent[buffer.offset + offset + 3];
- val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0);
- } else {
- if (offset + 2 < buffer.length)
- val = buffer.parent[buffer.offset + offset + 2] << 16;
- if (offset + 1 < buffer.length)
- val |= buffer.parent[buffer.offset + offset + 1] << 8;
- val |= buffer.parent[buffer.offset + offset];
- if (offset + 3 < buffer.length)
- val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);
- }
-
- return val;
-}
-
-Buffer.prototype.readUInt32LE = function(offset, noAssert) {
- return readUInt32(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readUInt32BE = function(offset, noAssert) {
- return readUInt32(this, offset, true, noAssert);
-};
-
-
-/*
- * Signed integer types, yay team! A reminder on how two's complement actually
- * works. The first bit is the signed bit, i.e. tells us whether or not the
- * number should be positive or negative. If the two's complement value is
- * positive, then we're done, as it's equivalent to the unsigned representation.
- *
- * Now if the number is positive, you're pretty much done, you can just leverage
- * the unsigned translations and return those. Unfortunately, negative numbers
- * aren't quite that straightforward.
- *
- * At first glance, one might be inclined to use the traditional formula to
- * translate binary numbers between the positive and negative values in two's
- * complement. (Though it doesn't quite work for the most negative value)
- * Mainly:
- * - invert all the bits
- * - add one to the result
- *
- * Of course, this doesn't quite work in Javascript. Take for example the value
- * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
- * course, Javascript will do the following:
- *
- * > ~0xff80
- * -65409
- *
- * Whoh there, Javascript, that's not quite right. But wait, according to
- * Javascript that's perfectly correct. When Javascript ends up seeing the
- * constant 0xff80, it has no notion that it is actually a signed number. It
- * assumes that we've input the unsigned value 0xff80. Thus, when it does the
- * binary negation, it casts it into a signed value, (positive 0xff80). Then
- * when you perform binary negation on that, it turns it into a negative number.
- *
- * Instead, we're going to have to use the following general formula, that works
- * in a rather Javascript friendly way. I'm glad we don't support this kind of
- * weird numbering scheme in the kernel.
- *
- * (BIT-MAX - (unsigned)val + 1) * -1
- *
- * The astute observer, may think that this doesn't make sense for 8-bit numbers
- * (really it isn't necessary for them). However, when you get 16-bit numbers,
- * you do. Let's go back to our prior example and see how this will look:
- *
- * (0xffff - 0xff80 + 1) * -1
- * (0x007f + 1) * -1
- * (0x0080) * -1
- */
-Buffer.prototype.readInt8 = function(offset, noAssert) {
- var buffer = this;
- var neg;
-
- if (!noAssert) {
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- if (offset >= buffer.length) return;
-
- neg = buffer.parent[buffer.offset + offset] & 0x80;
- if (!neg) {
- return (buffer.parent[buffer.offset + offset]);
- }
-
- return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1);
-};
-
-function readInt16(buffer, offset, isBigEndian, noAssert) {
- var neg, val;
-
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 1 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- val = readUInt16(buffer, offset, isBigEndian, noAssert);
- neg = val & 0x8000;
- if (!neg) {
- return val;
- }
-
- return (0xffff - val + 1) * -1;
-}
-
-Buffer.prototype.readInt16LE = function(offset, noAssert) {
- return readInt16(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readInt16BE = function(offset, noAssert) {
- return readInt16(this, offset, true, noAssert);
-};
-
-function readInt32(buffer, offset, isBigEndian, noAssert) {
- var neg, val;
-
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- val = readUInt32(buffer, offset, isBigEndian, noAssert);
- neg = val & 0x80000000;
- if (!neg) {
- return (val);
- }
-
- return (0xffffffff - val + 1) * -1;
-}
-
-Buffer.prototype.readInt32LE = function(offset, noAssert) {
- return readInt32(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readInt32BE = function(offset, noAssert) {
- return readInt32(this, offset, true, noAssert);
-};
-
-function readFloat(buffer, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
- 23, 4);
-}
-
-Buffer.prototype.readFloatLE = function(offset, noAssert) {
- return readFloat(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readFloatBE = function(offset, noAssert) {
- return readFloat(this, offset, true, noAssert);
-};
-
-function readDouble(buffer, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset + 7 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
- 52, 8);
-}
-
-Buffer.prototype.readDoubleLE = function(offset, noAssert) {
- return readDouble(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readDoubleBE = function(offset, noAssert) {
- return readDouble(this, offset, true, noAssert);
-};
-
-
-/*
- * We have to make sure that the value is a valid integer. This means that it is
- * non-negative. It has no fractional component and that it does not exceed the
- * maximum allowed value.
- *
- * value The number to check for validity
- *
- * max The maximum value
- */
-function verifuint(value, max) {
- assert.ok(typeof (value) == 'number',
- 'cannot write a non-number as a number');
-
- assert.ok(value >= 0,
- 'specified a negative value for writing an unsigned value');
-
- assert.ok(value <= max, 'value is larger than maximum value for type');
-
- assert.ok(Math.floor(value) === value, 'value has a fractional component');
-}
-
-Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
- var buffer = this;
-
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset < buffer.length,
- 'trying to write beyond buffer length');
-
- verifuint(value, 0xff);
- }
-
- if (offset < buffer.length) {
- buffer.parent[buffer.offset + offset] = value;
- }
-};
-
-function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 1 < buffer.length,
- 'trying to write beyond buffer length');
-
- verifuint(value, 0xffff);
- }
-
- for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {
- buffer.parent[buffer.offset + offset + i] =
- (value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>
- (isBigEndian ? 1 - i : i) * 8;
- }
-
-}
-
-Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
- writeUInt16(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
- writeUInt16(this, value, offset, true, noAssert);
-};
-
-function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'trying to write beyond buffer length');
-
- verifuint(value, 0xffffffff);
- }
-
- for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {
- buffer.parent[buffer.offset + offset + i] =
- (value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;
- }
-}
-
-Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
- writeUInt32(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
- writeUInt32(this, value, offset, true, noAssert);
-};
-
-
-/*
- * We now move onto our friends in the signed number category. Unlike unsigned
- * numbers, we're going to have to worry a bit more about how we put values into
- * arrays. Since we are only worrying about signed 32-bit values, we're in
- * slightly better shape. Unfortunately, we really can't do our favorite binary
- * & in this system. It really seems to do the wrong thing. For example:
- *
- * > -32 & 0xff
- * 224
- *
- * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
- * this aren't treated as a signed number. Ultimately a bad thing.
- *
- * What we're going to want to do is basically create the unsigned equivalent of
- * our representation and pass that off to the wuint* functions. To do that
- * we're going to do the following:
- *
- * - if the value is positive
- * we can pass it directly off to the equivalent wuint
- * - if the value is negative
- * we do the following computation:
- * mb + val + 1, where
- * mb is the maximum unsigned value in that byte size
- * val is the Javascript negative integer
- *
- *
- * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
- * you do out the computations:
- *
- * 0xffff - 128 + 1
- * 0xffff - 127
- * 0xff80
- *
- * You can then encode this value as the signed version. This is really rather
- * hacky, but it should work and get the job done which is our goal here.
- */
-
-/*
- * A series of checks to make sure we actually have a signed 32-bit number
- */
-function verifsint(value, max, min) {
- assert.ok(typeof (value) == 'number',
- 'cannot write a non-number as a number');
-
- assert.ok(value <= max, 'value larger than maximum allowed value');
-
- assert.ok(value >= min, 'value smaller than minimum allowed value');
-
- assert.ok(Math.floor(value) === value, 'value has a fractional component');
-}
-
-function verifIEEE754(value, max, min) {
- assert.ok(typeof (value) == 'number',
- 'cannot write a non-number as a number');
-
- assert.ok(value <= max, 'value larger than maximum allowed value');
-
- assert.ok(value >= min, 'value smaller than minimum allowed value');
-}
-
-Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
- var buffer = this;
-
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifsint(value, 0x7f, -0x80);
- }
-
- if (value >= 0) {
- buffer.writeUInt8(value, offset, noAssert);
- } else {
- buffer.writeUInt8(0xff + value + 1, offset, noAssert);
- }
-};
-
-function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 1 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifsint(value, 0x7fff, -0x8000);
- }
-
- if (value >= 0) {
- writeUInt16(buffer, value, offset, isBigEndian, noAssert);
- } else {
- writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
- }
-}
-
-Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
- writeInt16(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
- writeInt16(this, value, offset, true, noAssert);
-};
-
-function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifsint(value, 0x7fffffff, -0x80000000);
- }
-
- if (value >= 0) {
- writeUInt32(buffer, value, offset, isBigEndian, noAssert);
- } else {
- writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
- }
-}
-
-Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
- writeInt32(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
- writeInt32(this, value, offset, true, noAssert);
-};
-
-function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
- }
-
- require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
- 23, 4);
-}
-
-Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
- writeFloat(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
- writeFloat(this, value, offset, true, noAssert);
-};
-
-function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 7 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
- }
-
- require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
- 52, 8);
-}
-
-Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
- writeDouble(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
- writeDouble(this, value, offset, true, noAssert);
-};
-
-SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8;
-SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE;
-SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE;
-SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE;
-SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE;
-SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8;
-SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE;
-SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE;
-SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE;
-SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE;
-SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE;
-SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE;
-SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE;
-SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE;
-SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8;
-SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE;
-SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE;
-SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE;
-SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE;
-SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8;
-SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE;
-SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE;
-SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE;
-SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE;
-SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE;
-SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE;
-SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE;
-SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE;
-
-})()
-},{"assert":9,"./buffer_ieee754":14,"base64-js":15}],15:[function(require,module,exports){
-(function (exports) {
- 'use strict';
-
- var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-
- function b64ToByteArray(b64) {
- var i, j, l, tmp, placeHolders, arr;
-
- if (b64.length % 4 > 0) {
- throw 'Invalid string. Length must be a multiple of 4';
- }
-
- // the number of equal signs (place holders)
- // if there are two placeholders, than the two characters before it
- // represent one byte
- // if there is only one, then the three characters before it represent 2 bytes
- // this is just a cheap hack to not do indexOf twice
- placeHolders = b64.indexOf('=');
- placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;
-
- // base64 is 4/3 + up to two characters of the original data
- arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
-
- // if there are placeholders, only get up to the last complete 4 chars
- l = placeHolders > 0 ? b64.length - 4 : b64.length;
-
- for (i = 0, j = 0; i < l; i += 4, j += 3) {
- tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);
- arr.push((tmp & 0xFF0000) >> 16);
- arr.push((tmp & 0xFF00) >> 8);
- arr.push(tmp & 0xFF);
- }
-
- if (placeHolders === 2) {
- tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);
- arr.push(tmp & 0xFF);
- } else if (placeHolders === 1) {
- tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);
- arr.push((tmp >> 8) & 0xFF);
- arr.push(tmp & 0xFF);
- }
-
- return arr;
- }
-
- function uint8ToBase64(uint8) {
- var i,
- extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
- output = "",
- temp, length;
-
- function tripletToBase64 (num) {
- return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
- };
-
- // go through the array every three bytes, we'll deal with trailing stuff later
- for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
- temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
- output += tripletToBase64(temp);
- }
-
- // pad the end with zeros, but make sure to not forget the extra bytes
- switch (extraBytes) {
- case 1:
- temp = uint8[uint8.length - 1];
- output += lookup[temp >> 2];
- output += lookup[(temp << 4) & 0x3F];
- output += '==';
- break;
- case 2:
- temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);
- output += lookup[temp >> 10];
- output += lookup[(temp >> 4) & 0x3F];
- output += lookup[(temp << 2) & 0x3F];
- output += '=';
- break;
- }
-
- return output;
- }
-
- module.exports.toByteArray = b64ToByteArray;
- module.exports.fromByteArray = uint8ToBase64;
-}());
-
-},{}]},{},["E/GbHF"])
-;
-JSHINT = require('jshint').JSHINT;
-}());
diff --git a/dom/system/gonk/tests/marionette/ril_jshint/jshintrc b/dom/system/gonk/tests/marionette/ril_jshint/jshintrc
deleted file mode 100644
index 437fe1a6f..000000000
--- a/dom/system/gonk/tests/marionette/ril_jshint/jshintrc
+++ /dev/null
@@ -1,118 +0,0 @@
-{
- // JSHint Default Configuration File (as on JSHint website)
- // See http://jshint.com/docs/ for more details
-
- // Modify for RIL usage.
-
- "maxerr" : 10000, // {int} Maximum error before stopping
-
- // Enforcing
- "bitwise" : false, // true: Prohibit bitwise operators (&, |, ^, etc.)
- "camelcase" : false, // true: Identifiers must be in camelCase
- "curly" : false, // true: Require {} for every new block or scope
- "eqeqeq" : false, // true: Require triple equals (===) for comparison
- "forin" : false, // true: Require filtering for..in loops with obj.hasOwnProperty()
- "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
- //"indent" : 2, // {int} Number of spaces to use for indentation
- "latedef" : false, // true: Require variables/functions to be defined before being used
- "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
- "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
- "noempty" : false, // true: Prohibit use of empty blocks
- "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
- "plusplus" : false, // true: Prohibit use of `++` & `--`
- "quotmark" : false, // Quotation mark consistency:
- // false : do nothing (default)
- // true : ensure whatever is used is consistent
- // "single" : require single quotes
- // "double" : require double quotes
- "undef" : false, // true: Require all non-global variables to be declared (prevents global leaks)
- "unused" : false, // true: Require all defined variables be used
- "strict" : false, // true: Requires all functions run in ES5 Strict Mode
- "trailing" : false, // true: Prohibit trailing whitespaces
- "maxparams" : false, // {int} Max number of formal params allowed per function
- "maxdepth" : false, // {int} Max depth of nested blocks (within functions)
- "maxstatements" : false, // {int} Max number statements per function
- "maxcomplexity" : false, // {int} Max cyclomatic complexity per function
- "maxlen" : false, // {int} Max number of characters per line
-
- // Relaxing
- "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
- "boss" : false, // true: Tolerate assignments where comparisons would be expected
- "debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
- "eqnull" : true, // true: Tolerate use of `== null`
- "es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
- "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
- "moz" : true, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
- // (ex: `for each`, multiple try/catch, function expression…)
- "evil" : false, // true: Tolerate use of `eval` and `new Function()`
- "expr" : false, // true: Tolerate `ExpressionStatement` as Programs
- "funcscope" : false, // true: Tolerate defining variables inside control statements"
- "globalstrict" : true, // true: Allow global "use strict" (also enables 'strict')
- "iterator" : false, // true: Tolerate using the `__iterator__` property
- "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
- "laxbreak" : true, // true: Tolerate possibly unsafe line breakings
- "laxcomma" : false, // true: Tolerate comma-first style coding
- "loopfunc" : false, // true: Tolerate functions being defined in loops
- "multistr" : false, // true: Tolerate multi-line strings
- "proto" : true, // true: Tolerate using the `__proto__` property
- "scripturl" : false, // true: Tolerate script-targeted URLs
- "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
- "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
- "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
- "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
- "validthis" : true, // true: Tolerate using this in a non-constructor function
-
- // Environments
- "browser" : false, // Web Browser (window, document, etc)
- "couch" : false, // CouchDB
- "devel" : true, // Development/debugging (alert, confirm, etc)
- "dojo" : false, // Dojo Toolkit
- "jquery" : false, // jQuery
- "mootools" : false, // MooTools
- "node" : false, // Node.js
- "nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
- "prototypejs" : false, // Prototype and Scriptaculous
- "rhino" : false, // Rhino
- "worker" : true, // Web Workers
- "wsh" : false, // Windows Scripting Host
- "yui" : false, // Yahoo User Interface
-
- // Legacy
- "nomen" : false, // true: Prohibit dangling `_` in variables
- "onevar" : false, // true: Allow only one `var` statement per function
- "passfail" : false, // true: Stop on first error
- "white" : false, // true: Check against strict whitespace and indentation rules
-
- // Custom Globals
- "predef" : [ ], // additional predefined global variables
-
- "globals": {
- "ChromeWorker": false,
- "Components": false,
- "DOMRequestIpcHelper": false,
- "ObjectWrapper": false,
- "PhoneNumberUtils": false,
- "RILNetworkInterface": false,
- "Services": false,
- "Uint8Array": false,
- "WAP": false,
- "XPCOMUtils": false,
- "cpmm": false,
- "dump": false,
- "gAudioManager": false,
- "gMessageManager": false,
- "gMobileMessageDatabaseService": false,
- "gMobileMessageService": false,
- "gNetworkManager": false,
- "gPowerManagerService": false,
- "gSettingsService": false,
- "gSmsService": false,
- "gSystemMessenger": false,
- "gSystemWorkerManager": false,
- "gTimeService": false,
- "gUUIDGenerator": false,
- "ppmm": true,
-
- "__end_guardian_for_easy_sorting__": false
- }
-}
diff --git a/dom/system/gonk/tests/marionette/test_all_network_info.js b/dom/system/gonk/tests/marionette/test_all_network_info.js
deleted file mode 100644
index 5225ab6d6..000000000
--- a/dom/system/gonk/tests/marionette/test_all_network_info.js
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-var networkManager =
- Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
-ok(networkManager,
- "networkManager.constructor is " + networkManager.constructor);
-
-var wifiManager = window.navigator.mozWifiManager;
-ok(wifiManager, "wifiManager.constructor is " + wifiManager.constructor);
-
-function setEmulatorAPN() {
- let apn = [
- [{"carrier":"T-Mobile US",
- "apn":"epc.tmobile.com",
- "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types":["default","supl","mms","ims","dun", "fota"]}]
- ];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-function ensureWifiEnabled(aEnabled) {
- if (wifiManager.enabled === aEnabled) {
- log('Already ' + (aEnabled ? 'enabled' : 'disabled'));
- return Promise.resolve();
- }
- return requestWifiEnabled(aEnabled);
-}
-
-function requestWifiEnabled(aEnabled) {
- let promises = [];
-
- promises.push(waitForTargetEvent(wifiManager, aEnabled ? 'enabled' : 'disabled',
- function() {
- return wifiManager.enabled === aEnabled ? true : false;
- }));
- promises.push(setSettings(SETTINGS_KEY_WIFI_ENABLED, aEnabled));
-
- return Promise.all(promises);
-}
-
-// Test initial State
-function verifyInitialState() {
- log("= verifyInitialState =");
-
- // Data and wifi should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- })
- .then(() => ensureWifiEnabled(false));
-}
-
-function testAllNetworkInfo(aAnyConnected) {
- log("= testAllNetworkInfo = " + aAnyConnected);
-
- let allNetworkInfo = networkManager.allNetworkInfo;
- ok(allNetworkInfo, "NetworkManager.allNetworkInfo");
-
- let count = Object.keys(allNetworkInfo).length;
- ok(count > 0, "NetworkManager.allNetworkInfo count");
-
- let connected = false;
- for (let networkId in allNetworkInfo) {
- if (allNetworkInfo.hasOwnProperty(networkId)) {
- let networkInfo = allNetworkInfo[networkId];
- if (networkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
- connected = true;
- break;
- }
- }
- }
-
- is(aAnyConnected, connected, "NetworkManager.allNetworkInfo any connected");
-}
-
-// Start test
-startTestBase(function() {
-
- let origApnSettings, origWifiEnabled;
- return Promise.resolve()
- .then(() => {
- origWifiEnabled = wifiManager.enabled;
- })
- .then(() => verifyInitialState())
- .then(() => getSettings(SETTINGS_KEY_DATA_APN_SETTINGS))
- .then(value => {
- origApnSettings = value;
- })
- .then(() => setEmulatorAPN())
- .then(() => setDataEnabledAndWait(true))
- .then(() => testAllNetworkInfo(true))
- .then(() => setDataEnabledAndWait(false))
- .then(() => testAllNetworkInfo(false))
- // Restore original apn settings and wifi state.
- .then(() => {
- if (origApnSettings) {
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, origApnSettings);
- }
- })
- .then(() => ensureWifiEnabled(origWifiEnabled));
-});
diff --git a/dom/system/gonk/tests/marionette/test_data_connection.js b/dom/system/gonk/tests/marionette/test_data_connection.js
deleted file mode 100644
index 5a53b1e5f..000000000
--- a/dom/system/gonk/tests/marionette/test_data_connection.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-function setEmulatorAPN() {
- let apn = [
- [{"carrier":"T-Mobile US",
- "apn":"epc.tmobile.com",
- "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types":["default","supl","mms","ims","dun", "fota"]}]
- ];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-// Test initial State
-function testInitialState() {
- log("= testInitialState =");
-
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- });
-}
-
-// Test default data Connection
-function testDefaultDataConnection() {
- log("= testDefaultDataConnection =");
-
- // Enable default data
- return setDataEnabledAndWait(true)
- // Disable default data
- .then(() => setDataEnabledAndWait(false));
-}
-
-// Test non default data connection
-function testNonDefaultDataConnection() {
- log("= testNonDefaultDataConnection =");
-
- function doTestNonDefaultDataConnection(type) {
- log("doTestNonDefaultDataConnection: " + type);
-
- return setupDataCallAndWait(type)
- .then(() => deactivateDataCallAndWait(type));
- }
-
- let currentApn;
- return getSettings(SETTINGS_KEY_DATA_APN_SETTINGS)
- .then(value => {
- currentApn = value;
- })
- .then(setEmulatorAPN)
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_MMS))
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_SUPL))
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_IMS))
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_DUN))
- .then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_FOTA))
- // Restore APN settings
- .then(() => setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, currentApn));
-}
-
-// Start test
-startTestBase(function() {
- return testInitialState()
- .then(() => testDefaultDataConnection())
- .then(() => testNonDefaultDataConnection());
-});
diff --git a/dom/system/gonk/tests/marionette/test_data_connection_proxy.js b/dom/system/gonk/tests/marionette/test_data_connection_proxy.js
deleted file mode 100644
index a99187538..000000000
--- a/dom/system/gonk/tests/marionette/test_data_connection_proxy.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-const HTTP_PROXY = "10.0.2.200";
-const HTTP_PROXY_PORT = "8080";
-const MANUAL_PROXY_CONFIGURATION = 1;
-
-// Test initial State
-function verifyInitialState() {
- log("= verifyInitialState =");
-
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- });
-}
-
-function setTestApn() {
- let apn = [
- [ {"carrier": "T-Mobile US",
- "apn": "epc.tmobile.com",
- "proxy": HTTP_PROXY,
- "port": HTTP_PROXY_PORT,
- "mmsc": "http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types": ["default","supl","mms"]} ]
- ];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-function waitForHttpProxyVerified(aShouldBeSet) {
- let TIME_OUT_VALUE = 20000;
-
- return new Promise(function(aResolve, aReject) {
- try {
- waitFor(aResolve, () => {
- let proxyType = SpecialPowers.getIntPref("network.proxy.type");
- let httpProxy = SpecialPowers.getCharPref("network.proxy.http");
- let sslProxy = SpecialPowers.getCharPref("network.proxy.ssl");
- let httpProxyPort = SpecialPowers.getIntPref("network.proxy.http_port");
- let sslProxyPort = SpecialPowers.getIntPref("network.proxy.ssl_port");
-
- if ((aShouldBeSet &&
- proxyType == MANUAL_PROXY_CONFIGURATION &&
- httpProxy == HTTP_PROXY &&
- sslProxy == HTTP_PROXY &&
- httpProxyPort == HTTP_PROXY_PORT &&
- sslProxyPort == HTTP_PROXY_PORT) ||
- (!aShouldBeSet && proxyType != MANUAL_PROXY_CONFIGURATION &&
- !httpProxy && !sslProxy && !httpProxyPort && !sslProxyPort)) {
- return true;
- }
-
- return false;
- }, TIME_OUT_VALUE);
- } catch(aError) {
- // Timed out.
- aReject(aError);
- }
- });
-}
-
-function testDefaultDataHttpProxy() {
- log("= testDefaultDataHttpProxy =");
-
- return setDataEnabledAndWait(true)
- .then(() => waitForHttpProxyVerified(true))
- .then(() => setDataEnabledAndWait(false))
- .then(() => waitForHttpProxyVerified(false));
-}
-
-function testNonDefaultDataHttpProxy(aType) {
- log("= testNonDefaultDataHttpProxy - " + aType + " =");
-
- return setupDataCallAndWait(aType)
- // Http proxy should not be set for non-default data connections.
- .then(() => waitForHttpProxyVerified(false))
- .then(() => deactivateDataCallAndWait(aType));
-}
-
-// Start test
-startTestBase(function() {
- let origApnSettings;
- return verifyInitialState()
- .then(() => getSettings(SETTINGS_KEY_DATA_APN_SETTINGS))
- .then(value => {
- origApnSettings = value;
- })
- .then(() => setTestApn())
- .then(() => testDefaultDataHttpProxy())
- .then(() => testNonDefaultDataHttpProxy(NETWORK_TYPE_MOBILE_MMS))
- .then(() => testNonDefaultDataHttpProxy(NETWORK_TYPE_MOBILE_SUPL))
- // Restore APN settings
- .then(() => setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, origApnSettings));
-});
diff --git a/dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js b/dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js
deleted file mode 100644
index e178b8b65..000000000
--- a/dom/system/gonk/tests/marionette/test_dsds_numRadioInterfaces.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_CONTEXT = "chrome";
-
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/systemlibs.js");
-
-const NS_RIL_CONTRACTID = "@mozilla.org/ril;1";
-
-const PROP_RO_MOZ_RIL_NUMCLIENTS = "ro.moz.ril.numclients";
-
-const PREF_RIL_NUM_RADIO_INTERFACES = "ril.numRadioInterfaces";
-
-ok(libcutils, "libcutils is available");
-
-var propNum = (function() {
- try {
- let numString = libcutils.property_get(PROP_RO_MOZ_RIL_NUMCLIENTS, "1");
- let num = parseInt(numString, 10);
- if (num >= 0) {
- return num;
- }
- } catch (e) {}
-})();
-
-log("Retrieved '" + PROP_RO_MOZ_RIL_NUMCLIENTS + "' = " + propNum);
-ok(propNum, PROP_RO_MOZ_RIL_NUMCLIENTS);
-
-var prefNum = Services.prefs.getIntPref(PREF_RIL_NUM_RADIO_INTERFACES);
-log("Retrieved '" + PREF_RIL_NUM_RADIO_INTERFACES + "' = " + prefNum);
-
-var ril = Cc[NS_RIL_CONTRACTID].getService(Ci.nsIRadioInterfaceLayer);
-ok(ril, "ril.constructor is " + ril.constructor);
-
-var ifaceNum = ril.numRadioInterfaces;
-log("Retrieved 'nsIRadioInterfaceLayer.numRadioInterfaces' = " + ifaceNum);
-
-is(propNum, prefNum);
-is(propNum, ifaceNum);
-
-finish();
diff --git a/dom/system/gonk/tests/marionette/test_fakevolume.js b/dom/system/gonk/tests/marionette/test_fakevolume.js
deleted file mode 100644
index 173f9ac11..000000000
--- a/dom/system/gonk/tests/marionette/test_fakevolume.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 10000;
-
-var Cc = SpecialPowers.Cc;
-var Ci = SpecialPowers.Ci;
-
-var volumeService = Cc["@mozilla.org/telephony/volume-service;1"].getService(Ci.nsIVolumeService);
-ok(volumeService, "Should have volume service");
-
-var volName = "fake";
-var mountPoint = "/data/fake/storage";
-volumeService.createFakeVolume(volName, mountPoint);
-
-var vol = volumeService.getVolumeByName(volName);
-ok(vol, "volume shouldn't be null");
-
-is(volName, vol.name, "name");
-is(mountPoint, vol.mountPoint, "moutnPoint");
-is(Ci.nsIVolume.STATE_MOUNTED, vol.state, "state");
-
-ok(vol.mountGeneration > 0, "mount generation should not be zero");
-
-finish();
diff --git a/dom/system/gonk/tests/marionette/test_geolocation.js b/dom/system/gonk/tests/marionette/test_geolocation.js
deleted file mode 100644
index 201c8b3e3..000000000
--- a/dom/system/gonk/tests/marionette/test_geolocation.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 10000;
-
-var geolocation = window.navigator.geolocation;
-ok(geolocation);
-
-var sample = [];
-var result = [];
-var wpid;
-
-/**
- * Grant special power to get the geolocation
- */
-SpecialPowers.addPermission("geolocation", true, document);
-
-/**
- * Disable wifi geolocation provider
- */
-wifiUri = SpecialPowers.getCharPref("geo.wifi.uri");
-SpecialPowers.setCharPref("geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs?action=stop-responding");
-
-/**
- * Helper that compares the geolocation against the web API.
- */
-function verifyLocation() {
-
- log("Sample:" + sample.join(','));
- log("Result:" + result.join(','));
-
- for (i in sample) {
- is(sample.pop(), result.pop());
- }
-
- window.setTimeout(cleanup, 0);
-}
-
-/**
- * Test story begins here.
- */
-function setup() {
- log("Providing initial setup: set geographic position watcher.");
-
-
- wpid = geolocation.watchPosition(function(position) {
- log("Position changes: (" + position.coords.latitude + "/" + position.coords.longitude + ")");
- result.push(""+position.coords.latitude + "/" + position.coords.longitude);
- });
-
- lat = 0;
- lon = 0;
-
- cmd = "geo fix " + lon + " " + lat;
- sample.push(lat+"/"+lon);
-
- runEmulatorCmd(cmd, function(result) {
- window.setTimeout(movePosition_1, 0);
- });
-}
-
-function movePosition_1() {
- log("Geolocation changes. Move to Position 1.");
-
- lat = 25;
- lon = 121.56499833333334;
-
- cmd = "geo fix " + lon + " " + lat;
- sample.push(lat+"/"+lon);
-
- runEmulatorCmd(cmd, function(result) {
- window.setTimeout(movePosition_2, 0);
- });
-}
-
-function movePosition_2() {
- log("Geolocation changes to a negative longitude. Move to Position 2.");
-
- lat = 37.393;
- lon = -122.08199833333335;
-
- cmd = "geo fix " + lon + " " + lat;
- sample.push(lat+"/"+lon);
-
- runEmulatorCmd(cmd, function(result) {
- window.setTimeout(movePosition_3, 0);
- });
-}
-
-function movePosition_3() {
- log("Geolocation changes with WatchPosition. Move to Position 3.");
-
- lat = -22;
- lon = -43;
-
- cmd = "geo fix " + lon + " " + lat;
- sample.push(lat+"/"+lon);
-
- geolocation.getCurrentPosition(function(position) {
- log("getCurrentPosition: Expected location: ("+lat+"/"+lon+"); Current location: (" + position.coords.latitude + "/" + position.coords.longitude + ")");
- is(lat, position.coords.latitude);
- is(lon, position.coords.longitude);
- });
-
- runEmulatorCmd(cmd, function(result) {
- window.setTimeout(verifyLocation, 0);
- });
-}
-
-function cleanup() {
- geolocation.clearWatch(wpid);
- SpecialPowers.removePermission("geolocation", document);
- SpecialPowers.setCharPref("geo.wifi.uri", wifiUri);
- finish();
-}
-
-setup();
diff --git a/dom/system/gonk/tests/marionette/test_multiple_data_connection.js b/dom/system/gonk/tests/marionette/test_multiple_data_connection.js
deleted file mode 100644
index 24abd4451..000000000
--- a/dom/system/gonk/tests/marionette/test_multiple_data_connection.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-// Must sync with hardware/ril/reference-ril/reference-ril.c
-const MAX_DATA_CONTEXTS = 4;
-
-function setEmulatorAPN() {
- // Use different apn for each network type.
- let apn = [[ { "carrier":"T-Mobile US",
- "apn":"epc1.tmobile.com",
- "types":["default"] },
- { "carrier":"T-Mobile US",
- "apn":"epc2.tmobile.com",
- "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types":["mms"] },
- { "carrier":"T-Mobile US",
- "apn":"epc3.tmobile.com",
- "types":["supl"] },
- { "carrier":"T-Mobile US",
- "apn":"epc4.tmobile.com",
- "types":["ims"] },
- { "carrier":"T-Mobile US",
- "apn":"epc5.tmobile.com",
- "types":["dun"] },
- { "carrier":"T-Mobile US",
- "apn":"epc6.tmobile.com",
- "types":["fota"] }]];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-// Test initial State
-function testInitialState() {
- log("= testInitialState =");
-
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- });
-}
-
-function testSetupConcurrentDataCalls() {
- log("= testSetupConcurrentDataCalls =");
-
- let promise = Promise.resolve();
- // Skip default mobile type.
- for (let i = 1; i < MAX_DATA_CONTEXTS; i++) {
- let type = networkTypes[i];
- promise = promise.then(() => setupDataCallAndWait(type));
- }
- return promise;
-}
-
-function testDeactivateConcurrentDataCalls() {
- log("= testDeactivateConcurrentDataCalls =");
-
- let promise = Promise.resolve();
- // Skip default mobile type.
- for (let i = 1; i < MAX_DATA_CONTEXTS; i++) {
- let type = networkTypes[i];
- promise = promise.then(() => deactivateDataCallAndWait(type));
- }
- return promise;
-}
-
-// Start test
-startTestBase(function() {
-
- let origApnSettings;
- return testInitialState()
- .then(() => getSettings(SETTINGS_KEY_DATA_APN_SETTINGS))
- .then(value => {
- origApnSettings = value;
- })
- .then(() => setEmulatorAPN())
- .then(() => setDataEnabledAndWait(true))
- .then(() => testSetupConcurrentDataCalls())
- .then(() => testDeactivateConcurrentDataCalls())
- .then(() => setDataEnabledAndWait(false))
- .then(() => {
- if (origApnSettings) {
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, origApnSettings);
- }
- });
-});
diff --git a/dom/system/gonk/tests/marionette/test_network_active_changed.js b/dom/system/gonk/tests/marionette/test_network_active_changed.js
deleted file mode 100644
index 5886f37ed..000000000
--- a/dom/system/gonk/tests/marionette/test_network_active_changed.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-var networkManager =
- Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
-ok(networkManager,
- "networkManager.constructor is " + networkManager.constructor);
-
-function testInitialState() {
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then((enabled) => {
- is(enabled, false, "data should be off by default");
- is(networkManager.activeNetworkInfo, null,
- "networkManager.activeNetworkInfo should be null by default");
- });
-}
-
-function testActiveNetworkChangedBySwitchingDataCall(aDataCallEnabled) {
- log("Test active network by switching dataCallEnabled to " + aDataCallEnabled);
-
- let promises = [];
- promises.push(waitForObserverEvent(TOPIC_NETWORK_ACTIVE_CHANGED));
- promises.push(setSettings(SETTINGS_KEY_DATA_ENABLED, aDataCallEnabled));
-
- return Promise.all(promises).then(function(results) {
- let subject = results[0];
-
- if (aDataCallEnabled) {
- ok(subject instanceof Ci.nsINetworkInfo,
- "subject should be an instance of nsINetworkInfo");
- ok(subject instanceof Ci.nsIRilNetworkInfo,
- "subject should be an instance of nsIRilNetworkInfo");
- is(subject.type, NETWORK_TYPE_MOBILE,
- "subject.type should be NETWORK_TYPE_MOBILE");
- }
-
- is(subject, networkManager.activeNetworkInfo,
- "subject should be equal with networkManager.activeNetworkInfo");
- });
-}
-
-// Start test
-startTestBase(function() {
- return testInitialState()
- // Test active network changed by enabling data call.
- .then(() => testActiveNetworkChangedBySwitchingDataCall(true))
- // Test active network changed by disabling data call.
- .then(() => testActiveNetworkChangedBySwitchingDataCall(false));
-});
diff --git a/dom/system/gonk/tests/marionette/test_network_interface_list_service.js b/dom/system/gonk/tests/marionette/test_network_interface_list_service.js
deleted file mode 100644
index 549940fa5..000000000
--- a/dom/system/gonk/tests/marionette/test_network_interface_list_service.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-function getNetworkInfo(aType) {
- let networkListService =
- Cc["@mozilla.org/network/interface-list-service;1"].
- getService(Ci.nsINetworkInterfaceListService);
- // Get all available interfaces
- let networkList = networkListService.getDataInterfaceList(0);
-
- // Try to get nsINetworkInterface for aType.
- let numberOfInterface = networkList.getNumberOfInterface();
- for (let i = 0; i < numberOfInterface; i++) {
- let info = networkList.getInterfaceInfo(i);
- if (info.type === aType) {
- return info;
- }
- }
-
- return null;
-}
-
-// Test getDataInterfaceList by enabling/disabling mobile data.
-function testGetDataInterfaceList(aMobileDataEnabled) {
- log("Test getDataInterfaceList with mobile data " +
- aMobileDataEnabled ? "enabled" : "disabled");
-
- return setDataEnabledAndWait(aMobileDataEnabled)
- .then(() => getNetworkInfo(NETWORK_TYPE_MOBILE))
- .then((networkInfo) => {
- if (!networkInfo) {
- ok(false, "Should get an valid nsINetworkInfo for mobile");
- return;
- }
-
- ok(networkInfo instanceof Ci.nsINetworkInfo,
- "networkInfo should be an instance of nsINetworkInfo");
-
- let ipAddresses = {};
- let prefixs = {};
- let numOfGateways = {};
- let numOfDnses = {};
- let numOfIpAddresses = networkInfo.getAddresses(ipAddresses, prefixs);
- let gateways = networkInfo.getGateways(numOfGateways);
- let dnses = networkInfo.getDnses(numOfDnses);
-
- if (aMobileDataEnabled) {
- // Mobile data is enabled.
- is(networkInfo.state, NETWORK_STATE_CONNECTED, "check state");
- ok(numOfIpAddresses > 0, "check number of ipAddresses");
- ok(ipAddresses.value.length > 0, "check ipAddresses.length");
- ok(prefixs.value.length > 0, "check prefixs.length");
- ok(numOfGateways.value > 0, "check number of gateways");
- ok(prefixs.value.length > 0, "check prefixs.length");
- ok(gateways.length > 0, "check gateways.length");
- ok(numOfDnses.value > 0, "check number of dnses");
- ok(dnses.length > 0, "check dnses.length");
- } else {
- // Mobile data is disabled.
- is(networkInfo.state, NETWORK_STATE_DISCONNECTED, "check state");
- is(numOfIpAddresses, 0, "check number of ipAddresses");
- is(ipAddresses.value.length, 0, "check ipAddresses.length");
- is(prefixs.value.length, 0, "check prefixs.length");
- is(numOfGateways.value, 0, "check number of gateways");
- is(prefixs.value.length, 0, "check prefixs.length");
- is(gateways.length, 0, "check gateways.length");
- is(numOfDnses.value, 0, "check number of dnses");
- is(dnses.length, 0, "check dnses.length");
- }
- });
-}
-
-// Start test
-startTestBase(function() {
- return Promise.resolve()
- // Test initial State
- .then(() => {
- log("Test initial state");
-
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Mobile data must be off");
- });
- })
-
- // Test getDataInterfaceList with mobile data enabled.
- .then(() => testGetDataInterfaceList(true))
-
- // Test getDataInterfaceList with mobile data disabled.
- .then(() => testGetDataInterfaceList(false));
-});
diff --git a/dom/system/gonk/tests/marionette/test_network_interface_mtu.js b/dom/system/gonk/tests/marionette/test_network_interface_mtu.js
deleted file mode 100644
index 679efe2ed..000000000
--- a/dom/system/gonk/tests/marionette/test_network_interface_mtu.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-const TEST_MTU1 = "1410";
-const TEST_MTU2 = "1440";
-
-function setEmulatorAPN() {
- let apn = [
- [ { "carrier":"T-Mobile US",
- "apn":"epc1.tmobile.com",
- "types":["default"],
- "mtu": TEST_MTU1 },
- { "carrier":"T-Mobile US",
- "apn":"epc2.tmobile.com",
- "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
- "types":["supl","mms","ims","dun", "fota"],
- "mtu": TEST_MTU2 } ]
- ];
-
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, apn);
-}
-
-function verifyInitialState() {
- // Data should be off before starting any test.
- return getSettings(SETTINGS_KEY_DATA_ENABLED)
- .then(value => {
- is(value, false, "Data must be off");
- });
-}
-
-function verifyMtu(aInterfaceName, aMtu) {
- return runEmulatorShellCmdSafe(['ip', 'link', 'show', 'dev', aInterfaceName])
- .then(aLines => {
- // Sample output:
- //
- // 4: rmnet0: <BROADCAST,MULTICAST> mtu 1410 qdisc pfifo_fast state DOWN mode DEFAULT qlen 1000
- // link/ether 52:54:00:12:34:58 brd ff:ff:ff:ff:ff:ff
- //
- let mtu;
- aLines.some(function (aLine) {
- let tokens = aLine.trim().split(/\s+/);
- let mtuIndex = tokens.indexOf('mtu');
- if (mtuIndex < 0 || mtuIndex + 1 >= tokens.length) {
- return false;
- }
-
- mtu = tokens[mtuIndex + 1];
- return true;
- });
-
- is(mtu, aMtu, aInterfaceName + "'s mtu.");
- });
-}
-
-function testDefaultDataCallMtu() {
- log("= testDefaultDataCallMtu =");
-
- return setDataEnabledAndWait(true)
- .then(aNetworkInfo => verifyMtu(aNetworkInfo.name, TEST_MTU1))
- .then(() => setDataEnabledAndWait(false));
-}
-
-function testNonDefaultDataCallMtu() {
- log("= testNonDefaultDataCallMtu =");
-
- function doTestNonDefaultDataCallMtu(aType) {
- log("doTestNonDefaultDataCallMtu: " + aType);
-
- return setupDataCallAndWait(aType)
- .then(aNetworkInfo => verifyMtu(aNetworkInfo.name, TEST_MTU2))
- .then(() => deactivateDataCallAndWait(aType));
- }
-
- return doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_MMS)
- .then(() => doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_SUPL))
- .then(() => doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_IMS))
- .then(() => doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_DUN))
- .then(() => doTestNonDefaultDataCallMtu(NETWORK_TYPE_MOBILE_FOTA));
-}
-
-// Start test
-startTestBase(function() {
- let origApnSettings;
- return verifyInitialState()
- .then(() => getSettings(SETTINGS_KEY_DATA_APN_SETTINGS))
- .then(value => {
- origApnSettings = value;
- })
- .then(() => setEmulatorAPN())
- .then(() => testDefaultDataCallMtu())
- .then(() => testNonDefaultDataCallMtu())
- .then(() => {
- if (origApnSettings) {
- return setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, origApnSettings);
- }
- });
-});
diff --git a/dom/system/gonk/tests/marionette/test_ril_code_quality.py b/dom/system/gonk/tests/marionette/test_ril_code_quality.py
deleted file mode 100644
index d741d8a2e..000000000
--- a/dom/system/gonk/tests/marionette/test_ril_code_quality.py
+++ /dev/null
@@ -1,371 +0,0 @@
-"""
-The test performs the static code analysis check by JSHint.
-
-Target js files:
-- RadioInterfaceLayer.js
-- ril_worker.js
-- ril_consts.js
-
-If the js file contains the line of 'importScript()' (Ex: ril_worker.js), the
-test will perform a special merge step before excuting JSHint.
-
-Ex: Script A
---------------------------------
-importScripts('Script B')
-...
---------------------------------
-
-We merge these two scripts into one by the following way.
-
---------------------------------
-[Script B (ex: ril_consts.js)]
-(function(){ [Script A (ex: ril_worker.js)]
-})();
---------------------------------
-
-Script A (ril_worker.js) runs global strict mode.
-Script B (ril_consts.js) not.
-
-The above merge way ensures the correct scope of 'strict mode.'
-"""
-
-import bisect
-import inspect
-import os
-import os.path
-import re
-import unicodedata
-
-from marionette_harness import MarionetteTestCase
-
-
-class StringUtility:
-
- """A collection of some string utilities."""
-
- @staticmethod
- def find_match_lines(lines, pattern):
- """Return a list of lines that contains given pattern."""
- return [line for line in lines if pattern in line]
-
- @staticmethod
- def remove_non_ascii(data):
- """Remove non ascii characters in data and return it as new string."""
- if type(data).__name__ == 'unicode':
- data = unicodedata.normalize(
- 'NFKD', data).encode('ascii', 'ignore')
- return data
-
- @staticmethod
- def auto_close(lines):
- """Ensure every line ends with '\n'."""
- if lines and not lines[-1].endswith('\n'):
- lines[-1] += '\n'
- return lines
-
- @staticmethod
- def auto_wrap_strict_mode(lines):
- """Wrap by function scope if lines contain 'use strict'."""
- if StringUtility.find_match_lines(lines, 'use strict'):
- lines[0] = '(function(){' + lines[0]
- lines.append('})();\n')
- return lines
-
- @staticmethod
- def get_imported_list(lines):
- """Get a list of imported items."""
- return [item
- for line in StringUtility.find_match_lines(lines, 'importScripts')
- for item in StringUtility._get_imported_list_from_line(line)]
-
- @staticmethod
- def _get_imported_list_from_line(line):
- """Extract all items from 'importScripts(...)'.
-
- importScripts("ril_consts.js", "systemlibs.js")
- => ['ril_consts', 'systemlibs.js']
-
- """
- pattern = re.compile(r'\s*importScripts\((.*)\)')
- m = pattern.match(line)
- if not m:
- raise Exception('Parse importScripts error.')
- return [name.translate(None, '\' "') for name in m.group(1).split(',')]
-
-
-class ResourceUriFileReader:
-
- """Handle the process of reading the source code from system."""
-
- URI_PREFIX = 'resource://gre/'
- URI_PATH = {
- 'RadioInterfaceLayer.js': 'components/RadioInterfaceLayer.js',
- 'ril_worker.js': 'modules/ril_worker.js',
- 'ril_consts.js': 'modules/ril_consts.js',
- 'systemlibs.js': 'modules/systemlibs.js',
- 'worker_buf.js': 'modules/workers/worker_buf.js',
- }
-
- CODE_OPEN_CHANNEL_BY_URI = '''
- var Cc = Components.classes;
- var Ci = Components.interfaces;
- var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
- var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
- global.uri = '%(uri)s';
- global.channel = ios.newChannel2(global.uri,
- null,
- null,
- null, // aLoadingNode
- secMan.getSystemPrincipal(),
- null, // aTriggeringPrincipal
- Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
- Ci.nsIContentPolicy.TYPE_OTHER);
- '''
-
- CODE_GET_SPEC = '''
- return global.channel.URI.spec;
- '''
-
- CODE_READ_CONTENT = '''
- var Cc = Components.classes;
- var Ci = Components.interfaces;
-
- var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
- var inputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
-
- var jaruri = global.channel.URI.QueryInterface(Ci.nsIJARURI);
- var file = jaruri.JARFile.QueryInterface(Ci.nsIFileURL).file;
- var entry = jaruri.JAREntry;
- zipReader.open(file);
- inputStream.init(zipReader.getInputStream(entry));
- var content = inputStream.read(inputStream.available());
- inputStream.close();
- zipReader.close();
- return content;
- '''
-
- @classmethod
- def get_uri(cls, filename):
- """Convert filename to URI in system."""
- if filename.startswith(cls.URI_PREFIX):
- return filename
- else:
- return cls.URI_PREFIX + cls.URI_PATH[filename]
-
- def __init__(self, marionette):
- self.runjs = lambda x: marionette.execute_script(x,
- new_sandbox=False,
- sandbox='system')
-
- def read_file(self, filename):
- """Read file and return the contents as string."""
- content = self._read_uri(self.get_uri(filename))
- content = content.replace('"use strict";', '')
- return StringUtility.remove_non_ascii(content)
-
- def _read_uri(self, uri):
- """Read URI in system and return the contents as string."""
- # Open the uri as a channel.
- self.runjs(self.CODE_OPEN_CHANNEL_BY_URI % {'uri': uri})
-
- # Make sure spec is a jar uri, and not recursive.
- # Ex: 'jar:file:///system/b2g/omni.ja!/modules/ril_worker.js'
- #
- # For simplicity, we don't handle other special cases in this test.
- # If B2G build system changes in the future, such as put the jar in
- # another jar, the test case will fail.
- spec = self.runjs(self.CODE_GET_SPEC)
- if (not spec.startswith('jar:file://')) or (spec.count('jar:') != 1):
- raise Exception('URI resolve error')
-
- # Read the content from channel.
- content = self.runjs(self.CODE_READ_CONTENT)
- return content
-
-
-class JSHintEngine:
-
- """Invoke jshint script on system."""
-
- CODE_INIT_JSHINT = '''
- %(script)s;
- global.JSHINT = JSHINT;
- global.options = JSON.parse(%(config_string)s);
- global.globals = global.options.globals;
- delete global.options.globals;
- '''
-
- CODE_RUN_JSHINT = '''
- global.script = %(code)s;
- return global.JSHINT(global.script, global.options, global.globals);
- '''
-
- CODE_GET_JSHINT_ERROR = '''
- return global.JSHINT.errors;
- '''
-
- def __init__(self, marionette, script, config):
- # Remove single line comment in config.
- config = '\n'.join([line.partition('//')[0]
- for line in config.splitlines()])
-
- # Set global (JSHINT, options, global) in js environment.
- self.runjs = lambda x: marionette.execute_script(x,
- new_sandbox=False,
- sandbox='system')
- self.runjs(self.CODE_INIT_JSHINT %
- {'script': script, 'config_string': repr(config)})
-
- def run(self, code, filename=''):
- """Excute JShint check for the given code."""
- check_pass = self.runjs(self.CODE_RUN_JSHINT % {'code': repr(code)})
- errors = self.runjs(self.CODE_GET_JSHINT_ERROR)
- return check_pass, self._get_error_messages(errors, filename)
-
- def _get_error_messages(self, errors, filename=''):
- """
- Convert an error object to a list of readable string.
-
- [{"a": null, "c": null, "code": "W033", "d": null, "character": 6,
- "evidence": "var a", "raw": "Missing semicolon.",
- "reason": "Missing semicolon.", "b": null, "scope": "(main)", "line": 1,
- "id": "(error)"}]
- => line 1, col 6, Missing semicolon.
-
- """
- LINE, COL, REASON = u'line', u'character', u'reason'
- return ["%s: line %s, col %s, %s" %
- (filename, error[LINE], error[COL], error[REASON])
- for error in errors if error]
-
-
-class Linter:
-
- """Handle the linting related process."""
-
- def __init__(self, code_reader, jshint, reporter=None):
- """Set the linter with code_reader, jshint engine, and reporter.
-
- Should have following functionality.
- - code_reader.read_file(filename)
- - jshint.run(code, filename)
- - reporter([...])
-
- """
- self.code_reader = code_reader
- self.jshint = jshint
- if reporter is None:
- self.reporter = lambda x: '\n'.join(x)
- else:
- self.reporter = reporter
-
- def lint_file(self, filename):
- """Lint the file and return (pass, error_message)."""
- # Get code contents.
- code = self.code_reader.read_file(filename)
- lines = code.splitlines()
- import_list = StringUtility.get_imported_list(lines)
- if not import_list:
- check_pass, error_message = self.jshint.run(code, filename)
- else:
- newlines, info = self._merge_multiple_codes(filename, import_list)
- # Each line of |newlines| contains '\n'.
- check_pass, error_message = self.jshint.run(''.join(newlines))
- error_message = self._convert_merged_result(error_message, info)
- # Only keep errors for this file.
- error_message = [line for line in error_message
- if line.startswith(filename)]
- check_pass = (len(error_message) == 0)
- return check_pass, self.reporter(error_message)
-
- def _merge_multiple_codes(self, filename, import_list):
- """Merge multiple codes from filename and import_list."""
- dirname, filename = os.path.split(filename)
- dst_line = 1
- dst_results = []
- info = []
-
- # Put the imported script first, and then the original script.
- for f in import_list + [filename]:
- filepath = os.path.join(dirname, f)
-
- # Maintain a mapping table.
- # New line number after merge => original file and line number.
- info.append((dst_line, filepath, 1))
- try:
- code = self.code_reader.read_file(filepath)
- lines = code.splitlines(True) # Keep '\n'.
- src_results = StringUtility.auto_wrap_strict_mode(
- StringUtility.auto_close(lines))
- dst_results.extend(src_results)
- dst_line += len(src_results)
- except:
- info.pop()
- return dst_results, info
-
- def _convert_merged_result(self, error_lines, line_info):
- pattern = re.compile(r'(.*): line (\d+),(.*)')
- start_line = [info[0] for info in line_info]
- new_result_lines = []
- for line in error_lines:
- m = pattern.match(line)
- if not m:
- continue
-
- line_number, remain = int(m.group(2)), m.group(3)
-
- # [1, 2, 7, 8]
- # ^ for 7, pos = 3
- # ^ for 6, pos = 2
- pos = bisect.bisect_right(start_line, line_number)
- dst_line, name, src_line = line_info[pos - 1]
- real_line_number = line_number - dst_line + src_line
- new_result_lines.append(
- "%s: line %s,%s" % (name, real_line_number, remain))
- return new_result_lines
-
-
-class TestRILCodeQuality(MarionetteTestCase):
-
- JSHINT_PATH = 'ril_jshint/jshint.js'
- JSHINTRC_PATH = 'ril_jshint/jshintrc'
-
- def _read_local_file(self, filepath):
- """Read file content from local (folder of this test case)."""
- test_dir = os.path.dirname(inspect.getfile(TestRILCodeQuality))
- return open(os.path.join(test_dir, filepath)).read()
-
- def _get_extended_error_message(self, error_message):
- return '\n'.join(['See errors below and more information in Bug 880643',
- '\n'.join(error_message),
- 'See errors above and more information in Bug 880643'])
-
- def _check(self, filename):
- check_pass, error_message = self.linter.lint_file(filename)
- self.assertTrue(check_pass, error_message)
-
- def setUp(self):
- MarionetteTestCase.setUp(self)
- self.linter = Linter(
- ResourceUriFileReader(self.marionette),
- JSHintEngine(self.marionette,
- self._read_local_file(self.JSHINT_PATH),
- self._read_local_file(self.JSHINTRC_PATH)),
- self._get_extended_error_message)
-
- def tearDown(self):
- MarionetteTestCase.tearDown(self)
-
- def test_RadioInterfaceLayer(self):
- self._check('RadioInterfaceLayer.js')
-
- # Bug 936504. Disable the test for 'ril_worker.js'. It sometimes runs very
- # slow and causes the timeout fail on try server.
- #def test_ril_worker(self):
- # self._check('ril_worker.js')
-
- def test_ril_consts(self):
- self._check('ril_consts.js')
-
- def test_worker_buf(self):
- self._check('worker_buf.js')
diff --git a/dom/system/gonk/tests/marionette/test_screen_state.js b/dom/system/gonk/tests/marionette/test_screen_state.js
deleted file mode 100644
index 2281412d5..000000000
--- a/dom/system/gonk/tests/marionette/test_screen_state.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 10000;
-
-var Services = SpecialPowers.Services;
-
-function testScreenState(on, expected, msg) {
- // send event to RadioInterface
- Services.obs.notifyObservers(null, 'screen-state-changed', on);
- // maybe rild/qemu needs some time to process the event
- window.setTimeout(function() {
- runEmulatorCmd('gsm report creg', function(result) {
- is(result.pop(), 'OK', '\'gsm report creg\' successful');
- ok(result.indexOf(expected) !== -1, msg);
- runNextTest();
- })}, 1000);
-}
-
-function testScreenStateDisabled() {
- testScreenState('off', '+CREG: 1', 'screen is disabled');
-}
-
-function testScreenStateEnabled() {
- testScreenState('on', '+CREG: 2', 'screen is enabled');
-}
-
-var tests = [
- testScreenStateDisabled,
- testScreenStateEnabled
-];
-
-function runNextTest() {
- let test = tests.shift();
- if (!test) {
- cleanUp();
- return;
- }
-
- test();
-}
-
-function cleanUp() {
- finish();
-}
-
-runNextTest();
diff --git a/dom/system/gonk/tests/marionette/test_timezone_changes.js b/dom/system/gonk/tests/marionette/test_timezone_changes.js
deleted file mode 100644
index 11dbaec5a..000000000
--- a/dom/system/gonk/tests/marionette/test_timezone_changes.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-function init() {
- let promises = [];
-
- /*
- * The initial timezone of the emulator could be anywhere, depends the host
- * machine. Ensure resetting it to UTC before testing.
- */
- promises.push(runEmulatorCmdSafe('gsm timezone 0'));
- promises.push(new Promise((aResolve, aReject) => {
- waitFor(aResolve, () => {
- return new Date().getTimezoneOffset() === 0;
- });
- }));
-
- return Promise.all(promises);
-}
-
-function paddingZeros(aNumber, aLength) {
- let str = '' + aNumber;
- while (str.length < aLength) {
- str = '0' + str;
- }
-
- return str;
-}
-
-function verifyDate(aTestDate, aUTCOffsetDate) {
- // Verify basic properties.
- is(aUTCOffsetDate.getUTCFullYear(), aTestDate.getFullYear(), 'year');
- is(aUTCOffsetDate.getUTCMonth(), aTestDate.getMonth(), 'month');
- is(aUTCOffsetDate.getUTCDate(), aTestDate.getDate(), 'date');
- is(aUTCOffsetDate.getUTCHours(), aTestDate.getHours(), 'hours');
- is(aUTCOffsetDate.getUTCMinutes(), aTestDate.getMinutes(), 'minutes');
- is(aUTCOffsetDate.getUTCMilliseconds(), aTestDate.getMilliseconds(), 'milliseconds');
-
- // Ensure toLocaleString also uses correct timezone.
- // It uses ICU's timezone instead of the offset calculated from gecko prtime.
- let expectedDateString =
- paddingZeros(aUTCOffsetDate.getUTCMonth() + 1, 2) + '/' +
- paddingZeros(aUTCOffsetDate.getUTCDate(), 2);
- let dateString = aTestDate.toLocaleString('en-US', {
- month: '2-digit',
- day: '2-digit',
- });
- let expectedTimeString =
- paddingZeros(aUTCOffsetDate.getUTCHours(), 2) + ':' +
- paddingZeros(aUTCOffsetDate.getUTCMinutes(), 2);
- let timeString = aTestDate.toLocaleString('en-US', {
- hour12: false,
- hour: '2-digit',
- minute: '2-digit'
- });
-
- is(expectedDateString, dateString, 'dateString');
- is(expectedTimeString, timeString, 'timeString');
-}
-
-function waitForTimezoneUpdate(aTzOffset,
- aTestDateInMillis = 86400000, // Use 'UTC 00:00:00, 2nd of Jan, 1970' by default.
- aTransTzOffset, aTransTestDateInMillis) {
- return new Promise(function(aResolve, aReject) {
- window.addEventListener('moztimechange', function onevent(aEvent) {
- // Since there could be multiple duplicate moztimechange event, wait until
- // timezone is actually changed to expected value before removing the
- // listener.
- let testDate = new Date(aTestDateInMillis);
- if (testDate.getTimezoneOffset() === aTzOffset) {
- window.removeEventListener('moztimechange', onevent);
-
- // The UTC time of offsetDate is the same as the expected local time of
- // testDate. We'll use it to verify the values.
- let offsetDate = new Date(aTestDateInMillis - aTzOffset * 60 * 1000);
- verifyDate(testDate, offsetDate);
-
- // Verify transition time if given.
- if (aTransTzOffset !== undefined) {
- testDate = new Date(aTransTestDateInMillis);
- is(testDate.getTimezoneOffset(), aTransTzOffset);
-
- // Verify transition date.
- offsetDate = new Date(aTransTestDateInMillis - aTransTzOffset * 60 * 1000);
- verifyDate(testDate, offsetDate);
- }
-
- aResolve(aEvent);
- }
- });
- });
-}
-
-function testChangeNitzTimezone(aTzDiff) {
- let promises = [];
-
- // aTzOffset should be the expected value for getTimezoneOffset().
- // Note that getTimezoneOffset() is not so straightforward,
- // it values (UTC - localtime), so UTC+08:00 returns -480.
- promises.push(waitForTimezoneUpdate(-aTzDiff * 15));
- promises.push(runEmulatorCmdSafe('gsm timezone ' + aTzDiff));
-
- return Promise.all(promises);
-}
-
-function testChangeOlsonTimezone(aOlsonTz, aTzOffset, aTestDateInMillis,
- aTransTzOffset, aTransTestDateInMillis) {
- let promises = [];
-
- promises.push(waitForTimezoneUpdate(aTzOffset, aTestDateInMillis,
- aTransTzOffset, aTransTestDateInMillis));
- promises.push(setSettings('time.timezone', aOlsonTz));
-
- return Promise.all(promises);
-}
-
-// Start test
-startTestBase(function() {
- return init()
- .then(() => testChangeNitzTimezone(36)) // UTC+09:00
- .then(() => testChangeOlsonTimezone('America/New_York',
- 300, 1446357600000, // 2015/11/01 02:00 UTC-04:00 => 01:00 UTC-05:00 (EST)
- 240, 1425798000000)) // 2015/03/08 02:00 UTC-05:00 => 03:00 UTC-04:00 (EDT)
- .then(() => testChangeNitzTimezone(-22)) // UTC-05:30
- .then(() => testChangeNitzTimezone(51)) // UTC+12:45
- .then(() => testChangeOlsonTimezone('Australia/Adelaide',
- -570, 1428165000000, // 2015/04/05 03:00 UTC+10:30 => 02:00 UTC+09:30 (ACST)
- -630, 1443889800000)) // 2015/10/04 02:00 UTC+09:30 => 03:00 UTC+10:30 (ACDT)
- .then(() => testChangeNitzTimezone(-38)) // UTC-09:30
- .then(() => testChangeNitzTimezone(0)) // UTC
- .then(() => runEmulatorCmdSafe('gsm timezone auto'));
-});
diff --git a/dom/system/gonk/tests/test_ril_system_messenger.js b/dom/system/gonk/tests/test_ril_system_messenger.js
deleted file mode 100644
index a588d0ddb..000000000
--- a/dom/system/gonk/tests/test_ril_system_messenger.js
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-var RIL = {};
-Cu.import("resource://gre/modules/ril_consts.js", RIL);
-
-XPCOMUtils.defineLazyServiceGetter(this, "gStkCmdFactory",
- "@mozilla.org/icc/stkcmdfactory;1",
- "nsIStkCmdFactory");
-
-/**
- * Name space for RILSystemMessenger.jsm. Only initialized after first call to
- * newRILSystemMessenger.
- */
-var RSM;
-
-var gReceivedMsgType = null;
-var gReceivedMessage = null;
-
-/**
- * Create a new RILSystemMessenger instance.
- *
- * @return a RILSystemMessenger instance.
- */
-function newRILSystemMessenger() {
- if (!RSM) {
- RSM = Cu.import("resource://gre/modules/RILSystemMessenger.jsm", {});
- equal(typeof RSM.RILSystemMessenger, "function", "RSM.RILSystemMessenger");
- }
-
- let rsm = new RSM.RILSystemMessenger();
- rsm.broadcastMessage = (aType, aMessage) => {
- gReceivedMsgType = aType;
- gReceivedMessage = aMessage;
- };
-
- rsm.createCommandMessage = (aStkProactiveCmd) => {
- return gStkCmdFactory.createCommandMessage(aStkProactiveCmd);
- };
-
- return rsm;
-}
-
-function equal_received_system_message(aType, aMessage) {
- equal(aType, gReceivedMsgType);
- deepEqual(aMessage, gReceivedMessage);
- gReceivedMsgType = null;
- gReceivedMessage = null;
-}
-
-/**
- * Verify that each nsIXxxMessenger could be retrieved.
- */
-function run_test() {
- let telephonyMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsITelephonyMessenger);
-
- let smsMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsISmsMessenger);
-
- let cellbroadcastMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsICellbroadcastMessenger);
-
- let mobileConnectionMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsIMobileConnectionMessenger);
-
- let iccMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
- .getService(Ci.nsIIccMessenger);
-
- ok(telephonyMessenger !== null, "Get TelephonyMessenger.");
- ok(smsMessenger != null, "Get SmsMessenger.");
- ok(cellbroadcastMessenger != null, "Get CellbroadcastMessenger.");
- ok(mobileConnectionMessenger != null, "Get MobileConnectionMessenger.");
- ok(iccMessenger != null, "Get IccMessenger.");
-
- run_next_test();
-}
-
-/**
- * Verify RILSystemMessenger.notifyNewCall()
- */
-add_test(function test_telephony_messenger_notify_new_call() {
- let messenger = newRILSystemMessenger();
-
- messenger.notifyNewCall();
- equal_received_system_message("telephony-new-call", {});
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyCallEnded()
- */
-add_test(function test_telephony_messenger_notify_call_ended() {
- let messenger = newRILSystemMessenger();
-
- messenger.notifyCallEnded(1,
- "+0987654321",
- null,
- true,
- 500,
- false,
- true);
-
- equal_received_system_message("telephony-call-ended", {
- serviceId: 1,
- number: "+0987654321",
- emergency: true,
- duration: 500,
- direction: "incoming",
- hangUpLocal: true
- });
-
- // Verify 'optional' parameter of secondNumber.
- messenger.notifyCallEnded(1,
- "+0987654321",
- "+1234567890",
- true,
- 500,
- true,
- false);
-
- equal_received_system_message("telephony-call-ended", {
- serviceId: 1,
- number: "+0987654321",
- emergency: true,
- duration: 500,
- direction: "outgoing",
- hangUpLocal: false,
- secondNumber: "+1234567890"
- });
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifySms()
- */
-add_test(function test_sms_messenger_notify_sms() {
- let messenger = newRILSystemMessenger();
- let timestamp = Date.now();
- let sentTimestamp = timestamp + 100;
- let deliveryTimestamp = sentTimestamp + 100;
-
- // Verify 'sms-received' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_RECEIVED,
- 1,
- 2,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_RECEIVED,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_SUCCESS,
- "+0987654321",
- null,
- "Incoming message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_CLASS_2,
- timestamp,
- sentTimestamp,
- 0,
- false);
-
- equal_received_system_message("sms-received", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 1,
- threadId: 2,
- delivery: "received",
- deliveryStatus: "success",
- sender: "+0987654321",
- receiver: null,
- body: "Incoming message",
- messageClass: "class-2",
- timestamp: timestamp,
- sentTimestamp: sentTimestamp,
- deliveryTimestamp: 0,
- read: false
- });
-
- // Verify 'sms-sent' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_SENT,
- 3,
- 4,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_SENT,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_PENDING,
- null,
- "+0987654321",
- "Outgoing message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- 0,
- 0,
- true);
-
- equal_received_system_message("sms-sent", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 3,
- threadId: 4,
- delivery: "sent",
- deliveryStatus: "pending",
- sender: null,
- receiver: "+0987654321",
- body: "Outgoing message",
- messageClass: "normal",
- timestamp: timestamp,
- sentTimestamp: 0,
- deliveryTimestamp: 0,
- read: true
- });
-
- // Verify 'sms-delivery-success' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_DELIVERY_SUCCESS,
- 5,
- 6,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_SENT,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_SUCCESS,
- null,
- "+0987654321",
- "Outgoing message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- 0,
- deliveryTimestamp,
- true);
-
- equal_received_system_message("sms-delivery-success", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 5,
- threadId: 6,
- delivery: "sent",
- deliveryStatus: "success",
- sender: null,
- receiver: "+0987654321",
- body: "Outgoing message",
- messageClass: "normal",
- timestamp: timestamp,
- sentTimestamp: 0,
- deliveryTimestamp: deliveryTimestamp,
- read: true
- });
-
- // Verify 'sms-failed' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_SENT_FAILED,
- 7,
- 8,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_ERROR,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_ERROR,
- null,
- "+0987654321",
- "Outgoing message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- 0,
- 0,
- true);
-
- equal_received_system_message("sms-failed", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 7,
- threadId: 8,
- delivery: "error",
- deliveryStatus: "error",
- sender: null,
- receiver: "+0987654321",
- body: "Outgoing message",
- messageClass: "normal",
- timestamp: timestamp,
- sentTimestamp: 0,
- deliveryTimestamp: 0,
- read: true
- });
-
- // Verify 'sms-delivery-error' system message.
- messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_DELIVERY_ERROR,
- 9,
- 10,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_SENT,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_ERROR,
- null,
- "+0987654321",
- "Outgoing message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- 0,
- 0,
- true);
-
- equal_received_system_message("sms-delivery-error", {
- iccId: "99887766554433221100",
- type: "sms",
- id: 9,
- threadId: 10,
- delivery: "sent",
- deliveryStatus: "error",
- sender: null,
- receiver: "+0987654321",
- body: "Outgoing message",
- messageClass: "normal",
- timestamp: timestamp,
- sentTimestamp: 0,
- deliveryTimestamp: 0,
- read: true
- });
-
- // Verify the protection of invalid nsISmsMessenger.NOTIFICATION_TYPEs.
- try {
- messenger.notifySms(5,
- 1,
- 2,
- "99887766554433221100",
- Ci.nsISmsService.DELIVERY_TYPE_RECEIVED,
- Ci.nsISmsService.DELIVERY_STATUS_TYPE_SUCCESS,
- "+0987654321",
- null,
- "Incoming message",
- Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
- timestamp,
- sentTimestamp,
- 0,
- false);
- ok(false, "Failed to verify the protection of invalid nsISmsMessenger.NOTIFICATION_TYPE!");
- } catch (e) {}
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyCbMessageReceived()
- */
-add_test(function test_cellbroadcast_messenger_notify_cb_message_received() {
- let messenger = newRILSystemMessenger();
- let timestamp = Date.now();
-
- // Verify ETWS
- messenger.notifyCbMessageReceived(0,
- Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_CELL_IMMEDIATE,
- 256,
- 4352,
- null,
- null,
- Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_NORMAL,
- timestamp,
- Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID,
- true,
- Ci.nsICellBroadcastService.GSM_ETWS_WARNING_EARTHQUAKE,
- false,
- true);
- equal_received_system_message("cellbroadcast-received", {
- serviceId: 0,
- gsmGeographicalScope: "cell-immediate",
- messageCode: 256,
- messageId: 4352,
- language: null,
- body: null,
- messageClass: "normal",
- timestamp: timestamp,
- cdmaServiceCategory: null,
- etws: {
- warningType: "earthquake",
- emergencyUserAlert: false,
- popup: true
- }
- });
-
- // Verify Normal CB Message
- messenger.notifyCbMessageReceived(1,
- Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_PLMN,
- 0,
- 50,
- "en",
- "The quick brown fox jumps over the lazy dog",
- Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_NORMAL,
- timestamp,
- Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID,
- false,
- Ci.nsICellBroadcastService.GSM_ETWS_WARNING_INVALID,
- false,
- false);
- equal_received_system_message("cellbroadcast-received", {
- serviceId: 1,
- gsmGeographicalScope: "plmn",
- messageCode: 0,
- messageId: 50,
- language: "en",
- body: "The quick brown fox jumps over the lazy dog",
- messageClass: "normal",
- timestamp: timestamp,
- cdmaServiceCategory: null,
- etws: null
- });
-
- // Verify CB Message with ETWS Info
- messenger.notifyCbMessageReceived(0,
- Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_LOCATION_AREA,
- 0,
- 4354,
- "en",
- "Earthquake & Tsunami Warning!",
- Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_0,
- timestamp,
- Ci.nsICellBroadcastService.CDMA_SERVICE_CATEGORY_INVALID,
- true,
- Ci.nsICellBroadcastService.GSM_ETWS_WARNING_EARTHQUAKE_TSUNAMI,
- true,
- false);
- equal_received_system_message("cellbroadcast-received", {
- serviceId: 0,
- gsmGeographicalScope: "location-area",
- messageCode: 0,
- messageId: 4354,
- language: "en",
- body: "Earthquake & Tsunami Warning!",
- messageClass: "class-0",
- timestamp: timestamp,
- cdmaServiceCategory: null,
- etws: {
- warningType: "earthquake-tsunami",
- emergencyUserAlert: true,
- popup: false
- }
- });
-
- // Verify CDMA CB Message
- messenger.notifyCbMessageReceived(0,
- Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_INVALID,
- 0,
- 0,
- null,
- "CDMA CB Message",
- Ci.nsICellBroadcastService.GSM_MESSAGE_CLASS_NORMAL,
- timestamp,
- 512,
- false,
- Ci.nsICellBroadcastService.GSM_ETWS_WARNING_INVALID,
- false,
- false);
- equal_received_system_message("cellbroadcast-received", {
- serviceId: 0,
- gsmGeographicalScope: null,
- messageCode: 0,
- messageId: 0,
- language: null,
- body: "CDMA CB Message",
- messageClass: "normal",
- timestamp: timestamp,
- cdmaServiceCategory: 512,
- etws: null
- });
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyUssdReceived()
- */
-add_test(function test_mobileconnection_notify_ussd_received() {
- let messenger = newRILSystemMessenger();
-
- messenger.notifyUssdReceived(0, "USSD Message", false);
-
- equal_received_system_message("ussd-received", {
- serviceId: 0,
- message: "USSD Message",
- sessionEnded: false
- });
-
- messenger.notifyUssdReceived(1, "USSD Message", true);
-
- equal_received_system_message("ussd-received", {
- serviceId: 1,
- message: "USSD Message",
- sessionEnded: true
- });
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyCdmaInfoRecXXX()
- */
-add_test(function test_mobileconnection_notify_cdma_info() {
- let messenger = newRILSystemMessenger();
-
- messenger.notifyCdmaInfoRecDisplay(0, "CDMA Display Info");
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- display: "CDMA Display Info"
- });
-
- messenger.notifyCdmaInfoRecCalledPartyNumber(1, 1, 2, "+0987654321", 3, 4);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 1,
- calledNumber: {
- type: 1,
- plan: 2,
- number: "+0987654321",
- pi: 3,
- si: 4
- }
- });
-
- messenger.notifyCdmaInfoRecCallingPartyNumber(0, 5, 6, "+1234567890", 7, 8);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- callingNumber: {
- type: 5,
- plan: 6,
- number: "+1234567890",
- pi: 7,
- si: 8
- }
- });
-
- messenger.notifyCdmaInfoRecConnectedPartyNumber(1, 4, 3, "+56473839201", 2, 1);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 1,
- connectedNumber: {
- type: 4,
- plan: 3,
- number: "+56473839201",
- pi: 2,
- si: 1
- }
- });
-
- messenger.notifyCdmaInfoRecSignal(0, 1, 2, 3);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- signal: {
- type: 1,
- alertPitch: 2,
- signal: 3
- }
- });
-
- messenger.notifyCdmaInfoRecRedirectingNumber(1, 8, 7, "+1029384756", 6, 5, 4);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 1,
- redirect: {
- type: 8,
- plan: 7,
- number: "+1029384756",
- pi: 6,
- si: 5,
- reason: 4
- }
- });
-
- messenger.notifyCdmaInfoRecLineControl(0, 1, 0, 1, 255);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- lineControl: {
- polarityIncluded: 1,
- toggle: 0,
- reverse: 1,
- powerDenial: 255
- }
- });
-
- messenger.notifyCdmaInfoRecClir(1, 256);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 1,
- clirCause: 256
- });
-
- messenger.notifyCdmaInfoRecAudioControl(0, 255, -1);
-
- equal_received_system_message("cdma-info-rec-received", {
- clientId: 0,
- audioControl: {
- upLink: 255,
- downLink: -1
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Error Handling of StkProactiveCmdFactory.createCommand()
- */
-add_test(function test_icc_stk_cmd_factory_create_command_error() {
- let messenger = newRILSystemMessenger();
-
- // Verify the protection of invalid typeOfCommand.
- try {
- gStkCmdFactory.createCommand({
- commandNumber: 0,
- typeOfCommand: RIL.STK_CMD_MORE_TIME, // Invalid TypeOfCommand
- commandQualifier: 0x00
- });
-
- ok(false, "Failed to verify the protection of createCommand()!");
- } catch (e) {
- ok(e.message.indexOf("Unknown Command Type") !== -1,
- "Invalid typeOfCommand!");
- }
-
- run_next_test();
-});
-
-/**
- * Verify Error Handling of StkProactiveCmdFactory.createCommandMessage()
- */
-add_test(function test_icc_stk_cmd_factory_create_system_msg_invalid_cmd_type() {
- let messenger = newRILSystemMessenger();
- let iccId = "99887766554433221100";
-
- // Verify the protection of invalid typeOfCommand.
- try {
- gStkCmdFactory.createCommandMessage({
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd]),
-
- // nsIStkProactiveCmd
- commandNumber: 0,
- typeOfCommand: RIL.STK_CMD_MORE_TIME, // Invalid TypeOfCommand
- commandQualifier: 0
- });
-
- ok(false, "Failed to identify invalid typeOfCommand!");
- } catch (e) {
- ok(e.message.indexOf("Unknown Command Type") !== -1,
- "Invalid typeOfCommand!");
- }
-
- run_next_test();
-});
-
-/**
- * Verify Error Handling of StkProactiveCmdFactory.createCommandMessage()
- */
-add_test(function test_icc_stk_cmd_factory_create_system_msg_incorrect_cmd_type() {
- let messenger = newRILSystemMessenger();
- let iccId = "99887766554433221100";
-
- // Verify the protection of invalid typeOfCommand.
- try {
- gStkCmdFactory.createCommandMessage({
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
- Ci.nsIStkProvideLocalInfoCmd]),
-
- // nsIStkProactiveCmd
- commandNumber: 0,
- typeOfCommand: RIL.STK_CMD_POLL_INTERVAL, // Incorrect typeOfCommand
- commandQualifier: 0,
- // nsIStkProvideLocalInfoCmd
- localInfoType: 0x00,
- });
-
- ok(false, "Failed to identify incorrect typeOfCommand!");
- } catch (e) {
- ok(e.message.indexOf("Failed to convert command into concrete class: ") !== -1);
- }
-
- run_next_test();
-});
-
-/**
- * Verify RILSystemMessenger.notifyStkProactiveCommand()
- */
-add_test(function test_icc_notify_stk_proactive_command() {
- let messenger = newRILSystemMessenger();
- let iccId = "99887766554433221100";
- let WHT = 0xFFFFFFFF;
- let BLK = 0x000000FF;
- let RED = 0xFF0000FF;
- let GRN = 0x00FF00FF;
- let BLU = 0x0000FFFF;
- let TSP = 0;
- // Basic Image, see Anex B.1 in TS 31.102.
- let basicIcon = {
- width: 8,
- height: 8,
- codingScheme: "basic",
- pixels: [WHT, WHT, WHT, WHT, WHT, WHT, WHT, WHT,
- BLK, BLK, BLK, BLK, BLK, BLK, WHT, WHT,
- WHT, BLK, WHT, BLK, BLK, WHT, BLK, WHT,
- WHT, BLK, BLK, WHT, WHT, BLK, BLK, WHT,
- WHT, BLK, BLK, WHT, WHT, BLK, BLK, WHT,
- WHT, BLK, WHT, BLK, BLK, WHT, BLK, WHT,
- WHT, WHT, BLK, BLK, BLK, BLK, WHT, WHT,
- WHT, WHT, WHT, WHT, WHT, WHT, WHT, WHT]
- };
- // Color Image, see Anex B.2 in TS 31.102.
- let colorIcon = {
- width: 8,
- height: 8,
- codingScheme: "color",
- pixels: [BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU,
- BLU, RED, RED, RED, RED, RED, RED, BLU,
- BLU, RED, GRN, GRN, GRN, RED, RED, BLU,
- BLU, RED, RED, GRN, GRN, RED, RED, BLU,
- BLU, RED, RED, GRN, GRN, RED, RED, BLU,
- BLU, RED, RED, GRN, GRN, GRN, RED, BLU,
- BLU, RED, RED, RED, RED, RED, RED, BLU,
- BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU]
- };
- // Color Image with Transparency, see Anex B.2 in TS 31.102.
- let colorTransparencyIcon = {
- width: 8,
- height: 8,
- codingScheme: "color-transparency",
- pixels: [TSP, TSP, TSP, TSP, TSP, TSP, TSP, TSP,
- TSP, RED, RED, RED, RED, RED, RED, TSP,
- TSP, RED, GRN, GRN, GRN, RED, RED, TSP,
- TSP, RED, RED, GRN, GRN, RED, RED, TSP,
- TSP, RED, RED, GRN, GRN, RED, RED, TSP,
- TSP, RED, RED, GRN, GRN, GRN, RED, TSP,
- TSP, RED, RED, RED, RED, RED, RED, TSP,
- TSP, TSP, TSP, TSP, TSP, TSP, TSP, TSP]
- };
-
- let cmdCount = 0;
-
- // Test Messages:
- let messages = [
- // STK_CMD_REFRESH
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_REFRESH,
- commandQualifier: 0x04 // UICC Reset
- },
- // STK_CMD_POLL_INTERVAL
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_POLL_INTERVAL,
- commandQualifier: 0x00, // RFU
- options: {
- timeUnit: RIL.STK_TIME_UNIT_TENTH_SECOND,
- timeInterval: 0x05
- }
- },
- // STK_CMD_POLL_OFF
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_POLL_OFF,
- commandQualifier: 0x00, // RFU
- },
- // STK_CMD_PROVIDE_LOCAL_INFO
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_PROVIDE_LOCAL_INFO,
- commandQualifier: 0x01, // IMEI of the terminal
- options: {
- localInfoType: 0x01 // IMEI of the terminal
- }
- },
- // STK_CMD_SET_UP_EVENT_LIST with eventList
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_EVENT_LIST,
- commandQualifier: 0x00, // RFU
- options: {
- eventList: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C ]
- }
- },
- // STK_CMD_SET_UP_EVENT_LIST without eventList
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_EVENT_LIST,
- commandQualifier: 0x00, // RFU
- options: {
- eventList: null
- }
- },
- // STK_CMD_SET_UP_MENU with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_MENU,
- commandQualifier: 0x80, // bit 8: 1 = help information available
- options: {
- title: "Toolkit Menu 1",
- items: [
- { identifier: 0x01, text: "Menu Item 1" },
- { identifier: 0x02, text: "Menu Item 2" },
- { identifier: 0x03, text: "Menu Item 3" }
- ],
- isHelpAvailable: true
- }
- },
- // STK_CMD_SET_UP_MENU with optional properties including:
- // iconInfo for this menu, iconInfo for each item and nextActionList.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_MENU,
- commandQualifier: 0x00, // bit 8: 0 = help information is not available
- options: {
- title: "Toolkit Menu 2",
- items: [
- { identifier: 0x01,
- text: "Menu Item 1",
- iconSelfExplanatory: true,
- icons: [basicIcon]
- },
- { identifier: 0x02,
- text: "Menu Item 2",
- iconSelfExplanatory: false,
- icons: [basicIcon, colorIcon]
- },
- { identifier: 0x03,
- text: "Menu Item 3",
- iconSelfExplanatory: true,
- icons: [basicIcon, colorIcon, colorTransparencyIcon]
- },
- ],
- nextActionList: [
- RIL.STK_NEXT_ACTION_END_PROACTIVE_SESSION,
- RIL.STK_NEXT_ACTION_NULL,
- RIL.STK_NEXT_ACTION_NULL,
- RIL.STK_NEXT_ACTION_NULL
- ],
- iconSelfExplanatory: false,
- icons: [basicIcon, colorIcon, colorTransparencyIcon],
- isHelpAvailable: false
- }
- },
- // STK_CMD_SELECT_ITEM with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SELECT_ITEM,
- commandQualifier: RIL.STK_PRESENTATION_TYPE_NOT_SPECIFIED,
- options: {
- title: null,
- items: [
- { identifier: 0x01, text: "Menu Item 1" },
- { identifier: 0x02, text: "Menu Item 2" },
- { identifier: 0x03, text: "Menu Item 3" }
- ],
- presentationType: RIL.STK_PRESENTATION_TYPE_NOT_SPECIFIED,
- isHelpAvailable: false
- }
- },
- // STK_CMD_SELECT_ITEM with optional properties including:
- // title, iconInfo for this menu, iconInfo for each item and nextActionList.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SELECT_ITEM,
- commandQualifier: RIL.STK_PRESENTATION_TYPE_NAVIGATION_OPTIONS,
- options: {
- title: "Selected Toolkit Menu",
- items: [
- { identifier: 0x01,
- text: "Menu Item 1",
- iconSelfExplanatory: true,
- icons: [basicIcon]
- },
- { identifier: 0x02,
- text: "Menu Item 2",
- iconSelfExplanatory: false,
- icons: [basicIcon, colorIcon]
- },
- { identifier: 0x03,
- text: "Menu Item 3",
- iconSelfExplanatory: true,
- icons: [basicIcon, colorIcon, colorTransparencyIcon]
- },
- ],
- nextActionList: [
- RIL.STK_NEXT_ACTION_END_PROACTIVE_SESSION,
- RIL.STK_NEXT_ACTION_NULL,
- RIL.STK_NEXT_ACTION_NULL,
- RIL.STK_NEXT_ACTION_NULL
- ],
- defaultItem: 0x02,
- iconSelfExplanatory: false,
- icons: [basicIcon, colorIcon, colorTransparencyIcon],
- presentationType: RIL.STK_PRESENTATION_TYPE_NAVIGATION_OPTIONS,
- isHelpAvailable: false
- }
- },
- // STK_CMD_DISPLAY_TEXT with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_DISPLAY_TEXT,
- commandQualifier: 0x01, // bit 1: High Priority
- options: {
- text: "Display Text 1",
- isHighPriority: true,
- userClear: false,
- responseNeeded: false
- }
- },
- // STK_CMD_DISPLAY_TEXT with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_DISPLAY_TEXT,
- commandQualifier: 0x80, // bit 8: User Clear
- options: {
- text: "Display Text 2",
- isHighPriority: false,
- userClear: true,
- responseNeeded: true,
- duration: {
- timeUnit: RIL.STK_TIME_UNIT_TENTH_SECOND,
- timeInterval: 0x05
- },
- iconSelfExplanatory: true,
- icons: [basicIcon]
- }
- },
- // STK_CMD_SET_UP_IDLE_MODE_TEXT
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_IDLE_MODE_TEXT,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Setup Idle Mode Text"
- }
- },
- // STK_CMD_SEND_SS
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_SS,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Send SS",
- iconSelfExplanatory: true,
- icons: [colorIcon]
- }
- },
- // STK_CMD_SEND_USSD
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_USSD,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Send USSD"
- }
- },
- // STK_CMD_SEND_SMS
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_SMS,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Send SMS",
- iconSelfExplanatory: false,
- icons: [colorTransparencyIcon]
- }
- },
- // STK_CMD_SEND_DTMF
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_DTMF,
- commandQualifier: 0x00, // RFU
- options: {
- text: "Send DTMF",
- iconSelfExplanatory: true,
- icons: [basicIcon]
- }
- },
- // STK_CMD_GET_INKEY
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_GET_INKEY,
- commandQualifier: 0x84, // bit 3: isYesNoRequested, bit 8: isHelpAvailable
- options: {
- text: "Get Input Key",
- minLength: 1,
- maxLength: 1,
- duration: {
- timeUnit: RIL.STK_TIME_UNIT_SECOND,
- timeInterval: 0x0A
- },
- isAlphabet: false,
- isUCS2: false,
- isYesNoRequested: true,
- isHelpAvailable: true,
- defaultText: null,
- iconSelfExplanatory: false,
- icons: [colorIcon]
- }
- },
- // STK_CMD_GET_INPUT
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_GET_INPUT,
- commandQualifier: 0x0F, // bit 1-4: isAlphabet, isUCS2, hideInput, isPacked
- options: {
- text: "Get Input Text",
- minLength: 1,
- maxLength: 255,
- defaultText: "Default Input Text",
- isAlphabet: true,
- isUCS2: true,
- hideInput: true,
- isPacked: true,
- isHelpAvailable: false,
- defaultText: null,
- iconSelfExplanatory: true,
- icons: [basicIcon]
- }
- },
- // STK_CMD_SET_UP_CALL with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_CALL,
- commandQualifier: 0x00, // RFU
- options: {
- address: "+0987654321"
- }
- },
- // STK_CMD_SET_UP_CALL with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SET_UP_CALL,
- commandQualifier: 0x00, // RFU
- options: {
- address: "+0987654321",
- confirmMessage: {
- text: "Confirm Message",
- iconSelfExplanatory: false,
- icons: [colorIcon]
- },
- callMessage: {
- text: "Call Message",
- iconSelfExplanatory: true,
- icons: [basicIcon]
- },
- duration: {
- timeUnit: RIL.STK_TIME_UNIT_SECOND,
- timeInterval: 0x0A
- }
- }
- },
- // STK_CMD_LAUNCH_BROWSER with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_LAUNCH_BROWSER,
- commandQualifier: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER,
- options: {
- url: "http://www.mozilla.org",
- mode: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER
- }
- },
- // STK_CMD_LAUNCH_BROWSER with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_LAUNCH_BROWSER,
- commandQualifier: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER,
- options: {
- url: "http://www.mozilla.org",
- mode: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER,
- confirmMessage: {
- text: "Confirm Message for Launch Browser",
- iconSelfExplanatory: false,
- icons: [colorTransparencyIcon]
- }
- }
- },
- // STK_CMD_PLAY_TONE with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_PLAY_TONE,
- commandQualifier: 0x01, // isVibrate
- options: {
- text: null,
- isVibrate: true
- }
- },
- // STK_CMD_PLAY_TONE with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_PLAY_TONE,
- commandQualifier: 0x00, // isVibrate = false
- options: {
- text: "Play Tone",
- tone: RIL.STK_TONE_TYPE_CONGESTION,
- isVibrate: false,
- duration: {
- timeUnit: RIL.STK_TIME_UNIT_SECOND,
- timeInterval: 0x0A
- },
- iconSelfExplanatory: true,
- icons: [basicIcon]
- }
- },
- // STK_CMD_TIMER_MANAGEMENT with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_TIMER_MANAGEMENT,
- commandQualifier: RIL.STK_TIMER_DEACTIVATE,
- options: {
- timerId: 0x08,
- timerAction: RIL.STK_TIMER_DEACTIVATE
- }
- },
- // STK_CMD_TIMER_MANAGEMENT with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_TIMER_MANAGEMENT,
- commandQualifier: RIL.STK_TIMER_START,
- options: {
- timerId: 0x01,
- timerValue: (12 * 60 * 60) + (30 * 60) + (30), // 12:30:30
- timerAction: RIL.STK_TIMER_START
- }
- },
- // STK_CMD_OPEN_CHANNEL with mandatory properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_OPEN_CHANNEL,
- commandQualifier: 0x00, //RFU
- options: {
- text: null,
- }
- },
- // STK_CMD_OPEN_CHANNEL with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_OPEN_CHANNEL,
- commandQualifier: 0x00, //RFU
- options: {
- text: "Open Channel",
- iconSelfExplanatory: false,
- icons: [colorIcon]
- }
- },
- // STK_CMD_CLOSE_CHANNEL with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_CLOSE_CHANNEL,
- commandQualifier: 0x00, //RFU
- options: {
- text: "Close Channel",
- iconSelfExplanatory: true,
- icons: [colorTransparencyIcon]
- }
- },
- // STK_CMD_SEND_DATA with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_SEND_DATA,
- commandQualifier: 0x00, //RFU
- options: {
- text: null,
- iconSelfExplanatory: false,
- icons: [basicIcon]
- }
- },
- // STK_CMD_RECEIVE_DATA with optional properties.
- {
- commandNumber: ++cmdCount,
- typeOfCommand: RIL.STK_CMD_RECEIVE_DATA,
- commandQualifier: 0x00, //RFU
- options: {
- text: "Receive Data"
- }
- },
- null // Termination condition to run_next_test()
- ];
-
- messages.forEach(function(aMessage) {
- if (!aMessage) {
- run_next_test();
- return;
- }
-
- messenger.notifyStkProactiveCommand(iccId,
- gStkCmdFactory.createCommand(aMessage));
-
- equal_received_system_message("icc-stkcommand", {
- iccId: iccId,
- command: aMessage
- });
- });
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_barring_password.js b/dom/system/gonk/tests/test_ril_worker_barring_password.js
deleted file mode 100644
index fcd3e4405..000000000
--- a/dom/system/gonk/tests/test_ril_worker_barring_password.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-const PIN = "0000";
-const NEW_PIN = "1234";
-
-add_test(function test_change_call_barring_password() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
-
- function do_test(facility, pin, newPin) {
- buf.sendParcel = function fakeSendParcel () {
- // Request Type.
- equal(this.readInt32(), REQUEST_CHANGE_BARRING_PASSWORD);
-
- // Token : we don't care.
- this.readInt32();
-
- let parcel = this.readStringList();
- equal(parcel.length, 3);
- equal(parcel[0], facility);
- equal(parcel[1], pin);
- equal(parcel[2], newPin);
- };
-
- let options = {facility: facility, pin: pin, newPin: newPin};
- context.RIL.changeCallBarringPassword(options);
- }
-
- do_test(ICC_CB_FACILITY_BA_ALL, PIN, NEW_PIN);
-
- run_next_test();
-});
-
-add_test(function test_check_change_call_barring_password_result() {
- let barringPasswordOptions;
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
-
- let context = worker.ContextPool._contexts[0];
- context.RIL.changeCallBarringPassword =
- function fakeChangeCallBarringPassword(options) {
- barringPasswordOptions = options;
- context.RIL[REQUEST_CHANGE_BARRING_PASSWORD](0, {});
- };
-
- context.RIL.changeCallBarringPassword({pin: PIN, newPin: NEW_PIN});
-
- let postedMessage = workerHelper.postedMessage;
- equal(barringPasswordOptions.pin, PIN);
- equal(barringPasswordOptions.newPin, NEW_PIN);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_buf.js b/dom/system/gonk/tests/test_ril_worker_buf.js
deleted file mode 100644
index 30054a881..000000000
--- a/dom/system/gonk/tests/test_ril_worker_buf.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Add test function with specified parcel and request handler.
- *
- * @param parcel
- * Incoming parcel to be tested.
- * @param handler
- * Handler to be invoked as RIL request handler.
- */
-function add_test_incoming_parcel(parcel, handler) {
- add_test(function test_incoming_parcel() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // do nothing
- },
- postMessage: function(message) {
- // do nothing
- }
- });
-
- if (!parcel) {
- parcel = newIncomingParcel(-1,
- worker.RESPONSE_TYPE_UNSOLICITED,
- worker.REQUEST_VOICE_REGISTRATION_STATE,
- [0, 0, 0, 0]);
- }
-
- let context = worker.ContextPool._contexts[0];
- // supports only requests less or equal than UINT8_MAX(255).
- let buf = context.Buf;
- let request = parcel[buf.PARCEL_SIZE_SIZE + buf.UINT32_SIZE];
- context.RIL[request] = function ril_request_handler() {
- handler.apply(this, arguments);
- };
-
- worker.onRILMessage(0, parcel);
-
- // end of incoming parcel's trip, let's do next test.
- run_next_test();
- });
-}
-
-// Test normal parcel handling.
-add_test_incoming_parcel(null,
- function test_normal_parcel_handling() {
- let self = this;
- try {
- // reads exactly the same size, should not throw anything.
- self.context.Buf.readInt32();
- } catch (e) {
- ok(false, "Got exception: " + e);
- }
- }
-);
-
-// Test parcel under read.
-add_test_incoming_parcel(null,
- function test_parcel_under_read() {
- let self = this;
- try {
- // reads less than parcel size, should not throw.
- self.context.Buf.readUint16();
- } catch (e) {
- ok(false, "Got exception: " + e);
- }
- }
-);
-
-// Test parcel over read.
-add_test_incoming_parcel(null,
- function test_parcel_over_read() {
- let buf = this.context.Buf;
-
- // read all data available
- while (buf.readAvailable > 0) {
- buf.readUint8();
- }
-
- throws(function over_read_handler() {
- // reads more than parcel size, should throw an error.
- buf.readUint8();
- },"Trying to read data beyond the parcel end!");
- }
-);
-
-// Test Bug 814761: buffer overwritten
-add_test(function test_incoming_parcel_buffer_overwritten() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // do nothing
- },
- postMessage: function(message) {
- // do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- // A convenient alias.
- let buf = context.Buf;
-
- // Allocate an array of specified size and set each of its elements to value.
- function calloc(length, value) {
- let array = new Array(length);
- for (let i = 0; i < length; i++) {
- array[i] = value;
- }
- return array;
- }
-
- // Do nothing in handleParcel().
- let request = worker.REQUEST_VOICE_REGISTRATION_STATE;
- context.RIL[request] = null;
-
- // Prepare two parcels, whose sizes are both smaller than the incoming buffer
- // size but larger when combined, to trigger the bug.
- let pA_dataLength = buf.incomingBufferLength / 2;
- let pA = newIncomingParcel(-1,
- worker.RESPONSE_TYPE_UNSOLICITED,
- request,
- calloc(pA_dataLength, 1));
- let pA_parcelSize = pA.length - buf.PARCEL_SIZE_SIZE;
-
- let pB_dataLength = buf.incomingBufferLength * 3 / 4;
- let pB = newIncomingParcel(-1,
- worker.RESPONSE_TYPE_UNSOLICITED,
- request,
- calloc(pB_dataLength, 1));
- let pB_parcelSize = pB.length - buf.PARCEL_SIZE_SIZE;
-
- // First, send an incomplete pA and verifies related data pointer:
- let p1 = pA.subarray(0, pA.length - 1);
- worker.onRILMessage(0, p1);
- // The parcel should not have been processed.
- equal(buf.readAvailable, 0);
- // buf.currentParcelSize should have been set because incoming data has more
- // than 4 octets.
- equal(buf.currentParcelSize, pA_parcelSize);
- // buf.readIncoming should contains remaining unconsumed octets count.
- equal(buf.readIncoming, p1.length - buf.PARCEL_SIZE_SIZE);
- // buf.incomingWriteIndex should be ready to accept the last octet.
- equal(buf.incomingWriteIndex, p1.length);
-
- // Second, send the last octet of pA and whole pB. The Buf should now expand
- // to cover both pA & pB.
- let p2 = new Uint8Array(1 + pB.length);
- p2.set(pA.subarray(pA.length - 1), 0);
- p2.set(pB, 1);
- worker.onRILMessage(0, p2);
- // The parcels should have been both consumed.
- equal(buf.readAvailable, 0);
- // No parcel data remains.
- equal(buf.currentParcelSize, 0);
- // No parcel data remains.
- equal(buf.readIncoming, 0);
- // The Buf should now expand to cover both pA & pB.
- equal(buf.incomingWriteIndex, pA.length + pB.length);
-
- // end of incoming parcel's trip, let's do next test.
- run_next_test();
-});
-
-// Test Buf.readUint8Array.
-add_test_incoming_parcel(null,
- function test_buf_readUint8Array() {
- let buf = this.context.Buf;
-
- let u8array = buf.readUint8Array(1);
- equal(u8array instanceof Uint8Array, true);
- equal(u8array.length, 1);
- equal(buf.readAvailable, 3);
-
- u8array = buf.readUint8Array(2);
- equal(u8array.length, 2);
- equal(buf.readAvailable, 1);
-
- throws(function over_read_handler() {
- // reads more than parcel size, should throw an error.
- u8array = buf.readUint8Array(2);
- }, "Trying to read data beyond the parcel end!");
- }
-);
diff --git a/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js b/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js
deleted file mode 100644
index 335c0c403..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js
+++ /dev/null
@@ -1,234 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Helper function.
- */
-function newWorkerWithParcel(parcelBuf) {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let index = 0; // index for read
- let buf = parcelBuf;
-
- let context = worker.ContextPool._contexts[0];
- context.Buf.readUint8 = function() {
- return buf[index++];
- };
-
- context.Buf.readUint16 = function() {
- return buf[index++];
- };
-
- context.Buf.readInt32 = function() {
- return buf[index++];
- };
-
- context.Buf.seekIncoming = function(offset) {
- index += offset / context.Buf.UINT32_SIZE;
- };
-
- return worker;
-}
-
-// Test CDMA information record decoder.
-
-/**
- * Verify decoder for type DISPLAY
- */
-add_test(function test_display() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x00, // type: display
- 0x09, // length: 9
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x00]);
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].display, "Test Info");
-
- run_next_test();
-});
-
-/**
- * Verify decoder for type EXTENDED DISPLAY
- */
-add_test(function test_extended_display() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x07, // type: extended display
- 0x12, // length: 18
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x78, 0x74,
- 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x49, 0x6E,
- 0x66, 0x6F, 0x00, 0x00]);
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].display, "Test Extended Info");
-
- run_next_test();
-});
-
-/**
- * Verify decoder for mixed type
- */
-add_test(function test_mixed() {
- let worker = newWorkerWithParcel([
- 0x02, // two inforemation record
- 0x00, // type: display
- 0x0B, // length: 11
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x20, 0x31, 0x00,
- 0x07, // type: extended display
- 0x0B, // length: 11
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x20, 0x32, 0x00]);
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].display, "Test Info 1");
- equal(records[1].display, "Test Info 2");
-
- run_next_test();
-});
-
-/**
- * Verify decoder for multiple types
- */
-add_test(function test_multiple() {
- let worker = newWorkerWithParcel([
- 0x02, // two inforemation record
- 0x00, // type: display
- 0x0B, // length: 11
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x20, 0x31, 0x00,
- 0x00, // type: display
- 0x0B, // length: 11
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
- 0x6F, 0x20, 0x32, 0x00]);
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].display, "Test Info 1");
- equal(records[1].display, "Test Info 2");
-
- run_next_test();
-});
-
-/**
- * Verify decoder for Signal Type
- */
-add_test(function test_signal() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x04, // type: signal
- 0x01, // isPresent: non-zero
- 0x00, // signalType: Tone signal (00)
- 0x01, // alertPitch: High pitch
- 0x03]); // signal: Abbreviated intercept (000011)
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].signal.type, 0x00);
- equal(records[0].signal.alertPitch, 0x01);
- equal(records[0].signal.signal, 0x03);
-
- run_next_test();
-});
-
-/**
- * Verify decoder for Signal Type for Not Presented
- */
-add_test(function test_signal_not_present() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x04, // type: signal
- 0x00, // isPresent: zero
- 0x00, // signalType: Tone signal (00)
- 0x01, // alertPitch: High pitch
- 0x03]); // signal: Abbreviated intercept (000011)
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records.length, 0);
-
- run_next_test();
-});
-
-/**
- * Verify decoder for Line Control
- */
-add_test(function test_line_control() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x06, // type: line control
- 0x01, // polarity included
- 0x00, // not toggled
- 0x01, // reversed
- 0xFF]); // Power denial timeout: 255 * 5 ms
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].lineControl.polarityIncluded, 1);
- equal(records[0].lineControl.toggle, 0);
- equal(records[0].lineControl.reverse, 1);
- equal(records[0].lineControl.powerDenial, 255);
-
- run_next_test();
-});
-
-/**
- * Verify decoder for CLIR Cause
- */
-add_test(function test_clir() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x08, // type: clir
- 0x01]); // cause: Rejected by user
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].clirCause, 1);
-
- run_next_test();
-});
-
-/**
- * Verify decoder for Audio Control
- */
-add_test(function test_clir() {
- let worker = newWorkerWithParcel([
- 0x01, // one inforemation record
- 0x0A, // type: audio control
- 0x01, // uplink
- 0xFF]); // downlink
- let context = worker.ContextPool._contexts[0];
- let helper = context.CdmaPDUHelper;
- let records = helper.decodeInformationRecord();
-
- equal(records[0].audioControl.upLink, 1);
- equal(records[0].audioControl.downLink, 255);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js b/dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js
deleted file mode 100644
index d5645a3cf..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js
+++ /dev/null
@@ -1,470 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_ril_worker_cellbroadcast_activate() {
- let worker = newWorker({
- postRILMessage: function(id, parcel) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- let parcelTypes = [];
- let org_newParcel = context.Buf.newParcel;
- context.Buf.newParcel = function(type, options) {
- parcelTypes.push(type);
- org_newParcel.apply(this, arguments);
- };
-
- function setup(isCdma) {
- context.RIL._isCdma = isCdma;
- context.RIL.cellBroadcastDisabled = false;
- context.RIL.mergedCellBroadcastConfig = [1, 2, 4, 7]; // 1, 4-6
- parcelTypes = [];
- }
-
- function test(isCdma, expectedRequest) {
- setup(isCdma);
- context.RIL.setCellBroadcastDisabled({disabled: true});
- // Makesure that request parcel is sent out.
- notEqual(parcelTypes.indexOf(expectedRequest), -1);
- equal(context.RIL.cellBroadcastDisabled, true);
- }
-
- test(false, REQUEST_GSM_SMS_BROADCAST_ACTIVATION);
- test(true, REQUEST_CDMA_SMS_BROADCAST_ACTIVATION);
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_cellbroadcast_config() {
- let currentParcel;
- let worker = newWorker({
- postRILMessage: function(id, parcel) {
- currentParcel = parcel;
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- function U32ArrayFromParcelArray(pa) {
- do_print(pa);
- let out = [];
- for (let i = 0; i < pa.length; i += 4) {
- let data = pa[i] + (pa[i+1] << 8) + (pa[i+2] << 16) + (pa[i+3] << 24);
- out.push(data);
- }
- return out;
- }
-
- function test(isCdma, configs, expected) {
- let parcelType = isCdma ? REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG
- : REQUEST_GSM_SET_BROADCAST_SMS_CONFIG;
-
- let found = false;
- worker.postRILMessage = function(id, parcel) {
- let u32Parcel = U32ArrayFromParcelArray(Array.slice(parcel));
- if (u32Parcel[1] != parcelType) {
- return;
- }
-
- found = true;
- // Check parcel. Data start from 4th word (32bit)
- equal(u32Parcel.slice(3).toString(), expected);
- };
-
- context.RIL._isCdma = isCdma;
- context.RIL.setSmsBroadcastConfig(configs);
-
- // Makesure that request parcel is sent out.
- ok(found);
- }
-
- // (GSM) RIL writes the following data to outgoing parcel:
- // nums [(from, to, 0, 0xFF, 1), ... ]
- test(false,
- [1, 2, 4, 7] /* 1, 4-6 */,
- ["2", "1,1,0,255,1", "4,6,0,255,1"].join());
-
- // (CDMA) RIL writes the following data to outgoing parcel:
- // nums [(id, 0, 1), ... ]
- test(true,
- [1, 2, 4, 7] /* 1, 4-6 */,
- ["4", "1,0,1", "4,0,1", "5,0,1", "6,0,1"].join());
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_cellbroadcast_merge_config() {
- let worker = newWorker({
- postRILMessage: function(id, parcel) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- function test(isCdma, configs, expected) {
- context.RIL._isCdma = isCdma;
- context.RIL.cellBroadcastConfigs = configs;
- context.RIL._mergeAllCellBroadcastConfigs();
- equal(context.RIL.mergedCellBroadcastConfig.toString(), expected);
- }
-
- let configs = {
- MMI: [1, 2, 4, 7], // 1, 4-6
- CBMI: [6, 9], // 6-8
- CBMID: [8, 11], // 8-10
- CBMIR: [10, 13] // 10-12
- };
-
- test(false, configs, "1,2,4,13");
- test(true, configs, "1,2,4,7");
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_cellbroadcast_set_search_list() {
- let worker = newWorker({
- postRILMessage: function(id, parcel) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
-
- function test(aIsCdma, aSearchList, aExpected) {
- context.RIL._isCdma = aIsCdma;
-
- let options = { searchList: aSearchList };
- context.RIL.setCellBroadcastSearchList(options);
- // Enforce the MMI result to string for comparison.
- equal("" + context.RIL.cellBroadcastConfigs.MMI, aExpected);
- do_check_eq(options.errorMsg, undefined);
- }
-
- let searchListStr = "1,2,3,4";
- let searchList = { gsm: "1,2,3,4", cdma: "5,6,7,8" };
-
- test(false, searchListStr, "1,2,2,3,3,4,4,5");
- test(true, searchListStr, "1,2,2,3,3,4,4,5");
- test(false, searchList, "1,2,2,3,3,4,4,5");
- test(true, searchList, "5,6,6,7,7,8,8,9");
- test(false, null, "null");
- test(true, null, "null");
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_mergeCellBroadcastConfigs() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- function test(olist, from, to, expected) {
- let result = ril._mergeCellBroadcastConfigs(olist, from, to);
- equal(JSON.stringify(expected), JSON.stringify(result));
- }
-
- test(null, 0, 1, [0, 1]);
-
- test([10, 13], 7, 8, [ 7, 8, 10, 13]);
- test([10, 13], 7, 9, [ 7, 9, 10, 13]);
- test([10, 13], 7, 10, [ 7, 13]);
- test([10, 13], 7, 11, [ 7, 13]);
- test([10, 13], 7, 12, [ 7, 13]);
- test([10, 13], 7, 13, [ 7, 13]);
- test([10, 13], 7, 14, [ 7, 14]);
- test([10, 13], 7, 15, [ 7, 15]);
- test([10, 13], 7, 16, [ 7, 16]);
- test([10, 13], 8, 9, [ 8, 9, 10, 13]);
- test([10, 13], 8, 10, [ 8, 13]);
- test([10, 13], 8, 11, [ 8, 13]);
- test([10, 13], 8, 12, [ 8, 13]);
- test([10, 13], 8, 13, [ 8, 13]);
- test([10, 13], 8, 14, [ 8, 14]);
- test([10, 13], 8, 15, [ 8, 15]);
- test([10, 13], 8, 16, [ 8, 16]);
- test([10, 13], 9, 10, [ 9, 13]);
- test([10, 13], 9, 11, [ 9, 13]);
- test([10, 13], 9, 12, [ 9, 13]);
- test([10, 13], 9, 13, [ 9, 13]);
- test([10, 13], 9, 14, [ 9, 14]);
- test([10, 13], 9, 15, [ 9, 15]);
- test([10, 13], 9, 16, [ 9, 16]);
- test([10, 13], 10, 11, [10, 13]);
- test([10, 13], 10, 12, [10, 13]);
- test([10, 13], 10, 13, [10, 13]);
- test([10, 13], 10, 14, [10, 14]);
- test([10, 13], 10, 15, [10, 15]);
- test([10, 13], 10, 16, [10, 16]);
- test([10, 13], 11, 12, [10, 13]);
- test([10, 13], 11, 13, [10, 13]);
- test([10, 13], 11, 14, [10, 14]);
- test([10, 13], 11, 15, [10, 15]);
- test([10, 13], 11, 16, [10, 16]);
- test([10, 13], 12, 13, [10, 13]);
- test([10, 13], 12, 14, [10, 14]);
- test([10, 13], 12, 15, [10, 15]);
- test([10, 13], 12, 16, [10, 16]);
- test([10, 13], 13, 14, [10, 14]);
- test([10, 13], 13, 15, [10, 15]);
- test([10, 13], 13, 16, [10, 16]);
- test([10, 13], 14, 15, [10, 13, 14, 15]);
- test([10, 13], 14, 16, [10, 13, 14, 16]);
- test([10, 13], 15, 16, [10, 13, 15, 16]);
-
- test([10, 13, 14, 17], 7, 8, [ 7, 8, 10, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 9, [ 7, 9, 10, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 10, [ 7, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 11, [ 7, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 12, [ 7, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 13, [ 7, 13, 14, 17]);
- test([10, 13, 14, 17], 7, 14, [ 7, 17]);
- test([10, 13, 14, 17], 7, 15, [ 7, 17]);
- test([10, 13, 14, 17], 7, 16, [ 7, 17]);
- test([10, 13, 14, 17], 7, 17, [ 7, 17]);
- test([10, 13, 14, 17], 7, 18, [ 7, 18]);
- test([10, 13, 14, 17], 7, 19, [ 7, 19]);
- test([10, 13, 14, 17], 8, 9, [ 8, 9, 10, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 10, [ 8, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 11, [ 8, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 12, [ 8, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 13, [ 8, 13, 14, 17]);
- test([10, 13, 14, 17], 8, 14, [ 8, 17]);
- test([10, 13, 14, 17], 8, 15, [ 8, 17]);
- test([10, 13, 14, 17], 8, 16, [ 8, 17]);
- test([10, 13, 14, 17], 8, 17, [ 8, 17]);
- test([10, 13, 14, 17], 8, 18, [ 8, 18]);
- test([10, 13, 14, 17], 8, 19, [ 8, 19]);
- test([10, 13, 14, 17], 9, 10, [ 9, 13, 14, 17]);
- test([10, 13, 14, 17], 9, 11, [ 9, 13, 14, 17]);
- test([10, 13, 14, 17], 9, 12, [ 9, 13, 14, 17]);
- test([10, 13, 14, 17], 9, 13, [ 9, 13, 14, 17]);
- test([10, 13, 14, 17], 9, 14, [ 9, 17]);
- test([10, 13, 14, 17], 9, 15, [ 9, 17]);
- test([10, 13, 14, 17], 9, 16, [ 9, 17]);
- test([10, 13, 14, 17], 9, 17, [ 9, 17]);
- test([10, 13, 14, 17], 9, 18, [ 9, 18]);
- test([10, 13, 14, 17], 9, 19, [ 9, 19]);
- test([10, 13, 14, 17], 10, 11, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 10, 12, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 10, 13, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 10, 14, [10, 17]);
- test([10, 13, 14, 17], 10, 15, [10, 17]);
- test([10, 13, 14, 17], 10, 16, [10, 17]);
- test([10, 13, 14, 17], 10, 17, [10, 17]);
- test([10, 13, 14, 17], 10, 18, [10, 18]);
- test([10, 13, 14, 17], 10, 19, [10, 19]);
- test([10, 13, 14, 17], 11, 12, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 11, 13, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 11, 14, [10, 17]);
- test([10, 13, 14, 17], 11, 15, [10, 17]);
- test([10, 13, 14, 17], 11, 16, [10, 17]);
- test([10, 13, 14, 17], 11, 17, [10, 17]);
- test([10, 13, 14, 17], 11, 18, [10, 18]);
- test([10, 13, 14, 17], 11, 19, [10, 19]);
- test([10, 13, 14, 17], 12, 13, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 12, 14, [10, 17]);
- test([10, 13, 14, 17], 12, 15, [10, 17]);
- test([10, 13, 14, 17], 12, 16, [10, 17]);
- test([10, 13, 14, 17], 12, 17, [10, 17]);
- test([10, 13, 14, 17], 12, 18, [10, 18]);
- test([10, 13, 14, 17], 12, 19, [10, 19]);
- test([10, 13, 14, 17], 13, 14, [10, 17]);
- test([10, 13, 14, 17], 13, 15, [10, 17]);
- test([10, 13, 14, 17], 13, 16, [10, 17]);
- test([10, 13, 14, 17], 13, 17, [10, 17]);
- test([10, 13, 14, 17], 13, 18, [10, 18]);
- test([10, 13, 14, 17], 13, 19, [10, 19]);
- test([10, 13, 14, 17], 14, 15, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 14, 16, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 14, 17, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 14, 18, [10, 13, 14, 18]);
- test([10, 13, 14, 17], 14, 19, [10, 13, 14, 19]);
- test([10, 13, 14, 17], 15, 16, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 15, 17, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 15, 18, [10, 13, 14, 18]);
- test([10, 13, 14, 17], 15, 19, [10, 13, 14, 19]);
- test([10, 13, 14, 17], 16, 17, [10, 13, 14, 17]);
- test([10, 13, 14, 17], 16, 18, [10, 13, 14, 18]);
- test([10, 13, 14, 17], 16, 19, [10, 13, 14, 19]);
- test([10, 13, 14, 17], 17, 18, [10, 13, 14, 18]);
- test([10, 13, 14, 17], 17, 19, [10, 13, 14, 19]);
- test([10, 13, 14, 17], 18, 19, [10, 13, 14, 17, 18, 19]);
-
- test([10, 13, 16, 19], 7, 14, [ 7, 14, 16, 19]);
- test([10, 13, 16, 19], 7, 15, [ 7, 15, 16, 19]);
- test([10, 13, 16, 19], 7, 16, [ 7, 19]);
- test([10, 13, 16, 19], 8, 14, [ 8, 14, 16, 19]);
- test([10, 13, 16, 19], 8, 15, [ 8, 15, 16, 19]);
- test([10, 13, 16, 19], 8, 16, [ 8, 19]);
- test([10, 13, 16, 19], 9, 14, [ 9, 14, 16, 19]);
- test([10, 13, 16, 19], 9, 15, [ 9, 15, 16, 19]);
- test([10, 13, 16, 19], 9, 16, [ 9, 19]);
- test([10, 13, 16, 19], 10, 14, [10, 14, 16, 19]);
- test([10, 13, 16, 19], 10, 15, [10, 15, 16, 19]);
- test([10, 13, 16, 19], 10, 16, [10, 19]);
- test([10, 13, 16, 19], 11, 14, [10, 14, 16, 19]);
- test([10, 13, 16, 19], 11, 15, [10, 15, 16, 19]);
- test([10, 13, 16, 19], 11, 16, [10, 19]);
- test([10, 13, 16, 19], 12, 14, [10, 14, 16, 19]);
- test([10, 13, 16, 19], 12, 15, [10, 15, 16, 19]);
- test([10, 13, 16, 19], 12, 16, [10, 19]);
- test([10, 13, 16, 19], 13, 14, [10, 14, 16, 19]);
- test([10, 13, 16, 19], 13, 15, [10, 15, 16, 19]);
- test([10, 13, 16, 19], 13, 16, [10, 19]);
- test([10, 13, 16, 19], 14, 15, [10, 13, 14, 15, 16, 19]);
- test([10, 13, 16, 19], 14, 16, [10, 13, 14, 19]);
- test([10, 13, 16, 19], 15, 16, [10, 13, 15, 19]);
-
- run_next_test();
-});
-
-add_test(function test_ril_consts_cellbroadcast_misc() {
- // Must be 16 for indexing.
- equal(CB_DCS_LANG_GROUP_1.length, 16);
- equal(CB_DCS_LANG_GROUP_2.length, 16);
-
- // Array length must be even.
- equal(CB_NON_MMI_SETTABLE_RANGES.length & 0x01, 0);
- for (let i = 0; i < CB_NON_MMI_SETTABLE_RANGES.length;) {
- let from = CB_NON_MMI_SETTABLE_RANGES[i++];
- let to = CB_NON_MMI_SETTABLE_RANGES[i++];
- equal(from < to, true);
- }
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_checkCellBroadcastMMISettable() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- function test(from, to, expected) {
- equal(expected, ril._checkCellBroadcastMMISettable(from, to));
- }
-
- test(-2, -1, false);
- test(-1, 0, false);
- test(0, 1, true);
- test(1, 1, false);
- test(2, 1, false);
- test(65536, 65537, false);
-
- // We have both [4096, 4224), [4224, 4352), so it's actually [4096, 4352),
- // and [61440, 65536), [65535, 65536), so it's actually [61440, 65536).
- for (let i = 0; i < CB_NON_MMI_SETTABLE_RANGES.length;) {
- let from = CB_NON_MMI_SETTABLE_RANGES[i++];
- let to = CB_NON_MMI_SETTABLE_RANGES[i++];
- if ((from != 4224) && (from != 65535)) {
- test(from - 1, from, true);
- }
- test(from - 1, from + 1, false);
- test(from - 1, to, false);
- test(from - 1, to + 1, false);
- test(from, from + 1, false);
- test(from, to, false);
- test(from, to + 1, false);
- if ((from + 1) < to) {
- test(from + 1, to, false);
- test(from + 1, to + 1, false);
- }
- if ((to != 4224) && (to < 65535)) {
- test(to, to + 1, true);
- test(to + 1, to + 2, true);
- }
- }
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_CellBroadcastDisabled() {
- let count = 0;
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- if (message.rilMessageType == "cellbroadcast-received") {
- ok(true, "cellbroadcast-received: " + JSON.stringify(message));
- count++;
- }
- }
- });
-
- function buildPdu(aMessageId) {
- return "C002" + aMessageId + "011154741914AFA7C76B9058" +
- "FEBEBB41E6371EA4AEB7E173D0DB5E96" +
- "83E8E832881DD6E741E4F7B9D168341A" +
- "8D46A3D168341A8D46A3D168341A8D46" +
- "A3D168341A8D46A3D168341A8D46A3D1" +
- "68341A8D46A3D100";
- }
-
- worker.ContextPool._contexts[0].RIL.cellBroadcastDisabled = true;
-
- let networkAlertIds = [
- "1100", "1107", // ETWS
- "1112", "112F", // CMAS
- "1130", "18FF", // PWS
- ];
- networkAlertIds.forEach(aMessageId => {
- worker.onRILMessage(
- 0,
- newIncomingParcel(
- -1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(buildPdu(aMessageId))));
- });
- equal(count, networkAlertIds.length, "Alerts shall not be ignored.");
-
- count = 0;
- let normalMsgIds = [ "0000", "03E7", "1108", "1901" ];
- normalMsgIds.forEach(aMessageId => {
- worker.onRILMessage(
- 0,
- newIncomingParcel(
- -1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(buildPdu(aMessageId))));
- });
- equal(count, 0, "Normal messages shall be ignored.");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_gsm.js b/dom/system/gonk/tests/test_ril_worker_cellbroadcast_gsm.js
deleted file mode 100644
index b08b64135..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_gsm.js
+++ /dev/null
@@ -1,230 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_ril_worker_GsmPDUHelper_readCbDataCodingScheme() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- function test_dcs(dcs, encoding, language, hasLanguageIndicator, messageClass) {
- context.Buf.readUint8 = function() {
- return dcs;
- };
-
- let msg = {};
- context.GsmPDUHelper.readCbDataCodingScheme(msg);
-
- equal(msg.dcs, dcs);
- equal(msg.encoding, encoding);
- equal(msg.language, language);
- equal(msg.hasLanguageIndicator, hasLanguageIndicator);
- equal(msg.messageClass, messageClass);
- }
-
- function test_dcs_throws(dcs) {
- context.Buf.readUint8 = function() {
- return dcs;
- };
-
- throws(function() {
- context.GsmPDUHelper.readCbDataCodingScheme({});
- }, "Unsupported CBS data coding scheme: " + dcs);
- }
-
- // Group 0000
- for (let i = 0; i < 16; i++) {
- test_dcs(i, PDU_DCS_MSG_CODING_7BITS_ALPHABET, CB_DCS_LANG_GROUP_1[i],
- false, GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- }
-
- // Group 0001
- // 0000 GSM 7 bit default alphabet; message preceded by language indication.
- test_dcs(0x10, PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, true,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- // 0001 UCS2; message preceded by language indication.
- test_dcs(0x11, PDU_DCS_MSG_CODING_16BITS_ALPHABET, null, true,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
-
- // Group 0010
- // 0000..0100
- for (let i = 0; i < 5; i++) {
- test_dcs(0x20 + i, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- CB_DCS_LANG_GROUP_2[i], false,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- }
- // 0101..1111 Reserved
- for (let i = 5; i < 16; i++) {
- test_dcs(0x20 + i, PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, false,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- }
-
- // Group 0100, 0101, 1001
- for (let group of [0x40, 0x50, 0x90]) {
- for (let i = 0; i < 16; i++) {
- let encoding = i & 0x0C;
- if (encoding == 0x0C) {
- encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- }
- let messageClass = GECKO_SMS_MESSAGE_CLASSES[i & PDU_DCS_MSG_CLASS_BITS];
- test_dcs(group + i, encoding, null, false, messageClass);
- }
- }
-
- // Group 1111
- for (let i = 0; i < 16; i ++) {
- let encoding = i & 0x04 ? PDU_DCS_MSG_CODING_8BITS_ALPHABET
- : PDU_DCS_MSG_CODING_7BITS_ALPHABET;
- let messageClass;
- switch(i & PDU_DCS_MSG_CLASS_BITS) {
- case 0x01: messageClass = PDU_DCS_MSG_CLASS_USER_1; break;
- case 0x02: messageClass = PDU_DCS_MSG_CLASS_USER_2; break;
- case 0x03: messageClass = PDU_DCS_MSG_CLASS_3; break;
- default: messageClass = PDU_DCS_MSG_CLASS_NORMAL; break;
- }
- test_dcs(0xF0 + i, encoding, null, false,
- GECKO_SMS_MESSAGE_CLASSES[messageClass]);
- }
-
- // Group 0011, 1000, 1010, 1011, 1100
- // 0000..1111 Reserved
- for (let group of [0x30, 0x80, 0xA0, 0xB0, 0xC0]) {
- for (let i = 0; i < 16; i++) {
- test_dcs(group + i, PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, false,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- }
- }
-
- // Group 0110, 0111, 1101, 1110
- // TODO: unsupported
- for (let group of [0x60, 0x70, 0xD0, 0xE0]) {
- for (let i = 0; i < 16; i++) {
- test_dcs_throws(group + i);
- }
- }
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_GsmPDUHelper_readGsmCbData() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- function test_data(options, expected) {
- let readIndex = 0;
- context.Buf.readUint8 = function() {
- return options[3][readIndex++];
- };
- context.Buf.readUint8Array = function(length) {
- let array = new Uint8Array(length);
- for (let i = 0; i < length; i++) {
- array[i] = this.readUint8();
- }
- return array;
- };
-
- let msg = {
- encoding: options[0],
- language: options[1],
- hasLanguageIndicator: options[2]
- };
- context.GsmPDUHelper.readGsmCbData(msg, options[3].length);
-
- equal(msg.body, expected[0]);
- equal(msg.data == null, expected[1] == null);
- if (expected[1] != null) {
- equal(msg.data.length, expected[1].length);
- for (let i = 0; i < expected[1].length; i++) {
- equal(msg.data[i], expected[1][i]);
- }
- }
- equal(msg.language, expected[2]);
- }
-
- // We're testing Cell Broadcast message body with all zeros octet stream. As
- // shown in 3GPP TS 23.038, septet 0x00 will be decoded as '@' when both
- // langTableIndex and langShiftTableIndex equal to
- // PDU_DCS_MSG_CODING_7BITS_ALPHABET.
-
- // PDU_DCS_MSG_CODING_7BITS_ALPHABET
- test_data([PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, false,
- [0]],
- ["@", null, null]);
- test_data([PDU_DCS_MSG_CODING_7BITS_ALPHABET, null, true,
- [0, 0, 0, 0]],
- ["@", null, "@@"]);
- test_data([PDU_DCS_MSG_CODING_7BITS_ALPHABET, "@@", false,
- [0]],
- ["@", null, "@@"]);
-
- // PDU_DCS_MSG_CODING_8BITS_ALPHABET
- test_data([PDU_DCS_MSG_CODING_8BITS_ALPHABET, null, false,
- [0]],
- [null, [0], null]);
-
- // PDU_DCS_MSG_CODING_16BITS_ALPHABET
- test_data([PDU_DCS_MSG_CODING_16BITS_ALPHABET, null, false,
- [0x00, 0x40]],
- ["@", null, null]);
- test_data([PDU_DCS_MSG_CODING_16BITS_ALPHABET, null, true,
- [0x00, 0x00, 0x00, 0x40]],
- ["@", null, "@@"]);
- test_data([PDU_DCS_MSG_CODING_16BITS_ALPHABET, "@@", false,
- [0x00, 0x40]],
- ["@", null, "@@"]);
-
- run_next_test();
-});
-
-add_test(function test_ril_worker_Sim_Download_Message() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- ok(message.rilMessageType !== "cellbroadcast-received",
- "Data-Download message shall be ignored.");
- }
- });
-
- function buildPdu(aMessageId) {
- return "C002" + aMessageId + "011154741914AFA7C76B9058" +
- "FEBEBB41E6371EA4AEB7E173D0DB5E96" +
- "83E8E832881DD6E741E4F7B9D168341A" +
- "8D46A3D168341A8D46A3D168341A8D46" +
- "A3D168341A8D46A3D168341A8D46A3D1" +
- "68341A8D46A3D100";
- }
-
- ["1000", "107F", "1080", "10FF"].forEach(aMessageId => {
- worker.onRILMessage(
- 0,
- newIncomingParcel(
- -1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(buildPdu(aMessageId))));
- });
-
- ok(true, "All Data-Download Messages are ingored.");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_umts.js b/dom/system/gonk/tests/test_ril_worker_cellbroadcast_umts.js
deleted file mode 100644
index 0380c4122..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_umts.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-function buildHexStr(aNum, aNumSemiOctets) {
- let str = aNum.toString(16);
- while (str.length < aNumSemiOctets) {
- str = "0" + str;
- }
- return str;
-}
-
-/**
- * Verify GsmPDUHelper#readUmtsCbMessage with numOfPages from 1 to 15.
- */
-add_test(function test_GsmPDUHelper_readUmtsCbMessage_MultiParts() {
- let CB_UMTS_MESSAGE_PAGE_SIZE = 82;
- let CB_MAX_CONTENT_PER_PAGE_7BIT = 93;
- let workerHelper = newInterceptWorker(),
- worker = workerHelper.worker,
- context = worker.ContextPool._contexts[0],
- GsmPDUHelper = context.GsmPDUHelper;
-
- function test_MultiParts(aNumOfPages) {
- let pdu = buildHexStr(CB_UMTS_MESSAGE_TYPE_CBS, 2) // msg_type
- + buildHexStr(0, 4) // skip msg_id
- + buildHexStr(0, 4) // skip SN
- + buildHexStr(0, 2) // skip dcs
- + buildHexStr(aNumOfPages, 2); // set num_of_pages
- for (let i = 1; i <= aNumOfPages; i++) {
- pdu = pdu + buildHexStr(0, CB_UMTS_MESSAGE_PAGE_SIZE * 2)
- + buildHexStr(CB_UMTS_MESSAGE_PAGE_SIZE, 2); // msg_info_length
- }
-
- worker.onRILMessage(0, newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(pdu)));
-
- let postedMessage = workerHelper.postedMessage;
- equal("cellbroadcast-received", postedMessage.rilMessageType);
- equal(postedMessage.fullBody.length,
- aNumOfPages * CB_MAX_CONTENT_PER_PAGE_7BIT);
- }
-
- [1, 5, 15].forEach(function(i) {
- test_MultiParts(i);
- });
-
- run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper#readUmtsCbMessage with 8bit encoded.
- */
-add_test(function test_GsmPDUHelper_readUmtsCbMessage_Binary() {
- let CB_UMTS_MESSAGE_PAGE_SIZE = 82;
- let CB_MAX_CONTENT_PER_PAGE_7BIT = 93;
- let TEXT_BINARY = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFF";
- let workerHelper = newInterceptWorker(),
- worker = workerHelper.worker,
- context = worker.ContextPool._contexts[0],
- GsmPDUHelper = context.GsmPDUHelper;
-
- function test_MultiPartsBinary(aNumOfPages) {
- let pdu = buildHexStr(CB_UMTS_MESSAGE_TYPE_CBS, 2) // msg_type
- + buildHexStr(0, 4) // skip msg_id
- + buildHexStr(0, 4) // skip SN
- + buildHexStr(68, 2) // set DCS to 8bit data
- + buildHexStr(aNumOfPages, 2); // set num_of_pages
- for (let i = 1; i <= aNumOfPages; i++) {
- pdu = pdu + TEXT_BINARY
- + buildHexStr(CB_UMTS_MESSAGE_PAGE_SIZE, 2); // msg_info_length
- }
-
- worker.onRILMessage(0, newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS,
- hexStringToParcelByteArrayData(pdu)));
-
- let postedMessage = workerHelper.postedMessage;
- equal("cellbroadcast-received", postedMessage.rilMessageType);
- equal(postedMessage.fullData.length,
- aNumOfPages * CB_UMTS_MESSAGE_PAGE_SIZE);
- for (let i = 0; i < postedMessage.fullData.length; i++) {
- equal(postedMessage.fullData[i], 255);
- }
- }
-
- [1, 5, 15].forEach(function(i) {
- test_MultiPartsBinary(i);
- });
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cf.js b/dom/system/gonk/tests/test_ril_worker_cf.js
deleted file mode 100644
index b8db716b7..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cf.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-function toaFromString(number) {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
- return context.RIL._toaFromString(number);
-}
-
-add_test(function test_toaFromString_empty() {
- let retval = toaFromString("");
-
- equal(retval, TOA_UNKNOWN);
-
- run_next_test();
-});
-
-add_test(function test_toaFromString_undefined() {
- let retval = toaFromString();
-
- equal(retval, TOA_UNKNOWN);
-
- run_next_test();
-});
-
-add_test(function test_toaFromString_unknown() {
- let retval = toaFromString("666222333");
-
- equal(retval, TOA_UNKNOWN);
-
- run_next_test();
-});
-
-add_test(function test_toaFromString_international() {
- let retval = toaFromString("+34666222333");
-
- equal(retval, TOA_INTERNATIONAL);
-
- run_next_test();
-});
-
-add_test(function test_setCallForward_unconditional() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCallForward = function fakeSetCallForward(options) {
- context.RIL[REQUEST_SET_CALL_FORWARD](0, {});
- };
-
- context.RIL.setCallForward({
- action: CALL_FORWARD_ACTION_REGISTRATION,
- reason: CALL_FORWARD_REASON_UNCONDITIONAL,
- serviceClass: ICC_SERVICE_CLASS_VOICE,
- number: "666222333",
- timeSeconds: 10
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
-
- run_next_test();
-});
-
-add_test(function test_queryCallForwardStatus_unconditional() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCallForward = function fakeSetCallForward(options) {
- context.RIL[REQUEST_SET_CALL_FORWARD](0, {});
- };
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.Buf.readString = function fakeReadString() {
- return "+34666222333";
- };
-
- context.RIL.queryCallForwardStatus = function fakeQueryCallForward(options) {
- context.Buf.int32Array = [
- 0, // rules.timeSeconds
- 145, // rules.toa
- 49, // rules.serviceClass
- CALL_FORWARD_REASON_UNCONDITIONAL, // rules.reason
- 1, // rules.active
- 1 // rulesLength
- ];
- context.RIL[REQUEST_QUERY_CALL_FORWARD_STATUS](1, {});
- };
-
- context.RIL.queryCallForwardStatus({
- action: CALL_FORWARD_ACTION_QUERY_STATUS,
- reason: CALL_FORWARD_REASON_UNCONDITIONAL,
- serviceClass: ICC_SERVICE_CLASS_VOICE,
- number: "666222333",
- timeSeconds: 10
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- ok(Array.isArray(postedMessage.rules));
- do_print(postedMessage.rules.length);
- equal(postedMessage.rules.length, 1);
- ok(postedMessage.rules[0].active);
- equal(postedMessage.rules[0].reason, CALL_FORWARD_REASON_UNCONDITIONAL);
- equal(postedMessage.rules[0].number, "+34666222333");
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_clip.js b/dom/system/gonk/tests/test_ril_worker_clip.js
deleted file mode 100644
index d1ce5f617..000000000
--- a/dom/system/gonk/tests/test_ril_worker_clip.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_queryCLIP_provisioned() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.queryCLIP = function fakeQueryCLIP(options) {
- context.Buf.int32Array = [
- 1, // CLIP provisioned.
- 1 // Length.
- ];
- context.RIL[REQUEST_QUERY_CLIP](1, {});
- };
-
- context.RIL.queryCLIP({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- equal(postedMessage.provisioned, 1);
- run_next_test();
-});
-
-add_test(function test_getCLIP_error_generic_failure_invalid_length() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.queryCLIP = function fakeQueryCLIP(options) {
- context.Buf.int32Array = [
- 1, // CLIP provisioned.
- 0 // Length.
- ];
- context.RIL[REQUEST_QUERY_CLIP](1, {});
- };
-
- context.RIL.queryCLIP({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_clir.js b/dom/system/gonk/tests/test_ril_worker_clir.js
deleted file mode 100644
index 5882a3c4c..000000000
--- a/dom/system/gonk/tests/test_ril_worker_clir.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-// Calling line identification restriction constants.
-
-// Uses subscription default value.
-const CLIR_DEFAULT = 0;
-// Restricts CLI presentation.
-const CLIR_INVOCATION = 1;
-// Allows CLI presentation.
-const CLIR_SUPPRESSION = 2;
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_setCLIR_success() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCLIR = function fakeSetCLIR(options) {
- context.RIL[REQUEST_SET_CLIR](0, {
- rilMessageType: "setCLIR"
- });
- };
-
- context.RIL.setCLIR({
- clirMode: CLIR_DEFAULT
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
-
- run_next_test();
-});
-
-add_test(function test_setCLIR_generic_failure() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCLIR = function fakeSetCLIR(options) {
- context.RIL[REQUEST_SET_CLIR](0, {
- rilMessageType: "setCLIR",
- errorMsg: GECKO_ERROR_GENERIC_FAILURE
- });
- };
-
- context.RIL.setCLIR({
- clirMode: CLIR_DEFAULT
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
-
- run_next_test();
-});
-
-add_test(function test_getCLIR_n0_m1() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.getCLIR = function fakeGetCLIR(options) {
- context.Buf.int32Array = [
- 1, // Presentation indicator is used according to the subscription
- // of the CLIR service.
- 0, // CLIR provisioned in permanent mode.
- 2 // Length.
- ];
- context.RIL[REQUEST_GET_CLIR](1, {
- rilMessageType: "setCLIR"
- });
- };
-
- context.RIL.getCLIR({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- equal(postedMessage.n, 0);
- equal(postedMessage.m, 1);
- run_next_test();
-});
-
-add_test(function test_getCLIR_error_generic_failure_invalid_length() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.getCLIR = function fakeGetCLIR(options) {
- context.Buf.int32Array = [
- 1, // Presentation indicator is used according to the subscription
- // of the CLIR service.
- 0, // CLIR provisioned in permanent mode.
- 0 // Length (invalid one).
- ];
- context.RIL[REQUEST_GET_CLIR](1, {
- rilMessageType: "setCLIR"
- });
- };
-
- context.RIL.getCLIR({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_cw.js b/dom/system/gonk/tests/test_ril_worker_cw.js
deleted file mode 100644
index efa8b5c21..000000000
--- a/dom/system/gonk/tests/test_ril_worker_cw.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_setCallWaiting_success() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
- context.RIL[REQUEST_SET_CALL_WAITING](0, {});
- };
-
- context.RIL.setCallWaiting({
- enabled: true
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
-
- run_next_test();
-});
-
-add_test(function test_setCallWaiting_generic_failure() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
- context.RIL[REQUEST_SET_CALL_WAITING](0, {
- errorMsg: GECKO_ERROR_GENERIC_FAILURE
- });
- };
-
- context.RIL.setCallWaiting({
- enabled: true
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
-
- run_next_test();
-});
-
-add_test(function test_queryCallWaiting_success_enabled_true() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
- context.Buf.int32Array = [
- 1, // serviceClass
- 1, // enabled
- 2 // length
- ];
- context.RIL[REQUEST_QUERY_CALL_WAITING](1, {});
- };
-
- context.RIL.queryCallWaiting({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- equal(postedMessage.serviceClass, 1);
- run_next_test();
-});
-
-add_test(function test_queryCallWaiting_success_enabled_false() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32 = function fakeReadUint32() {
- return context.Buf.int32Array.pop();
- };
-
- context.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
- context.Buf.int32Array = [
- 1, // serviceClass
- 0, // enabled
- 2 // length
- ];
- context.RIL[REQUEST_QUERY_CALL_WAITING](1, {});
- };
-
- context.RIL.queryCallWaiting({});
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- equal(postedMessage.serviceClass, ICC_SERVICE_CLASS_NONE);
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_ecm.js b/dom/system/gonk/tests/test_ril_worker_ecm.js
deleted file mode 100644
index d10cba9ec..000000000
--- a/dom/system/gonk/tests/test_ril_worker_ecm.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-var timeoutCallback = null;
-var timeoutDelayMs = 0;
-const TIMER_ID = 1234;
-const TIMEOUT_VALUE = 300000; // 5 mins.
-
-// No window in xpcshell-test. Create our own timer mechanism.
-
-function setTimeout(callback, timeoutMs) {
- timeoutCallback = callback;
- timeoutDelayMs = timeoutMs;
- equal(timeoutMs, TIMEOUT_VALUE);
- return TIMER_ID;
-}
-
-function clearTimeout(timeoutId) {
- equal(timeoutId, TIMER_ID);
- timeoutCallback = null;
-}
-
-function fireTimeout() {
- notEqual(timeoutCallback, null);
- if (timeoutCallback) {
- timeoutCallback();
- timeoutCallback = null;
- }
-}
-
-add_test(function test_enter_emergencyCbMode() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- // Do it twice. Should always send the event.
- for (let i = 0; i < 2; ++i) {
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- let postedMessage = workerHelper.postedMessage;
-
- // Should store the mode.
- equal(context.RIL._isInEmergencyCbMode, true);
-
- // Should notify change.
- equal(postedMessage.rilMessageType, "emergencyCbModeChange");
- equal(postedMessage.active, true);
- equal(postedMessage.timeoutMs, TIMEOUT_VALUE);
-
- // Should start timer.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
- }
-
- run_next_test();
-});
-
-add_test(function test_exit_emergencyCbMode() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- context.RIL[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE]();
- let postedMessage = workerHelper.postedMessage;
-
- // Should store the mode.
- equal(context.RIL._isInEmergencyCbMode, false);
-
- // Should notify change.
- equal(postedMessage.rilMessageType, "emergencyCbModeChange");
- equal(postedMessage.active, false);
-
- // Should clear timer.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, null);
-
- run_next_test();
-});
-
-add_test(function test_request_exit_emergencyCbMode_when_timeout() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- equal(context.RIL._isInEmergencyCbMode, true);
- equal(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
-
- let parcelTypes = [];
- context.Buf.newParcel = function(type, options) {
- parcelTypes.push(type);
- };
-
- // Timeout.
- fireTimeout();
-
- // Should clear timeout event.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, null);
-
- // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
- notEqual(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
-
- run_next_test();
-});
-
-add_test(function test_request_exit_emergencyCbMode_when_dial() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- equal(context.RIL._isInEmergencyCbMode, true);
- equal(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
-
- let parcelTypes = [];
- context.Buf.newParcel = function(type, options) {
- parcelTypes.push(type);
- };
-
- // Dial non-emergency call.
- context.RIL.dial({number: "0912345678",
- isEmergency: false,
- isDialEmergency: false});
-
- // Should clear timeout event.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, null);
-
- // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
- notEqual(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
-
- run_next_test();
-});
-
-add_test(function test_request_exit_emergencyCbMode_explicitly() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
- equal(context.RIL._isInEmergencyCbMode, true);
- equal(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
-
- let parcelTypes = [];
- context.Buf.newParcel = function(type, options) {
- parcelTypes.push(type);
- };
-
- context.RIL.handleChromeMessage({rilMessageType: "exitEmergencyCbMode"});
- context.RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE](1, {
- rilMessageType: "exitEmergencyCbMode"
- });
- let postedMessage = workerHelper.postedMessage;
-
- // Should clear timeout event.
- equal(context.RIL._exitEmergencyCbModeTimeoutID, null);
-
- // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
- notEqual(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
-
- // Send back the response.
- equal(postedMessage.rilMessageType, "exitEmergencyCbMode");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_BerTlvHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_BerTlvHelper.js
deleted file mode 100644
index 89fcd874d..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_BerTlvHelper.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-// Test ICC_COMMAND_GET_RESPONSE with FCP template format.
-/**
- * Verify transparent structure with FCP template format.
- */
-add_test(function test_fcp_template_for_transparent_structure() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
-
- let tag_test = [
- 0x62,
- 0x22,
- 0x82, 0x02, 0x41, 0x21,
- 0x83, 0x02, 0x2F, 0xE2,
- 0xA5, 0x09, 0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00,
- 0x8A, 0x01, 0x05,
- 0x8B, 0x03, 0x2F, 0x06, 0x0B,
- 0x80, 0x02, 0x00, 0x0A,
- 0x88, 0x01, 0x10];
-
- for (let i = 0; i < tag_test.length; i++) {
- pduHelper.writeHexOctet(tag_test[i]);
- }
-
- let berTlv = berHelper.decode(tag_test.length);
- let iter = berTlv.value.values();
- let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
- equal(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_STRUCTURE_TRANSPARENT]);
-
- tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
- equal(tlv.value.fileId, 0x2FE2);
-
- tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
- equal(tlv.value.fileSizeData, 0x0A);
-
- run_next_test();
-});
-
-/**
- * Verify linear fixed structure with FCP template format.
- */
-add_test(function test_fcp_template_for_linear_fixed_structure() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
-
- let tag_test = [
- 0x62,
- 0x1E,
- 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01,
- 0x83, 0x02, 0x6F, 0x40,
- 0xA5, 0x03, 0x92, 0x01, 0x00,
- 0x8A, 0x01, 0x07,
- 0x8B, 0x03, 0x6F, 0x06, 0x02,
- 0x80, 0x02, 0x00, 0x1A,
- 0x88, 0x00];
-
- for (let i = 0; i < tag_test.length; i++) {
- pduHelper.writeHexOctet(tag_test[i]);
- }
-
- let berTlv = berHelper.decode(tag_test.length);
- let iter = berTlv.value.values();
- let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
- equal(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_STRUCTURE_LINEAR_FIXED]);
- equal(tlv.value.recordLength, 0x1A);
- equal(tlv.value.numOfRecords, 0x01);
-
- tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
- equal(tlv.value.fileId, 0x6F40);
-
- tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
- equal(tlv.value.fileSizeData, 0x1A);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js b/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js
deleted file mode 100644
index dc7eb93b9..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js
+++ /dev/null
@@ -1,282 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify RIL.iccGetCardLockEnabled
- */
-add_test(function test_icc_get_card_lock_enabled() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let ril = context.RIL;
- ril.aid = "123456789";
-
- function do_test(aLock) {
- const serviceClass = ICC_SERVICE_CLASS_VOICE |
- ICC_SERVICE_CLASS_DATA |
- ICC_SERVICE_CLASS_FAX;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), REQUEST_QUERY_FACILITY_LOCK)
-
- // Token : we don't care.
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 4);
- equal(parcel[0], GECKO_CARDLOCK_TO_FACILITY[aLock]);
- equal(parcel[1], "");
- equal(parcel[2], serviceClass.toString());
- equal(parcel[3], ril.aid);
- };
-
- ril.iccGetCardLockEnabled({lockType: aLock});
- }
-
- do_test(GECKO_CARDLOCK_PIN)
- do_test(GECKO_CARDLOCK_FDN)
-
- run_next_test();
-});
-
-add_test(function test_path_id_for_spid_and_spn() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }});
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ICCFileHelper = context.ICCFileHelper;
-
- // Test SIM
- RIL.appType = CARD_APPTYPE_SIM;
- equal(ICCFileHelper.getEFPath(ICC_EF_SPDI),
- EF_PATH_MF_SIM + EF_PATH_DF_GSM);
- equal(ICCFileHelper.getEFPath(ICC_EF_SPN),
- EF_PATH_MF_SIM + EF_PATH_DF_GSM);
-
- // Test USIM
- RIL.appType = CARD_APPTYPE_USIM;
- equal(ICCFileHelper.getEFPath(ICC_EF_SPDI),
- EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
- equal(ICCFileHelper.getEFPath(ICC_EF_SPDI),
- EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
- run_next_test();
-});
-
-/**
- * Verify RIL.iccSetCardLockEnabled
- */
-add_test(function test_icc_set_card_lock_enabled() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let ril = context.RIL;
- ril.aid = "123456789";
-
- function do_test(aLock, aPassword, aEnabled) {
- const serviceClass = ICC_SERVICE_CLASS_VOICE |
- ICC_SERVICE_CLASS_DATA |
- ICC_SERVICE_CLASS_FAX;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SET_FACILITY_LOCK);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 5);
- equal(parcel[0], GECKO_CARDLOCK_TO_FACILITY[aLock]);
- equal(parcel[1], aEnabled ? "1" : "0");
- equal(parcel[2], aPassword);
- equal(parcel[3], serviceClass.toString());
- equal(parcel[4], ril.aid);
- };
-
- ril.iccSetCardLockEnabled({
- lockType: aLock,
- enabled: aEnabled,
- password: aPassword});
- }
-
- do_test(GECKO_CARDLOCK_PIN, "1234", true);
- do_test(GECKO_CARDLOCK_PIN, "1234", false);
- do_test(GECKO_CARDLOCK_FDN, "4321", true);
- do_test(GECKO_CARDLOCK_FDN, "4321", false);
-
- run_next_test();
-});
-
-/**
- * Verify RIL.iccChangeCardLockPassword
- */
-add_test(function test_icc_change_card_lock_password() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let ril = context.RIL;
-
-
- function do_test(aLock, aPassword, aNewPassword) {
- let GECKO_CARDLOCK_TO_REQUEST = {};
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PIN] = REQUEST_CHANGE_SIM_PIN;
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PIN2] = REQUEST_CHANGE_SIM_PIN2;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), GECKO_CARDLOCK_TO_REQUEST[aLock]);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 3);
- equal(parcel[0], aPassword);
- equal(parcel[1], aNewPassword);
- equal(parcel[2], ril.aid);
- };
-
- ril.iccChangeCardLockPassword({
- lockType: aLock,
- password: aPassword,
- newPassword: aNewPassword});
- }
-
- do_test(GECKO_CARDLOCK_PIN, "1234", "4321");
- do_test(GECKO_CARDLOCK_PIN2, "1234", "4321");
-
- run_next_test();
-});
-
-/**
- * Verify RIL.iccUnlockCardLock - PIN
- */
-add_test(function test_icc_unlock_card_lock_pin() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let buf = context.Buf;
- ril.aid = "123456789";
-
- function do_test(aLock, aPassword) {
- let GECKO_CARDLOCK_TO_REQUEST = {};
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PIN] = REQUEST_ENTER_SIM_PIN;
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PIN2] = REQUEST_ENTER_SIM_PIN2;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), GECKO_CARDLOCK_TO_REQUEST[aLock]);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 2);
- equal(parcel[0], aPassword);
- equal(parcel[1], ril.aid);
- };
-
- ril.iccUnlockCardLock({
- lockType: aLock,
- password: aPassword
- });
- }
-
- do_test(GECKO_CARDLOCK_PIN, "1234");
- do_test(GECKO_CARDLOCK_PIN2, "1234");
-
- run_next_test();
-});
-
-/**
- * Verify RIL.iccUnlockCardLock - PUK
- */
-add_test(function test_icc_unlock_card_lock_puk() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let buf = context.Buf;
- ril.aid = "123456789";
-
- function do_test(aLock, aPassword, aNewPin) {
- let GECKO_CARDLOCK_TO_REQUEST = {};
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PUK] = REQUEST_ENTER_SIM_PUK;
- GECKO_CARDLOCK_TO_REQUEST[GECKO_CARDLOCK_PUK2] = REQUEST_ENTER_SIM_PUK2;
-
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), GECKO_CARDLOCK_TO_REQUEST[aLock]);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 3);
- equal(parcel[0], aPassword);
- equal(parcel[1], aNewPin);
- equal(parcel[2], ril.aid);
- };
-
- ril.iccUnlockCardLock({
- lockType: aLock,
- password: aPassword,
- newPin: aNewPin
- });
- }
-
- do_test(GECKO_CARDLOCK_PUK, "12345678", "1234");
- do_test(GECKO_CARDLOCK_PUK2, "12345678", "1234");
-
- run_next_test();
-});
-
-/**
- * Verify RIL.iccUnlockCardLock - Depersonalization
- */
-add_test(function test_icc_unlock_card_lock_depersonalization() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let buf = context.Buf;
-
- function do_test(aPassword) {
- buf.sendParcel = function fakeSendParcel() {
- // Request Type.
- equal(this.readInt32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data
- let parcel = this.readStringList();
- equal(parcel.length, 1);
- equal(parcel[0], aPassword);
- };
-
- ril.iccUnlockCardLock({
- lockType: GECKO_CARDLOCK_NCK,
- password: aPassword
- });
- }
-
- do_test("12345678");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_CardState.js b/dom/system/gonk/tests/test_ril_worker_icc_CardState.js
deleted file mode 100644
index 788df5073..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_CardState.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_personalization_state() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
-
- function testPersonalization(isCdma, cardPersoState, geckoCardState) {
- let iccStatus = {
- cardState: CARD_STATE_PRESENT,
- gsmUmtsSubscriptionAppIndex: (!isCdma) ? 0 : -1,
- cdmaSubscriptionAppIndex: (isCdma) ? 0 : -1,
- apps: [
- {
- app_state: CARD_APPSTATE_SUBSCRIPTION_PERSO,
- perso_substate: cardPersoState
- }],
- };
-
- ril._isCdma = isCdma;
- ril._processICCStatus(iccStatus);
- equal(ril.cardState, geckoCardState);
- }
-
- // Test GSM personalization state.
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK,
- Ci.nsIIcc.CARD_STATE_NETWORK_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET,
- Ci.nsIIcc.CARD_STATE_NETWORK_SUBSET_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE,
- Ci.nsIIcc.CARD_STATE_CORPORATE_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
- Ci.nsIIcc.CARD_STATE_SERVICE_PROVIDER_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SIM,
- Ci.nsIIcc.CARD_STATE_SIM_LOCKED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
- Ci.nsIIcc.CARD_STATE_NETWORK_PUK_REQUIRED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK,
- Ci.nsIIcc.CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
- Ci.nsIIcc.CARD_STATE_CORPORATE_PUK_REQUIRED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
- Ci.nsIIcc.CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED);
- testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SIM_PUK,
- Ci.nsIIcc.CARD_STATE_SIM_PUK_REQUIRED);
-
- testPersonalization(false, CARD_PERSOSUBSTATE_UNKNOWN,
- Ci.nsIIcc.CARD_STATE_UNKNOWN);
- testPersonalization(false, CARD_PERSOSUBSTATE_IN_PROGRESS,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
- testPersonalization(false, CARD_PERSOSUBSTATE_READY,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_READY);
-
- // Test CDMA personalization state.
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1,
- Ci.nsIIcc.CARD_STATE_NETWORK1_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2,
- Ci.nsIIcc.CARD_STATE_NETWORK2_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD,
- Ci.nsIIcc.CARD_STATE_HRPD_NETWORK_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE,
- Ci.nsIIcc.CARD_STATE_RUIM_CORPORATE_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
- Ci.nsIIcc.CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM,
- Ci.nsIIcc.CARD_STATE_RUIM_LOCKED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK,
- Ci.nsIIcc.CARD_STATE_NETWORK1_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK,
- Ci.nsIIcc.CARD_STATE_NETWORK2_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD_PUK,
- Ci.nsIIcc.CARD_STATE_HRPD_NETWORK_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK,
- Ci.nsIIcc.CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
- Ci.nsIIcc.CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
- testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM_PUK,
- Ci.nsIIcc.CARD_STATE_RUIM_PUK_REQUIRED);
-
- testPersonalization(true, CARD_PERSOSUBSTATE_UNKNOWN,
- Ci.nsIIcc.CARD_STATE_UNKNOWN);
- testPersonalization(true, CARD_PERSOSUBSTATE_IN_PROGRESS,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
- testPersonalization(true, CARD_PERSOSUBSTATE_READY,
- Ci.nsIIcc.CARD_STATE_PERSONALIZATION_READY);
-
- run_next_test();
-});
-
-/**
- * Verify SIM app_state in _processICCStatus
- */
-add_test(function test_card_app_state() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
-
- function testCardAppState(cardAppState, geckoCardState) {
- let iccStatus = {
- cardState: CARD_STATE_PRESENT,
- gsmUmtsSubscriptionAppIndex: 0,
- apps: [
- {
- app_state: cardAppState
- }],
- };
-
- ril._processICCStatus(iccStatus);
- equal(ril.cardState, geckoCardState);
- }
-
- testCardAppState(CARD_APPSTATE_ILLEGAL,
- Ci.nsIIcc.CARD_STATE_ILLEGAL);
- testCardAppState(CARD_APPSTATE_PIN,
- Ci.nsIIcc.CARD_STATE_PIN_REQUIRED);
- testCardAppState(CARD_APPSTATE_PUK,
- Ci.nsIIcc.CARD_STATE_PUK_REQUIRED);
- testCardAppState(CARD_APPSTATE_READY,
- Ci.nsIIcc.CARD_STATE_READY);
- testCardAppState(CARD_APPSTATE_UNKNOWN,
- Ci.nsIIcc.CARD_STATE_UNKNOWN);
- testCardAppState(CARD_APPSTATE_DETECTED,
- Ci.nsIIcc.CARD_STATE_UNKNOWN);
-
- run_next_test();
-});
-
-/**
- * Verify permanent blocked for ICC.
- */
-add_test(function test_icc_permanent_blocked() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
-
- function testPermanentBlocked(pin1_replaced, universalPINState, pin1) {
- let iccStatus = {
- cardState: CARD_STATE_PRESENT,
- gsmUmtsSubscriptionAppIndex: 0,
- universalPINState: universalPINState,
- apps: [
- {
- pin1_replaced: pin1_replaced,
- pin1: pin1
- }]
- };
-
- ril._processICCStatus(iccStatus);
- equal(ril.cardState, Ci.nsIIcc.CARD_STATE_PERMANENT_BLOCKED);
- }
-
- testPermanentBlocked(1,
- CARD_PINSTATE_ENABLED_PERM_BLOCKED,
- CARD_PINSTATE_UNKNOWN);
- testPermanentBlocked(1,
- CARD_PINSTATE_ENABLED_PERM_BLOCKED,
- CARD_PINSTATE_ENABLED_PERM_BLOCKED);
- testPermanentBlocked(0,
- CARD_PINSTATE_UNKNOWN,
- CARD_PINSTATE_ENABLED_PERM_BLOCKED);
-
- run_next_test();
-});
-
-/**
- * Verify ICC without app index.
- */
-add_test(function test_icc_without_app_index() {
- const ICCID = "123456789";
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- let iccStatus = {
- cardState: CARD_STATE_PRESENT,
- gsmUmtsSubscriptionAppIndex: -1,
- universalPINState: CARD_PINSTATE_DISABLED,
- apps: [
- {
- app_state: CARD_APPSTATE_READY
- }]
- };
-
- context.ICCRecordHelper.readICCID = function fakeReadICCID() {
- ril.iccInfo.iccid = ICCID;
- };
-
- ril._processICCStatus(iccStatus);
-
- // Should read icc id event if the app index is -1.
- equal(ril.iccInfo.iccid, ICCID);
- // cardState is "unknown" if the app index is -1.
- equal(ril.cardState, GECKO_CARDSTATE_UNKNOWN);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_GsmPDUHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_GsmPDUHelper.js
deleted file mode 100644
index 0d074da79..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_GsmPDUHelper.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify GsmPDUHelper.writeTimestamp
- */
-add_test(function test_write_timestamp() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
-
- // current date
- let dateInput = new Date();
- let dateOutput = new Date();
- helper.writeTimestamp(dateInput);
- dateOutput.setTime(helper.readTimestamp());
-
- equal(dateInput.getFullYear(), dateOutput.getFullYear());
- equal(dateInput.getMonth(), dateOutput.getMonth());
- equal(dateInput.getDate(), dateOutput.getDate());
- equal(dateInput.getHours(), dateOutput.getHours());
- equal(dateInput.getMinutes(), dateOutput.getMinutes());
- equal(dateInput.getSeconds(), dateOutput.getSeconds());
- equal(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
-
- // 2034-01-23 12:34:56 -0800 GMT
- let time = Date.UTC(2034, 1, 23, 12, 34, 56);
- time = time - (8 * 60 * 60 * 1000);
- dateInput.setTime(time);
- helper.writeTimestamp(dateInput);
- dateOutput.setTime(helper.readTimestamp());
-
- equal(dateInput.getFullYear(), dateOutput.getFullYear());
- equal(dateInput.getMonth(), dateOutput.getMonth());
- equal(dateInput.getDate(), dateOutput.getDate());
- equal(dateInput.getHours(), dateOutput.getHours());
- equal(dateInput.getMinutes(), dateOutput.getMinutes());
- equal(dateInput.getSeconds(), dateOutput.getSeconds());
- equal(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
-
- run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper.octectToBCD and GsmPDUHelper.BCDToOctet
- */
-add_test(function test_octect_BCD() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
-
- // 23
- let number = 23;
- let octet = helper.BCDToOctet(number);
- equal(helper.octetToBCD(octet), number);
-
- // 56
- number = 56;
- octet = helper.BCDToOctet(number);
- equal(helper.octetToBCD(octet), number);
-
- // 0x23
- octet = 0x23;
- number = helper.octetToBCD(octet);
- equal(helper.BCDToOctet(number), octet);
-
- // 0x56
- octet = 0x56;
- number = helper.octetToBCD(octet);
- equal(helper.BCDToOctet(number), octet);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCContactHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCContactHelper.js
deleted file mode 100644
index 29b83b76a..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCContactHelper.js
+++ /dev/null
@@ -1,1042 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Test error message returned in onerror for readICCContacts.
- */
-add_test(function test_error_message_read_icc_contact () {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- function do_test(options, expectedErrorMsg) {
- ril.sendChromeMessage = function(message) {
- equal(message.errorMsg, expectedErrorMsg);
- }
- ril.readICCContacts(options);
- }
-
- // Error 1, didn't specify correct contactType.
- do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
-
- // Error 2, specifying a non-supported contactType.
- ril.appType = CARD_APPTYPE_USIM;
- do_test({contactType: "foo"}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
-
- // Error 3, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
- // but forget to add implemenetations for it.
- USIM_PBR_FIELDS.push("pbc");
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN},
- CONTACT_ERR_FIELD_NOT_SUPPORTED);
-
- run_next_test();
-});
-
-/**
- * Test error message returned in onerror for updateICCContact.
- */
-add_test(function test_error_message_update_icc_contact() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
-
- const ICCID = "123456789";
- ril.iccInfo.iccid = ICCID;
-
- function do_test(options, expectedErrorMsg) {
- ril.sendChromeMessage = function(message) {
- equal(message.errorMsg, expectedErrorMsg);
- }
- ril.updateICCContact(options);
- }
-
- // Error 1, didn't specify correct contactType.
- do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
-
- // Error 2, specifying a correct contactType, but without providing 'contact'.
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN},
- CONTACT_ERR_REQUEST_NOT_SUPPORTED);
-
- // Error 3, specifying a non-supported contactType.
- ril.appType = CARD_APPTYPE_USIM;
- do_test({contactType: GECKO_CARDCONTACT_TYPE_SDN, contact: {}},
- CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
-
- // Error 4, without supplying pin2.
- do_test({contactType: GECKO_CARDCONTACT_TYPE_FDN,
- contact: {contactId: ICCID + "1"}},
- GECKO_ERROR_SIM_PIN2);
-
- // Error 5, No free record found in EF_ADN.
- let record = context.ICCRecordHelper;
- record.readPBR = function(onsuccess, onerror) {
- onsuccess([{adn: {fileId: 0x4f3a}}]);
- };
-
- let io = context.ICCIOHelper;
- io.loadLinearFixedEF = function(options) {
- options.totalRecords = 1;
- options.p1 = 1;
- options.callback(options);
- };
-
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN, contact: {}},
- CONTACT_ERR_NO_FREE_RECORD_FOUND);
-
- // Error 6, ICC IO Error.
- io.loadLinearFixedEF = function(options) {
- ril[REQUEST_SIM_IO](0, {
- errorMsg: GECKO_ERROR_GENERIC_FAILURE
- });
- };
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN,
- contact: {contactId: ICCID + "1"}},
- GECKO_ERROR_GENERIC_FAILURE);
-
- // Error 7, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
- // but forget to add implemenetations for it.
- USIM_PBR_FIELDS.push("pbc");
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN,
- contact: {contactId: ICCID + "1"}},
- CONTACT_ERR_FIELD_NOT_SUPPORTED);
-
- // Error 8, EF_PBR doesn't exist.
- record.readPBR = function(onsuccess, onerror) {
- onsuccess([]);
- };
-
- do_test({contactType: GECKO_CARDCONTACT_TYPE_ADN,
- contact: {contactId: ICCID + "1"}},
- CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.readICCContacts
- */
-add_test(function test_read_icc_contacts() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- let ril = context.RIL;
- let test_data = [
- //Record 1.
- {
- comment: "Test read SIM adn contact",
- rawData: {
- simType: CARD_APPTYPE_SIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 2.
- {
- comment: "Test read SIM fdn contact",
- rawData: {
- simType: CARD_APPTYPE_SIM,
- contactType: GECKO_CARDCONTACT_TYPE_FDN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 3.
- {
- comment: "Test read USIM adn contact",
- rawData: {
- simType: CARD_APPTYPE_USIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- pbrs: [{adn:{fileId: 0x6f3a}, email: {}, anr0: {}}],
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- email: "hello@mail.com",
- anr: "123456",
- },
- expectedContact: [{
- pbrIndex: 0,
- recordId: 1,
- alphaId: "name",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }],
- },
- //Record 4.
- {
- comment: "Test read USIM adn contacts",
- rawData: {
- simType: CARD_APPTYPE_USIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- pbrs: [{adn:{fileId: 0x6f3a}, email: {}, anr0: {}},
- {adn:{fileId: 0x6f3b}, email: {}, anr0: {}}],
- adnLike: [{recordId: 1, alphaId: "name1", number: "111111"},
- {recordId: 2, alphaId: "name2", number: "222222"}],
- email: "hello@mail.com",
- anr: "123456",
- },
- expectedContact: [
- {
- pbrIndex: 0,
- recordId: 1,
- alphaId: "name1",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 0,
- recordId: 2,
- alphaId: "name2",
- number: "222222",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 1,
- recordId: 1,
- alphaId: "name1",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 1,
- recordId: 2,
- alphaId: "name2",
- number: "222222",
- email: "hello@mail.com",
- anr: ["123456"]
- }
- ],
- },
- //Record 5.
- {
- comment: "Test read USIM fdn contact",
- rawData: {
- simType: CARD_APPTYPE_USIM,
- contactType: GECKO_CARDCONTACT_TYPE_FDN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 6.
- {
- comment: "Test read RUIM adn contact",
- rawData: {
- simType: CARD_APPTYPE_RUIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 7.
- {
- comment: "Test read RUIM fdn contact",
- rawData: {
- simType: CARD_APPTYPE_RUIM,
- contactType: GECKO_CARDCONTACT_TYPE_FDN,
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- },
- expectedContact: [{
- recordId: 1,
- alphaId: "name",
- number: "111111"
- }],
- },
- //Record 8.
- {
- comment: "Test read RUIM adn contact with enhanced phone book",
- rawData: {
- simType: CARD_APPTYPE_RUIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- pbrs: [{adn:{fileId: 0x6f3a}, email: {}, anr0: {}}],
- adnLike: [{recordId: 1, alphaId: "name", number: "111111"}],
- email: "hello@mail.com",
- anr: "123456",
- enhancedPhoneBook: true,
- },
- expectedContact: [{
- pbrIndex: 0,
- recordId: 1,
- alphaId: "name",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }],
- },
- //Record 9.
- {
- comment: "Test read RUIM adn contacts with enhanced phone book",
- rawData: {
- simType: CARD_APPTYPE_RUIM,
- contactType: GECKO_CARDCONTACT_TYPE_ADN,
- pbrs: [{adn:{fileId: 0x6f3a}, email: {}, anr0: {}},
- {adn:{fileId: 0x6f3b}, email: {}, anr0: {}}],
- adnLike: [{recordId: 1, alphaId: "name1", number: "111111"},
- {recordId: 2, alphaId: "name2", number: "222222"}],
- email: "hello@mail.com",
- anr: "123456",
- enhancedPhoneBook: true,
- },
- expectedContact: [
- {
- pbrIndex: 0,
- recordId: 1,
- alphaId: "name1",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 0,
- recordId: 2,
- alphaId: "name2",
- number: "222222",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 1,
- recordId: 1,
- alphaId: "name1",
- number: "111111",
- email: "hello@mail.com",
- anr: ["123456"]
- }, {
- pbrIndex: 1,
- recordId: 2,
- alphaId: "name2",
- number: "222222",
- email: "hello@mail.com",
- anr: ["123456"]
- }
- ],
- },
- ];
-
- function do_test(aTestData, aExpectedContact) {
- ril.appType = aTestData.simType;
- ril._isCdma = (aTestData.simType === CARD_APPTYPE_RUIM);
- ril.iccInfoPrivate.cst = (aTestData.enhancedPhoneBook) ?
- [0x20, 0x0C, 0x0, 0x0, 0x0]:
- [0x20, 0x00, 0x0, 0x0, 0x0];
-
- ril.iccInfoPrivate.sst = (aTestData.simType === CARD_APPTYPE_SIM)?
- [0x20, 0x0, 0x0, 0x0, 0x0]:
- [0x2, 0x0, 0x0, 0x0, 0x0];
-
- // Override some functions to test.
- contactHelper.getContactFieldRecordId = function(pbr, contact, field, onsuccess, onerror) {
- onsuccess(1);
- };
-
- record.readPBR = function readPBR(onsuccess, onerror) {
- onsuccess(JSON.parse(JSON.stringify(aTestData.pbrs)));
- };
-
- record.readADNLike = function readADNLike(fileId, extFileId, onsuccess, onerror) {
- onsuccess(JSON.parse(JSON.stringify(aTestData.adnLike)));
- };
-
- record.readEmail = function readEmail(fileId, fileType, recordNumber, onsuccess, onerror) {
- onsuccess(aTestData.email);
- };
-
- record.readANR = function readANR(fileId, fileType, recordNumber, onsuccess, onerror) {
- onsuccess(aTestData.anr);
- };
-
- let onsuccess = function onsuccess(contacts) {
- for (let i = 0; i < contacts.length; i++) {
- do_print("check contacts[" + i + "]:" + JSON.stringify(contacts[i]));
- deepEqual(contacts[i], aExpectedContact[i]);
- }
- };
-
- let onerror = function onerror(errorMsg) {
- do_print("readICCContacts failed: " + errorMsg);
- ok(false);
- };
-
- contactHelper.readICCContacts(aTestData.simType, aTestData.contactType, onsuccess, onerror);
- }
-
- for (let i = 0; i < test_data.length; i++) {
- do_print(test_data[i].comment);
- do_test(test_data[i].rawData, test_data[i].expectedContact);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.updateICCContact with appType is CARD_APPTYPE_USIM.
- */
-add_test(function test_update_icc_contact() {
- const ADN_RECORD_ID = 100;
- const ADN_SFI = 1;
- const IAP_FILE_ID = 0x4f17;
- const EMAIL_FILE_ID = 0x4f50;
- const EMAIL_RECORD_ID = 20;
- const ANR0_FILE_ID = 0x4f11;
- const ANR0_RECORD_ID = 30;
- const EXT_RECORD_ID = 0x01;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- let ril = context.RIL;
-
- function do_test(aSimType, aContactType, aContact, aPin2, aFileType, aHaveIapIndex, aEnhancedPhoneBook) {
- ril.appType = aSimType;
- ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
- ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x20, 0x0C, 0x28, 0x0, 0x20]
- : [0x20, 0x0, 0x28, 0x0, 0x20];
- ril.iccInfoPrivate.sst = (aSimType === CARD_APPTYPE_SIM)?
- [0x20, 0x0, 0x28, 0x0, 0x20]:
- [0x16, 0x0, 0x0, 0x0, 0x0];
-
- recordHelper.readPBR = function(onsuccess, onerror) {
- if (aFileType === ICC_USIM_TYPE1_TAG) {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE1_TAG},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE1_TAG},
- ext1: {fileId: ICC_EF_EXT1}
-
- }]);
- } else if (aFileType === ICC_USIM_TYPE2_TAG) {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN,
- sfi: ADN_SFI},
- iap: {fileId: IAP_FILE_ID},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 0},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 1},
- ext1: {fileId: ICC_EF_EXT1}
- }]);
- }
- };
-
- recordHelper.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- if (aContactType === GECKO_CARDCONTACT_TYPE_FDN) {
- equal(fileId, ICC_EF_FDN);
- } else if (aContactType === GECKO_CARDCONTACT_TYPE_ADN) {
- equal(fileId, ICC_EF_ADN);
- }
-
- if (aContact.number.length > ADN_MAX_NUMBER_DIGITS) {
- equal(extRecordNumber, EXT_RECORD_ID);
- } else {
- equal(extRecordNumber, 0xff);
- }
-
- equal(pin2, aPin2);
- equal(contact.alphaId, aContact.alphaId);
- equal(contact.number, aContact.number);
- onsuccess({alphaId: contact.alphaId,
- number: contact.number.substring(0, ADN_MAX_NUMBER_DIGITS)});
- };
-
- recordHelper.getADNLikeExtensionRecordNumber = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess(EXT_RECORD_ID);
- };
-
- recordHelper.updateExtension = function(fileId, recordNumber, number, onsuccess, onerror) {
- onsuccess();
- };
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- onsuccess(EXT_RECORD_ID);
- };
-
- recordHelper.cleanEFRecord = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess();
- }
-
- recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
- equal(fileId, IAP_FILE_ID);
- equal(recordNumber, ADN_RECORD_ID);
- onsuccess((aHaveIapIndex) ? [EMAIL_RECORD_ID, ANR0_RECORD_ID]
- : [0xff, 0xff]);
- };
-
- recordHelper.updateIAP = function(fileId, recordNumber, iap, onsuccess, onerror) {
- equal(fileId, IAP_FILE_ID);
- equal(recordNumber, ADN_RECORD_ID);
- onsuccess();
- };
-
- recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
- equal(pbr.email.fileId, EMAIL_FILE_ID);
- if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
- equal(recordNumber, ADN_RECORD_ID);
- } else if (pbr.email.fileType === ICC_USIM_TYPE2_TAG) {
- equal(recordNumber, EMAIL_RECORD_ID);
- }
- equal(email, aContact.email);
- onsuccess(email);
- };
-
- recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
- equal(pbr.anr0.fileId, ANR0_FILE_ID);
- if (pbr.anr0.fileType === ICC_USIM_TYPE1_TAG) {
- equal(recordNumber, ADN_RECORD_ID);
- } else if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
- equal(recordNumber, ANR0_RECORD_ID);
- }
- if (Array.isArray(aContact.anr)) {
- equal(number, aContact.anr[0]);
- }
- onsuccess(number);
- };
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- let recordId = 0;
- if (fileId === EMAIL_FILE_ID) {
- recordId = EMAIL_RECORD_ID;
- } else if (fileId === ANR0_FILE_ID) {
- recordId = ANR0_RECORD_ID;
- }
- onsuccess(recordId);
- };
-
- let isSuccess = false;
- let onsuccess = function onsuccess(updatedContact) {
- equal(ADN_RECORD_ID, updatedContact.recordId);
- equal(aContact.alphaId, updatedContact.alphaId);
- equal(aContact.number.substring(0, ADN_MAX_NUMBER_DIGITS + EXT_MAX_NUMBER_DIGITS),
- updatedContact.number);
- if ((aSimType == CARD_APPTYPE_USIM || aSimType == CARD_APPTYPE_RUIM) &&
- (aFileType == ICC_USIM_TYPE1_TAG || aFileType == ICC_USIM_TYPE2_TAG)) {
- if (aContact.hasOwnProperty('email')) {
- equal(aContact.email, updatedContact.email);
- }
-
- if (aContact.hasOwnProperty('anr')) {
- equal(aContact.anr[0], updatedContact.anr[0]);
- }
- } else {
- equal(updatedContact.email, null);
- equal(updatedContact.anr, null);
- }
-
- do_print("updateICCContact success");
- isSuccess = true;
- };
-
- let onerror = function onerror(errorMsg) {
- do_print("updateICCContact failed: " + errorMsg);
- };
-
- contactHelper.updateICCContact(aSimType, aContactType, aContact, aPin2, onsuccess, onerror);
- ok(isSuccess);
- }
-
- let contacts = [
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test",
- number: "123456",
- email: "test@mail.com",
- anr: ["+654321"]
- },
- // a contact without email and anr.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test2",
- number: "123456",
- },
- // a contact with email but no anr.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test3",
- number: "123456",
- email: "test@mail.com"
- },
- // a contact with anr but no email.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test4",
- number: "123456",
- anr: ["+654321"]
- },
- // a contact number over 20 digits.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test4",
- number: "0123456789012345678901234567890123456789",
- anr: ["+654321"]
- },
- // a contact number over 40 digits.
- {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test5",
- number: "01234567890123456789012345678901234567890123456789",
- anr: ["+654321"]
- }];
-
- for (let i = 0; i < contacts.length; i++) {
- let contact = contacts[i];
- // SIM
- do_print("Test update SIM adn contacts");
- do_test(CARD_APPTYPE_SIM, GECKO_CARDCONTACT_TYPE_ADN, contact);
-
- do_print("Test update SIM fdn contacts");
- do_test(CARD_APPTYPE_SIM, GECKO_CARDCONTACT_TYPE_FDN, contact, "1234");
-
- // USIM
- do_print("Test update USIM adn contacts");
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE1_TAG);
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE2_TAG, true);
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE2_TAG, false);
-
- do_print("Test update USIM fdn contacts");
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_FDN, contact, "1234");
-
- // RUIM
- do_print("Test update RUIM adn contacts");
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_ADN, contact);
-
- do_print("Test update RUIM fdn contacts");
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_FDN, contact, "1234");
-
- // RUIM with enhanced phone book
- do_print("Test update RUIM adn contacts with enhanced phone book");
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE1_TAG, null,true);
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE2_TAG, true, true);
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null,
- ICC_USIM_TYPE2_TAG, false, true);
-
- do_print("Test update RUIM fdn contacts with enhanced phone book");
- do_test(CARD_APPTYPE_RUIM, GECKO_CARDCONTACT_TYPE_FDN, contact, "1234",
- null, true);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.updateICCContact with appType is CARD_APPTYPE_USIM and
- * insufficient space to store Type 2 USIM contact fields.
- */
-add_test(function test_update_icc_contact_full_email_and_anr_field() {
- const ADN_RECORD_ID = 100;
- const ADN_SFI = 1;
- const IAP_FILE_ID = 0x4f17;
- const EMAIL_FILE_ID = 0x4f50;
- const EMAIL_RECORD_ID = 20;
- const ANR0_FILE_ID = 0x4f11;
- const ANR0_RECORD_ID = 30;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- let ril = context.RIL;
-
- function do_test(aSimType, aContactType, aContact, aPin2) {
- ril.appType = CARD_APPTYPE_USIM;
- ril.iccInfoPrivate.sst = [0x2, 0x0, 0x0, 0x0, 0x0];
-
- recordHelper.readPBR = function(onsuccess, onerror) {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN,
- sfi: ADN_SFI},
- iap: {fileId: IAP_FILE_ID},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 0},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 1}
- }]);
- };
-
- recordHelper.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- if (aContactType === GECKO_CARDCONTACT_TYPE_ADN) {
- equal(fileId, ICC_EF_ADN);
- }
- equal(pin2, aPin2);
- equal(contact.alphaId, aContact.alphaId);
- equal(contact.number, aContact.number);
- onsuccess({alphaId: contact.alphaId,
- number: contact.number});
- };
-
- recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
- equal(fileId, IAP_FILE_ID);
- equal(recordNumber, ADN_RECORD_ID);
- onsuccess([0xff, 0xff]);
- };
-
- recordHelper.updateIAP = function(fileId, recordNumber, iap, onsuccess, onerror) {
- equal(fileId, IAP_FILE_ID);
- equal(recordNumber, ADN_RECORD_ID);
- onsuccess();
- };
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- let recordId = 0;
- // emulate email and anr don't have free record.
- if (fileId === EMAIL_FILE_ID || fileId === ANR0_FILE_ID) {
- onerror(CONTACT_ERR_NO_FREE_RECORD_FOUND);
- } else {
- onsuccess(recordId);
- }
- };
-
- let isSuccess = false;
- let onsuccess = function onsuccess(updatedContact) {
- equal(ADN_RECORD_ID, updatedContact.recordId);
- equal(aContact.alphaId, updatedContact.alphaId);
- equal(updatedContact.email, null);
- equal(updatedContact.anr, null);
-
- do_print("updateICCContact success");
- isSuccess = true;
- };
-
- let onerror = function onerror(errorMsg) {
- do_print("updateICCContact failed: " + errorMsg);
- };
-
- contactHelper.updateICCContact(aSimType, aContactType, aContact, aPin2, onsuccess, onerror);
- ok(isSuccess);
- }
-
- let contact = {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test",
- number: "123456",
- email: "test@mail.com",
- anr: ["+654321"]
- };
-
- // USIM
- do_print("Test update USIM adn contacts");
- do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null);
-
- run_next_test();
-});
-
-/**
- * Verify updateICCContact with removal of anr and email with File Type 1.
- */
-add_test(function test_update_icc_contact_with_remove_type1_attr() {
- const ADN_RECORD_ID = 100;
- const IAP_FILE_ID = 0x4f17;
- const EMAIL_FILE_ID = 0x4f50;
- const EMAIL_RECORD_ID = 20;
- const ANR0_FILE_ID = 0x4f11;
- const ANR0_RECORD_ID = 30;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
-
- recordHelper.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- onsuccess({alphaId: contact.alphaId,
- number: contact.number});
- };
-
- let contact = {
- pbrIndex: 0,
- recordId: ADN_RECORD_ID,
- alphaId: "test2",
- number: "123456",
- };
-
- recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess([EMAIL_RECORD_ID, ANR0_RECORD_ID]);
- };
-
- recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
- ok(email == null);
- onsuccess(email);
- };
-
- recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
- ok(number == null);
- onsuccess(number);
- };
-
- function do_test(type) {
- recordHelper.readPBR = function(onsuccess, onerror) {
- if (type == ICC_USIM_TYPE1_TAG) {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE1_TAG},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE1_TAG}}]);
- } else {
- onsuccess([{
- adn: {fileId: ICC_EF_ADN},
- iap: {fileId: IAP_FILE_ID},
- email: {fileId: EMAIL_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 0},
- anr0: {fileId: ANR0_FILE_ID,
- fileType: ICC_USIM_TYPE2_TAG,
- indexInIAP: 1}}]);
- }
- };
-
- let successCb = function(updatedContact) {
- equal(updatedContact.email, null);
- equal(updatedContact.anr, null);
- ok(true);
- };
-
- let errorCb = function(errorMsg) {
- do_print(errorMsg);
- ok(false);
- };
-
- contactHelper.updateICCContact(CARD_APPTYPE_USIM,
- GECKO_CARDCONTACT_TYPE_ADN,
- contact, null, successCb, errorCb);
- }
-
- do_test(ICC_USIM_TYPE1_TAG);
- do_test(ICC_USIM_TYPE2_TAG);
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.findFreeICCContact in SIM
- */
-add_test(function test_find_free_icc_contact_sim() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- // Correct record Id starts with 1, so put a null element at index 0.
- let records = [null];
- const MAX_RECORDS = 3;
- const PBR_INDEX = 0;
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- if (records.length > MAX_RECORDS) {
- onerror("No free record found.");
- return;
- }
-
- onsuccess(records.length);
- };
-
- let successCb = function(pbrIndex, recordId) {
- equal(pbrIndex, PBR_INDEX);
- records[recordId] = {};
- };
-
- let errorCb = function(errorMsg) {
- do_print(errorMsg);
- ok(false);
- };
-
- for (let i = 0; i < MAX_RECORDS; i++) {
- contactHelper.findFreeICCContact(CARD_APPTYPE_SIM,
- GECKO_CARDCONTACT_TYPE_ADN,
- successCb, errorCb);
- }
- // The 1st element, records[0], is null.
- equal(records.length - 1, MAX_RECORDS);
-
- // Now the EF is full, so finding a free one should result failure.
- successCb = function(pbrIndex, recordId) {
- ok(false);
- };
-
- errorCb = function(errorMsg) {
- ok(errorMsg === "No free record found.");
- };
- contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, GECKO_CARDCONTACT_TYPE_ADN,
- successCb, errorCb);
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.findFreeICCContact in USIM
- */
-add_test(function test_find_free_icc_contact_usim() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let recordHelper = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- const ADN1_FILE_ID = 0x6f3a;
- const ADN2_FILE_ID = 0x6f3b;
- const MAX_RECORDS = 3;
-
- // The adn in the first phonebook set has already two records, which means
- // only 1 free record remained.
- let pbrs = [{adn: {fileId: ADN1_FILE_ID, records: [null, {}, {}]}},
- {adn: {fileId: ADN2_FILE_ID, records: [null]}}];
-
- recordHelper.readPBR = function readPBR(onsuccess, onerror) {
- onsuccess(pbrs);
- };
-
- recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
- let pbr = (fileId == ADN1_FILE_ID ? pbrs[0]: pbrs[1]);
- if (pbr.adn.records.length > MAX_RECORDS) {
- onerror("No free record found.");
- return;
- }
-
- onsuccess(pbr.adn.records.length);
- };
-
- let successCb = function(pbrIndex, recordId) {
- equal(pbrIndex, 0);
- pbrs[pbrIndex].adn.records[recordId] = {};
- };
-
- let errorCb = function(errorMsg) {
- ok(false);
- };
-
- contactHelper.findFreeICCContact(CARD_APPTYPE_USIM,
- GECKO_CARDCONTACT_TYPE_ADN,
- successCb, errorCb);
-
- // Now the EF_ADN in the 1st phonebook set is full, so the next free contact
- // will come from the 2nd phonebook set.
- successCb = function(pbrIndex, recordId) {
- equal(pbrIndex, 1);
- equal(recordId, 1);
- }
- contactHelper.findFreeICCContact(CARD_APPTYPE_USIM,
- GECKO_CARDCONTACT_TYPE_ADN,
- successCb, errorCb);
-
- run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.updateADNLikeWithExtension
- */
-add_test(function test_update_adn_like_with_extension() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let record = context.ICCRecordHelper;
- let contactHelper = context.ICCContactHelper;
- ril.appType = CARD_APPTYPE_SIM;
- // Correct record Id starts from 1, so put a null element at index 0.
- // ext_records contains data at index 1, and it only has 1 free record at index 2.
- let notFree = 0x01;
- let ext_records = [null, notFree, null];
-
- function do_test(contact, extRecordNumber, expectedExtRecordNumber, expectedNumber, expectedCleanEFRecord) {
- // Override some functions to test.
- record.getADNLikeExtensionRecordNumber = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess(extRecordNumber);
- }
-
- record.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
- equal(extRecordNumber, expectedExtRecordNumber);
- onsuccess({alphaId: contact.alphaId,
- number: contact.number.substring(0, ADN_MAX_NUMBER_DIGITS)});
- }
-
- record.updateExtension = function(fileId, recordNumber, number, onsuccess, onerror) {
- if (recordNumber > ext_records.length) {
- onerror("updateExtension failed.");
- return;
- }
- ext_records[recordNumber] = number;
- onsuccess();
- }
-
- record.findFreeRecordId = function(fileId, onsuccess, onerror) {
- for (let i = 1; i < ext_records.length; i++) {
- if (!ext_records[i]) {
- onsuccess(i);
- return;
- }
- }
-
- onerror("No free record found.");
- }
-
- let isCleanEFRecord = false;
- record.cleanEFRecord = function(fileId, recordNumber, onsuccess, onerror) {
- if (recordNumber > ext_records.length) {
- onerror("cleanEFRecord failed.");
- return;
- }
- ext_records[recordNumber] = null;
- isCleanEFRecord = true;
- onsuccess();
- }
-
- let successCb = function successCb(updatedContact) {
- equal(updatedContact.number, expectedNumber);
- };
-
- let errorCb = function errorCb(errorMsg) {
- do_print("updateADNLikeWithExtension failed, msg = " + errorMsg);
- ok(false);
- };
-
- contactHelper.updateADNLikeWithExtension(ICC_EF_ADN, ICC_EF_EXT1, contact, null, successCb, errorCb);
-
- if (expectedCleanEFRecord) {
- ok(isCleanEFRecord);
- }
- }
-
- // Update extension record with previous extension record number.
- do_test({recordId: 1, alphaId: "test", number: "001122334455667788991234"}, 0x01, 0x01, "001122334455667788991234");
- // Update extension record and find a free record.
- do_test({recordId: 1, alphaId: "test", number: "001122334455667788995678"}, 0xff, 0x02, "001122334455667788995678");
- // Update extension record with no free extension record.
- do_test({recordId: 1, alphaId: "test", number: "001122334455667788994321"}, 0xff, 0xff, "00112233445566778899");
- // Update extension record with clean previous extension record.
- do_test({recordId: 1, alphaId: "test", number: "00112233445566778899"}, 0x01, 0xff, "00112233445566778899", true);
- // Update extension record with no extension record and previous extension record.
- do_test({recordId: 1, alphaId: "test", number: "00112233445566778899"}, 0xff, 0xff, "00112233445566778899");
-
- run_next_test();
-}); \ No newline at end of file
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCIOHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCIOHelper.js
deleted file mode 100644
index e690b1206..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCIOHelper.js
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify ICCIOHelper.loadLinearFixedEF with recordSize.
- */
-add_test(function test_load_linear_fixed_ef() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let io = context.ICCIOHelper;
-
- io.getResponse = function fakeGetResponse(options) {
- // When recordSize is provided, loadLinearFixedEF should call iccIO directly.
- ok(false);
- run_next_test();
- };
-
- ril.iccIO = function fakeIccIO(options) {
- ok(true);
- run_next_test();
- };
-
- io.loadLinearFixedEF({recordSize: 0x20});
-});
-
-/**
- * Verify ICCIOHelper.loadLinearFixedEF without recordSize.
- */
-add_test(function test_load_linear_fixed_ef() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let io = context.ICCIOHelper;
-
- io.getResponse = function fakeGetResponse(options) {
- ok(true);
- run_next_test();
- };
-
- ril.iccIO = function fakeIccIO(options) {
- // When recordSize is not provided, loadLinearFixedEF should call getResponse.
- ok(false);
- run_next_test();
- };
-
- io.loadLinearFixedEF({});
-});
-
-/**
- * Verify ICC IO Error.
- */
-add_test(function test_process_icc_io_error() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
-
- function do_test(sw1, sw2, expectedErrorMsg) {
- let called = false;
- function errorCb(errorMsg) {
- called = true;
- equal(errorMsg, expectedErrorMsg);
- }
-
- // Write sw1 and sw2 to buffer.
- buf.writeInt32(sw1);
- buf.writeInt32(sw2);
-
- context.RIL[REQUEST_SIM_IO](0, {fileId: 0xffff,
- command: 0xff,
- onerror: errorCb});
-
- // onerror callback should be triggered.
- ok(called);
- }
-
- let TEST_DATA = [
- // [sw1, sw2, expectError]
- [ICC_STATUS_ERROR_COMMAND_NOT_ALLOWED, 0xff, GECKO_ERROR_GENERIC_FAILURE],
- [ICC_STATUS_ERROR_WRONG_PARAMETERS, 0xff, GECKO_ERROR_GENERIC_FAILURE],
- ];
-
- for (let i = 0; i < TEST_DATA.length; i++) {
- do_test.apply(null, TEST_DATA[i]);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCIOHelper.processICCIOGetResponse for EF_TYPE_TRANSPARENT.
- */
-add_test(function test_icc_io_get_response_for_transparent_structure() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let iccioHelper = context.ICCIOHelper;
- let pduHelper = context.GsmPDUHelper;
-
- let responseArray = [
- // SIM response.
- [0x00, 0x00, 0x00, 0x0A, 0x2F, 0xE2, 0x04, 0x00, 0x0A, 0xA0, 0xAA, 0x00,
- 0x02, 0x00, 0x00],
- // USIM response.
- [0x62, 0x22, 0x82, 0x02, 0x41, 0x21, 0x83, 0x02, 0x2F, 0xE2, 0xA5, 0x09,
- 0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x05,
- 0x8B, 0x03, 0x2F, 0x06, 0x0B, 0x80, 0x02, 0x00, 0x0A, 0x88, 0x01, 0x10]
- ];
-
- for (let i = 0; i < responseArray.length; i++) {
- let strLen = responseArray[i].length * 2;
- buf.writeInt32(strLen);
- for (let j = 0; j < responseArray[i].length; j++) {
- pduHelper.writeHexOctet(responseArray[i][j]);
- }
- buf.writeStringDelimiter(strLen);
-
- let options = {fileId: ICC_EF_ICCID,
- structure: EF_STRUCTURE_TRANSPARENT};
- iccioHelper.processICCIOGetResponse(options);
-
- equal(options.fileSize, 0x0A);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCIOHelper.processICCIOGetResponse for EF_TYPE_LINEAR_FIXED.
- */
-add_test(function test_icc_io_get_response_for_linear_fixed_structure() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let iccioHelper = context.ICCIOHelper;
- let pduHelper = context.GsmPDUHelper;
-
- let responseArray = [
- // SIM response.
- [0x00, 0x00, 0x00, 0x1A, 0x6F, 0x40, 0x04, 0x00, 0x11, 0xA0, 0xAA, 0x00,
- 0x02, 0x01, 0x1A],
- // USIM response.
- [0x62, 0x1E, 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01, 0x83, 0x02, 0x6F,
- 0x40, 0xA5, 0x03, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x07, 0x8B, 0x03, 0x6F,
- 0x06, 0x02, 0x80, 0x02, 0x00, 0x1A, 0x88, 0x00]
- ];
-
- for (let i = 0; i < responseArray.length; i++) {
- let strLen = responseArray[i].length * 2;
- buf.writeInt32(strLen);
- for (let j = 0; j < responseArray[i].length; j++) {
- pduHelper.writeHexOctet(responseArray[i][j]);
- }
- buf.writeStringDelimiter(strLen);
-
- let options = {fileId: ICC_EF_MSISDN,
- structure: EF_STRUCTURE_LINEAR_FIXED};
- iccioHelper.processICCIOGetResponse(options);
-
- equal(options.fileSize, 0x1A);
- equal(options.recordSize, 0x1A);
- equal(options.totalRecords, 0x01);
- }
-
- run_next_test();
-});
-
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js
deleted file mode 100644
index 91495b1b7..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js
+++ /dev/null
@@ -1,652 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify ICCPDUHelper#readICCUCS2String()
- */
-add_test(function test_read_icc_ucs2_string() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- // 0x80
- let text = "TEST";
- helper.writeUCS2String(text);
- // Also write two unused octets.
- let ffLen = 2;
- for (let i = 0; i < ffLen; i++) {
- helper.writeHexOctet(0xff);
- }
- equal(iccHelper.readICCUCS2String(0x80, (2 * text.length) + ffLen), text);
-
- // 0x81
- let array = [0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca,
- 0xff, 0xff];
- let len = array.length;
- for (let i = 0; i < len; i++) {
- helper.writeHexOctet(array[i]);
- }
- equal(iccHelper.readICCUCS2String(0x81, len), "Mozilla\u694a");
-
- // 0x82
- let array2 = [0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61,
- 0xca, 0xff, 0xff];
- let len2 = array2.length;
- for (let i = 0; i < len2; i++) {
- helper.writeHexOctet(array2[i]);
- }
- equal(iccHelper.readICCUCS2String(0x82, len2), "Mozilla\u694a");
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#writeICCUCS2String()
- */
-add_test(function test_write_icc_ucs2_string() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let alphaLen = 18;
- let test_data = [
- {
- encode: 0x80,
- // string only contain one character.
- data: "\u82b3"
- }, {
- encode: 0x80,
- // 2 UCS2 character not located in the same half-page.
- data: "Fire \u82b3\u8233"
- }, {
- encode: 0x80,
- // 2 UCS2 character not located in the same half-page.
- data: "\u694a\u704a"
- }, {
- encode: 0x81,
- // 2 UCS2 character within same half-page.
- data: "Fire \u6901\u697f"
- }, {
- encode: 0x81,
- // 2 UCS2 character within same half-page.
- data: "Fire \u6980\u69ff"
- }, {
- encode: 0x82,
- // 2 UCS2 character within same half-page, but bit 8 is different.
- data: "Fire \u0514\u0593"
- }, {
- encode: 0x82,
- // 2 UCS2 character over 0x81 can encode range.
- data: "Fire \u8000\u8001"
- }, {
- encode: 0x82,
- // 2 UCS2 character over 0x81 can encode range.
- data: "Fire \ufffd\ufffe"
- }];
-
- for (let i = 0; i < test_data.length; i++) {
- let test = test_data[i];
- let writtenStr = iccHelper.writeICCUCS2String(alphaLen, test.data);
- equal(writtenStr, test.data);
- equal(helper.readHexOctet(), test.encode);
- equal(iccHelper.readICCUCS2String(test.encode, alphaLen - 1), test.data);
- }
-
- // This string use 0x80 encoded and the maximum capacity is 17 octets.
- // Each alphabet takes 2 octets, thus the first 8 alphabets can be written.
- let str = "Mozilla \u82b3\u8233 On Fire";
- let writtenStr = iccHelper.writeICCUCS2String(alphaLen, str);
- equal(writtenStr, str.substring(0, 8));
- equal(helper.readHexOctet(), 0x80);
- equal(iccHelper.readICCUCS2String(0x80, alphaLen - 1), str.substring(0, 8));
-
- // This string use 0x81 encoded and the maximum capacity is 15 octets.
- // Each alphabet takes 1 octets, thus the first 15 alphabets can be written.
- str = "Mozilla \u6901\u697f On Fire";
- writtenStr = iccHelper.writeICCUCS2String(alphaLen, str);
- equal(writtenStr, str.substring(0, 15));
- equal(helper.readHexOctet(), 0x81);
- equal(iccHelper.readICCUCS2String(0x81, alphaLen - 1), str.substring(0, 15));
-
- // This string use 0x82 encoded and the maximum capacity is 14 octets.
- // Each alphabet takes 1 octets, thus the first 14 alphabets can be written.
- str = "Mozilla \u0514\u0593 On Fire";
- writtenStr = iccHelper.writeICCUCS2String(alphaLen, str);
- equal(writtenStr, str.substring(0, 14));
- equal(helper.readHexOctet(), 0x82);
- equal(iccHelper.readICCUCS2String(0x82, alphaLen - 1), str.substring(0, 14));
-
- run_next_test();
-});
-/**
- * Verify ICCPDUHelper#readDiallingNumber
- */
-add_test(function test_read_dialling_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let str = "123456789";
-
- helper.readHexOctet = function() {
- return 0x81;
- };
-
- helper.readSwappedNibbleExtendedBcdString = function(len) {
- return str.substring(0, len);
- };
-
- for (let i = 0; i < str.length; i++) {
- equal(str.substring(0, i - 1), // -1 for the TON
- iccHelper.readDiallingNumber(i));
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#read8BitUnpackedToString
- */
-add_test(function test_read_8bit_unpacked_to_string() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- // Test 1: Read GSM alphabets.
- // Write alphabets before ESCAPE.
- for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
- helper.writeHexOctet(i);
- }
-
- // Write two ESCAPEs to make it become ' '.
- helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
- helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
-
- for (let i = PDU_NL_EXTENDED_ESCAPE + 1; i < langTable.length; i++) {
- helper.writeHexOctet(i);
- }
-
- // Also write two unused fields.
- let ffLen = 2;
- for (let i = 0; i < ffLen; i++) {
- helper.writeHexOctet(0xff);
- }
-
- equal(iccHelper.read8BitUnpackedToString(PDU_NL_EXTENDED_ESCAPE),
- langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
- equal(iccHelper.read8BitUnpackedToString(2), " ");
- equal(iccHelper.read8BitUnpackedToString(langTable.length -
- PDU_NL_EXTENDED_ESCAPE - 1 + ffLen),
- langTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
-
- // Test 2: Read GSM extended alphabets.
- for (let i = 0; i < langShiftTable.length; i++) {
- helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
- helper.writeHexOctet(i);
- }
-
- // Read string before RESERVED_CONTROL.
- equal(iccHelper.read8BitUnpackedToString(PDU_NL_RESERVED_CONTROL * 2),
- langShiftTable.substring(0, PDU_NL_RESERVED_CONTROL));
- // ESCAPE + RESERVED_CONTROL will become ' '.
- equal(iccHelper.read8BitUnpackedToString(2), " ");
- // Read string between RESERVED_CONTROL and EXTENDED_ESCAPE.
- equal(iccHelper.read8BitUnpackedToString(
- (PDU_NL_EXTENDED_ESCAPE - PDU_NL_RESERVED_CONTROL - 1) * 2),
- langShiftTable.substring(PDU_NL_RESERVED_CONTROL + 1,
- PDU_NL_EXTENDED_ESCAPE));
- // ESCAPE + ESCAPE will become ' '.
- equal(iccHelper.read8BitUnpackedToString(2), " ");
- // Read remaining string.
- equal(iccHelper.read8BitUnpackedToString(
- (langShiftTable.length - PDU_NL_EXTENDED_ESCAPE - 1) * 2),
- langShiftTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#writeStringTo8BitUnpacked.
- *
- * Test writing GSM 8 bit alphabets.
- */
-add_test(function test_write_string_to_8bit_unpacked() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- // Length of trailing 0xff.
- let ffLen = 2;
- let str;
-
- // Test 1, write GSM alphabets.
- let writtenStr = iccHelper.writeStringTo8BitUnpacked(langTable.length + ffLen, langTable);
- equal(writtenStr, langTable);
-
- for (let i = 0; i < langTable.length; i++) {
- equal(helper.readHexOctet(), i);
- }
-
- for (let i = 0; i < ffLen; i++) {
- equal(helper.readHexOctet(), 0xff);
- }
-
- // Test 2, write GSM extended alphabets.
- str = "\u000c\u20ac";
- writtenStr = iccHelper.writeStringTo8BitUnpacked(4, str);
- equal(writtenStr, str);
- equal(iccHelper.read8BitUnpackedToString(4), str);
-
- // Test 3, write GSM and GSM extended alphabets.
- // \u000c, \u20ac are from gsm extended alphabets.
- // \u00a3 is from gsm alphabet.
- str = "\u000c\u20ac\u00a3";
-
- // 2 octets * 2 = 4 octets for 2 gsm extended alphabets,
- // 1 octet for 1 gsm alphabet,
- // 2 octes for trailing 0xff.
- // "Totally 7 octets are to be written."
- writtenStr = iccHelper.writeStringTo8BitUnpacked(7, str);
- equal(writtenStr, str);
- equal(iccHelper.read8BitUnpackedToString(7), str);
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#writeStringTo8BitUnpacked with maximum octets written.
- */
-add_test(function test_write_string_to_8bit_unpacked_with_max_octets_written() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- // The maximum of the number of octets that can be written is 3.
- // Only 3 characters shall be written even the length of the string is 4.
- let writtenStr = iccHelper.writeStringTo8BitUnpacked(3, langTable.substring(0, 4));
- equal(writtenStr, langTable.substring(0, 3));
- helper.writeHexOctet(0xff); // dummy octet.
- for (let i = 0; i < 3; i++) {
- equal(helper.readHexOctet(), i);
- }
- ok(helper.readHexOctet() != 4);
-
- // \u000c is GSM extended alphabet, 2 octets.
- // \u00a3 is GSM alphabet, 1 octet.
- let str = "\u000c\u00a3";
- writtenStr = iccHelper.writeStringTo8BitUnpacked(3, str);
- equal(writtenStr, str.substring(0, 2));
- equal(iccHelper.read8BitUnpackedToString(3), str);
-
- str = "\u00a3\u000c";
- writtenStr = iccHelper.writeStringTo8BitUnpacked(3, str);
- equal(writtenStr, str.substring(0, 2));
- equal(iccHelper.read8BitUnpackedToString(3), str);
-
- // 2 GSM extended alphabets cost 4 octets, but maximum is 3, so only the 1st
- // alphabet can be written.
- str = "\u000c\u000c";
- writtenStr = iccHelper.writeStringTo8BitUnpacked(3, str);
- helper.writeHexOctet(0xff); // dummy octet.
- equal(writtenStr, str.substring(0, 1));
- equal(iccHelper.read8BitUnpackedToString(4), str.substring(0, 1));
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.readAlphaIdentifier
- */
-add_test(function test_read_alpha_identifier() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- // UCS2: 0x80
- let text = "TEST";
- helper.writeHexOctet(0x80);
- helper.writeUCS2String(text);
- // Also write two unused octets.
- let ffLen = 2;
- for (let i = 0; i < ffLen; i++) {
- helper.writeHexOctet(0xff);
- }
- equal(iccHelper.readAlphaIdentifier(1 + (2 * text.length) + ffLen), text);
-
- // UCS2: 0x81
- let array = [0x81, 0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
- for (let i = 0; i < array.length; i++) {
- helper.writeHexOctet(array[i]);
- }
- equal(iccHelper.readAlphaIdentifier(array.length), "Mozilla\u694a");
-
- // UCS2: 0x82
- let array2 = [0x82, 0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
- for (let i = 0; i < array2.length; i++) {
- helper.writeHexOctet(array2[i]);
- }
- equal(iccHelper.readAlphaIdentifier(array2.length), "Mozilla\u694a");
-
- // GSM 8 Bit Unpacked
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
- helper.writeHexOctet(i);
- }
- equal(iccHelper.readAlphaIdentifier(PDU_NL_EXTENDED_ESCAPE),
- langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeAlphaIdentifier
- */
-add_test(function test_write_alpha_identifier() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- // Length of trailing 0xff.
- let ffLen = 2;
-
- // Removal
- let writenAlphaId = iccHelper.writeAlphaIdentifier(10, null);
- equal(writenAlphaId, "");
- equal(iccHelper.readAlphaIdentifier(10), "");
-
- // GSM 8 bit
- let str = "Mozilla";
- writenAlphaId = iccHelper.writeAlphaIdentifier(str.length + ffLen, str);
- equal(writenAlphaId , str);
- equal(iccHelper.readAlphaIdentifier(str.length + ffLen), str);
-
- // UCS2
- str = "Mozilla\u8000";
- writenAlphaId = iccHelper.writeAlphaIdentifier(str.length * 2 + ffLen, str);
- equal(writenAlphaId , str);
- // * 2 for each character will be encoded to UCS2 alphabets.
- equal(iccHelper.readAlphaIdentifier(str.length * 2 + ffLen), str);
-
- // Test with maximum octets written.
- // 1 coding scheme (0x80) and 1 UCS2 character, total 3 octets.
- str = "\u694a";
- writenAlphaId = iccHelper.writeAlphaIdentifier(3, str);
- equal(writenAlphaId , str);
- equal(iccHelper.readAlphaIdentifier(3), str);
-
- // 1 coding scheme (0x80) and 2 UCS2 characters, total 5 octets.
- // numOctets is limited to 4, so only 1 UCS2 character can be written.
- str = "\u694a\u69ca";
- writenAlphaId = iccHelper.writeAlphaIdentifier(4, str);
- helper.writeHexOctet(0xff); // dummy octet.
- equal(writenAlphaId , str.substring(0, 1));
- equal(iccHelper.readAlphaIdentifier(5), str.substring(0, 1));
-
- // Write 0 octet.
- writenAlphaId = iccHelper.writeAlphaIdentifier(0, "1");
- helper.writeHexOctet(0xff); // dummy octet.
- equal(writenAlphaId, "");
- equal(iccHelper.readAlphaIdentifier(1), "");
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.readAlphaIdDiallingNumber
- */
-add_test(function test_read_alpha_id_dialling_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let buf = context.Buf;
- const recordSize = 32;
-
- function testReadAlphaIdDiallingNumber(contact) {
- iccHelper.readAlphaIdentifier = function() {
- return contact.alphaId;
- };
-
- iccHelper.readNumberWithLength = function() {
- return contact.number;
- };
-
- let strLen = recordSize * 2;
- buf.writeInt32(strLen); // fake length
- helper.writeHexOctet(0xff); // fake CCP
- helper.writeHexOctet(0xff); // fake EXT1
- buf.writeStringDelimiter(strLen);
-
- let contactR = iccHelper.readAlphaIdDiallingNumber(recordSize);
- if (contact.alphaId == "" && contact.number == "") {
- equal(contactR, null);
- } else {
- equal(contactR.alphaId, contact.alphaId);
- equal(contactR.number, contact.number);
- }
- }
-
- testReadAlphaIdDiallingNumber({alphaId: "AlphaId", number: "0987654321"});
- testReadAlphaIdDiallingNumber({alphaId: "", number: ""});
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeAlphaIdDiallingNumber
- */
-add_test(function test_write_alpha_id_dialling_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.ICCPDUHelper;
- const recordSize = 32;
-
- // Write a normal contact.
- let contactW = {
- alphaId: "Mozilla",
- number: "1234567890"
- };
-
- let writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
- contactW.alphaId,
- contactW.number, 0xff);
-
- let contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(writtenContact.alphaId, contactR.alphaId);
- equal(writtenContact.number, contactR.number);
- equal(0xff, contactR.extRecordNumber);
-
- // Write a contact with alphaId encoded in UCS2 and number has '+'.
- let contactUCS2 = {
- alphaId: "火狐",
- number: "+1234567890"
- };
-
- writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
- contactUCS2.alphaId,
- contactUCS2.number, 0xff);
- contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(writtenContact.alphaId, contactR.alphaId);
- equal(writtenContact.number, contactR.number);
- equal(0xff, contactR.extRecordNumber);
-
- // Write a null contact (Removal).
- writtenContact = helper.writeAlphaIdDiallingNumber(recordSize);
- contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(contactR, null);
- equal(writtenContact.alphaId, "");
- equal(writtenContact.number, "");
-
- // Write a longer alphaId/dialling number
- // Dialling Number : Maximum 20 digits(10 octets).
- // Alpha Identifier: 32(recordSize) - 14 (10 octets for Dialling Number, 1
- // octet for TON/NPI, 1 for number length octet, and 2 for
- // Ext) = Maximum 18 octets.
- let longContact = {
- alphaId: "AAAAAAAAABBBBBBBBBCCCCCCCCC",
- number: "123456789012345678901234567890",
- };
-
- writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
- longContact.alphaId,
- longContact.number, 0xff);
- contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(writtenContact.alphaId, contactR.alphaId);
- equal(writtenContact.number, contactR.number);
- equal(0xff, contactR.extRecordNumber);
-
- // Add '+' to number and test again.
- longContact.number = "+123456789012345678901234567890";
- writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
- longContact.alphaId,
- longContact.number, 0xff);
- contactR = helper.readAlphaIdDiallingNumber(recordSize);
- equal(writtenContact.alphaId, contactR.alphaId);
- equal(writtenContact.number, contactR.number);
- equal(0xff, contactR.extRecordNumber);
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeDiallingNumber
- */
-add_test(function test_write_dialling_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.ICCPDUHelper;
-
- // with +
- let number = "+123456";
- let len = 4;
- helper.writeDiallingNumber(number);
- equal(helper.readDiallingNumber(len), number);
-
- // without +
- number = "987654";
- len = 4;
- helper.writeDiallingNumber(number);
- equal(helper.readDiallingNumber(len), number);
-
- number = "9876543";
- len = 5;
- helper.writeDiallingNumber(number);
- equal(helper.readDiallingNumber(len), number);
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.readNumberWithLength
- */
-add_test(function test_read_number_with_length() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- let numbers = [
- {
- number: "123456789",
- expectedNumber: "123456789"
- },
- {
- number: "",
- expectedNumber: ""
- },
- // Invalid length of BCD number/SSC contents
- {
- number: "12345678901234567890123",
- expectedNumber: ""
- },
- ];
-
- // To avoid obtaining wrong buffer content.
- context.Buf.seekIncoming = function(offset) {
- };
-
- function do_test(aNumber, aExpectedNumber) {
- iccHelper.readDiallingNumber = function(numLen) {
- return aNumber.substring(0, numLen);
- };
-
- if (aNumber) {
- helper.writeHexOctet(aNumber.length + 1);
- } else {
- helper.writeHexOctet(0xff);
- }
-
- equal(iccHelper.readNumberWithLength(), aExpectedNumber);
- }
-
- for (let i = 0; i < numbers.length; i++) {
- do_test(numbers[i].number, numbers[i].expectedNumber);
- }
-
- run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeNumberWithLength
- */
-add_test(function test_write_number_with_length() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- function test(number, expectedNumber) {
- expectedNumber = expectedNumber || number;
- let writeNumber = iccHelper.writeNumberWithLength(number);
- equal(writeNumber, expectedNumber);
- let numLen = helper.readHexOctet();
- equal(expectedNumber, iccHelper.readDiallingNumber(numLen));
- for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
- equal(0xff, helper.readHexOctet());
- }
- }
-
- // without +
- test("123456789");
-
- // with +
- test("+987654321");
-
- // extended BCD coding
- test("1*2#3,4*5#6,");
-
- // with + and extended BCD coding
- test("+1*2#3,4*5#6,");
-
- // non-supported characters should not be written.
- test("(1)23-456+789", "123456789");
-
- test("++(01)2*3-4#5,6+7(8)9*0#1,", "+012*34#5,6789*0#1,");
-
- // over maximum 20 digits should be truncated.
- test("012345678901234567890123456789", "01234567890123456789");
-
- // null
- iccHelper.writeNumberWithLength(null);
- for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES + 1); i++) {
- equal(0xff, helper.readHexOctet());
- }
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCRecordHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCRecordHelper.js
deleted file mode 100644
index 00c55873d..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCRecordHelper.js
+++ /dev/null
@@ -1,1080 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify ICCRecordHelper.readPBR
- */
-add_test(function test_read_pbr() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let pbr_1 = [
- 0xa8, 0x05, 0xc0, 0x03, 0x4f, 0x3a, 0x01
- ];
-
- // Write data size
- buf.writeInt32(pbr_1.length * 2);
-
- // Write pbr
- for (let i = 0; i < pbr_1.length; i++) {
- helper.writeHexOctet(pbr_1[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(pbr_1.length * 2);
-
- options.totalRecords = 2;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- io.loadNextRecord = function fakeLoadNextRecord(options) {
- let pbr_2 = [
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- ];
-
- options.p1++;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let successCb = function successCb(pbrs) {
- equal(pbrs[0].adn.fileId, 0x4f3a);
- equal(pbrs.length, 1);
- };
-
- let errorCb = function errorCb(errorMsg) {
- do_print("Reading EF_PBR failed, msg = " + errorMsg);
- ok(false);
- };
-
- record.readPBR(successCb, errorCb);
-
- // Check cache pbrs when 2nd call
- let ifLoadEF = false;
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- ifLoadEF = true;
- }
- record.readPBR(successCb, errorCb);
- ok(!ifLoadEF);
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.readEmail
- */
-add_test(function test_read_email() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let recordSize;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let email_1 = [
- 0x65, 0x6D, 0x61, 0x69, 0x6C,
- 0x00, 0x6D, 0x6F, 0x7A, 0x69,
- 0x6C, 0x6C, 0x61, 0x2E, 0x63,
- 0x6F, 0x6D, 0x02, 0x23];
-
- // Write data size
- buf.writeInt32(email_1.length * 2);
-
- // Write email
- for (let i = 0; i < email_1.length; i++) {
- helper.writeHexOctet(email_1[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(email_1.length * 2);
-
- recordSize = email_1.length;
- options.recordSize = recordSize;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function doTestReadEmail(type, expectedResult) {
- let fileId = 0x6a75;
- let recordNumber = 1;
-
- // fileId and recordNumber are dummy arguments.
- record.readEmail(fileId, type, recordNumber, function(email) {
- equal(email, expectedResult);
- });
- };
-
- doTestReadEmail(ICC_USIM_TYPE1_TAG, "email@mozilla.com$#");
- doTestReadEmail(ICC_USIM_TYPE2_TAG, "email@mozilla.com");
- equal(record._emailRecordSize, recordSize);
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateEmail
- */
-add_test(function test_update_email() {
- const recordSize = 0x20;
- const recordNumber = 1;
- const fileId = 0x4f50;
- const NUM_TESTS = 2;
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let ril = context.RIL;
- ril.appType = CARD_APPTYPE_USIM;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
- let pbr = {email: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
- adn: {sfi: 1}};
- let count = 0;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- function do_test(pbr, expectedEmail, expectedAdnRecordId) {
- buf.sendParcel = function() {
- count++;
-
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
-
- // p1.
- equal(this.readInt32(), recordNumber);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), recordSize);
-
- // data.
- let strLen = this.readInt32();
- let email;
- if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
- email = iccHelper.read8BitUnpackedToString(recordSize);
- } else {
- email = iccHelper.read8BitUnpackedToString(recordSize - 2);
- equal(pduHelper.readHexOctet(), pbr.adn.sfi);
- equal(pduHelper.readHexOctet(), expectedAdnRecordId);
- }
- this.readStringDelimiter(strLen);
- equal(email, expectedEmail);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
-
- if (count == NUM_TESTS) {
- run_next_test();
- }
- };
- recordHelper.updateEmail(pbr, recordNumber, expectedEmail, expectedAdnRecordId);
- }
-
- do_test(pbr, "test@mail.com");
- pbr.email.fileType = ICC_USIM_TYPE2_TAG;
- do_test(pbr, "test@mail.com", 1);
-});
-
-/**
- * Verify ICCRecordHelper.readANR
- */
-add_test(function test_read_anr() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let recordSize;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let anr_1 = [
- 0x01, 0x05, 0x81, 0x10, 0x32,
- 0x54, 0xF6, 0xFF, 0xFF];
-
- // Write data size
- buf.writeInt32(anr_1.length * 2);
-
- // Write anr
- for (let i = 0; i < anr_1.length; i++) {
- helper.writeHexOctet(anr_1[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(anr_1.length * 2);
-
- recordSize = anr_1.length;
- options.recordSize = recordSize;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function doTestReadAnr(fileType, expectedResult) {
- let fileId = 0x4f11;
- let recordNumber = 1;
-
- // fileId and recordNumber are dummy arguments.
- record.readANR(fileId, fileType, recordNumber, function(anr) {
- equal(anr, expectedResult);
- });
- };
-
- doTestReadAnr(ICC_USIM_TYPE1_TAG, "0123456");
- equal(record._anrRecordSize, recordSize);
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateANR
- */
-add_test(function test_update_anr() {
- const recordSize = 0x20;
- const recordNumber = 1;
- const fileId = 0x4f11;
- const NUM_TESTS = 2;
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
- let ril = context.RIL;
- ril.appType = CARD_APPTYPE_USIM;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
- let pbr = {anr0: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
- adn: {sfi: 1}};
- let count = 0;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- function do_test(pbr, expectedANR, expectedAdnRecordId) {
- buf.sendParcel = function() {
- count++;
-
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
-
- // p1.
- equal(this.readInt32(), recordNumber);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), recordSize);
-
- // data.
- let strLen = this.readInt32();
- // EF_AAS, ignore.
- pduHelper.readHexOctet();
- equal(iccHelper.readNumberWithLength(), expectedANR);
- // EF_CCP, ignore.
- pduHelper.readHexOctet();
- // EF_EXT1, ignore.
- pduHelper.readHexOctet();
- if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
- equal(pduHelper.readHexOctet(), pbr.adn.sfi);
- equal(pduHelper.readHexOctet(), expectedAdnRecordId);
- }
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
-
- if (count == NUM_TESTS) {
- run_next_test();
- }
- };
- recordHelper.updateANR(pbr, recordNumber, expectedANR, expectedAdnRecordId);
- }
-
- do_test(pbr, "+123456789");
- pbr.anr0.fileType = ICC_USIM_TYPE2_TAG;
- do_test(pbr, "123456789", 1);
-});
-
-/**
- * Verify ICCRecordHelper.readIAP
- */
-add_test(function test_read_iap() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let recordSize;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let iap_1 = [0x01, 0x02];
-
- // Write data size/
- buf.writeInt32(iap_1.length * 2);
-
- // Write iap.
- for (let i = 0; i < iap_1.length; i++) {
- helper.writeHexOctet(iap_1[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(iap_1.length * 2);
-
- recordSize = iap_1.length;
- options.recordSize = recordSize;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function doTestReadIAP(expectedIAP) {
- const fileId = 0x4f17;
- const recordNumber = 1;
-
- let successCb = function successCb(iap) {
- for (let i = 0; i < iap.length; i++) {
- equal(expectedIAP[i], iap[i]);
- }
- run_next_test();
- }.bind(this);
-
- let errorCb = function errorCb(errorMsg) {
- do_print(errorMsg);
- ok(false);
- run_next_test();
- }.bind(this);
-
- record.readIAP(fileId, recordNumber, successCb, errorCb);
- };
-
- doTestReadIAP([1, 2]);
-});
-
-/**
- * Verify ICCRecordHelper.updateIAP
- */
-add_test(function test_update_iap() {
- const recordSize = 2;
- const recordNumber = 1;
- const fileId = 0x4f17;
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- ril.appType = CARD_APPTYPE_USIM;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
- let count = 0;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- function do_test(expectedIAP) {
- buf.sendParcel = function() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
-
- // p1.
- equal(this.readInt32(), recordNumber);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), recordSize);
-
- // data.
- let strLen = this.readInt32();
- for (let i = 0; i < recordSize; i++) {
- equal(expectedIAP[i], pduHelper.readHexOctet());
- }
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
-
- run_next_test();
- };
- recordHelper.updateIAP(fileId, recordNumber, expectedIAP);
- }
-
- do_test([1, 2]);
-});
-
-/**
- * Verify ICCRecordHelper.readADNLike.
- */
-add_test(function test_read_adn_like() {
- const RECORD_SIZE = 0x20;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let ril = context.RIL;
-
- function do_test(extFileId, rawEF, expectedExtRecordNumber, expectedNumber) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(rawEF.length * 2);
-
- // Write adn
- for (let i = 0; i < rawEF.length; i += 2) {
- helper.writeHexOctet(parseInt(rawEF.substr(i, 2), 16));
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(rawEF.length * 2);
-
- options.p1 = 1;
- options.recordSize = RECORD_SIZE;
- options.totalRecords = 1;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readExtension = function(fileId, recordNumber, onsuccess, onerror) {
- onsuccess("1234");
- }
-
- let successCb = function successCb(contacts) {
- ok(contacts[0].number == expectedNumber);
- };
-
- let errorCb = function errorCb(errorMsg) {
- do_print("Reading ADNLike failed, msg = " + errorMsg);
- ok(false);
- };
-
- record.readADNLike(ICC_EF_ADN, extFileId, successCb, errorCb);
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- // Valid extension
- do_test(ICC_EF_EXT1,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ff01",
- 0x01,"998877665544332211001234");
- // Empty extension
- do_test(ICC_EF_EXT1,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ffff",
- 0xff, "99887766554433221100");
- // Unsupport extension
- do_test(null,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ffff",
- 0xff, "99887766554433221100");
- // Empty dialling number contact
- do_test(null,"436f6e74616374303031ffffffffffffffffffffffffffffffffffffffffffff",
- 0xff, "");
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateADNLike.
- */
-add_test(function test_update_adn_like() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let record = context.ICCRecordHelper;
- let io = context.ICCIOHelper;
- let pdu = context.ICCPDUHelper;
- let buf = context.Buf;
-
- ril.appType = CARD_APPTYPE_SIM;
- const recordSize = 0x20;
- let fileId;
-
- // Override.
- io.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- buf.sendParcel = function() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- equal(this.readString(), EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
-
- // p1.
- equal(this.readInt32(), 1);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), 0x20);
-
- // data.
- let contact = pdu.readAlphaIdDiallingNumber(0x20);
- equal(contact.alphaId, "test");
- equal(contact.number, "123456");
- equal(contact.extRecordNumber, "0xff");
-
- // pin2.
- if (fileId == ICC_EF_ADN) {
- equal(this.readString(), null);
- } else {
- equal(this.readString(), "1111");
- }
-
- // AID. Ignore because it's from modem.
- this.readInt32();
-
- if (fileId == ICC_EF_FDN) {
- run_next_test();
- }
- };
-
- fileId = ICC_EF_ADN;
- record.updateADNLike(fileId, 0xff,
- {recordId: 1, alphaId: "test", number: "123456"});
-
- fileId = ICC_EF_FDN;
- record.updateADNLike(fileId, 0xff,
- {recordId: 1, alphaId: "test", number: "123456"},
- "1111");
-});
-
-/**
- * Verify ICCRecordHelper.findFreeRecordId.
- */
-add_test(function test_find_free_record_id() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let ril = context.RIL;
-
- function writeRecord(record) {
- // Write data size
- buf.writeInt32(record.length * 2);
-
- for (let i = 0; i < record.length; i++) {
- pduHelper.writeHexOctet(record[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(record.length * 2);
- }
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Some random data.
- let record = [0x12, 0x34, 0x56, 0x78, 0x90];
- options.p1 = 1;
- options.totalRecords = 2;
- writeRecord(record);
- if (options.callback) {
- options.callback(options);
- }
- };
-
- ril.iccIO = function fakeIccIO(options) {
- // Unused bytes.
- let record = [0xff, 0xff, 0xff, 0xff, 0xff];
- writeRecord(record);
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let fileId = 0x0000; // Dummy.
- recordHelper.findFreeRecordId(
- fileId,
- function(recordId) {
- equal(recordId, 2);
- run_next_test();
- }.bind(this),
- function(errorMsg) {
- do_print(errorMsg);
- ok(false);
- run_next_test();
- }.bind(this));
-});
-
-/**
- * Verify ICCRecordHelper.fetchICCRecords.
- */
-add_test(function test_fetch_icc_recodes() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let iccRecord = context.ICCRecordHelper;
- let simRecord = context.SimRecordHelper;
- let ruimRecord = context.RuimRecordHelper;
- let fetchTag = 0x00;
-
- simRecord.fetchSimRecords = function() {
- fetchTag = 0x01;
- };
-
- ruimRecord.fetchRuimRecords = function() {
- fetchTag = 0x02;
- };
-
- RIL.appType = CARD_APPTYPE_SIM;
- iccRecord.fetchICCRecords();
- equal(fetchTag, 0x01);
-
- RIL.appType = CARD_APPTYPE_RUIM;
- iccRecord.fetchICCRecords();
- equal(fetchTag, 0x02);
-
- RIL.appType = CARD_APPTYPE_USIM;
- iccRecord.fetchICCRecords();
- equal(fetchTag, 0x01);
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_ICCID.
- */
-add_test(function test_handling_iccid() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.ICCRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- ril.reportStkServiceIsRunning = function fakeReportStkServiceIsRunning() {
- };
-
- function do_test(rawICCID, expectedICCID) {
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(rawICCID.length);
-
- // Write data
- for (let i = 0; i < rawICCID.length; i += 2) {
- helper.writeHexOctet(parseInt(rawICCID.substr(i, 2), 16));
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(rawICCID.length);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readICCID();
-
- equal(ril.iccInfo.iccid, expectedICCID);
- }
-
- // Invalid value 0xE at high nibbile + low nibbile contains 0xF.
- do_test("9868002E90909F001519", "89860020909");
- // Invalid value 0xD at low nibbile.
- do_test("986800D2909090001519", "8986002090909005191");
- // Invalid value 0xC at low nibbile.
- do_test("986800C2909090001519", "8986002090909005191");
- // Invalid value 0xB at low nibbile.
- do_test("986800B2909090001519", "8986002090909005191");
- // Invalid value 0xA at low nibbile.
- do_test("986800A2909090001519", "8986002090909005191");
- // Valid ICCID.
- do_test("98101430121181157002", "89014103211118510720");
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.readExtension
- */
-add_test(function test_read_extension() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function do_test(rawExtension, expectedExtensionNumber) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(rawExtension.length * 2);
-
- // Write ext
- for (let i = 0; i < rawExtension.length; i += 2) {
- helper.writeHexOctet(parseInt(rawExtension.substr(i, 2), 16));
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(rawExtension.length);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let successCb = function successCb(number) {
- do_print("extension number:" + number);
- equal(number, expectedExtensionNumber);
- };
-
- let errorCb = function errorCb() {
- ok(expectedExtensionNumber == null);
- };
-
- record.readExtension(0x6f4a, 1, successCb, errorCb);
- }
-
- // Test unsupported record type 0x01
- do_test("010a10325476981032547698ff", "");
- // Test invalid length 0xc1
- do_test("020c10325476981032547698ff", null);
- // Test extension chain which we don't support
- do_test("020a1032547698103254769802", "01234567890123456789");
- // Test valid Extension
- do_test("020a10325476981032547698ff", "01234567890123456789");
- // Test valid Extension
- do_test("0209103254769810325476ffff", "012345678901234567");
- // Test empty Extension
- do_test("02ffffffffffffffffffffffff", "");
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateExtension
- */
-add_test(function test_update_extension() {
- const RECORD_SIZE = 13;
- const RECORD_NUMBER = 1;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = RECORD_SIZE;
- ril.iccIO(options);
- };
-
- function do_test(fileId, number, expectedNumber) {
- buf.sendParcel = function() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- if (ril.appType == CARD_APPTYPE_SIM || ril.appType == CARD_APPTYPE_RUIM) {
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
- } else{
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
- }
-
- // p1.
- equal(this.readInt32(), RECORD_NUMBER);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), RECORD_SIZE);
-
- // data.
- let strLen = this.readInt32();
- // Extension record
- let recordType = pduHelper.readHexOctet();
-
- equal(recordType, 0x02);
- equal(pduHelper.readHexOctet(), 10);
- equal(
- pduHelper.readSwappedNibbleExtendedBcdString(EXT_MAX_NUMBER_DIGITS - 1),
- expectedNumber);
-
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
- };
-
- recordHelper.updateExtension(fileId, RECORD_NUMBER, number);
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- do_test(ICC_EF_EXT1, "01234567890123456789", "01234567890123456789");
- // We don't support extension chain.
- do_test(ICC_EF_EXT1, "012345678901234567891234", "01234567890123456789");
-
- ril.appType = CARD_APPTYPE_USIM;
- do_test(ICC_EF_EXT1, "01234567890123456789", "01234567890123456789");
-
- ril.appType = CARD_APPTYPE_RUIM;
- do_test(ICC_EF_EXT1, "01234567890123456789", "01234567890123456789");
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.cleanEFRecord
- */
-add_test(function test_clean_ef_record() {
- const RECORD_SIZE = 13;
- const RECORD_NUMBER = 1;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- let recordHelper = context.ICCRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
-
- // Override.
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = RECORD_SIZE;
- ril.iccIO(options);
- };
-
- function do_test(fileId) {
- buf.sendParcel = function() {
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), fileId);
-
- // pathId.
- if (ril.appType == CARD_APPTYPE_SIM || ril.appType == CARD_APPTYPE_RUIM) {
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
- } else{
- equal(this.readString(),
- EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
- }
-
- // p1.
- equal(this.readInt32(), RECORD_NUMBER);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), RECORD_SIZE);
-
- // data.
- let strLen = this.readInt32();
- // Extension record
- for (let i = 0; i < RECORD_SIZE; i++) {
- equal(pduHelper.readHexOctet(), 0xff);
- }
-
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
- };
-
- recordHelper.cleanEFRecord(fileId, RECORD_NUMBER);
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- do_test(ICC_EF_EXT1);
-
- run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.getADNLikeExtensionRecordNumber
- */
-add_test(function test_get_adn_like_extension_record_number() {
- const RECORD_SIZE = 0x20;
-
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let record = context.ICCRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function do_test(rawEF, expectedRecordNumber) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(rawEF.length * 2);
-
- // Write ext
- for (let i = 0; i < rawEF.length; i += 2) {
- helper.writeHexOctet(parseInt(rawEF.substr(i, 2), 16));
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(rawEF.length);
- options.recordSize = RECORD_SIZE;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let isSuccess = false;
- let successCb = function successCb(number) {
- equal(number, expectedRecordNumber);
- isSuccess = true;
- };
-
- let errorCb = function errorCb(errorMsg) {
- do_print("Reading ADNLike failed, msg = " + errorMsg);
- ok(false);
- };
-
- record.getADNLikeExtensionRecordNumber(ICC_EF_ADN, 1, successCb, errorCb);
- ok(isSuccess);
- }
-
- // Valid Extension, Alpha Id(Encoded with GSM 8 bit): "Contact001",
- // Dialling Number: 99887766554433221100, Ext1: 0x01
- do_test("436f6e74616374303031ffffffffffffffff0b8199887766554433221100ff01", 0x01);
- // Empty Extension, Alpha Id(Encoded with GSM 8 bit): "Contact001", Ext1: 0xff
- do_test("436f6e74616374303031ffffffffffffffffffffffffffffffffffffffffffff", 0xff);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js
deleted file mode 100644
index b23d0b598..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js
+++ /dev/null
@@ -1,326 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify ICCUtilsHelper.isICCServiceAvailable.
- */
-add_test(function test_is_icc_service_available() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ICCUtilsHelper = context.ICCUtilsHelper;
- let RIL = context.RIL;
-
- function test_table(sst, geckoService, simEnabled, usimEnabled) {
- RIL.iccInfoPrivate.sst = sst;
- RIL.appType = CARD_APPTYPE_SIM;
- equal(ICCUtilsHelper.isICCServiceAvailable(geckoService), simEnabled);
- RIL.appType = CARD_APPTYPE_USIM;
- equal(ICCUtilsHelper.isICCServiceAvailable(geckoService), usimEnabled);
- }
-
- test_table([0x08], "ADN", true, false);
- test_table([0x08], "FDN", false, false);
- test_table([0x08], "SDN", false, true);
-
- run_next_test();
-});
-
-/**
- * Verify ICCUtilsHelper.isGsm8BitAlphabet
- */
-add_test(function test_is_gsm_8bit_alphabet() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ICCUtilsHelper = context.ICCUtilsHelper;
- const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
- equal(ICCUtilsHelper.isGsm8BitAlphabet(langTable), true);
- equal(ICCUtilsHelper.isGsm8BitAlphabet(langShiftTable), true);
- equal(ICCUtilsHelper.isGsm8BitAlphabet("\uaaaa"), false);
-
- run_next_test();
-});
-
-/**
- * Verify ICCUtilsHelper.parsePbrTlvs
- */
-add_test(function test_parse_pbr_tlvs() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
-
- let pbrTlvs = [
- {tag: ICC_USIM_TYPE1_TAG,
- length: 0x0F,
- value: [{tag: ICC_USIM_EFADN_TAG,
- length: 0x03,
- value: [0x4F, 0x3A, 0x02]},
- {tag: ICC_USIM_EFIAP_TAG,
- length: 0x03,
- value: [0x4F, 0x25, 0x01]},
- {tag: ICC_USIM_EFPBC_TAG,
- length: 0x03,
- value: [0x4F, 0x09, 0x04]}]
- },
- {tag: ICC_USIM_TYPE2_TAG,
- length: 0x05,
- value: [{tag: ICC_USIM_EFEMAIL_TAG,
- length: 0x03,
- value: [0x4F, 0x50, 0x0B]},
- {tag: ICC_USIM_EFANR_TAG,
- length: 0x03,
- value: [0x4F, 0x11, 0x02]},
- {tag: ICC_USIM_EFANR_TAG,
- length: 0x03,
- value: [0x4F, 0x12, 0x03]}]
- },
- {tag: ICC_USIM_TYPE3_TAG,
- length: 0x0A,
- value: [{tag: ICC_USIM_EFCCP1_TAG,
- length: 0x03,
- value: [0x4F, 0x3D, 0x0A]},
- {tag: ICC_USIM_EFEXT1_TAG,
- length: 0x03,
- value: [0x4F, 0x4A, 0x03]}]
- },
- ];
-
- let pbr = context.ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
- equal(pbr.adn.fileId, 0x4F3a);
- equal(pbr.iap.fileId, 0x4F25);
- equal(pbr.pbc.fileId, 0x4F09);
- equal(pbr.email.fileId, 0x4F50);
- equal(pbr.anr0.fileId, 0x4f11);
- equal(pbr.anr1.fileId, 0x4f12);
- equal(pbr.ccp1.fileId, 0x4F3D);
- equal(pbr.ext1.fileId, 0x4F4A);
-
- run_next_test();
-});
-
-/**
- * Verify MCC and MNC parsing
- */
-add_test(function test_mcc_mnc_parsing() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.ICCUtilsHelper;
-
- function do_test(imsi, mncLength, expectedMcc, expectedMnc) {
- let result = helper.parseMccMncFromImsi(imsi, mncLength);
-
- if (!imsi) {
- equal(result, null);
- return;
- }
-
- equal(result.mcc, expectedMcc);
- equal(result.mnc, expectedMnc);
- }
-
- // Test the imsi is null.
- do_test(null, null, null, null);
-
- // Test MCC is Taiwan
- do_test("466923202422409", 0x02, "466", "92");
- do_test("466923202422409", 0x03, "466", "923");
- do_test("466923202422409", null, "466", "92");
-
- // Test MCC is US
- do_test("310260542718417", 0x02, "310", "26");
- do_test("310260542718417", 0x03, "310", "260");
- do_test("310260542718417", null, "310", "260");
-
- run_next_test();
-});
-
-add_test(function test_get_network_name_from_icc() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ICCUtilsHelper = context.ICCUtilsHelper;
-
- function testGetNetworkNameFromICC(operatorData, expectedResult) {
- let result = ICCUtilsHelper.getNetworkNameFromICC(operatorData.mcc,
- operatorData.mnc,
- operatorData.lac);
-
- if (expectedResult == null) {
- equal(result, expectedResult);
- } else {
- equal(result.fullName, expectedResult.longName);
- equal(result.shortName, expectedResult.shortName);
- }
- }
-
- // Before EF_OPL and EF_PNN have been loaded.
- testGetNetworkNameFromICC({mcc: "123", mnc: "456", lac: 0x1000}, null);
- testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x2000}, null);
-
- // Set HPLMN
- RIL.iccInfo.mcc = "123";
- RIL.iccInfo.mnc = "456";
-
- RIL.voiceRegistrationState = {
- cell: {
- gsmLocationAreaCode: 0x1000
- }
- };
- RIL.operator = {};
-
- // Set EF_PNN
- RIL.iccInfoPrivate = {
- PNN: [
- {"fullName": "PNN1Long", "shortName": "PNN1Short"},
- {"fullName": "PNN2Long", "shortName": "PNN2Short"},
- {"fullName": "PNN3Long", "shortName": "PNN3Short"},
- {"fullName": "PNN4Long", "shortName": "PNN4Short"},
- {"fullName": "PNN5Long", "shortName": "PNN5Short"},
- {"fullName": "PNN6Long", "shortName": "PNN6Short"},
- {"fullName": "PNN7Long", "shortName": "PNN7Short"},
- {"fullName": "PNN8Long", "shortName": "PNN8Short"}
- ]
- };
-
- // EF_OPL isn't available
- ICCUtilsHelper.isICCServiceAvailable = function fakeIsICCServiceAvailable(service) {
- return false;
- };
-
- // EF_OPL isn't available and current isn't in HPLMN,
- testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x1000}, null);
-
- // EF_OPL isn't available and current is in HPLMN,
- // the first record of PNN should be returned.
- testGetNetworkNameFromICC({mcc: "123", mnc: "456", lac: 0x1000},
- {longName: "PNN1Long", shortName: "PNN1Short"});
-
- // EF_OPL is available
- ICCUtilsHelper.isICCServiceAvailable = function fakeIsICCServiceAvailable(service) {
- return service === "OPL";
- };
-
- // Set EF_OPL
- RIL.iccInfoPrivate.OPL = [
- {
- "mcc": "123",
- "mnc": "456",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 4
- },
- {
- "mcc": "321",
- "mnc": "654",
- "lacTacStart": 0,
- "lacTacEnd": 0x0010,
- "pnnRecordId": 3
- },
- {
- "mcc": "321",
- "mnc": "654",
- "lacTacStart": 0x0100,
- "lacTacEnd": 0x1010,
- "pnnRecordId": 2
- },
- {
- "mcc": ";;;",
- "mnc": "01",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 5
- },
- {
- "mcc": "00;",
- "mnc": "02",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 6
- },
- {
- "mcc": "001",
- "mnc": ";;",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 7
- },
- {
- "mcc": "002",
- "mnc": "0;",
- "lacTacStart": 0,
- "lacTacEnd": 0xFFFE,
- "pnnRecordId": 8
- }
- ];
-
- // Both EF_PNN and EF_OPL are presented, and current PLMN is HPLMN,
- testGetNetworkNameFromICC({mcc: "123", mnc: "456", lac: 0x1000},
- {longName: "PNN4Long", shortName: "PNN4Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the second PNN record.
- testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x1000},
- {longName: "PNN2Long", shortName: "PNN2Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the thrid PNN record.
- testGetNetworkNameFromICC({mcc: "321", mnc: "654", lac: 0x0001},
- {longName: "PNN3Long", shortName: "PNN3Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the 5th PNN record after wild char (ie: ';') handling.
- testGetNetworkNameFromICC({mcc: "001", mnc: "01", lac: 0x0001},
- {longName: "PNN5Long", shortName: "PNN5Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the 6th PNN record after wild char (ie: ';') handling.
- testGetNetworkNameFromICC({mcc: "001", mnc: "02", lac: 0x0001},
- {longName: "PNN6Long", shortName: "PNN6Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the 7th PNN record after wild char (ie: ';') handling.
- testGetNetworkNameFromICC({mcc: "001", mnc: "03", lac: 0x0001},
- {longName: "PNN7Long", shortName: "PNN7Short"});
-
- // Current PLMN is not HPLMN, and according to LAC, we should get
- // the 8th PNN record after wild char (ie: ';') handling.
- testGetNetworkNameFromICC({mcc: "002", mnc: "03", lac: 0x0001},
- {longName: "PNN8Long", shortName: "PNN8Short"});
-
- run_next_test();
-});
-
-/**
- * Verify ICCUtilsHelper.isCphsServiceAvailable.
- */
-add_test(function test_is_cphs_service_available() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ICCUtilsHelper = context.ICCUtilsHelper;
- let RIL = context.RIL;
- RIL.iccInfoPrivate.cphsSt = new Uint8Array(2);
-
- function test_table(cphsSt, geckoService) {
- RIL.iccInfoPrivate.cphsSt.set(cphsSt);
-
- for (let service in GECKO_ICC_SERVICES.cphs) {
- equal(ICCUtilsHelper.isCphsServiceAvailable(service),
- geckoService == service);
- }
- }
-
- test_table([0x03, 0x00], "CSP");
- test_table([0x0C, 0x00], "SST");
- test_table([0x30, 0x00], "MBN");
- test_table([0xC0, 0x00], "ONSF");
- test_table([0x00, 0x03], "INFO_NUM");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_IconLoader.js b/dom/system/gonk/tests/test_ril_worker_icc_IconLoader.js
deleted file mode 100644
index 8bcd26ffe..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_IconLoader.js
+++ /dev/null
@@ -1,771 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify IconLoader.loadIcons with recordNumbers array length being 1.
- * Query images of one record at a time.
- */
-add_test(function test_load_icon_basic() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let iconLoader = context.IconLoader;
- let simRecordHelper = context.SimRecordHelper;
-
- let test_data = [
- {rawData: [
- {codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- width: 0x10,
- height: 0x10,
- body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
- 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff]}],
- expected: [
- {width: 0x10,
- height: 0x10,
- pixels: [/* 1st byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 2nd byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 3rd byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 4th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 5th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 6th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 7th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 8th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 9th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 10th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 11th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 12th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 13th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 14th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 15th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 16th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 17th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 18th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 19th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 20th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 21th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 22th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 23th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 24th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 25th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 26th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 27th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 28th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 29th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 30th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 31th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 32th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff]}]},
- {rawData: [
- {codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- width: 0x10,
- height: 0x10,
- bitsPerImgPoint: 0x04,
- numOfClutEntries: 0x10,
- body: [0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xcc, 0xfc, 0xcc,
- 0xcf, 0xcf, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf,
- 0xcc, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcc,
- 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc,
- 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc, 0xcf,
- 0xfc, 0xcc, 0xfc, 0xcc, 0xcf, 0xcf, 0xfc, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
- 0x99, 0x99],
- clut: [0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
- 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80,
- 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80,
- 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xff]}],
- expected: [
- {width: 0x10,
- height: 0x10,
- pixels: [0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff]}]},
- {rawData: [
- {codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- width: 0x03,
- height: 0x03,
- bitsPerImgPoint: 0x05,
- numOfClutEntries: 0x20,
- body: [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
- clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
- 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
- 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
- 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f]},
- {codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- width: 0x10,
- height: 0x10,
- body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
- 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff]}],
- expected: [
- {width: 0x03,
- height: 0x03,
- pixels: [0x000102ff, 0x060708ff, 0x0c0d0eff, 0x121314ff, 0x18191aff,
- 0x1e1f20ff, 0x242526ff, 0x2a2b2cff, 0x333435ff]},
- {width: 0x10,
- height: 0x10,
- pixels: [/* 1st byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 2nd byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 3rd byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 4th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 5th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 6th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 7th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 8th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 9th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 10th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 11th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 12th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 13th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 14th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 15th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 16th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 17th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 18th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 19th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 20th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 21th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 22th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 23th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 24th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 25th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 26th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 27th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 28th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 29th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 30th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 31th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 32th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff]}]},
- {rawData: [
- {codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- width: 0x04,
- height: 0x04,
- bitsPerImgPoint: 0x04,
- numOfClutEntries: 0x10,
- body: [0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88],
- clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
- 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
- 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f]}],
- expected: [
- {width: 0x04,
- height: 0x04,
- pixels: [0x00000000, 0x00000000, 0x2a2b2cff, 0x2a2b2cff, 0x272829ff,
- 0x272829ff, 0x242526ff, 0x242526ff, 0x212223ff, 0x212223ff,
- 0x1e1f20ff, 0x1e1f20ff, 0x1b1c1dff, 0x1b1c1dff, 0x18191aff,
- 0x18191aff]}]}];
-
- function do_test(test_data, expected) {
- simRecordHelper.readIMG = function fakeReadIMG(recordNumber, onsuccess, onerror) {
- onsuccess(test_data);
- };
-
- let onsuccess = function(icons) {
- // Query one record at a time.
- equal(icons.length, 1);
- equal(icons[0].length, expected.length);
- for (let i = 0; i < icons[0].length; i++) {
- // Read the i_th image of the record.
- let icon = icons[0][i];
- let exp = expected[i];
- equal(icon.width, exp.width);
- equal(icon.height, exp.height);
- equal(icon.pixels.length, exp.pixels.length);
- for (let j = 0; j < icon.pixels.length; j++) {
- equal(icon.pixels[j], exp.pixels[j]);
- }
- }
- };
-
- iconLoader.loadIcons([0], onsuccess);
- }
-
- for (let i = 0; i < test_data.length; i++) {
- do_test(test_data[i].rawData, test_data[i].expected);
- }
-
- run_next_test();
-});
-
-/**
- * Verify IconLoader.loadIcons.
- */
-add_test(function test_load_icons() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let iconLoader = context.IconLoader;
- let simRecordHelper = context.SimRecordHelper;
-
- let test_data = {
- rawData: [
- // Record 1.
- [{codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- width: 0x10,
- height: 0x10,
- body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
- 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff]}],
- // Record 2.
- [{codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- width: 0x10,
- height: 0x10,
- bitsPerImgPoint: 0x04,
- numOfClutEntries: 0x10,
- body: [0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xcc, 0xfc, 0xcc,
- 0xcf, 0xcf, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf,
- 0xcc, 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcc,
- 0xfc, 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc,
- 0xcf, 0xcf, 0xff, 0xfc, 0xff, 0xcf, 0xcf, 0xcc, 0xcf,
- 0xfc, 0xcc, 0xfc, 0xcc, 0xcf, 0xcf, 0xfc, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
- 0x99, 0x99],
- clut: [0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
- 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80,
- 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80,
- 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xff]}],
- // Record 3.
- [{codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- width: 0x03,
- height: 0x03,
- bitsPerImgPoint: 0x05,
- numOfClutEntries: 0x20,
- body: [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
- clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
- 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
- 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
- 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f]},
- {codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- width: 0x10,
- height: 0x10,
- body: [0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x9d, 0xe9, 0xa1, 0x2d, 0xa1, 0x2d, 0xa1, 0x2b,
- 0xa1, 0x2b, 0x9d, 0xe9, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff]}],
- // Record 4.
- [{codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- width: 0x04,
- height: 0x04,
- bitsPerImgPoint: 0x04,
- numOfClutEntries: 0x10,
- body: [0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88],
- clut: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
- 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
- 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f]}]],
- expected: [
- // Record 1.
- [{width: 0x10,
- height: 0x10,
- pixels: [/* 1st byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 2nd byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 3rd byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 4th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 5th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 6th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 7th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 8th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 9th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 10th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 11th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 12th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 13th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 14th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 15th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 16th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 17th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 18th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 19th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 20th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 21th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 22th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 23th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 24th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 25th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 26th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 27th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 28th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 29th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 30th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 31th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 32th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff]}],
- // Record 2.
- [{width: 0x10,
- height: 0x10,
- pixels: [0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff,
- 0xffffffff, 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff,
- 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
- 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
- 0xff0000ff]}],
- // Record 3.
- [{width: 0x03,
- height: 0x03,
- pixels: [0x000102ff, 0x060708ff, 0x0c0d0eff, 0x121314ff, 0x18191aff,
- 0x1e1f20ff, 0x242526ff, 0x2a2b2cff, 0x333435ff]},
- {width: 0x10,
- height: 0x10,
- pixels: [/* 1st byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 2nd byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 3rd byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 4th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 5th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 6th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 7th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 8th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 9th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 10th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 11th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 12th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 13th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 14th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 15th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 16th byte of body: 0x2d */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 17th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 18th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 19th byte of body: 0xa1 */
- 0xffffffff, 0x000000ff, 0xffffffff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 20th byte of body: 0x2b */
- 0x000000ff, 0x000000ff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0xffffffff, 0xffffffff,
- /* 21th byte of body: 0x9d */
- 0xffffffff, 0x000000ff, 0x000000ff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0x000000ff, 0xffffffff,
- /* 22th byte of body: 0xe9 */
- 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0xffffffff,
- 0x000000ff, 0x000000ff, 0xffffffff,
- /* 23th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 24th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 25th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 26th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 27th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 28th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 29th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 30th byte of body: 0x00 */
- 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
- 0x000000ff, 0x000000ff, 0x000000ff,
- /* 31th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff,
- /* 32th byte of body: 0xff */
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff]}],
- // Record 4.
- [{width: 0x04,
- height: 0x04,
- pixels: [0x00000000, 0x00000000, 0x2a2b2cff, 0x2a2b2cff, 0x272829ff,
- 0x272829ff, 0x242526ff, 0x242526ff, 0x212223ff, 0x212223ff,
- 0x1e1f20ff, 0x1e1f20ff, 0x1b1c1dff, 0x1b1c1dff, 0x18191aff,
- 0x18191aff]}]]};
-
- function do_test() {
- simRecordHelper.readIMG = function fakeReadIMG(recordNumber, onsuccess, onerror) {
- onsuccess(test_data.rawData[recordNumber]);
- };
-
- let onsuccess = function(icons) {
- equal(icons.length, test_data.expected.length);
- for (let i = 0; i < icons.length; i++) {
- for (let j = 0; j < icons[i].length; j++) {
- // Read the j_th image from the i_th record.
- let icon = icons[i][j];
- let expected = test_data.expected[i][j];
- equal(icon.width, expected.width);
- equal(icon.height, expected.height);
- equal(icon.pixels.length, expected.pixels.length);
- for (let k = 0; k < icon.pixels.length; k++) {
- equal(icon.pixels[k], expected.pixels[k]);
- }
- }
- }
- };
-
- let recordNumbers = [0, 1, 2, 3];
- iconLoader.loadIcons(recordNumbers, onsuccess);
- }
-
- do_test();
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js b/dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js
deleted file mode 100644
index 6500cc663..000000000
--- a/dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js
+++ /dev/null
@@ -1,1648 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify reading EF_AD and parsing MCC/MNC
- */
-add_test(function test_reading_ad_and_parsing_mcc_mnc() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function do_test(mncLengthInEf, imsi, expectedMcc, expectedMnc) {
- ril.iccInfoPrivate.imsi = imsi;
-
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- let ad = [0x00, 0x00, 0x00];
- if (typeof mncLengthInEf === 'number') {
- ad.push(mncLengthInEf);
- }
-
- // Write data size
- buf.writeInt32(ad.length * 2);
-
- // Write data
- for (let i = 0; i < ad.length; i++) {
- helper.writeHexOctet(ad[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(ad.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readAD();
-
- equal(ril.iccInfo.mcc, expectedMcc);
- equal(ril.iccInfo.mnc, expectedMnc);
- }
-
- do_test(undefined, "466923202422409", "466", "92" );
- do_test(0x00, "466923202422409", "466", "92" );
- do_test(0x01, "466923202422409", "466", "92" );
- do_test(0x02, "466923202422409", "466", "92" );
- do_test(0x03, "466923202422409", "466", "923");
- do_test(0x04, "466923202422409", "466", "92" );
- do_test(0xff, "466923202422409", "466", "92" );
-
- do_test(undefined, "310260542718417", "310", "260");
- do_test(0x00, "310260542718417", "310", "260");
- do_test(0x01, "310260542718417", "310", "260");
- do_test(0x02, "310260542718417", "310", "26" );
- do_test(0x03, "310260542718417", "310", "260");
- do_test(0x04, "310260542718417", "310", "260");
- do_test(0xff, "310260542718417", "310", "260");
-
- run_next_test();
-});
-
-add_test(function test_reading_optional_efs() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let gsmPdu = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function buildSST(supportedEf) {
- let sst = [];
- let len = supportedEf.length;
- for (let i = 0; i < len; i++) {
- let index, bitmask, iccService;
- if (ril.appType === CARD_APPTYPE_SIM) {
- iccService = GECKO_ICC_SERVICES.sim[supportedEf[i]];
- iccService -= 1;
- index = Math.floor(iccService / 4);
- bitmask = 2 << ((iccService % 4) << 1);
- } else if (ril.appType === CARD_APPTYPE_USIM){
- iccService = GECKO_ICC_SERVICES.usim[supportedEf[i]];
- iccService -= 1;
- index = Math.floor(iccService / 8);
- bitmask = 1 << ((iccService % 8) << 0);
- }
-
- if (sst) {
- sst[index] |= bitmask;
- }
- }
- return sst;
- }
-
- ril.updateCellBroadcastConfig = function fakeUpdateCellBroadcastConfig() {
- // Ignore updateCellBroadcastConfig after reading SST
- };
-
- function do_test(sst, supportedEf) {
- // Clone supportedEf to local array for testing
- let testEf = supportedEf.slice(0);
-
- record.readMSISDN = function fakeReadMSISDN() {
- testEf.splice(testEf.indexOf("MSISDN"), 1);
- };
-
- record.readMBDN = function fakeReadMBDN() {
- testEf.splice(testEf.indexOf("MDN"), 1);
- };
-
- record.readMWIS = function fakeReadMWIS() {
- testEf.splice(testEf.indexOf("MWIS"), 1);
- };
-
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(sst.length * 2);
-
- // Write data
- for (let i = 0; i < sst.length; i++) {
- gsmPdu.writeHexOctet(sst[i] || 0);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(sst.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
-
- if (testEf.length !== 0) {
- do_print("Un-handled EF: " + JSON.stringify(testEf));
- ok(false);
- }
- };
-
- record.readSST();
- }
-
- // TODO: Add all necessary optional EFs eventually
- let supportedEf = ["MSISDN", "MDN", "MWIS"];
- ril.appType = CARD_APPTYPE_SIM;
- do_test(buildSST(supportedEf), supportedEf);
- ril.appType = CARD_APPTYPE_USIM;
- do_test(buildSST(supportedEf), supportedEf);
-
- run_next_test();
-});
-
-/**
- * Verify fetchSimRecords.
- */
-add_test(function test_fetch_sim_records() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let iccRecord = context.ICCRecordHelper;
- let simRecord = context.SimRecordHelper;
-
- function testFetchSimRecordes(expectCalled, expectCphsSuccess) {
- let ifCalled = [];
-
- RIL.getIMSI = function() {
- ifCalled.push("getIMSI");
- };
-
- simRecord.readAD = function() {
- ifCalled.push("readAD");
- };
-
- simRecord.readCphsInfo = function(onsuccess, onerror) {
- ifCalled.push("readCphsInfo");
- if (expectCphsSuccess) {
- onsuccess();
- } else {
- onerror();
- }
- };
-
- simRecord.readSST = function() {
- ifCalled.push("readSST");
- };
-
- simRecord.fetchSimRecords();
-
- for (let i = 0; i < expectCalled.length; i++ ) {
- if (ifCalled[i] != expectCalled[i]) {
- do_print(expectCalled[i] + " is not called.");
- ok(false);
- }
- }
- }
-
- let expectCalled = ["getIMSI", "readAD", "readCphsInfo", "readSST"];
- testFetchSimRecordes(expectCalled, true);
- testFetchSimRecordes(expectCalled, false);
-
- run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.readMWIS
- */
-add_test(function test_read_mwis() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let recordHelper = context.SimRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let mwisData;
- let postedMessage;
-
- worker.postMessage = function fakePostMessage(message) {
- postedMessage = message;
- };
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- if (mwisData) {
- // Write data size
- buf.writeInt32(mwisData.length * 2);
-
- // Write MWIS
- for (let i = 0; i < mwisData.length; i++) {
- helper.writeHexOctet(mwisData[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(mwisData.length * 2);
-
- options.recordSize = mwisData.length;
- if (options.callback) {
- options.callback(options);
- }
- } else {
- do_print("mwisData[] is not set.");
- }
- };
-
- function buildMwisData(isActive, msgCount) {
- if (msgCount < 0 || msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) {
- msgCount = 0;
- } else if (msgCount > 255) {
- msgCount = 255;
- }
-
- mwisData = [ (isActive) ? 0x01 : 0x00,
- msgCount,
- 0xFF, 0xFF, 0xFF ];
- }
-
- function do_test(isActive, msgCount) {
- buildMwisData(isActive, msgCount);
- recordHelper.readMWIS();
-
- equal("iccmwis", postedMessage.rilMessageType);
- equal(isActive, postedMessage.mwi.active);
- equal((isActive) ? msgCount : 0, postedMessage.mwi.msgCount);
- }
-
- do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
- do_test(true, 1);
- do_test(true, 255);
-
- do_test(false, 0);
- do_test(false, 255); // Test the corner case when mwi is disable with incorrect msgCount.
-
- run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.updateMWIS
- */
-add_test(function test_update_mwis() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- ril.appType = CARD_APPTYPE_USIM;
- ril.iccInfoPrivate.mwis = [0x00, 0x00, 0x00, 0x00, 0x00];
- let recordHelper = context.SimRecordHelper;
- let buf = context.Buf;
- let ioHelper = context.ICCIOHelper;
- let recordSize = ril.iccInfoPrivate.mwis.length;
- let recordNum = 1;
-
- ioHelper.updateLinearFixedEF = function(options) {
- options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
- options.command = ICC_COMMAND_UPDATE_RECORD;
- options.p1 = options.recordNumber;
- options.p2 = READ_RECORD_ABSOLUTE_MODE;
- options.p3 = recordSize;
- ril.iccIO(options);
- };
-
- function do_test(isActive, count) {
- let mwis = ril.iccInfoPrivate.mwis;
- let isUpdated = false;
-
- function buildMwisData() {
- let result = mwis.slice(0);
- result[0] = isActive? (mwis[0] | 0x01) : (mwis[0] & 0xFE);
- result[1] = (count === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : count;
-
- return result;
- }
-
- buf.sendParcel = function() {
- isUpdated = true;
-
- // Request Type.
- equal(this.readInt32(), REQUEST_SIM_IO);
-
- // Token : we don't care
- this.readInt32();
-
- // command.
- equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
- // fileId.
- equal(this.readInt32(), ICC_EF_MWIS);
-
- // pathId.
- equal(this.readString(),
- EF_PATH_MF_SIM + ((ril.appType === CARD_APPTYPE_USIM) ? EF_PATH_ADF_USIM : EF_PATH_DF_GSM));
-
- // p1.
- equal(this.readInt32(), recordNum);
-
- // p2.
- equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
- // p3.
- equal(this.readInt32(), recordSize);
-
- // data.
- let strLen = this.readInt32();
- equal(recordSize * 2, strLen);
- let expectedMwis = buildMwisData();
- for (let i = 0; i < recordSize; i++) {
- equal(expectedMwis[i], pduHelper.readHexOctet());
- }
- this.readStringDelimiter(strLen);
-
- // pin2.
- equal(this.readString(), null);
-
- // AID. Ignore because it's from modem.
- this.readInt32();
- };
-
- ok(!isUpdated);
-
- recordHelper.updateMWIS({ active: isActive,
- msgCount: count });
-
- ok((ril.iccInfoPrivate.mwis) ? isUpdated : !isUpdated);
- }
-
- do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
- do_test(true, 1);
- do_test(true, 255);
-
- do_test(false, 0);
-
- // Test if Path ID is correct for SIM.
- ril.appType = CARD_APPTYPE_SIM;
- do_test(false, 0);
-
- // Test if loadLinearFixedEF() is not invoked in updateMWIS() when
- // EF_MWIS is not loaded/available.
- delete ril.iccInfoPrivate.mwis;
- do_test(false, 0);
-
- run_next_test();
-});
-
-/**
- * Verify the call flow of receiving Class 2 SMS stored in SIM:
- * 1. UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM.
- * 2. SimRecordHelper.readSMS().
- * 3. sendChromeMessage() with rilMessageType == "sms-received".
- */
-add_test(function test_read_new_sms_on_sim() {
- // Instead of reusing newUint8Worker defined in this file,
- // we define our own worker to fake the methods in WorkerBuffer dynamically.
- function newSmsOnSimWorkerHelper() {
- let _postedMessage;
- let _worker = newWorker({
- postRILMessage: function(data) {
- },
- postMessage: function(message) {
- _postedMessage = message;
- }
- });
-
- _worker.debug = do_print;
-
- return {
- get postedMessage() {
- return _postedMessage;
- },
- get worker() {
- return _worker;
- },
- fakeWokerBuffer: function() {
- let context = _worker.ContextPool._contexts[0];
- let index = 0; // index for read
- let buf = [];
- context.Buf.writeUint8 = function(value) {
- buf.push(value);
- };
- context.Buf.readUint8 = function() {
- return buf[index++];
- };
- context.Buf.seekIncoming = function(offset) {
- index += offset;
- };
- context.Buf.getReadAvailable = function() {
- return buf.length - index;
- };
- }
- };
- }
-
- let workerHelper = newSmsOnSimWorkerHelper();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.ICCIOHelper.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // SimStatus: Unread, SMSC:+0123456789, Sender: +9876543210, Text: How are you?
- let SimSmsPduHex = "0306911032547698040A9189674523010000208062917314080CC8F71D14969741F977FD07"
- // In 4.2.25 EF_SMS Short Messages of 3GPP TS 31.102:
- // 1. Record length == 176 bytes.
- // 2. Any bytes in the record following the TPDU shall be filled with 'FF'.
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
-
- workerHelper.fakeWokerBuffer();
-
- context.Buf.writeString(SimSmsPduHex);
-
- options.recordSize = 176; // Record length is fixed to 176 bytes.
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function newSmsOnSimParcel() {
- let data = new Uint8Array(4 + 4); // Int32List with 1 element.
- let offset = 0;
-
- function writeInt(value) {
- data[offset++] = value & 0xFF;
- data[offset++] = (value >> 8) & 0xFF;
- data[offset++] = (value >> 16) & 0xFF;
- data[offset++] = (value >> 24) & 0xFF;
- }
-
- writeInt(1); // Length of Int32List
- writeInt(1); // RecordNum = 1.
-
- return newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM,
- data);
- }
-
- function do_test() {
- worker.onRILMessage(0, newSmsOnSimParcel());
-
- let postedMessage = workerHelper.postedMessage;
-
- equal("sms-received", postedMessage.rilMessageType);
- equal("+0123456789", postedMessage.SMSC);
- equal("+9876543210", postedMessage.sender);
- equal("How are you?", postedMessage.body);
- }
-
- do_test();
-
- run_next_test();
-});
-
-/**
- * Verify the result of updateDisplayCondition after reading EF_SPDI | EF_SPN.
- */
-add_test(function test_update_display_condition() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function do_test_spdi() {
- // No EF_SPN, but having EF_SPDI.
- // It implies "ril.iccInfoPrivate.spnDisplayCondition = undefined;".
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // PLMN lists are : 234-136 and 466-92.
- let spdi = [0xA3, 0x0B, 0x80, 0x09, 0x32, 0x64, 0x31, 0x64, 0x26, 0x9F,
- 0xFF, 0xFF, 0xFF];
-
- // Write data size.
- buf.writeInt32(spdi.length * 2);
-
- // Write data.
- for (let i = 0; i < spdi.length; i++) {
- helper.writeHexOctet(spdi[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(spdi.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readSPDI();
-
- equal(ril.iccInfo.isDisplayNetworkNameRequired, true);
- equal(ril.iccInfo.isDisplaySpnRequired, false);
- }
-
- function do_test_spn(displayCondition,
- expectedPlmnNameDisplay,
- expectedSpnDisplay) {
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // "Android" as Service Provider Name.
- let spn = [0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64];
- if (typeof displayCondition === 'number') {
- spn.unshift(displayCondition);
- }
-
- // Write data size.
- buf.writeInt32(spn.length * 2);
-
- // Write data.
- for (let i = 0; i < spn.length; i++) {
- helper.writeHexOctet(spn[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(spn.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readSPN();
-
- equal(ril.iccInfo.isDisplayNetworkNameRequired, expectedPlmnNameDisplay);
- equal(ril.iccInfo.isDisplaySpnRequired, expectedSpnDisplay);
- }
-
- // Create empty operator object.
- ril.operator = {};
- // Setup SIM MCC-MNC to 310-260 as home network.
- ril.iccInfo.mcc = 310;
- ril.iccInfo.mnc = 260;
-
- do_test_spdi();
-
- // No network.
- do_test_spn(0x00, true, true);
- do_test_spn(0x01, true, true);
- do_test_spn(0x02, true, false);
- do_test_spn(0x03, true, false);
-
- // Home network.
- ril.operator.mcc = 310;
- ril.operator.mnc = 260;
- do_test_spn(0x00, false, true);
- do_test_spn(0x01, true, true);
- do_test_spn(0x02, false, true);
- do_test_spn(0x03, true, true);
-
- // Not HPLMN but in PLMN list.
- ril.iccInfoPrivate.SPDI = [{"mcc":"234","mnc":"136"},{"mcc":"466","mnc":"92"}];
- ril.operator.mcc = 466;
- ril.operator.mnc = 92;
- do_test_spn(0x00, false, true);
- do_test_spn(0x01, true, true);
- do_test_spn(0x02, false, true);
- do_test_spn(0x03, true, true);
- ril.iccInfoPrivate.SPDI = null; // reset SPDI to null;
-
- // Non-Home network.
- ril.operator.mcc = 466;
- ril.operator.mnc = 01;
- do_test_spn(0x00, true, true);
- do_test_spn(0x01, true, true);
- do_test_spn(0x02, true, false);
- do_test_spn(0x03, true, false);
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with ICC_IMG_CODING_SCHEME_BASIC
- */
-add_test(function test_reading_img_basic() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- {img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06],
- iidf: [
- [/* Header */
- 0x05, 0x05,
- /* Image body */
- 0x11, 0x33, 0x55, 0xfe]],
- expected: [
- {width: 0x05,
- height: 0x05,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x11, 0x33, 0x55, 0xfe]}]},
- {img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06,
- /* Padding */
- 0xff, 0xff],
- iidf: [
- [/* Header */
- 0x05, 0x05,
- /* Image body */
- 0x11, 0x33, 0x55, 0xfe]],
- expected: [
- {width: 0x05,
- height: 0x05,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x11, 0x33, 0x55, 0xfe]}]},
- {img: [0x02, 0x10, 0x01, 0x11, 0x4f, 0x04, 0x00, 0x05, 0x00, 0x04, 0x10,
- 0x01, 0x11, 0x4f, 0x05, 0x00, 0x05, 0x00, 0x04],
- iidf: [
- [/* Data offset */
- 0xff, 0xff, 0xff, 0xff, 0xff,
- /* Header */
- 0x10, 0x01,
- /* Image body */
- 0x11, 0x99,
- /* Trailing data */
- 0xff, 0xff, 0xff],
- [/* Data offset */
- 0xff, 0xff, 0xff, 0xff, 0xff,
- /* Header */
- 0x10, 0x01,
- /* Image body */
- 0x99, 0x11]],
- expected: [
- {width: 0x10,
- height: 0x01,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x11, 0x99]},
- {width: 0x10,
- height: 0x01,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x99, 0x11]}]},
- {img: [0x01, 0x28, 0x20, 0x11, 0x4f, 0xac, 0x00, 0x0b, 0x00, 0xa2],
- iidf: [
- [/* Data offset */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- /* Header */
- 0x28, 0x20,
- /* Image body */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
- 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
- 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
- 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
- 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
- 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
- 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x00, 0x01, 0x02,
- 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
- 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
- 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f]],
- expected: [
- {width: 0x28,
- height: 0x20,
- codingScheme: ICC_IMG_CODING_SCHEME_BASIC,
- body: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
- 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
- 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
- 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
- 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
- 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x00, 0x01, 0x02, 0x03,
- 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
- 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
- 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
- 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f]}]}];
-
- function do_test(img, iidf, expected) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let instanceIndex = 0;
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf[instanceIndex].length * 2);
-
- // Write data
- for (let i = 0; i < iidf[instanceIndex].length; i++) {
- helper.writeHexOctet(iidf[instanceIndex][i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf[instanceIndex].length * 2);
-
- instanceIndex++;
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function(icons) {
- equal(icons.length, expected.length);
- for (let i = 0; i < icons.length; i++) {
- let icon = icons[i];
- let exp = expected[i];
- equal(icon.width, exp.width);
- equal(icon.height, exp.height);
- equal(icon.codingScheme, exp.codingScheme);
-
- equal(icon.body.length, exp.body.length);
- for (let j = 0; j < icon.body.length; j++) {
- equal(icon.body[j], exp.body[j]);
- }
- }
- };
- record.readIMG(0, onsuccess);
- }
-
- for (let i = 0; i< test_data.length; i++) {
- do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected);
- }
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with the case data length is not enough
- */
-add_test(function test_reading_img_length_error() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- {/* Offset length not enough, should be 4. */
- img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x04, 0x00, 0x06],
- iidf: [0xff, 0xff, 0xff, // Offset.
- 0x05, 0x05, 0x11, 0x22, 0x33, 0xfe]},
- {/* iidf data length not enough, should be 6. */
- img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06],
- iidf: [0x05, 0x05, 0x11, 0x22, 0x33]}];
-
- function do_test(img, iidf) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf.length * 2);
-
- // Write data
- for (let i = 0; i < iidf.length; i++) {
- helper.writeHexOctet(iidf[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function() {
- do_print("onsuccess shouldn't be called.");
- ok(false);
- };
-
- let onerror = function() {
- do_print("onerror called as expected.");
- ok(true);
- };
-
- record.readIMG(0, onsuccess, onerror);
- }
-
- for (let i = 0; i < test_data.length; i++) {
- do_test(test_data[i].img, test_data[i].iidf);
- }
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with an invalid fileId
- */
-add_test(function test_reading_img_invalid_fileId() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- // Test invalid fileId: 0x5f00.
- let img_test = [0x01, 0x05, 0x05, 0x11, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x06];
- let iidf_test = [0x05, 0x05, 0x11, 0x22, 0x33, 0xfe];
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img_test.length * 2);
-
- // Write data
- for (let i = 0; i < img_test.length; i++) {
- helper.writeHexOctet(img_test[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img_test.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf_test.length * 2);
-
- // Write data
- for (let i = 0; i < iidf_test.length; i++) {
- helper.writeHexOctet(iidf_test[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf_test.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function() {
- do_print("onsuccess shouldn't be called.");
- ok(false);
- };
-
- let onerror = function() {
- do_print("onerror called as expected.");
- ok(true);
- };
-
- record.readIMG(0, onsuccess, onerror);
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG with a wrong record length
- */
-add_test(function test_reading_img_wrong_record_length() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00],
- [0x02, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06]];
-
- function do_test(img) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function() {
- do_print("onsuccess shouldn't be called.");
- ok(false);
- };
-
- let onerror = function() {
- do_print("onerror called as expected.");
- ok(true);
- };
-
- record.readIMG(0, onsuccess, onerror);
- }
-
- for (let i = 0; i < test_data.length; i++) {
- do_test(test_data[i]);
- }
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with ICC_IMG_CODING_SCHEME_COLOR
- */
-add_test(function test_reading_img_color() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- {img: [0x01, 0x05, 0x05, 0x21, 0x4f, 0x11, 0x00, 0x00, 0x00, 0x13],
- iidf: [
- [/* Header */
- 0x05, 0x05, 0x03, 0x08, 0x00, 0x13,
- /* Image body */
- 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0,
- 0xb0, 0xc0, 0xd0,
- /* Clut entries */
- 0x00, 0x01, 0x02,
- 0x10, 0x11, 0x12,
- 0x20, 0x21, 0x22,
- 0x30, 0x31, 0x32,
- 0x40, 0x41, 0x42,
- 0x50, 0x51, 0x52,
- 0x60, 0x61, 0x62,
- 0x70, 0x71, 0x72]],
- expected: [
- {width: 0x05,
- height: 0x05,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- bitsPerImgPoint: 0x03,
- numOfClutEntries: 0x08,
- body: [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0,
- 0xc0, 0xd0],
- clut: [0x00, 0x01, 0x02,
- 0x10, 0x11, 0x12,
- 0x20, 0x21, 0x22,
- 0x30, 0x31, 0x32,
- 0x40, 0x41, 0x42,
- 0x50, 0x51, 0x52,
- 0x60, 0x61, 0x62,
- 0x70, 0x71, 0x72]}]},
- {img: [0x02, 0x01, 0x06, 0x21, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08, 0x01,
- 0x06, 0x21, 0x4f, 0x44, 0x00, 0x02, 0x00, 0x08],
- iidf: [
- [/* Data offset */
- 0xff, 0xff,
- /* Header */
- 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
- /* Image body */
- 0x40, 0x50,
- /* Clut offset */
- 0xaa, 0xbb, 0xcc,
- /* Clut entries */
- 0x01, 0x03, 0x05,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65],
- [/* Data offset */
- 0xff, 0xff,
- /* Header */
- 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
- /* Image body */
- 0x4f, 0x5f,
- /* Clut offset */
- 0xaa, 0xbb, 0xcc,
- /* Clut entries */
- 0x11, 0x13, 0x15,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]],
- expected: [
- {width: 0x01,
- height: 0x06,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- bitsPerImgPoint: 0x02,
- numOfClutEntries: 0x04,
- body: [0x40, 0x50],
- clut: [0x01, 0x03, 0x05,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]},
- {width: 0x01,
- height: 0x06,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR,
- bitsPerImgPoint: 0x02,
- numOfClutEntries: 0x04,
- body: [0x4f, 0x5f],
- clut: [0x11, 0x13, 0x15,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]}]}];
-
- function do_test(img, iidf, expected) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let instanceIndex = 0;
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf[instanceIndex].length * 2);
-
- // Write data
- for (let i = 0; i < iidf[instanceIndex].length; i++) {
- helper.writeHexOctet(iidf[instanceIndex][i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf[instanceIndex].length * 2);
-
- instanceIndex++;
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function(icons) {
- equal(icons.length, expected.length);
- for (let i = 0; i < icons.length; i++) {
- let icon = icons[i];
- let exp = expected[i];
- equal(icon.width, exp.width);
- equal(icon.height, exp.height);
- equal(icon.codingScheme, exp.codingScheme);
-
- equal(icon.body.length, exp.body.length);
- for (let j = 0; j < icon.body.length; j++) {
- equal(icon.body[j], exp.body[j]);
- }
-
- equal(icon.clut.length, exp.clut.length);
- for (let j = 0; j < icon.clut.length; j++) {
- equal(icon.clut[j], exp.clut[j]);
- }
- }
- };
-
- record.readIMG(0, onsuccess);
- }
-
- for (let i = 0; i< test_data.length; i++) {
- do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected);
- }
- run_next_test();
-});
-
-/**
- * Verify reading EF_IMG and EF_IIDF with
- * ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY
- */
-add_test(function test_reading_img_color() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let helper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [
- {img: [0x01, 0x05, 0x05, 0x22, 0x4f, 0x11, 0x00, 0x00, 0x00, 0x13],
- iidf: [
- [/* Header */
- 0x05, 0x05, 0x03, 0x08, 0x00, 0x13,
- /* Image body */
- 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0,
- 0xb0, 0xc0, 0xd0,
- /* Clut entries */
- 0x00, 0x01, 0x02,
- 0x10, 0x11, 0x12,
- 0x20, 0x21, 0x22,
- 0x30, 0x31, 0x32,
- 0x40, 0x41, 0x42,
- 0x50, 0x51, 0x52,
- 0x60, 0x61, 0x62,
- 0x70, 0x71, 0x72]],
- expected: [
- {width: 0x05,
- height: 0x05,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- bitsPerImgPoint: 0x03,
- numOfClutEntries: 0x08,
- body: [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,
- 0xa0, 0xb0, 0xc0, 0xd0],
- clut: [0x00, 0x01, 0x02,
- 0x10, 0x11, 0x12,
- 0x20, 0x21, 0x22,
- 0x30, 0x31, 0x32,
- 0x40, 0x41, 0x42,
- 0x50, 0x51, 0x52,
- 0x60, 0x61, 0x62,
- 0x70, 0x71, 0x72]}]},
- {img: [0x02, 0x01, 0x06, 0x22, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08, 0x01,
- 0x06, 0x22, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08],
- iidf: [
- [/* Data offset */
- 0xff, 0xff,
- /* Header */
- 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
- /* Image body */
- 0x40, 0x50,
- /* Clut offset */
- 0x0a, 0x0b, 0x0c,
- /* Clut entries */
- 0x01, 0x03, 0x05,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65],
- [/* Data offset */
- 0xff, 0xff,
- /* Header */
- 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d,
- /* Image body */
- 0x4f, 0x5f,
- /* Clut offset */
- 0x0a, 0x0b, 0x0c,
- /* Clut entries */
- 0x11, 0x13, 0x15,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]],
- expected: [
- {width: 0x01,
- height: 0x06,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- bitsPerImgPoint: 0x02,
- numOfClutEntries: 0x04,
- body: [0x40, 0x50],
- clut: [0x01, 0x03, 0x05,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]},
- {width: 0x01,
- height: 0x06,
- codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY,
- bitsPerImgPoint: 0x02,
- numOfClutEntries: 0x04,
- body: [0x4f, 0x5f],
- clut: [0x11, 0x13, 0x15,
- 0x21, 0x23, 0x25,
- 0x41, 0x43, 0x45,
- 0x61, 0x63, 0x65]}]}];
-
- function do_test(img, iidf, expected) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size
- buf.writeInt32(img.length * 2);
-
- // Write data
- for (let i = 0; i < img.length; i++) {
- helper.writeHexOctet(img[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(img.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let instanceIndex = 0;
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(iidf[instanceIndex].length * 2);
-
- // Write data
- for (let i = 0; i < iidf[instanceIndex].length; i++) {
- helper.writeHexOctet(iidf[instanceIndex][i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(iidf[instanceIndex].length * 2);
-
- instanceIndex++;
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- let onsuccess = function(icons) {
- equal(icons.length, expected.length);
- for (let i = 0; i < icons.length; i++) {
- let icon = icons[i];
- let exp = expected[i];
- equal(icon.width, exp.width);
- equal(icon.height, exp.height);
- equal(icon.codingScheme, exp.codingScheme);
-
- equal(icon.body.length, exp.body.length);
- for (let j = 0; j < icon.body.length; j++) {
- equal(icon.body[j], exp.body[j]);
- }
-
- equal(icon.clut.length, exp.clut.length);
- for (let j = 0; j < icon.clut.length; j++) {
- equal(icon.clut[j], exp.clut[j]);
- }
- }
- };
-
- record.readIMG(0, onsuccess);
- }
-
- for (let i = 0; i< test_data.length; i++) {
- do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected);
- }
- run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.readCphsInfo
- */
-add_test(function test_read_cphs_info() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let pduHelper = context.GsmPDUHelper;
- let recordHelper = context.SimRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let cphsPDU = new Uint8Array(3);
-
- io.loadTransparentEF = function(options) {
- if (cphsPDU) {
- // Write data size
- buf.writeInt32(cphsPDU.length * 2);
-
- // Write CPHS INFO
- for (let i = 0; i < cphsPDU.length; i++) {
- pduHelper.writeHexOctet(cphsPDU[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(cphsPDU.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- } else {
- do_print("cphsPDU[] is not set.");
- }
- };
-
- function do_test(cphsInfo, cphsSt) {
- let onsuccess = false;
- let onerror = false;
-
- delete RIL.iccInfoPrivate.cphsSt;
- cphsPDU.set(cphsInfo);
- recordHelper.readCphsInfo(() => { onsuccess = true; },
- () => { onerror = true; });
-
- ok((cphsSt) ? onsuccess : onerror);
- ok(!((cphsSt) ? onerror : onsuccess));
- if (cphsSt) {
- equal(RIL.iccInfoPrivate.cphsSt.length, cphsSt.length);
- for (let i = 0; i < cphsSt.length; i++) {
- equal(RIL.iccInfoPrivate.cphsSt[i], cphsSt[i]);
- }
- } else {
- equal(RIL.iccInfoPrivate.cphsSt, cphsSt);
- }
- }
-
- do_test([
- 0x01, // Phase 1
- 0xFF, // All available & activated
- 0x03 // All available & activated
- ],
- [
- 0x3F, // All services except ONSF(bit 8-7) are available and activated.
- 0x00 // INFO_NUM shall not be available & activated.
- ]);
-
- do_test([
- 0x02, // Phase 2
- 0xFF, // All available & activated
- 0x03 // All available & activated
- ],
- [
- 0xF3, // All services except ONSF are available and activated.
- 0x03 // INFO_NUM shall not be available & activated.
- ]);
-
- do_test([
- 0x03, // Phase 3
- 0xFF, // All available & activated
- 0x03 // All available & activated
- ],
- undefined); // RIL.iccInfoPrivate.cphsSt shall be remained as 'undefined'.
-
- run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.readMBDN/SimRecordHelper.readCphsMBN
- */
-add_test(function test_read_voicemail_number() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let pduHelper = context.GsmPDUHelper;
- let recordHelper = context.SimRecordHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
- let postedMessage;
-
- worker.postMessage = function(message) {
- postedMessage = message;
- };
-
- io.loadLinearFixedEF = function(options) {
- let mbnData = [
- 0x56, 0x6F, 0x69, 0x63, 0x65, 0x6D, 0x61, 0x69,
- 0x6C, 0xFF, // Alpha Identifier: Voicemail
- 0x03, // Length of BCD number: 3
- 0x80, // TOA: Unknown
- 0x11, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, // Dialing Number: 111
- 0xFF, // Capability/Configuration Record Identifier
- 0xFF // Extension Record Identifier
- ];
-
- // Write data size
- buf.writeInt32(mbnData.length * 2);
-
- // Write MBN
- for (let i = 0; i < mbnData.length; i++) {
- pduHelper.writeHexOctet(mbnData[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(mbnData.length * 2);
-
- options.recordSize = mbnData.length;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function do_test(funcName, msgCount) {
- postedMessage = null;
- delete RIL.iccInfoPrivate.mbdn;
- recordHelper[funcName]();
-
- equal("iccmbdn", postedMessage.rilMessageType);
- equal("Voicemail", postedMessage.alphaId);
- equal("111", postedMessage.number);
- }
-
- do_test("readMBDN");
- do_test("readCphsMBN");
-
- run_next_test();
-});
-
-/**
- * Verify the recovery from SimRecordHelper.readCphsMBN() if MBDN is not valid
- * or is empty after SimRecordHelper.readMBDN().
- */
-add_test(function test_read_mbdn_recovered_from_cphs_mbn() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let pduHelper = context.GsmPDUHelper;
- let recordHelper = context.SimRecordHelper;
- let iccUtilsHelper = context.ICCUtilsHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- io.loadLinearFixedEF = function(options) {
- let mbnData = [
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
- ];
-
- // Write data size
- buf.writeInt32(mbnData.length * 2);
-
- // Write MBN
- for (let i = 0; i < mbnData.length; i++) {
- pduHelper.writeHexOctet(mbnData[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(mbnData.length * 2);
-
- options.recordSize = mbnData.length;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- iccUtilsHelper.isCphsServiceAvailable = function(geckoService) {
- return geckoService == "MBN";
- };
-
- let isRecovered = false;
- recordHelper.readCphsMBN = function(onComplete) {
- isRecovered = true;
- };
-
- recordHelper.readMBDN();
-
- equal(RIL.iccInfoPrivate.mbdn, undefined);
- ok(isRecovered);
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_PNN with different coding scheme.
- */
-add_test(function test_pnn_with_different_coding_scheme() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [{
- // Cell Broadcast data coding scheme - "Test1"
- pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x1E, 0x03],
- expectedResult: "Test1"
- },{
- // UCS2 with 0x80 - "Test1"
- pnn: [0x43, 0x0C, 0x90, 0x80, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x31],
- expectedResult: "Test1"
- },{
- // UCS2 with 0x81 - "Mozilla\u694a"
- pnn: [0x43, 0x0E, 0x90, 0x81, 0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff],
- expectedResult: "Mozilla\u694a"
- },{
- // UCS2 with 0x82 - "Mozilla\u694a"
- pnn: [0x43, 0x0F, 0x90, 0x82, 0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff],
- expectedResult: "Mozilla\u694a"
- }];
-
- function do_test_pnn(pnn, expectedResult) {
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- // Write data size.
- buf.writeInt32(pnn.length * 2);
-
- // Write data.
- for (let i = 0; i < pnn.length; i++) {
- pduHelper.writeHexOctet(pnn[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(pnn.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- record.readPNN();
-
- equal(ril.iccInfoPrivate.PNN[0].fullName, expectedResult);
- // Reset PNN info for next test
- ril.iccInfoPrivate.PNN = null;
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- for (let i = 0; i < test_data.length; i++) {
- do_test_pnn(test_data[i].pnn, test_data[i].expectedResult);
- }
-
- run_next_test();
-});
-
-/**
- * Verify reading EF_PNN with different content.
- */
-add_test(function test_pnn_with_different_content() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let record = context.SimRecordHelper;
- let pduHelper = context.GsmPDUHelper;
- let ril = context.RIL;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- let test_data = [{
- // [0]: {"fullName":"Test1","shortName":"Test1"}
- pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x1E, 0x03,
- 0x45, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x1E, 0x03],
- expectedResult: {"fullName": "Test1","shortName": "Test1"}
- },{
- // [1]: {"fullName":"Test2"}
- pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x2E, 0x03],
- expectedResult: {"fullName": "Test2"}
- },{
- // [2]: undefined
- pnn: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
- },{
- // [3]: {"fullName": "Test4"}
- pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x4E, 0x03],
- expectedResult: {"fullName": "Test4"}
- },{
- // [4]: undefined
- pnn: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
- }];
-
- function do_test_pnn() {
- ril.iccIO = function fakeIccIO(options) {
- let index = options.p1 - 1;
- let pnn = test_data[index].pnn;
-
- // Write data size.
- buf.writeInt32(pnn.length * 2);
-
- // Write data.
- for (let i = 0; i < pnn.length; i++) {
- pduHelper.writeHexOctet(pnn[i]);
- }
-
- // Write string delimiter.
- buf.writeStringDelimiter(pnn.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- options.p1 = 1;
- options.totalRecords = test_data.length;
-
- ril.iccIO(options);
- };
-
- record.readPNN();
-
- equal(test_data.length, ril.iccInfoPrivate.PNN.length);
- for (let i = 0; i < test_data.length; i++) {
- if (test_data[i].expectedResult) {
- equal(test_data[i].expectedResult.fullName,
- ril.iccInfoPrivate.PNN[i].fullName);
- equal(test_data[i].expectedResult.shortName,
- ril.iccInfoPrivate.PNN[i].shortName);
- } else {
- equal(test_data[i].expectedResult, ril.iccInfoPrivate.PNN[i]);
- }
- }
- }
-
- ril.appType = CARD_APPTYPE_SIM;
- do_test_pnn();
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_ruim.js b/dom/system/gonk/tests/test_ril_worker_ruim.js
deleted file mode 100644
index 0ddc10f29..000000000
--- a/dom/system/gonk/tests/test_ril_worker_ruim.js
+++ /dev/null
@@ -1,328 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify RUIM Service.
- */
-add_test(function test_is_ruim_service_available() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- context.RIL._isCdma = true;
- context.RIL.appType = CARD_APPTYPE_RUIM;
-
- function test_table(cst, geckoService, enabled) {
- context.RIL.iccInfoPrivate.cst = cst;
- equal(context.ICCUtilsHelper.isICCServiceAvailable(geckoService),
- enabled);
- }
-
- test_table([0x0, 0x0, 0x0, 0x0, 0x03], "SPN", true);
- test_table([0x0, 0x0, 0x0, 0x03, 0x0], "SPN", false);
- test_table([0x0, 0x0C, 0x0, 0x0, 0x0], "ENHANCED_PHONEBOOK", true);
- test_table([0x0, 0x0, 0x0, 0x0, 0x0], "ENHANCED_PHONEBOOK", false);
-
- run_next_test();
-});
-
-/**
- * Verify EF_PATH for RUIM file.
- */
-add_test(function test_ruim_file_path_id() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ICCFileHelper = context.ICCFileHelper;
-
- RIL.appType = CARD_APPTYPE_RUIM;
- equal(ICCFileHelper.getEFPath(ICC_EF_CSIM_CST),
- EF_PATH_MF_SIM + EF_PATH_DF_CDMA);
-
- run_next_test();
-});
-
-add_test(function test_fetch_ruim_recodes() {
- let worker = newWorker();
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ruimHelper = context.RuimRecordHelper;
-
- function testFetchRuimRecordes(expectCalled) {
- let ifCalled = [];
-
- ruimHelper.getIMSI_M = function() {
- ifCalled.push("getIMSI_M");
- };
-
- ruimHelper.readCST = function() {
- ifCalled.push("readCST");
- };
-
- ruimHelper.readCDMAHome = function() {
- ifCalled.push("readCDMAHome");
- };
-
- RIL.getCdmaSubscription = function() {
- ifCalled.push("getCdmaSubscription");
- };
-
- ruimHelper.fetchRuimRecords();
-
- for (let i = 0; i < expectCalled.length; i++ ) {
- if (ifCalled[i] != expectCalled[i]) {
- do_print(expectCalled[i] + " is not called.");
- ok(false);
- }
- }
- }
-
- let expectCalled = ["getIMSI_M", "readCST", "readCDMAHome",
- "getCdmaSubscription"];
- testFetchRuimRecordes(expectCalled);
-
- run_next_test();
-});
-
-/**
- * Verify RuimRecordHelper.decodeIMSIValue
- */
-add_test(function test_decode_imsi_value() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
-
- function testDecodeImsiValue(encoded, length, expect) {
- let decoded = context.RuimRecordHelper.decodeIMSIValue(encoded, length);
-
- equal(expect, decoded);
- }
-
- testDecodeImsiValue( 99, 2, "00");
- testDecodeImsiValue( 90, 2, "01");
- testDecodeImsiValue( 19, 2, "20");
- testDecodeImsiValue( 23, 2, "34");
- testDecodeImsiValue(999, 3, "000");
- testDecodeImsiValue(990, 3, "001");
- testDecodeImsiValue(909, 3, "010");
- testDecodeImsiValue( 99, 3, "100");
- testDecodeImsiValue(901, 3, "012");
- testDecodeImsiValue( 19, 3, "120");
- testDecodeImsiValue( 91, 3, "102");
- testDecodeImsiValue(199, 3, "200");
- testDecodeImsiValue(123, 3, "234");
- testDecodeImsiValue(578, 3, "689");
-
- run_next_test();
-});
-
-/**
- * Verify RuimRecordHelper.getIMSI_M
- */
-add_test(function test_get_imsi_m() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function testDecodeImsi(encodedImsi, expectedImsi) {
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(encodedImsi.length * 2);
-
- // Write imsi
- for (let i = 0; i < encodedImsi.length; i++) {
- helper.writeHexOctet(encodedImsi[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(encodedImsi.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- context.RuimRecordHelper.getIMSI_M();
- let imsi = context.RIL.iccInfoPrivate.imsi;
-
- equal(expectedImsi, imsi)
- }
-
- let imsi_1 = "466050081062861";
- testDecodeImsi([0x0, 0xe5, 0x03, 0xee, 0xca, 0x17, 0x5e, 0x80, 0x63, 0x01], imsi_1);
-
- let imsi_2 = "460038351175976";
- testDecodeImsi([0x0, 0xd4, 0x02, 0x61, 0x97, 0x01, 0x5c, 0x80, 0x67, 0x01], imsi_2);
-
- run_next_test();
-});
-
-/**
- * Verify RuimRecordHelper.readCDMAHome
- */
-add_test(function test_read_cdmahome() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
- let cdmaHome = [0xc1, 0x34, 0xff, 0xff, 0x00];
-
- // Write data size
- buf.writeInt32(cdmaHome.length * 2);
-
- // Write cdma home file.
- for (let i = 0; i < cdmaHome.length; i++) {
- helper.writeHexOctet(cdmaHome[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(cdmaHome.length * 2);
-
- // We just have 1 test record.
-
- options.totalRecords = 1;
- if (options.callback) {
- options.callback(options);
- }
- };
-
- function testCdmaHome(expectedSystemIds, expectedNetworkIds) {
- context.RuimRecordHelper.readCDMAHome();
- let cdmaHome = context.RIL.cdmaHome;
- for (let i = 0; i < expectedSystemIds.length; i++) {
- equal(cdmaHome.systemId[i], expectedSystemIds[i]);
- equal(cdmaHome.networkId[i], expectedNetworkIds[i]);
- }
- equal(cdmaHome.systemId.length, expectedSystemIds.length);
- equal(cdmaHome.networkId.length, expectedNetworkIds.length);
- }
-
- testCdmaHome([13505], [65535]);
-
- run_next_test();
-});
-
-/**
- * Verify reading CDMA EF_SPN
- */
-add_test(function test_read_cdmaspn() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = context.Buf;
- let io = context.ICCIOHelper;
-
- function testReadSpn(file, expectedSpn, expectedDisplayCondition) {
- io.loadTransparentEF = function fakeLoadTransparentEF(options) {
- // Write data size
- buf.writeInt32(file.length * 2);
-
- // Write file.
- for (let i = 0; i < file.length; i++) {
- helper.writeHexOctet(file[i]);
- }
-
- // Write string delimiter
- buf.writeStringDelimiter(file.length * 2);
-
- if (options.callback) {
- options.callback(options);
- }
- };
-
- context.RuimRecordHelper.readSPN();
- equal(context.RIL.iccInfo.spn, expectedSpn);
- equal(context.RIL.iccInfoPrivate.spnDisplayCondition,
- expectedDisplayCondition);
- }
-
- testReadSpn([0x01, 0x04, 0x06, 0x4e, 0x9e, 0x59, 0x2a, 0x96,
- 0xfb, 0x4f, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff],
- String.fromCharCode(0x4e9e) +
- String.fromCharCode(0x592a) +
- String.fromCharCode(0x96fb) +
- String.fromCharCode(0x4fe1),
- 0x1);
-
- // Test when there's no tailing 0xff in spn string.
- testReadSpn([0x01, 0x04, 0x06, 0x4e, 0x9e, 0x59, 0x2a, 0x96,
- 0xfb, 0x4f, 0xe1],
- String.fromCharCode(0x4e9e) +
- String.fromCharCode(0x592a) +
- String.fromCharCode(0x96fb) +
- String.fromCharCode(0x4fe1),
- 0x1);
-
- run_next_test();
-});
-
-/**
- * Verify display condition for CDMA.
- */
-add_test(function test_cdma_spn_display_condition() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
- let RIL = context.RIL;
- let ICCUtilsHelper = context.ICCUtilsHelper;
-
- // Set cdma.
- RIL._isCdma = true;
-
- // Test updateDisplayCondition runs before any of SIM file is ready.
- equal(ICCUtilsHelper.updateDisplayCondition(), true);
- equal(RIL.iccInfo.isDisplayNetworkNameRequired, true);
- equal(RIL.iccInfo.isDisplaySpnRequired, false);
-
- // Test with value.
- function testDisplayCondition(ruimDisplayCondition,
- homeSystemIds, homeNetworkIds,
- currentSystemId, currentNetworkId,
- expectUpdateDisplayCondition,
- expectIsDisplaySPNRequired) {
- RIL.iccInfoPrivate.spnDisplayCondition = ruimDisplayCondition;
- RIL.cdmaHome = {
- systemId: homeSystemIds,
- networkId: homeNetworkIds
- };
- RIL.voiceRegistrationState.cell = {
- cdmaSystemId: currentSystemId,
- cdmaNetworkId: currentNetworkId
- };
-
- equal(ICCUtilsHelper.updateDisplayCondition(), expectUpdateDisplayCondition);
- equal(RIL.iccInfo.isDisplayNetworkNameRequired, false);
- equal(RIL.iccInfo.isDisplaySpnRequired, expectIsDisplaySPNRequired);
- };
-
- // SPN is not required when ruimDisplayCondition is false.
- testDisplayCondition(0x0, [123], [345], 123, 345, true, false);
-
- // System id and network id are all match.
- testDisplayCondition(0x1, [123], [345], 123, 345, true, true);
-
- // Network is 65535, we should only need to match system id.
- testDisplayCondition(0x1, [123], [65535], 123, 345, false, true);
-
- // Not match.
- testDisplayCondition(0x1, [123], [456], 123, 345, true, false);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms.js b/dom/system/gonk/tests/test_ril_worker_sms.js
deleted file mode 100644
index 7c1b972a7..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms.js
+++ /dev/null
@@ -1,273 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "gSmsSegmentHelper", function() {
- let ns = {};
- Cu.import("resource://gre/modules/SmsSegmentHelper.jsm", ns);
- return ns.SmsSegmentHelper;
-});
-
-const ESCAPE = "\uffff";
-const RESCTL = "\ufffe";
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify receiving SMS-DELIVERY messages
- */
-
-function hexToNibble(nibble) {
- nibble &= 0x0f;
- if (nibble < 10) {
- nibble += 48; // ASCII '0'
- } else {
- nibble += 55; // ASCII 'A'
- }
- return nibble;
-}
-
-function pduToParcelData(pdu) {
- let dataLength = 4 + pdu.length * 4 + 4;
- let data = new Uint8Array(dataLength);
- let offset = 0;
-
- // String length
- data[offset++] = pdu.length & 0xFF;
- data[offset++] = (pdu.length >> 8) & 0xFF;
- data[offset++] = (pdu.length >> 16) & 0xFF;
- data[offset++] = (pdu.length >> 24) & 0xFF;
-
- // PDU data
- for (let i = 0; i < pdu.length; i++) {
- let hi = (pdu[i] >>> 4) & 0x0F;
- let lo = pdu[i] & 0x0F;
-
- data[offset++] = hexToNibble(hi);
- data[offset++] = 0;
- data[offset++] = hexToNibble(lo);
- data[offset++] = 0;
- }
-
- // String delimitor
- data[offset++] = 0;
- data[offset++] = 0;
- data[offset++] = 0;
- data[offset++] = 0;
-
- return data;
-}
-
-function compose7bitPdu(lst, sst, data, septets) {
- if ((lst == 0) && (sst == 0)) {
- return [0x00, // SMSC
- PDU_MTI_SMS_DELIVER, // firstOctet
- 1, 0x00, 0, // senderAddress
- 0x00, // protocolIdentifier
- PDU_DCS_MSG_CODING_7BITS_ALPHABET, // dataCodingScheme
- 0, 0, 0, 0, 0, 0, 0, // y m d h m s tz
- septets] // userDataLength
- .concat(data);
- }
-
- return [0x00, // SMSC
- PDU_MTI_SMS_DELIVER | PDU_UDHI, // firstOctet
- 1, 0x00, 0, // senderAddress
- 0x00, // protocolIdentifier
- PDU_DCS_MSG_CODING_7BITS_ALPHABET, // dataCodingScheme
- 0, 0, 0, 0, 0, 0, 0, // y m d h m s tz
- 8 + septets, // userDataLength
- 6, // user data header length
- PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT, 1, lst, // PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT
- PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT, 1, sst] // PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT
- .concat(data);
-}
-
-function composeUcs2Pdu(rawBytes) {
- return [0x00, // SMSC
- PDU_MTI_SMS_DELIVER, // firstOctet
- 1, 0x00, 0, // senderAddress
- 0x00, // protocolIdentifier
- PDU_DCS_MSG_CODING_16BITS_ALPHABET, // dataCodingScheme
- 0, 0, 0, 0, 0, 0, 0, // y m d h m s tz
- rawBytes.length] // userDataLength
- .concat(rawBytes);
-}
-
-function newSmsParcel(pdu) {
- return newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_NEW_SMS,
- pduToParcelData(pdu));
-}
-
-function removeSpecialChar(str, needle) {
- for (let i = 0; i < needle.length; i++) {
- let pos;
- while ((pos = str.indexOf(needle[i])) >= 0) {
- str = str.substring(0, pos) + str.substring(pos + 1);
- }
- }
- return str;
-}
-
-function newWriteHexOctetAsUint8Worker() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- context.GsmPDUHelper.writeHexOctet = function(value) {
- context.Buf.writeUint8(value);
- };
-
- return worker;
-}
-
-function add_test_receiving_sms(expected, pdu) {
- add_test(function test_receiving_sms() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- do_print("fullBody: " + message.fullBody);
- equal(expected, message.fullBody)
- }
- });
-
- do_print("expect: " + expected);
- do_print("pdu: " + pdu);
- worker.onRILMessage(0, newSmsParcel(pdu));
-
- run_next_test();
- });
-}
-
-var test_receiving_7bit_alphabets__worker;
-function test_receiving_7bit_alphabets(lst, sst) {
- if (!test_receiving_7bit_alphabets__worker) {
- test_receiving_7bit_alphabets__worker = newWriteHexOctetAsUint8Worker();
- }
- let worker = test_receiving_7bit_alphabets__worker;
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = context.Buf;
-
- function get7bitRawBytes(expected) {
- buf.outgoingIndex = 0;
- helper.writeStringAsSeptets(expected, 0, lst, sst);
-
- let subArray = buf.outgoingBytes.subarray(0, buf.outgoingIndex);
- return Array.slice(subArray);
- }
-
- let langTable = PDU_NL_LOCKING_SHIFT_TABLES[lst];
- let langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[sst];
-
- let text = removeSpecialChar(langTable + langShiftTable, ESCAPE + RESCTL);
- for (let i = 0; i < text.length;) {
- let len = Math.min(70, text.length - i);
- let expected = text.substring(i, i + len);
- let septets =
- gSmsSegmentHelper.countGsm7BitSeptets(expected, langTable, langShiftTable);
- let rawBytes = get7bitRawBytes(expected);
- let pdu = compose7bitPdu(lst, sst, rawBytes, septets);
- add_test_receiving_sms(expected, pdu);
-
- i += len;
- }
-}
-
-function test_receiving_ucs2_alphabets(text) {
- let worker = test_receiving_7bit_alphabets__worker;
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
-
- function getUCS2RawBytes(expected) {
- buf.outgoingIndex = 0;
- context.GsmPDUHelper.writeUCS2String(expected);
-
- let subArray = buf.outgoingBytes.subarray(0, buf.outgoingIndex);
- return Array.slice(subArray);
- }
-
- for (let i = 0; i < text.length;) {
- let len = Math.min(70, text.length - i);
- let expected = text.substring(i, i + len);
- let rawBytes = getUCS2RawBytes(expected);
- let pdu = composeUcs2Pdu(rawBytes);
- add_test_receiving_sms(expected, pdu);
-
- i += len;
- }
-}
-
-var ucs2str = "";
-for (let lst = 0; lst < PDU_NL_LOCKING_SHIFT_TABLES.length; lst++) {
- ucs2str += PDU_NL_LOCKING_SHIFT_TABLES[lst];
- for (let sst = 0; sst < PDU_NL_SINGLE_SHIFT_TABLES.length; sst++) {
- test_receiving_7bit_alphabets(lst, sst);
-
- if (lst == 0) {
- ucs2str += PDU_NL_SINGLE_SHIFT_TABLES[sst];
- }
- }
-}
-test_receiving_ucs2_alphabets(ucs2str);
-
-// Bug 820220: B2G SMS: wrong order and truncated content in multi-part messages
-add_test(function test_sendSMS_UCS2_without_langIndex_langShiftIndex_defined() {
- let worker = newWriteHexOctetAsUint8Worker();
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.sendParcel = function() {
- // Each sendParcel() call represents one outgoing segment of a multipart
- // SMS message. Here, we have the first segment send, so it's "Hello "
- // only.
- //
- // 4(parcel size) + 4(request type) + 4(token)
- // + 4(two messages) + 4(null SMSC) + 4(message string length)
- // + 1(first octet) + 1(message reference)
- // + 2(DA len, TOA) + 4(addr)
- // + 1(pid) + 1(dcs)
- // + 1(UDL) + 6(UDHL, type, len, ref, max, seq)
- // + 12(2 * strlen("Hello "))
- // + 4(two delimitors) = 57
- //
- // If we have additional 6(type, len, langIndex, type len, langShiftIndex)
- // octets here, then bug 809553 is not fixed.
- equal(this.outgoingIndex, 57);
-
- run_next_test();
- };
-
- context.RIL.sendSMS({
- number: "1",
- segmentMaxSeq: 2,
- fullBody: "Hello World!",
- dcs: PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- segmentRef16Bit: false,
- userDataHeaderLength: 5,
- requestStatusReport: true,
- segments: [
- {
- body: "Hello ",
- encodedBodyLength: 12,
- }, {
- body: "World!",
- encodedBodyLength: 12,
- }
- ],
- });
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_cdma.js b/dom/system/gonk/tests/test_ril_worker_sms_cdma.js
deleted file mode 100644
index 85d0b6e0c..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_cdma.js
+++ /dev/null
@@ -1,298 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/*
- * Helper function to covert a HEX string to a byte array.
- *
- * @param hexString
- * A hexadecimal string of which the length is even.
- */
-function hexStringToBytes(hexString) {
- let bytes = [];
-
- let length = hexString.length;
-
- for (let i = 0; i < length; i += 2) {
- bytes.push(Number.parseInt(hexString.substr(i, 2), 16));
- }
-
- return bytes;
-}
-
-/*
- * Helper function to covert a byte array to a HEX string.
- *
- * @param bytes
- * Could be a regular byte array or Uint8Array.
- */
-function bytesToHexString(bytes) {
- let hexString = "";
- let hex;
-
- for (let i = 0; i < bytes.length; i++) {
- hex = bytes[i].toString(16).toUpperCase();
- if (hex.length === 1) {
- hexString += "0";
- }
- hexString += hex;
- }
-
- return hexString;
-}
-
-/*
- * Helper function to ecode Opaque UserData
- *
- * @param msg_type
- * PDU_CDMA_MSG_TYPE_SUBMIT or PDU_CDMA_MSG_TYPE_DELIVER
- * @param data
- * The byte array of opaque data to be encoded.
- */
-function encodeOpaqueUserData(bitBufferHelper, options) {
- let bearerDataBuffer = [];
- bitBufferHelper.startWrite(bearerDataBuffer);
-
- // Msg-Id
- bitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_MSG_ID, 8);
- bitBufferHelper.writeBits(3, 8);
- bitBufferHelper.writeBits(options.msg_type, 4); // MSG_TYPE
- bitBufferHelper.writeBits(1, 16); // MSG_ID
- bitBufferHelper.flushWithPadding(); // HEADER_IND (1) + RESERVED (3)
-
- // User Data
- bitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_BODY, 8);
- let dataLength = options.data.length;
- bitBufferHelper.writeBits(2 + dataLength, 8); // 2 bytes for MSG_ENCODING, NUM_FIELDS
- bitBufferHelper.writeBits(PDU_CDMA_MSG_CODING_OCTET, 5); //MSG_ENCODING
- // MSG_TYPE is omitted if MSG_ENCODING is CODING_OCTET
- bitBufferHelper.writeBits(dataLength, 8); // NUM_FIELDS
- for (let i = 0; i < dataLength; i++) { // CHARi
- bitBufferHelper.writeBits(options.data[i], 8);
- }
- bitBufferHelper.flushWithPadding(); // RESERVED (3 filling bits)
-
- return bearerDataBuffer;
-}
-
-function newSmsParcel(cdmaPduHelper, pdu) {
- return newIncomingParcel(-1,
- RESPONSE_TYPE_UNSOLICITED,
- UNSOLICITED_RESPONSE_CDMA_NEW_SMS,
- pduToParcelData(cdmaPduHelper, pdu));
-}
-
-/*
- * Helper function to encode PDU into Parcel.
- * See ril_cdma_sms.h for the structure definition of RIL_CDMA_SMS_Message
- *
- * @param teleservice
- * The Teleservice-Id of this PDU.
- * See PDU_CDMA_MSG_TELESERIVCIE_ID_XXX in ril_const.js.
- * @param address
- * The Orginating or Destinating address.
- * @param bearerData
- * The byte array of the encoded bearer data.
- */
-function pduToParcelData(cdmaPduHelper, pdu) {
-
- let addrInfo = cdmaPduHelper.encodeAddr(pdu.address);
- // Teleservice, isServicePresent, ServiceCategory,
- // addrInfo {digitMode, numberMode, numberType, numberPlan, address.length, address}
- // Sub Address
- // bearerData length, bearerData.
- let dataLength = 4 + 4 + 4
- + (5 + addrInfo.address.length) * 4
- + 3 * 4
- + 4 + pdu.bearerData.length * 4;
-
- let data = new Uint8Array(dataLength);
- let offset = 0;
-
- function writeInt(value) {
- data[offset++] = value & 0xFF;
- data[offset++] = (value >> 8) & 0xFF;
- data[offset++] = (value >> 16) & 0xFF;
- data[offset++] = (value >> 24) & 0xFF;
- }
-
- function writeByte(value) {
- data[offset++] = value & 0xFF;
- data[offset++] = 0;
- data[offset++] = 0;
- data[offset++] = 0;
- }
-
- // Teleservice
- writeInt(pdu.teleservice);
-
- // isServicePresent
- writeByte(0);
-
- // ServiceCategory
- writeInt(PDU_CDMA_MSG_CATEGORY_UNSPEC);
-
- // AddrInfo
- writeByte(addrInfo.digitMode);
- writeByte(addrInfo.numberMode);
- writeByte(addrInfo.numberType);
- writeByte(addrInfo.numberPlan);
- let addressLength = addrInfo.address.length;
- writeByte(addressLength);
- for (let i = 0; i < addressLength; i++) {
- writeByte(addrInfo.address[i]);
- }
-
- // Subaddress
- writeByte(0);
- writeByte(0);
- writeByte(0);
-
- // Bearer Data Length
- dataLength = pdu.bearerData.length;
- writeByte(dataLength);
-
- // Bearer Data
- for (let i = 0; i < dataLength; i++) {
- writeByte(pdu.bearerData[i]);
- }
-
- return data;
-}
-
-/**
- * Verify CDMA SMS Delivery ACK Message.
- */
-add_test(function test_processCdmaSmsStatusReport() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- function test_StatusReport(errorClass, msgStatus) {
- let msgId = 0;
- let sentSmsMap = context.RIL._pendingSentSmsMap;
-
- sentSmsMap[msgId] = {};
-
- let message = {
- SMSC: "",
- mti: 0,
- udhi: 0,
- sender: "0987654321",
- recipient: null,
- pid: PDU_PID_DEFAULT,
- epid: PDU_PID_DEFAULT,
- dcs: 0,
- mwi: null,
- replace: false,
- header: null,
- body: "Status: Sent, Dest: 0987654321",
- data: null,
- timestamp: new Date().valueOf(),
- language: null,
- status: null,
- scts: null,
- dt: null,
- encoding: PDU_CDMA_MSG_CODING_7BITS_ASCII,
- messageClass: GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- messageType: PDU_CDMA_MSG_TYPE_P2P,
- serviceCategory: 0,
- subMsgType: PDU_CDMA_MSG_TYPE_DELIVER_ACK,
- msgId: msgId,
- errorClass: errorClass,
- msgStatus: msgStatus
- };
-
- context.RIL._processCdmaSmsStatusReport(message);
-
- let postedMessage = workerHelper.postedMessage;
-
- // Check if pending token is removed.
- ok((errorClass === 2) ? !!sentSmsMap[msgId] : !sentSmsMap[msgId]);
-
- // Check the response message accordingly.
- if (errorClass === -1) {
- // Check if the report is treated as normal incoming SMS
- equal("sms-received", postedMessage.rilMessageType);
- } else if (errorClass === 2) {
- // Do nothing.
- } else {
- // Check Delivery Status
- if (errorClass === 0) {
- equal(postedMessage.deliveryStatus, GECKO_SMS_DELIVERY_STATUS_SUCCESS);
- } else {
- equal(postedMessage.deliveryStatus, GECKO_SMS_DELIVERY_STATUS_ERROR);
- }
- }
- }
-
- test_StatusReport(-1, -1); // Message Status Sub-parameter is absent.
- test_StatusReport(0, 0); // 00|000000: no error|Message accepted
- test_StatusReport(2, 4); // 10|000100: temporary condition|Network congestion
- test_StatusReport(3, 5); // 11|000101: permanent condition|Network error
-
- run_next_test();
-});
-
-/**
- * Verify WAP Push over CDMA SMS Message.
- */
-add_test(function test_processCdmaSmsWapPush() {
- let workerHelper = newInterceptWorker(),
- worker = workerHelper.worker,
- context = worker.ContextPool._contexts[0],
- bitBufferHelper = context.BitBufferHelper,
- cdmaPduHelper = context.CdmaPDUHelper;
-
- function test_CdmaSmsWapPdu(wdpData, reversed) {
- let orig_address = "0987654321",
- hexString,
- fullDataHexString = "";
-
- for (let i = 0; i < wdpData.length; i++) {
- let dataIndex = (reversed) ? (wdpData.length - i - 1) : i;
- hexString = "00"; // MSG_TYPE
- hexString += bytesToHexString([wdpData.length]); // TOTAL_SEG
- hexString += bytesToHexString([dataIndex]); // SEG_NUM (zero-based)
- if ((dataIndex === 0)) {
- hexString += "23F00B84"; // SOURCE_PORT, DEST_PORT for 1st segment
- }
- hexString += wdpData[dataIndex]; // WDP DATA
-
- do_print("hexString: " + hexString);
-
- fullDataHexString += wdpData[i];
-
- let pdu = {
- teleservice: PDU_CDMA_MSG_TELESERIVCIE_ID_WAP,
- address: orig_address,
- bearerData: encodeOpaqueUserData(bitBufferHelper,
- { msg_type: PDU_CDMA_MSG_TYPE_DELIVER,
- data: hexStringToBytes(hexString) })
- };
-
- worker.onRILMessage(0, newSmsParcel(cdmaPduHelper, pdu));
- }
-
- let postedMessage = workerHelper.postedMessage;
-
- do_print("fullDataHexString: " + fullDataHexString);
-
- equal("sms-received", postedMessage.rilMessageType);
- equal(PDU_CDMA_MSG_TELESERIVCIE_ID_WAP, postedMessage.teleservice);
- equal(orig_address, postedMessage.sender);
- equal(0x23F0, postedMessage.header.originatorPort);
- equal(0x0B84, postedMessage.header.destinationPort);
- equal(fullDataHexString, bytesToHexString(postedMessage.data));
- }
-
- // Verify Single WAP PDU
- test_CdmaSmsWapPdu(["000102030405060708090A0B0C0D0E0F"]);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_cdmapduhelper.js b/dom/system/gonk/tests/test_ril_worker_sms_cdmapduhelper.js
deleted file mode 100644
index 276728f2f..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_cdmapduhelper.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify CdmaPDUHelper#encodeUserDataReplyOption.
- */
-add_test(function test_CdmaPDUHelper_encodeUserDataReplyOption() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- let testDataBuffer = [];
- context.BitBufferHelper.startWrite(testDataBuffer);
-
- let helper = context.CdmaPDUHelper;
- helper.encodeUserDataReplyOption({requestStatusReport: true});
-
- let expectedDataBuffer = [PDU_CDMA_MSG_USERDATA_REPLY_OPTION, 0x01, 0x40];
-
- equal(testDataBuffer.length, expectedDataBuffer.length);
-
- for (let i = 0; i < expectedDataBuffer.length; i++) {
- equal(testDataBuffer[i], expectedDataBuffer[i]);
- }
-
- run_next_test();
-});
-
-/**
- * Verify CdmaPDUHelper#cdma_decodeUserDataMsgStatus.
- */
-add_test(function test_CdmaPDUHelper_decodeUserDataMsgStatus() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- let helper = context.CdmaPDUHelper;
- function test_MsgStatus(octet) {
- let testDataBuffer = [octet];
- context.BitBufferHelper.startRead(testDataBuffer);
- let result = helper.decodeUserDataMsgStatus();
-
- equal(result.errorClass, octet >>> 6);
- equal(result.msgStatus, octet & 0x3F);
- }
-
- // 00|000000: no error|Message accepted
- test_MsgStatus(0x00);
-
- // 10|000100: temporary condition|Network congestion
- test_MsgStatus(0x84);
-
- // 11|000101: permanent condition|Network error
- test_MsgStatus(0xC5);
-
- run_next_test();
-});
-
-/**
- * Verify CdmaPDUHelper#decodeCdmaPDUMsg.
- * - encoding by shift-jis
- */
-add_test(function test_CdmaPDUHelper_decodeCdmaPDUMsg_Shift_jis() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
- let context = worker.ContextPool._contexts[0];
-
- let helper = context.CdmaPDUHelper;
- function test_decodePDUMsg(testDataBuffer, expected, encoding, msgType, msgBodySize) {
- context.BitBufferHelper.startRead(testDataBuffer);
- let result = helper.decodeCdmaPDUMsg(encoding, msgType, msgBodySize);
- equal(result, expected);
- }
-
- // Shift-JIS has 1 byte and 2 byte code for one character and has some types of characters:
- // Hiragana, Kanji, Katakana(fullwidth, halfwidth)...
- // This test is a combination of 1 byte and 2 byte code and types of characters.
-
- // test case 1
- let testDataBuffer1 = [0x82, 0x58, 0x33, 0x41, 0x61, 0x33, 0x82, 0x60,
- 0x82, 0x81, 0x33, 0xB1, 0xAF, 0x33, 0x83, 0x41,
- 0x83, 0x96, 0x33, 0x82, 0xA0, 0x33, 0x93, 0xFA,
- 0x33, 0x3A, 0x3C, 0x33, 0x81, 0x80, 0x81, 0x8E,
- 0x33, 0x31, 0x82, 0x51, 0x41, 0x61, 0x82, 0x51,
- 0x82, 0x60, 0x82, 0x81, 0x82, 0x51, 0xB1, 0xAF,
- 0x82, 0x51, 0x83, 0x41, 0x83, 0x96, 0x82, 0x51,
- 0x82, 0xA0, 0x82, 0x51, 0x93, 0xFA, 0x82, 0x51,
- 0x3A, 0x3C, 0x82, 0x51, 0x81, 0x80, 0x81, 0x8E,
- 0x82, 0x51];
-
- test_decodePDUMsg(
- testDataBuffer1,
- "\uFF19\u0033\u0041\u0061\u0033\uFF21\uFF41\u0033\uFF71\uFF6F\u0033\u30A2\u30F6\u0033\u3042\u0033\u65E5\u0033\u003A\u003C\u0033\u00F7\u2103\u0033\u0031\uFF12\u0041\u0061\uFF12\uFF21\uFF41\uFF12\uFF71\uFF6F\uFF12\u30A2\u30F6\uFF12\u3042\uFF12\u65E5\uFF12\u003A\u003C\uFF12\u00F7\u2103\uFF12",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer1.length
- );
-
- // test case 2
- let testDataBuffer2 = [0x31, 0x51, 0x63, 0x82, 0x58, 0x51, 0x63, 0x82,
- 0x60, 0x82, 0x81, 0x51, 0x63, 0xB1, 0xAF, 0x51,
- 0x63, 0x83, 0x41, 0x83, 0x96, 0x51, 0x63, 0x82,
- 0xA0, 0x51, 0x63, 0x93, 0xFA, 0x51, 0x63, 0x3A,
- 0x3C, 0x51, 0x63, 0x81, 0x80, 0x81, 0x8E, 0x51,
- 0x63, 0x31, 0x82, 0x70, 0x82, 0x85, 0x82, 0x58,
- 0x82, 0x70, 0x82, 0x85, 0x41, 0x61, 0x82, 0x70,
- 0x82, 0x85, 0xB1, 0xAF, 0x82, 0x70, 0x82, 0x85,
- 0x83, 0x41, 0x83, 0x96, 0x82, 0x70, 0x82, 0x85,
- 0x82, 0xA0, 0x82, 0x70, 0x82, 0x85, 0x93, 0xFA,
- 0x82, 0x70, 0x82, 0x85, 0x3A, 0x3C, 0x82, 0x70,
- 0x82, 0x85, 0x81, 0x80, 0x81, 0x8E, 0x82, 0x70,
- 0x82, 0x85];
-
- test_decodePDUMsg(
- testDataBuffer2,
- "\u0031\u0051\u0063\uFF19\u0051\u0063\uFF21\uFF41\u0051\u0063\uFF71\uFF6F\u0051\u0063\u30A2\u30F6\u0051\u0063\u3042\u0051\u0063\u65E5\u0051\u0063\u003A\u003C\u0051\u0063\u00F7\u2103\u0051\u0063\u0031\uFF31\uFF45\uFF19\uFF31\uFF45\u0041\u0061\uFF31\uFF45\uFF71\uFF6F\uFF31\uFF45\u30A2\u30F6\uFF31\uFF45\u3042\uFF31\uFF45\u65E5\uFF31\uFF45\u003A\u003C\uFF31\uFF45\u00F7\u2103\uFF31\uFF45",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer2.length
- );
-
- // test case 3
- let testDataBuffer3 = [0x31, 0xC2, 0xDF, 0x82, 0x58, 0xC2, 0xDF, 0x41,
- 0x61, 0xC2, 0xDF, 0x82, 0x60, 0x82, 0x81, 0xC2,
- 0xDF, 0x83, 0x41, 0x83, 0x96, 0xC2, 0xDF, 0x82,
- 0xA0, 0xC2, 0xDF, 0x93, 0xFA, 0xC2, 0xDF, 0x3A,
- 0x3C, 0xC2, 0xDF, 0x81, 0x80, 0x81, 0x8E, 0xC2,
- 0xDF, 0x31, 0x83, 0x51, 0x83, 0x87, 0x82, 0x58,
- 0x83, 0x51, 0x83, 0x87, 0x41, 0x61, 0x83, 0x51,
- 0x83, 0x87, 0x82, 0x60, 0x82, 0x81, 0x83, 0x51,
- 0x83, 0x87, 0xB1, 0xAF, 0x83, 0x51, 0x83, 0x87,
- 0x82, 0xA0, 0x83, 0x51, 0x83, 0x87, 0x93, 0xFA,
- 0x83, 0x51, 0x83, 0x87, 0x3A, 0x3C, 0x83, 0x51,
- 0x83, 0x87, 0x81, 0x80, 0x81, 0x8E, 0x83, 0x51,
- 0x83, 0x87];
-
- test_decodePDUMsg(
- testDataBuffer3,
- "\u0031\uFF82\uFF9F\uFF19\uFF82\uFF9F\u0041\u0061\uFF82\uFF9F\uFF21\uFF41\uFF82\uFF9F\u30A2\u30F6\uFF82\uFF9F\u3042\uFF82\uFF9F\u65E5\uFF82\uFF9F\u003A\u003C\uFF82\uFF9F\u00F7\u2103\uFF82\uFF9F\u0031\u30B2\u30E7\uFF19\u30B2\u30E7\u0041\u0061\u30B2\u30E7\uFF21\uFF41\u30B2\u30E7\uFF71\uFF6F\u30B2\u30E7\u3042\u30B2\u30E7\u65E5\u30B2\u30E7\u003A\u003C\u30B2\u30E7\u00F7\u2103\u30B2\u30E7",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer3.length
- );
-
- // test case 4
- let testDataBuffer4 = [0x31, 0x82, 0xB0, 0x82, 0x58, 0x82, 0xB0, 0x41,
- 0x61, 0x82, 0xB0, 0x82, 0x60, 0x82, 0x81, 0x82,
- 0xB0, 0xB1, 0xAF, 0x82, 0xB0, 0x83, 0x41, 0x83,
- 0x96, 0x82, 0xB0, 0x93, 0xFA, 0x82, 0xB0, 0x3A,
- 0x3C, 0x82, 0xB0, 0x81, 0x80, 0x81, 0x8E, 0x82,
- 0xB0, 0x31, 0x88, 0xA4, 0x82, 0x58, 0x88, 0xA4,
- 0x41, 0x61, 0x88, 0xA4, 0x82, 0x60, 0x82, 0x81,
- 0x88, 0xA4, 0xB1, 0xAF, 0x88, 0xA4, 0x83, 0x41,
- 0x83, 0x96, 0x88, 0xA4, 0x82, 0xA0, 0x88, 0xA4,
- 0x3A, 0x3C, 0x88, 0xA4, 0x81, 0x80, 0x81, 0x8E,
- 0x88, 0xA4];
-
- test_decodePDUMsg(
- testDataBuffer4,
- "\u0031\u3052\uFF19\u3052\u0041\u0061\u3052\uFF21\uFF41\u3052\uFF71\uFF6F\u3052\u30A2\u30F6\u3052\u65E5\u3052\u003A\u003C\u3052\u00F7\u2103\u3052\u0031\u611B\uFF19\u611B\u0041\u0061\u611B\uFF21\uFF41\u611B\uFF71\uFF6F\u611B\u30A2\u30F6\u611B\u3042\u611B\u003A\u003C\u611B\u00F7\u2103\u611B",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer4.length
- );
-
- // test case 5
- let testDataBuffer5 = [0x31, 0x40, 0x82, 0x58, 0x40, 0x41, 0x61, 0x40,
- 0x82, 0x60, 0x82, 0x81, 0x40, 0xB1, 0xAF, 0x40,
- 0x83, 0x41, 0x83, 0x96, 0x40, 0x82, 0xA0, 0x40,
- 0x93, 0xFA, 0x40, 0x81, 0x80, 0x81, 0x8E, 0x40,
- 0x31, 0x81, 0x9B, 0x82, 0x58, 0x81, 0x9B, 0x41,
- 0x61, 0x81, 0x9B, 0x82, 0x60, 0x82, 0x81, 0x81,
- 0x9B, 0xB1, 0xAF, 0x81, 0x9B, 0x83, 0x41, 0x83,
- 0x96, 0x81, 0x9B, 0x82, 0xA0, 0x81, 0x9B, 0x93,
- 0xFA, 0x81, 0x9B, 0x3A, 0x3C, 0x81, 0x9B];
-
- test_decodePDUMsg(
- testDataBuffer5,
- "\u0031\u0040\uFF19\u0040\u0041\u0061\u0040\uFF21\uFF41\u0040\uFF71\uFF6F\u0040\u30A2\u30F6\u0040\u3042\u0040\u65E5\u0040\u00F7\u2103\u0040\u0031\u25CB\uFF19\u25CB\u0041\u0061\u25CB\uFF21\uFF41\u25CB\uFF71\uFF6F\u25CB\u30A2\u30F6\u25CB\u3042\u25CB\u65E5\u25CB\u003A\u003C\u25CB",
- PDU_CDMA_MSG_CODING_SHIFT_JIS,
- undefined,
- testDataBuffer5.length
- );
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_gsmpduhelper.js b/dom/system/gonk/tests/test_ril_worker_sms_gsmpduhelper.js
deleted file mode 100644
index f52c64cf8..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_gsmpduhelper.js
+++ /dev/null
@@ -1,282 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify GsmPDUHelper#readDataCodingScheme.
- */
-add_test(function test_GsmPDUHelper_readDataCodingScheme() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- function test_dcs(dcs, encoding, messageClass, mwi) {
- helper.readHexOctet = function() {
- return dcs;
- }
-
- let msg = {};
- helper.readDataCodingScheme(msg);
-
- equal(msg.dcs, dcs);
- equal(msg.encoding, encoding);
- equal(msg.messageClass, messageClass);
- equal(msg.mwi == null, mwi == null);
- if (mwi != null) {
- equal(msg.mwi.active, mwi.active);
- equal(msg.mwi.discard, mwi.discard);
- equal(msg.mwi.msgCount, mwi.msgCount);
- }
- }
-
- // Group 00xx
- // Bit 3 and 2 indicate the character set being used.
- test_dcs(0x00, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x04, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x08, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x0C, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- // Bit 4, if set to 0, indicates that bits 1 to 0 are reserved and have no
- // message class meaning.
- test_dcs(0x01, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x02, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x03, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- // Bit 4, if set to 1, indicates that bits 1 to 0 have a message class meaning.
- test_dcs(0x10, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
- test_dcs(0x11, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]);
- test_dcs(0x12, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]);
- test_dcs(0x13, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]);
-
- // Group 01xx
- test_dcs(0x50, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
-
- // Group 1000..1011: reserved
- test_dcs(0x8F, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0x9F, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0xAF, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
- test_dcs(0xBF, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
-
- // Group 1100: Message Waiting Indication Group: Discard Message
- // Bit 3 indicates Indication Sense:
- test_dcs(0xC0, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: false, discard: true, msgCount: 0});
- test_dcs(0xC8, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: true, msgCount: -1});
- // Bit 2 is reserved, and set to 0:
- test_dcs(0xCC, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: true, msgCount: -1});
-
- // Group 1101: Message Waiting Indication Group: Store Message
- // Bit 3 indicates Indication Sense:
- test_dcs(0xD0, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: false, discard: false, msgCount: 0});
- test_dcs(0xD8, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: false, msgCount: -1});
- // Bit 2 is reserved, and set to 0:
- test_dcs(0xDC, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: false, msgCount: -1});
-
- // Group 1110: Message Waiting Indication Group: Store Message, UCS2
- // Bit 3 indicates Indication Sense:
- test_dcs(0xE0, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: false, discard: false, msgCount: 0});
- test_dcs(0xE8, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: false, msgCount: -1});
- // Bit 2 is reserved, and set to 0:
- test_dcs(0xEC, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
- {active: true, discard: false, msgCount: -1});
-
- // Group 1111
- test_dcs(0xF0, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
- test_dcs(0xF1, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]);
- test_dcs(0xF2, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]);
- test_dcs(0xF3, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]);
- test_dcs(0xF4, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
- test_dcs(0xF5, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]);
- test_dcs(0xF6, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]);
- test_dcs(0xF7, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]);
- // Bit 3 is reserved and should be set to 0, but if it doesn't we should
- // ignore it.
- test_dcs(0xF8, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
- GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
-
- run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper#writeStringAsSeptets() padding bits handling.
- */
-add_test(function test_GsmPDUHelper_writeStringAsSeptets() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- helper.resetOctetWritten = function() {
- helper.octetsWritten = 0;
- };
- helper.writeHexOctet = function() {
- helper.octetsWritten++;
- };
-
- let base = "AAAAAAAA"; // Base string of 8 characters long
- for (let len = 0; len < 8; len++) {
- let str = base.substring(0, len);
-
- for (let paddingBits = 0; paddingBits < 8; paddingBits++) {
- do_print("Verifying GsmPDUHelper.writeStringAsSeptets("
- + str + ", " + paddingBits + ", <default>, <default>)");
- helper.resetOctetWritten();
- helper.writeStringAsSeptets(str, paddingBits, PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT);
- equal(Math.ceil(((len * 7) + paddingBits) / 8),
- helper.octetsWritten);
- }
- }
-
- run_next_test();
-});
-
-/**
- * Verify that encoding with Spanish locking shift table generates the same
- * septets as with GSM default alphabet table.
- *
- * Bug 1138841 - Incorrect Spanish national language locking shift table
- * definition.
- */
-add_test(function test_GsmPDUHelper_writeStringAsSeptets_spanish_fallback() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- let buf = [];
- helper.writeHexOctet = function(octet) {
- buf.push(octet);
- }
-
- // Simple message string which is covered by GSM default alphabet.
- let msg = "The quick brown fox jumps over the lazy dog";
-
- // Encoded with GSM default alphabet.
- helper.writeStringAsSeptets(msg, 0 /* paddingBits */,
- PDU_NL_IDENTIFIER_DEFAULT, PDU_NL_IDENTIFIER_DEFAULT);
- let octetsWithDefaultTable = buf;
- buf = [];
-
- // Encoded with Spanish locking shift table.
- helper.writeStringAsSeptets(msg, 0 /* paddingBits */,
- PDU_NL_IDENTIFIER_SPANISH, PDU_NL_IDENTIFIER_SPANISH);
-
- // The length and content should be equal to what encoded with GSM default
- // alphabet.
- equal(octetsWithDefaultTable.length, buf.length);
- for (let i = 0; i < buf.length; i++) {
- equal(octetsWithDefaultTable[i], buf[i]);
- }
-
- run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper#readAddress
- */
-add_test(function test_GsmPDUHelper_readAddress() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- function test_address(addrHex, addrString) {
- let uint16Array = [];
- let ix = 0;
- for (let i = 0; i < addrHex.length; ++i) {
- uint16Array[i] = addrHex[i].charCodeAt();
- }
-
- context.Buf.readUint16 = function(){
- if(ix >= uint16Array.length) {
- do_throw("out of range in uint16Array");
- }
- return uint16Array[ix++];
- }
- let length = helper.readHexOctet();
- let parsedAddr = helper.readAddress(length);
- equal(parsedAddr, addrString);
- }
-
- // For AlphaNumeric
- test_address("04D01100", "_@");
- test_address("04D01000", "\u0394@");
-
- // Direct prepand
- test_address("0B914151245584F6", "+14154255486");
- test_address("0E914151245584B633", "+14154255486#33");
-
- // PDU_TOA_NATIONAL
- test_address("0BA14151245584F6", "14154255486");
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_nl_tables.js b/dom/system/gonk/tests/test_ril_worker_sms_nl_tables.js
deleted file mode 100644
index 32bc5dc2a..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_nl_tables.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-const ESCAPE = "\uffff";
-const RESCTL = "\ufffe";
-const LF = "\n";
-const CR = "\r";
-const SP = " ";
-const FF = "\u000c";
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify validity of the national language tables
- */
-add_test(function test_nl_locking_shift_tables_validity() {
- for (let lst = 0; lst < PDU_NL_LOCKING_SHIFT_TABLES.length; lst++) {
- do_print("Verifying PDU_NL_LOCKING_SHIFT_TABLES[" + lst + "]");
-
- let table = PDU_NL_LOCKING_SHIFT_TABLES[lst];
-
- // Make sure table length is 128, or it will break table lookup algorithm.
- equal(table.length, 128);
-
- // Make sure special values are preserved.
- equal(table[PDU_NL_EXTENDED_ESCAPE], ESCAPE);
- equal(table[PDU_NL_LINE_FEED], LF);
- equal(table[PDU_NL_CARRIAGE_RETURN], CR);
- equal(table[PDU_NL_SPACE], SP);
- }
-
- run_next_test();
-});
-
-add_test(function test_nl_single_shift_tables_validity() {
- for (let sst = 0; sst < PDU_NL_SINGLE_SHIFT_TABLES.length; sst++) {
- do_print("Verifying PDU_NL_SINGLE_SHIFT_TABLES[" + sst + "]");
-
- let table = PDU_NL_SINGLE_SHIFT_TABLES[sst];
-
- // Make sure table length is 128, or it will break table lookup algorithm.
- equal(table.length, 128);
-
- // Make sure special values are preserved.
- equal(table[PDU_NL_EXTENDED_ESCAPE], ESCAPE);
- equal(table[PDU_NL_PAGE_BREAK], FF);
- equal(table[PDU_NL_RESERVED_CONTROL], RESCTL);
- }
-
- run_next_test();
-});
-
-add_test(function test_gsm_sms_strict_7bit_charmap_validity() {
- let defaultTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- let defaultShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
- for (let from in GSM_SMS_STRICT_7BIT_CHARMAP) {
- let to = GSM_SMS_STRICT_7BIT_CHARMAP[from];
- do_print("Verifying GSM_SMS_STRICT_7BIT_CHARMAP[\"\\u0x"
- + from.charCodeAt(0).toString(16) + "\"] => \"\\u"
- + to.charCodeAt(0).toString(16) + "\"");
-
- // Make sure "from" is not in default table
- equal(defaultTable.indexOf(from), -1);
- equal(defaultShiftTable.indexOf(from), -1);
- // Make sure "to" is in default table
- if ((defaultTable.indexOf(to) < 0)
- && (defaultShiftTable.indexOf(to) < 0)) {
- equal(false, true);
- }
- }
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_sms_segment_info.js b/dom/system/gonk/tests/test_ril_worker_sms_segment_info.js
deleted file mode 100644
index 2b29ac60e..000000000
--- a/dom/system/gonk/tests/test_ril_worker_sms_segment_info.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "gSmsSegmentHelper", function() {
- let ns = {};
- Cu.import("resource://gre/modules/SmsSegmentHelper.jsm", ns);
- return ns.SmsSegmentHelper;
-});
-
-const ESCAPE = "\uffff";
-const RESCTL = "\ufffe";
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Verify SmsSegmentHelper#countGsm7BitSeptets() and
- * GsmPDUHelper#writeStringAsSeptets() algorithm match each other.
- */
-add_test(function test_SmsSegmentHelper__countGsm7BitSeptets() {
- let worker = newWorker({
- postRILMessage: function(data) {
- // Do nothing
- },
- postMessage: function(message) {
- // Do nothing
- }
- });
-
- let context = worker.ContextPool._contexts[0];
- let helper = context.GsmPDUHelper;
- helper.resetOctetWritten = function() {
- helper.octetsWritten = 0;
- };
- helper.writeHexOctet = function() {
- helper.octetsWritten++;
- };
-
- function do_check_calc(str, expectedCalcLen, lst, sst, strict7BitEncoding, strToWrite) {
- equal(expectedCalcLen,
- gSmsSegmentHelper
- .countGsm7BitSeptets(str,
- PDU_NL_LOCKING_SHIFT_TABLES[lst],
- PDU_NL_SINGLE_SHIFT_TABLES[sst],
- strict7BitEncoding));
-
- helper.resetOctetWritten();
- strToWrite = strToWrite || str;
- helper.writeStringAsSeptets(strToWrite, 0, lst, sst);
- equal(Math.ceil(expectedCalcLen * 7 / 8), helper.octetsWritten);
- }
-
- // Test calculation encoded message length using both locking/single shift tables.
- for (let lst = 0; lst < PDU_NL_LOCKING_SHIFT_TABLES.length; lst++) {
- let langTable = PDU_NL_LOCKING_SHIFT_TABLES[lst];
-
- let str = langTable.substring(0, PDU_NL_EXTENDED_ESCAPE)
- + langTable.substring(PDU_NL_EXTENDED_ESCAPE + 1);
-
- for (let sst = 0; sst < PDU_NL_SINGLE_SHIFT_TABLES.length; sst++) {
- let langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[sst];
-
- // <escape>, <resctrl> should be ignored.
- do_check_calc(ESCAPE + RESCTL, 0, lst, sst);
-
- // Characters defined in locking shift table should be encoded directly.
- do_check_calc(str, str.length, lst, sst);
-
- let [str1, str2] = ["", ""];
- for (let i = 0; i < langShiftTable.length; i++) {
- if ((i == PDU_NL_EXTENDED_ESCAPE) || (i == PDU_NL_RESERVED_CONTROL)) {
- continue;
- }
-
- let c = langShiftTable[i];
- if (langTable.indexOf(c) >= 0) {
- str1 += c;
- } else {
- str2 += c;
- }
- }
-
- // Characters found in both locking/single shift tables should be
- // directly encoded.
- do_check_calc(str1, str1.length, lst, sst);
-
- // Characters found only in single shift tables should be encoded as
- // <escape><code>, therefore doubles its original length.
- do_check_calc(str2, str2.length * 2, lst, sst);
- }
- }
-
- // Bug 790192: support strict GSM SMS 7-Bit encoding
- let str = "", strToWrite = "", gsmLen = 0;
- for (let c in GSM_SMS_STRICT_7BIT_CHARMAP) {
- str += c;
- strToWrite += GSM_SMS_STRICT_7BIT_CHARMAP[c];
- if (PDU_NL_LOCKING_SHIFT_TABLES.indexOf(GSM_SMS_STRICT_7BIT_CHARMAP[c])) {
- gsmLen += 1;
- } else {
- gsmLen += 2;
- }
- }
- do_check_calc(str, gsmLen,
- PDU_NL_IDENTIFIER_DEFAULT, PDU_NL_IDENTIFIER_DEFAULT,
- true, strToWrite);
-
- run_next_test();
-});
-
diff --git a/dom/system/gonk/tests/test_ril_worker_smsc_address.js b/dom/system/gonk/tests/test_ril_worker_smsc_address.js
deleted file mode 100644
index c8c283b7c..000000000
--- a/dom/system/gonk/tests/test_ril_worker_smsc_address.js
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-const SMSC_ATT = '+13123149810';
-const SMSC_ATT_TYPO = '+++1312@@@314$$$9,8,1,0';
-const SMSC_ATT_TEXT = '"+13123149810",145';
-const SMSC_ATT_TEXT_INCORRECT_TOA = '"+13123149810",129';
-const SMSC_ATT_PDU = '07913121139418F0';
-const SMSC_O2 = '+447802000332';
-const SMSC_O2_TEXT = '"+447802000332",145';
-const SMSC_O2_PDU = '0791448720003023';
-const SMSC_EMPTY = '';
-const SMSC_TON_UNKNOWN = '0407485455'
-const SMSC_TON_UNKNOWN_TEXT = '"0407485455",129';
-const SMSC_TON_UNKNOWN_TEXT_NO_TOA = '"0407485455"';
-const SMSC_TON_UNKNOWN_TEXT_INVALID_TOA = '"0407485455",abc';
-const SMSC_TON_UNKNOWN_PDU = '06814070844555';
-const SMSC_EMPTY_PDU = 'FFFFFFFFFFFFFFFFFFFFFFFF';
-const SMSC_EMPTY_TEXT = '';
-
-function run_test() {
- run_next_test();
-}
-
-function setSmsc(context, smsc, ton, npi, expected) {
- context.Buf.postRILMessage = function() {
- equal(this.readString(), expected);
- };
-
- context.RIL.setSmscAddress({
- smscAddress: smsc,
- typeOfNumber: ton,
- numberPlanIdentification: npi
- });
-}
-
-function getSmsc(worker, context, raw, smsc, ton, npi) {
- worker.postMessage = function(message) {
- equal(message.smscAddress, smsc);
- equal(message.typeOfNumber, ton);
- equal(message.numberPlanIdentification, npi);
- }
-
- context.Buf.writeString(raw);
- context.RIL[REQUEST_GET_SMSC_ADDRESS](0, { rilMessageType: "getSmscAddress"});
-}
-
-add_test(function test_setSmscAddress() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let parcelTypes = [];
- context.Buf.newParcel = (type, options) => parcelTypes.push(type);
-
- // Test text mode.
- worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "text";
-
- setSmsc(context, SMSC_ATT, 1, 1, SMSC_ATT_TEXT);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_O2, 1, 1, SMSC_O2_TEXT);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_ATT_TYPO, 1, 1, SMSC_ATT_TEXT);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_TON_UNKNOWN, 0, 1, SMSC_TON_UNKNOWN_TEXT);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- // Test pdu mode.
- worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "pdu";
-
- setSmsc(context, SMSC_ATT, 1, 1, SMSC_ATT_PDU);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_O2, 1, 1, SMSC_O2_PDU);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_ATT_TYPO, 1, 1, SMSC_ATT_PDU);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- setSmsc(context, SMSC_TON_UNKNOWN, 0, 1, SMSC_TON_UNKNOWN_PDU);
- equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
-
- run_next_test();
-});
-
-add_test(function test_getSmscAddress() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
-
- // Test text mode.
- worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "text";
- getSmsc(worker, context, SMSC_ATT_TEXT, SMSC_ATT, 1, 1);
- getSmsc(worker, context, SMSC_ATT_TEXT_INCORRECT_TOA, SMSC_ATT, 1, 1);
- getSmsc(worker, context, SMSC_O2_TEXT, SMSC_O2, 1, 1);
- getSmsc(worker, context, SMSC_TON_UNKNOWN_TEXT, SMSC_TON_UNKNOWN, 0, 1);
- getSmsc(worker, context, SMSC_TON_UNKNOWN_TEXT_NO_TOA, SMSC_TON_UNKNOWN, 0, 1);
- getSmsc(worker, context, SMSC_TON_UNKNOWN_TEXT_INVALID_TOA, SMSC_TON_UNKNOWN,
- 0, 1);
- getSmsc(worker, context, SMSC_EMPTY_TEXT, SMSC_EMPTY, 0, 1);
-
- // Test pdu mode.
- worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "pdu";
- getSmsc(worker, context, SMSC_ATT_PDU, SMSC_ATT, 1, 1);
- getSmsc(worker, context, SMSC_O2_PDU, SMSC_O2, 1, 1);
- getSmsc(worker, context, SMSC_TON_UNKNOWN_PDU, SMSC_TON_UNKNOWN, 0, 1);
- getSmsc(worker, context, SMSC_EMPTY_PDU, SMSC_EMPTY, 0, 1);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_ssn.js b/dom/system/gonk/tests/test_ril_worker_ssn.js
deleted file mode 100644
index ea0a2a599..000000000
--- a/dom/system/gonk/tests/test_ril_worker_ssn.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_notification() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- function Call(callIndex, number) {
- this.callIndex = callIndex;
- this.number = number;
- }
-
- Call.prototype = {
- // Should use CALL_STATE_ACTIVE.
- // Any new outgoing call (state = dialing or alerting) will be drop if there
- // is no pending outgoing call created before.
- state: CALL_STATE_ACTIVE,
- //callIndex: 0,
- toa: 0,
- isMpty: false,
- isMT: false,
- als: 0,
- isVoice: true,
- isVoicePrivacy: false,
- //number: null,
- numberPresentation: 0,
- name: null,
- namePresentation: 0,
- uusInfo: null
- };
-
- let oneCall = {
- 0: new Call(0, '00000')
- };
-
- let twoCalls = {
- 0: new Call(0, '00000'),
- 1: new Call(1, '11111')
- };
-
- function testNotification(calls, code, number, resultNotification) {
-
- let testInfo = {calls: calls, code: code, number: number,
- resultNotification: resultNotification};
- do_print('Test case info: ' + JSON.stringify(testInfo));
-
- // Set current calls.
- context.RIL.sendChromeMessage({
- rilMessageType: "currentCalls",
- calls: calls
- });
-
- let notificationInfo = {
- notificationType: 1, // MT
- code: code,
- index: 0,
- type: 0,
- number: number
- };
-
- context.RIL._processSuppSvcNotification(notificationInfo);
-
- let postedMessage = workerHelper.postedMessage;
- equal(postedMessage.rilMessageType, 'suppSvcNotification');
- equal(postedMessage.number, number);
- equal(postedMessage.notification, resultNotification);
-
- // Clear all existed calls.
- context.RIL.sendChromeMessage({
- rilMessageType: "currentCalls",
- calls: {}
- });
- }
-
- testNotification(oneCall, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, null,
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- testNotification(oneCall, SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED, null,
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, null,
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_RETRIEVED, null,
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, '00000',
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, '11111',
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- testNotification(twoCalls, SUPP_SVC_NOTIFICATION_CODE2_PUT_ON_HOLD, '22222',
- GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD);
-
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_stk.js b/dom/system/gonk/tests/test_ril_worker_stk.js
deleted file mode 100644
index 49b914e89..000000000
--- a/dom/system/gonk/tests/test_ril_worker_stk.js
+++ /dev/null
@@ -1,1698 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-/**
- * Helper function.
- */
-function newUint8SupportOutgoingIndexWorker() {
- let worker = newWorker();
- let index = 4; // index for read
- let buf = [0, 0, 0, 0]; // Preserved parcel size
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.writeUint8 = function(value) {
- if (context.Buf.outgoingIndex >= buf.length) {
- buf.push(value);
- } else {
- buf[context.Buf.outgoingIndex] = value;
- }
-
- context.Buf.outgoingIndex++;
- };
-
- context.Buf.readUint8 = function() {
- return buf[index++];
- };
-
- context.Buf.seekIncoming = function(offset) {
- index += offset;
- };
-
- worker.debug = do_print;
-
- return worker;
-}
-
-// Test RIL requests related to STK.
-/**
- * Verify if RIL.sendStkTerminalProfile be called.
- */
-add_test(function test_if_send_stk_terminal_profile() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let profileSend = false;
- context.RIL.sendStkTerminalProfile = function(data) {
- profileSend = true;
- };
-
- let iccStatus = {
- gsmUmtsSubscriptionAppIndex: 0,
- apps: [{
- app_state: CARD_APPSTATE_READY,
- app_type: CARD_APPTYPE_USIM
- }],
- };
- worker.RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = false;
-
- context.RIL._processICCStatus(iccStatus);
-
- equal(profileSend, false);
-
- run_next_test();
-});
-
-/**
- * Verify RIL.sendStkTerminalProfile
- */
-add_test(function test_send_stk_terminal_profile() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let ril = context.RIL;
- let buf = context.Buf;
-
- ril.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
-
- buf.seekIncoming(8);
- let profile = buf.readString();
- for (let i = 0; i < STK_SUPPORTED_TERMINAL_PROFILE.length; i++) {
- equal(parseInt(profile.substring(2 * i, 2 * i + 2), 16),
- STK_SUPPORTED_TERMINAL_PROFILE[i]);
- }
-
- run_next_test();
-});
-
-/**
- * Verify STK terminal response
- */
-add_test(function test_stk_terminal_response() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 44 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // TEXT LENGTH(10))
- equal(this.readInt32(), 44);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_PROVIDE_LOCAL_INFO);
- equal(pduHelper.readHexOctet(), STK_LOCAL_INFO_NNA);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_OK);
-
- // Text
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 8);
- equal(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_7BIT_PACKED);
- equal(pduHelper.readSeptetsToString(7, 0, PDU_NL_IDENTIFIER_DEFAULT,
- PDU_NL_IDENTIFIER_DEFAULT), "Mozilla");
-
- run_next_test();
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_PROVIDE_LOCAL_INFO,
- commandQualifier: STK_LOCAL_INFO_NNA,
- options: {
- isPacked: true
- }
- },
- input: "Mozilla",
- resultCode: STK_RESULT_OK
- };
- context.RIL.sendStkTerminalResponse(response);
-});
-
-/**
- * Verify STK terminal response : GET INPUT with empty string.
- *
- * @See |TERMINAL RESPONSE: GET INPUT 1.9.1A| of 27.22.4.3.1 GET INPUT (normal)
- * in TS 102 384.
- */
-add_test(function test_stk_terminal_response_get_input_empty_string() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 30 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // TEXT LENGTH(3))
- equal(this.readInt32(), 30);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_GET_INPUT);
- equal(pduHelper.readHexOctet(), 0x00);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_OK);
-
- // Text
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_8BIT);
-
- run_next_test();
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_GET_INPUT,
- commandQualifier: 0x00,
- options: {
- minLength: 0,
- maxLength: 1,
- defaultText: "<SEND>"
- }
- },
- input: "",
- resultCode: STK_RESULT_OK
- };
- context.RIL.sendStkTerminalResponse(response);
-});
-
-/**
- * Verify STK terminal response : GET INPUT with 160 unpacked characters.
- *
- * @See |TERMINAL RESPONSE: GET INPUT 1.8.1| of 27.22.4.3.1 GET INPUT (normal)
- * in TS 102 384.
- */
-add_test(function test_stk_terminal_response_get_input_160_unpacked_characters() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
- let iccPduHelper = context.ICCPDUHelper;
- let TEST_TEXT_STRING = "***1111111111###" +
- "***2222222222###" +
- "***3333333333###" +
- "***4444444444###" +
- "***5555555555###" +
- "***6666666666###" +
- "***7777777777###" +
- "***8888888888###" +
- "***9999999999###" +
- "***0000000000###";
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 352 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // TEXT LENGTH(164))
- equal(this.readInt32(), 352);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_GET_INPUT);
- equal(pduHelper.readHexOctet(), 0x00);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_OK);
-
- // Text
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- // C-TLV Length Encoding: 161 = 0x81 0xA1
- equal(pduHelper.readHexOctet(), 0x81);
- equal(pduHelper.readHexOctet(), 0xA1);
- equal(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_8BIT);
- equal(iccPduHelper.read8BitUnpackedToString(160), TEST_TEXT_STRING);
-
- run_next_test();
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_GET_INPUT,
- commandQualifier: 0x00,
- options: {
- minLength: 160,
- maxLength: 160,
- text: TEST_TEXT_STRING
- }
- },
- input: TEST_TEXT_STRING,
- resultCode: STK_RESULT_OK
- };
- context.RIL.sendStkTerminalResponse(response);
-});
-
-/**
- * Verify STK terminal response : GET_INKEY - NO_RESPONSE_FROM_USER with
- * duration provided.
- *
- * @See |27.22.4.2.8 GET INKEY (Variable Time out)| in TS 102 384.
- */
-add_test(function test_stk_terminal_response_get_inkey_no_response_from_user() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 32 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // DURATION(4))
- equal(this.readInt32(), 32);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_GET_INKEY);
- equal(pduHelper.readHexOctet(), 0x00);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_NO_RESPONSE_FROM_USER);
-
- // Duration, Type-Length-Value(Time unit, Time interval)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DURATION);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_TIME_UNIT_SECOND);
- equal(pduHelper.readHexOctet(), 10);
-
- run_next_test();
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_GET_INKEY,
- commandQualifier: 0x00,
- options: {
- duration: {
- timeUnit: STK_TIME_UNIT_SECOND,
- timeInterval: 10
- },
- text: 'Enter "+"'
- }
- },
- resultCode: STK_RESULT_NO_RESPONSE_FROM_USER
- };
- context.RIL.sendStkTerminalResponse(response);
-});
-
-/**
- * Verify STK terminal response : GET_INKEY - YES/NO request
- */
-add_test(function test_stk_terminal_response_get_inkey() {
- function do_test(isYesNo) {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 32 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(3) +
- // TEXT LENGTH(4))
- equal(this.readInt32(), 32);
-
- // Command Details, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_GET_INKEY);
- equal(pduHelper.readHexOctet(), 0x04);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_RESULT_OK);
-
- // Yes/No response
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_TEXT_STRING |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_TEXT_CODING_GSM_8BIT);
- equal(pduHelper.readHexOctet(), isYesNo ? 0x01 : 0x00);
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_GET_INKEY,
- commandQualifier: 0x04,
- options: {
- isYesNoRequested: true
- }
- },
- isYesNo: isYesNo,
- resultCode: STK_RESULT_OK
- };
-
- context.RIL.sendStkTerminalResponse(response);
- };
-
- // Test "Yes" response
- do_test(true);
- // Test "No" response
- do_test(false);
-
- run_next_test();
-});
-
-/**
- * Verify STK terminal response with additional information.
- */
-add_test(function test_stk_terminal_response_with_additional_info() {
- function do_test(aInfo) {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Length 26 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
- // TLV_DEVICE_ID_SIZE(4) +
- // TLV_RESULT_SIZE(4))
- equal(this.readInt32(), 26);
-
- // Command Details, Type-Length-Value(commandNumber, typeOfCommand, commandQualifier)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 3);
- equal(pduHelper.readHexOctet(), 0x01);
- equal(pduHelper.readHexOctet(), STK_CMD_DISPLAY_TEXT);
- equal(pduHelper.readHexOctet(), 0x01);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Result, Type-Length-Value(General result, Additional information on result)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_RESULT |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
- equal(pduHelper.readHexOctet(), aInfo);
- };
-
- let response = {
- command: {
- commandNumber: 0x01,
- typeOfCommand: STK_CMD_DISPLAY_TEXT,
- commandQualifier: 0x01,
- options: {
- isHighPriority: true
- }
- },
- resultCode: STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS,
- additionalInformation: aInfo
- };
-
- context.RIL.sendStkTerminalResponse(response);
- };
-
- do_test(0x01); // 'Screen is busy'
-
- run_next_test();
-});
-
-// Test ComprehensionTlvHelper
-
-/**
- * Verify ComprehensionTlvHelper.writeLocationInfoTlv
- */
-add_test(function test_write_location_info_tlv() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let tlvHelper = context.ComprehensionTlvHelper;
-
- // Test with 2-digit mnc, and gsmCellId obtained from UMTS network.
- let loc = {
- mcc: "466",
- mnc: "92",
- gsmLocationAreaCode : 10291,
- gsmCellId: 19072823
- };
- tlvHelper.writeLocationInfoTlv(loc);
-
- let tag = pduHelper.readHexOctet();
- equal(tag, COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
-
- let length = pduHelper.readHexOctet();
- equal(length, 9);
-
- let mcc_mnc = pduHelper.readSwappedNibbleBcdString(3);
- equal(mcc_mnc, "46692");
-
- let lac = (pduHelper.readHexOctet() << 8) | pduHelper.readHexOctet();
- equal(lac, 10291);
-
- let cellId = (pduHelper.readHexOctet() << 24) |
- (pduHelper.readHexOctet() << 16) |
- (pduHelper.readHexOctet() << 8) |
- (pduHelper.readHexOctet());
- equal(cellId, 19072823);
-
- // Test with 1-digit mnc, and gsmCellId obtained from GSM network.
- loc = {
- mcc: "466",
- mnc: "02",
- gsmLocationAreaCode : 10291,
- gsmCellId: 65534
- };
- tlvHelper.writeLocationInfoTlv(loc);
-
- tag = pduHelper.readHexOctet();
- equal(tag, COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
-
- length = pduHelper.readHexOctet();
- equal(length, 7);
-
- mcc_mnc = pduHelper.readSwappedNibbleBcdString(3);
- equal(mcc_mnc, "46602");
-
- lac = (pduHelper.readHexOctet() << 8) | pduHelper.readHexOctet();
- equal(lac, 10291);
-
- cellId = (pduHelper.readHexOctet() << 8) | (pduHelper.readHexOctet());
- equal(cellId, 65534);
-
- // Test with 3-digit mnc, and gsmCellId obtained from GSM network.
- loc = {
- mcc: "466",
- mnc: "222",
- gsmLocationAreaCode : 10291,
- gsmCellId: 65534
- };
- tlvHelper.writeLocationInfoTlv(loc);
-
- tag = pduHelper.readHexOctet();
- equal(tag, COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
-
- length = pduHelper.readHexOctet();
- equal(length, 7);
-
- mcc_mnc = pduHelper.readSwappedNibbleBcdString(3);
- equal(mcc_mnc, "466222");
-
- lac = (pduHelper.readHexOctet() << 8) | pduHelper.readHexOctet();
- equal(lac, 10291);
-
- cellId = (pduHelper.readHexOctet() << 8) | (pduHelper.readHexOctet());
- equal(cellId, 65534);
-
- run_next_test();
-});
-
-/**
- * Verify ComprehensionTlvHelper.writeErrorNumber
- */
-add_test(function test_write_disconnecting_cause() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let tlvHelper = context.ComprehensionTlvHelper;
-
- tlvHelper.writeCauseTlv(RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BUSY]);
- let tag = pduHelper.readHexOctet();
- equal(tag, COMPREHENSIONTLV_TAG_CAUSE | COMPREHENSIONTLV_FLAG_CR);
- let len = pduHelper.readHexOctet();
- equal(len, 2); // We have one cause.
- let standard = pduHelper.readHexOctet();
- equal(standard, 0x60);
- let cause = pduHelper.readHexOctet();
- equal(cause, 0x80 | CALL_FAIL_BUSY);
-
- run_next_test();
-});
-
-/**
- * Verify ComprehensionTlvHelper.getSizeOfLengthOctets
- */
-add_test(function test_get_size_of_length_octets() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let tlvHelper = context.ComprehensionTlvHelper;
-
- let length = 0x70;
- equal(tlvHelper.getSizeOfLengthOctets(length), 1);
-
- length = 0x80;
- equal(tlvHelper.getSizeOfLengthOctets(length), 2);
-
- length = 0x180;
- equal(tlvHelper.getSizeOfLengthOctets(length), 3);
-
- length = 0x18000;
- equal(tlvHelper.getSizeOfLengthOctets(length), 4);
-
- run_next_test();
-});
-
-/**
- * Verify ComprehensionTlvHelper.writeLength
- */
-add_test(function test_write_length() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let tlvHelper = context.ComprehensionTlvHelper;
-
- let length = 0x70;
- tlvHelper.writeLength(length);
- equal(pduHelper.readHexOctet(), length);
-
- length = 0x80;
- tlvHelper.writeLength(length);
- equal(pduHelper.readHexOctet(), 0x81);
- equal(pduHelper.readHexOctet(), length);
-
- length = 0x180;
- tlvHelper.writeLength(length);
- equal(pduHelper.readHexOctet(), 0x82);
- equal(pduHelper.readHexOctet(), (length >> 8) & 0xff);
- equal(pduHelper.readHexOctet(), length & 0xff);
-
- length = 0x18000;
- tlvHelper.writeLength(length);
- equal(pduHelper.readHexOctet(), 0x83);
- equal(pduHelper.readHexOctet(), (length >> 16) & 0xff);
- equal(pduHelper.readHexOctet(), (length >> 8) & 0xff);
- equal(pduHelper.readHexOctet(), length & 0xff);
-
- run_next_test();
-});
-
-// Test Proactive commands.
-
-function test_stk_proactive_command(aOptions) {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
- let stkFactory = context.StkCommandParamsFactory;
-
- let testPdu = aOptions.pdu;
- let testTypeOfCommand = aOptions.typeOfCommand;
- let testIcons = aOptions.icons;
- let testFunc = aOptions.testFunc;
-
- if (testIcons) {
- let ril = context.RIL;
- ril.iccInfoPrivate.sst = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x30]; //IMG: 39
- ril.appType = CARD_APPTYPE_SIM;
-
- // skip asynchornous process in IconLoader.loadIcons().
- let iconLoader = context.IconLoader;
- iconLoader.loadIcons = (recordNumbers, onsuccess, onerror) => {
- onsuccess(testIcons);
- };
- }
-
- for(let i = 0 ; i < testPdu.length; i++) {
- pduHelper.writeHexOctet(testPdu[i]);
- }
-
- let berTlv = berHelper.decode(testPdu.length);
- let ctlvs = berTlv.value;
- let ctlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
- let cmdDetails = ctlv.value;
- equal(cmdDetails.typeOfCommand, testTypeOfCommand);
-
- stkFactory.createParam(cmdDetails, ctlvs, (aResult) => {
- cmdDetails.options = aResult;
- testFunc(context, cmdDetails, ctlvs);
- });
-}
-
-/**
- * Verify Proactive command helper : searchForSelectedTags
- */
-add_test(function test_stk_proactive_command_search_for_selected_tags() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
-
- let tag_test = [
- 0xD0,
- 0x3E,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x31,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x32,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x33,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x34,
- 0x85, 0x0A, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x20, 0x69, 0x64, 0x20, 0x35,
- 0x85, 0x00];
-
- for (let i = 0; i < tag_test.length; i++) {
- pduHelper.writeHexOctet(tag_test[i]);
- }
-
- let berTlv = berHelper.decode(tag_test.length);
- let selectedCtlvs =
- stkHelper.searchForSelectedTags(berTlv.value, [COMPREHENSIONTLV_TAG_ALPHA_ID]);
- let tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 1");
-
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 2");
-
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 3");
-
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 4");
-
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- equal(tlv.value.identifier, "alpha id 5");
-
- // emulate that the alpha identifier is provided and is a null data object,
- // which is converted to an empty string in ICCPDUHelper.
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- strictEqual(tlv.value.identifier, "");
-
- // emulate that the alpha identifier is not provided
- tlv = selectedCtlvs.retrieve(COMPREHENSIONTLV_TAG_ALPHA_ID);
- strictEqual(tlv, undefined);
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Refresh
- */
-add_test(function test_stk_proactive_command_refresh() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x10,
- 0x81, 0x03, 0x01, 0x01, 0x01,
- 0x82, 0x02, 0x81, 0x82,
- 0x92, 0x05, 0x01, 0x3F, 0x00, 0x2F, 0xE2
- ],
- typeOfCommand: STK_CMD_REFRESH,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let stkHelper = context.StkProactiveCmdHelper;
- let ctlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_FILE_LIST, ctlvs);
- equal(ctlv.value.fileList, "3F002FE2");
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Play Tone
- */
-add_test(function test_stk_proactive_command_play_tone() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x1F,
- 0x81, 0x03, 0x01, 0x20, 0x00,
- 0x82, 0x02, 0x81, 0x03,
- 0x85, 0x09, 0x44, 0x69, 0x61, 0x6C, 0x20, 0x54, 0x6F, 0x6E, 0x65,
- 0x8E, 0x01, 0x01,
- 0x84, 0x02, 0x01, 0x05,
- 0x9E, 0x02, 0x00, 0x01
- ],
- typeOfCommand: STK_CMD_PLAY_TONE,
- icons: [1],
- testFunc: (context, cmdDetails, ctlvs) => {
- let playTone = cmdDetails.options;
-
- equal(playTone.text, "Dial Tone");
- equal(playTone.tone, STK_TONE_TYPE_DIAL_TONE);
- equal(playTone.duration.timeUnit, STK_TIME_UNIT_SECOND);
- equal(playTone.duration.timeInterval, 5);
- equal(playTone.iconSelfExplanatory, true);
- equal(playTone.icons, 1);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Poll Interval
- */
-add_test(function test_stk_proactive_command_poll_interval() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0D,
- 0x81, 0x03, 0x01, 0x03, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x84, 0x02, 0x01, 0x14
- ],
- typeOfCommand: STK_CMD_POLL_INTERVAL,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let interval = cmdDetails.options;
-
- equal(interval.timeUnit, STK_TIME_UNIT_SECOND);
- equal(interval.timeInterval, 0x14);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command: Display Text
- */
-add_test(function test_stk_proactive_command_display_text() {
- test_stk_proactive_command({
- pdu: [
- 0xd0,
- 0x2c,
- 0x81, 0x03, 0x01, 0x21, 0x80,
- 0x82, 0x02, 0x81, 0x02,
- 0x0d, 0x1d, 0x00, 0xd3, 0x30, 0x9b, 0xfc, 0x06, 0xc9, 0x5c, 0x30, 0x1a,
- 0xa8, 0xe8, 0x02, 0x59, 0xc3, 0xec, 0x34, 0xb9, 0xac, 0x07, 0xc9, 0x60,
- 0x2f, 0x58, 0xed, 0x15, 0x9b, 0xb9, 0x40,
- 0x9e, 0x02, 0x00, 0x01
- ],
- typeOfCommand: STK_CMD_DISPLAY_TEXT,
- icons: [1],
- testFunc: (context, cmdDetails, ctlvs) => {
- let textMsg = cmdDetails.options;
-
- equal(textMsg.text, "Saldo 2.04 E. Validez 20/05/13. ");
- equal(textMsg.iconSelfExplanatory, true);
- equal(textMsg.icons, 1);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command: Set Up Event List.
- */
-add_test(function test_stk_proactive_command_event_list() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0F,
- 0x81, 0x03, 0x01, 0x05, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x99, 0x04, 0x00, 0x01, 0x02, 0x03
- ],
- typeOfCommand: STK_CMD_SET_UP_EVENT_LIST,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let event = cmdDetails.options;
-
- equal(Array.isArray(event.eventList), true);
-
- for (let i = 0; i < event.eventList.length; i++) {
- equal(event.eventList[i], i);
- }
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Get Input
- */
-add_test(function test_stk_proactive_command_get_input() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x22,
- 0x81, 0x03, 0x01, 0x23, 0x8F,
- 0x82, 0x02, 0x81, 0x82,
- 0x8D, 0x05, 0x04, 0x54, 0x65, 0x78, 0x74,
- 0x91, 0x02, 0x01, 0x10,
- 0x17, 0x08, 0x04, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74,
- 0x9E, 0x02, 0x00, 0x01
- ],
- typeOfCommand: STK_CMD_GET_INPUT,
- icons: [1],
- testFunc: (context, cmdDetails, ctlvs) => {
- let input = cmdDetails.options;
-
- equal(input.text, "Text");
- equal(input.isAlphabet, true);
- equal(input.isUCS2, true);
- equal(input.hideInput, true);
- equal(input.isPacked, true);
- equal(input.isHelpAvailable, true);
- equal(input.minLength, 0x01);
- equal(input.maxLength, 0x10);
- equal(input.defaultText, "Default");
- equal(input.iconSelfExplanatory, true);
- equal(input.icons, 1);
- }
- });
-
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x11,
- 0x81, 0x03, 0x01, 0x23, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x8D, 0x00,
- 0x91, 0x02, 0x01, 0x10,
- 0x17, 0x00
- ],
- typeOfCommand: STK_CMD_GET_INPUT,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let input = cmdDetails.options;
-
- equal(input.text, null);
- equal(input.minLength, 0x01);
- equal(input.maxLength, 0x10);
- equal(input.defaultText, null);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : More Time
- */
-add_test(function test_stk_proactive_command_more_time() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
-
- let more_time_1 = [
- 0xD0,
- 0x09,
- 0x81, 0x03, 0x01, 0x02, 0x00,
- 0x82, 0x02, 0x81, 0x82];
-
- for(let i = 0 ; i < more_time_1.length; i++) {
- pduHelper.writeHexOctet(more_time_1[i]);
- }
-
- let berTlv = berHelper.decode(more_time_1.length);
- let ctlvs = berTlv.value;
- let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
- equal(tlv.value.commandNumber, 0x01);
- equal(tlv.value.typeOfCommand, STK_CMD_MORE_TIME);
- equal(tlv.value.commandQualifier, 0x00);
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Select Item
- */
-add_test(function test_stk_proactive_command_select_item() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x3D,
- 0x81, 0x03, 0x01, 0x24, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
- 0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
- 0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
- 0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
- 0x18, 0x03, 0x10, 0x15, 0x20,
- 0x90, 0x01, 0x01,
- 0x9E, 0x02, 0x00, 0x01,
- 0x9F, 0x04, 0x00, 0x01, 0x02, 0x03
- ],
- typeOfCommand: STK_CMD_SELECT_ITEM,
- icons: [1, 1, 2, 3],
- testFunc: (context, cmdDetails, ctlvs) => {
- let menu = cmdDetails.options;
-
- equal(menu.title, "Title");
- equal(menu.iconSelfExplanatory, true);
- equal(menu.icons, 1);
- equal(menu.items[0].identifier, 1);
- equal(menu.items[0].text, "item 1");
- equal(menu.items[0].iconSelfExplanatory, true);
- equal(menu.items[0].icons, 1);
- equal(menu.items[1].identifier, 2);
- equal(menu.items[1].text, "item 2");
- equal(menu.items[1].iconSelfExplanatory, true);
- equal(menu.items[1].icons, 2);
- equal(menu.items[2].identifier, 3);
- equal(menu.items[2].text, "item 3");
- equal(menu.items[2].iconSelfExplanatory, true);
- equal(menu.items[2].icons, 3);
- equal(menu.nextActionList[0], STK_CMD_SET_UP_CALL);
- equal(menu.nextActionList[1], STK_CMD_LAUNCH_BROWSER);
- equal(menu.nextActionList[2], STK_CMD_PLAY_TONE);
- equal(menu.defaultItem, 0x00);
- }
- });
-
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x33,
- 0x81, 0x03, 0x01, 0x24, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
- 0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
- 0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
- 0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
- 0x18, 0x03, 0x00, 0x15, 0x81,
- 0x90, 0x01, 0x03
- ],
- typeOfCommand: STK_CMD_SELECT_ITEM,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let menu = cmdDetails.options;
-
- equal(menu.title, "Title");
- equal(menu.items[0].identifier, 1);
- equal(menu.items[0].text, "item 1");
- equal(menu.items[1].identifier, 2);
- equal(menu.items[1].text, "item 2");
- equal(menu.items[2].identifier, 3);
- equal(menu.items[2].text, "item 3");
- equal(menu.nextActionList[0], STK_NEXT_ACTION_NULL);
- equal(menu.nextActionList[1], STK_CMD_LAUNCH_BROWSER);
- equal(menu.nextActionList[2], STK_NEXT_ACTION_END_PROACTIVE_SESSION);
- equal(menu.defaultItem, 0x02);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Set Up Menu
- */
-add_test(function test_stk_proactive_command_set_up_menu() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x3A,
- 0x81, 0x03, 0x01, 0x25, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
- 0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
- 0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
- 0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
- 0x18, 0x03, 0x10, 0x15, 0x20,
- 0x9E, 0x02, 0x00, 0x01,
- 0x9F, 0x04, 0x00, 0x01, 0x02, 0x03
- ],
- typeOfCommand: STK_CMD_SET_UP_MENU,
- icons: [1, 1, 2, 3],
- testFunc: (context, cmdDetails, ctlvs) => {
- let menu = cmdDetails.options;
-
- equal(menu.title, "Title");
- equal(menu.iconSelfExplanatory, true);
- equal(menu.icons, 1);
- equal(menu.items[0].identifier, 1);
- equal(menu.items[0].text, "item 1");
- equal(menu.items[0].iconSelfExplanatory, true);
- equal(menu.items[0].icons, 1);
- equal(menu.items[1].identifier, 2);
- equal(menu.items[1].text, "item 2");
- equal(menu.items[1].iconSelfExplanatory, true);
- equal(menu.items[1].icons, 2);
- equal(menu.items[2].identifier, 3);
- equal(menu.items[2].text, "item 3");
- equal(menu.items[2].iconSelfExplanatory, true);
- equal(menu.items[2].icons, 3);
- equal(menu.nextActionList[0], STK_CMD_SET_UP_CALL);
- equal(menu.nextActionList[1], STK_CMD_LAUNCH_BROWSER);
- equal(menu.nextActionList[2], STK_CMD_PLAY_TONE);
- }
- });
-
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x30,
- 0x81, 0x03, 0x01, 0x25, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x54, 0x69, 0x74, 0x6C, 0x65,
- 0x8F, 0x07, 0x01, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x31,
- 0x8F, 0x07, 0x02, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x32,
- 0x8F, 0x07, 0x03, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x33,
- 0x18, 0x03, 0x81, 0x00, 0x00
- ],
- typeOfCommand: STK_CMD_SET_UP_MENU,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let menu = cmdDetails.options;
-
- equal(menu.title, "Title");
- equal(menu.items[0].identifier, 1);
- equal(menu.items[0].text, "item 1");
- equal(menu.items[1].identifier, 2);
- equal(menu.items[1].text, "item 2");
- equal(menu.items[2].identifier, 3);
- equal(menu.items[2].text, "item 3");
- equal(menu.nextActionList[0], STK_NEXT_ACTION_END_PROACTIVE_SESSION);
- equal(menu.nextActionList[1], STK_NEXT_ACTION_NULL);
- equal(menu.nextActionList[2], STK_NEXT_ACTION_NULL);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Set Up Call
- */
-add_test(function test_stk_proactive_command_set_up_call() {
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x31,
- 0x81, 0x03, 0x01, 0x10, 0x04,
- 0x82, 0x02, 0x81, 0x82,
- 0x05, 0x0A, 0x44, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74,
- 0x86, 0x09, 0x81, 0x10, 0x32, 0x04, 0x21, 0x43, 0x65, 0x1C, 0x2C,
- 0x05, 0x07, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
- 0x9E, 0x02, 0x00, 0x01,
- 0x9E, 0x02, 0x01, 0x02
- ],
- typeOfCommand: STK_CMD_SET_UP_CALL,
- icons: [1, 2],
- testFunc: (context, cmdDetails, ctlvs) => {
- let setupCall = cmdDetails.options;
-
- equal(setupCall.address, "012340123456,1,2");
- equal(setupCall.confirmMessage.text, "Disconnect");
- equal(setupCall.confirmMessage.iconSelfExplanatory, true);
- equal(setupCall.confirmMessage.icons, 1);
- equal(setupCall.callMessage.text, "Message");
- equal(setupCall.callMessage.iconSelfExplanatory, false);
- equal(setupCall.callMessage.icons, 2);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Timer Management
- */
-add_test(function test_stk_proactive_command_timer_management() {
- // Timer Management - Start
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x11,
- 0x81, 0x03, 0x01, 0x27, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0xA4, 0x01, 0x01,
- 0xA5, 0x03, 0x10, 0x20, 0x30
- ],
- typeOfCommand: STK_CMD_TIMER_MANAGEMENT,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- equal(cmdDetails.commandQualifier, STK_TIMER_START);
-
- let timer = cmdDetails.options;
-
- equal(timer.timerId, 0x01);
- equal(timer.timerValue, (0x01 * 60 * 60) + (0x02 * 60) + 0x03);
- }
- });
-
- // Timer Management - Deactivate
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0C,
- 0x81, 0x03, 0x01, 0x27, 0x01,
- 0x82, 0x02, 0x81, 0x82,
- 0xA4, 0x01, 0x01
- ],
- typeOfCommand: STK_CMD_TIMER_MANAGEMENT,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- equal(cmdDetails.commandQualifier, STK_TIMER_DEACTIVATE);
-
- let timer = cmdDetails.options;
-
- equal(timer.timerId, 0x01);
- ok(timer.timerValue === undefined);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive Command : Provide Local Information
- */
-add_test(function test_stk_proactive_command_provide_local_information() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
- let stkCmdHelper = context.StkCommandParamsFactory;
-
- // Verify IMEI
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x09,
- 0x81, 0x03, 0x01, 0x26, 0x01,
- 0x82, 0x02, 0x81, 0x82
- ],
- typeOfCommand: STK_CMD_PROVIDE_LOCAL_INFO,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- equal(cmdDetails.commandQualifier, STK_LOCAL_INFO_IMEI);
-
- let provideLocalInfo = cmdDetails.options;
- equal(provideLocalInfo.localInfoType, STK_LOCAL_INFO_IMEI);
- }
- });
-
- // Verify Date and Time Zone
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x09,
- 0x81, 0x03, 0x01, 0x26, 0x03,
- 0x82, 0x02, 0x81, 0x82
- ],
- typeOfCommand: STK_CMD_PROVIDE_LOCAL_INFO,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- equal(cmdDetails.commandQualifier, STK_LOCAL_INFO_DATE_TIME_ZONE);
-
- let provideLocalInfo = cmdDetails.options;
- equal(provideLocalInfo.localInfoType, STK_LOCAL_INFO_DATE_TIME_ZONE);
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Proactive command : BIP Messages
- */
-add_test(function test_stk_proactive_command_open_channel() {
- let worker = newUint8Worker();
- let context = worker.ContextPool._contexts[0];
- let pduHelper = context.GsmPDUHelper;
- let berHelper = context.BerTlvHelper;
- let stkHelper = context.StkProactiveCmdHelper;
- let stkCmdHelper = context.StkCommandParamsFactory;
-
- // Open Channel
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0F,
- 0x81, 0x03, 0x01, 0x40, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x04, 0x4F, 0x70, 0x65, 0x6E //alpha id: "Open"
- ],
- typeOfCommand: STK_CMD_OPEN_CHANNEL,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let bipMsg = cmdDetails.options;
-
- equal(bipMsg.text, "Open");
- }
- });
-
- // Close Channel
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x10,
- 0x81, 0x03, 0x01, 0x41, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x05, 0x43, 0x6C, 0x6F, 0x73, 0x65 //alpha id: "Close"
- ],
- typeOfCommand: STK_CMD_CLOSE_CHANNEL,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let bipMsg = cmdDetails.options;
-
- equal(bipMsg.text, "Close");
- }
- });
-
- // Receive Data
- test_stk_proactive_command({
- pdu: [
- 0XD0,
- 0X12,
- 0x81, 0x03, 0x01, 0x42, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x07, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65 //alpha id: "Receive"
- ],
- typeOfCommand: STK_CMD_RECEIVE_DATA,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let bipMsg = cmdDetails.options;
-
- equal(bipMsg.text, "Receive");
- }
- });
-
- // Send Data
- test_stk_proactive_command({
- pdu: [
- 0xD0,
- 0x0F,
- 0x81, 0x03, 0x01, 0x43, 0x00,
- 0x82, 0x02, 0x81, 0x82,
- 0x85, 0x04, 0x53, 0x65, 0x6E, 0x64 //alpha id: "Send"
- ],
- typeOfCommand: STK_CMD_SEND_DATA,
- icons: null,
- testFunc: (context, cmdDetails, ctlvs) => {
- let bipMsg = cmdDetails.options;
-
- equal(bipMsg.text, "Send");
- }
- });
-
- run_next_test();
-});
-
-/**
- * Verify Event Download Command : Location Status
- */
-add_test(function test_stk_event_download_location_status() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 42 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) +
- // TLV_EVENT_LIST_SIZE(3) +
- // TLV_LOCATION_STATUS_SIZE(3) +
- // TLV_LOCATION_INFO_GSM_SIZE(9))
- equal(this.readInt32(), 42);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 19 = TLV_DEVICE_ID_SIZE(4) +
- // TLV_EVENT_LIST_SIZE(3) +
- // TLV_LOCATION_STATUS_SIZE(3) +
- // TLV_LOCATION_INFO_GSM_SIZE(9)
- equal(pduHelper.readHexOctet(), 19);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_LOCATION_STATUS);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Location Status, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_LOCATION_STATUS |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_SERVICE_STATE_NORMAL);
-
- // Location Info, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_LOCATION_INFO |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 7);
-
- equal(pduHelper.readHexOctet(), 0x21); // MCC + MNC
- equal(pduHelper.readHexOctet(), 0x63);
- equal(pduHelper.readHexOctet(), 0x54);
- equal(pduHelper.readHexOctet(), 0); // LAC
- equal(pduHelper.readHexOctet(), 0);
- equal(pduHelper.readHexOctet(), 0); // Cell ID
- equal(pduHelper.readHexOctet(), 0);
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_LOCATION_STATUS,
- locationStatus: STK_SERVICE_STATE_NORMAL,
- locationInfo: {
- mcc: "123",
- mnc: "456",
- gsmLocationAreaCode: 0,
- gsmCellId: 0
- }
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
-
-// Test Event Download commands.
-
-/**
- * Verify Event Download Command : Language Selection
- */
-add_test(function test_stk_event_download_language_selection() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
- let iccHelper = context.ICCPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 26 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) +
- // TLV_EVENT_LIST_SIZE(3) +
- // TLV_LANGUAGE(4))
- equal(this.readInt32(), 26);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 19 = TLV_DEVICE_ID_SIZE(4) +
- // TLV_EVENT_LIST_SIZE(3) +
- // TLV_LANGUAGE(4)
- equal(pduHelper.readHexOctet(), 11);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_LANGUAGE_SELECTION);
-
- // Device Identifies, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Language, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_LANGUAGE);
- equal(pduHelper.readHexOctet(), 2);
- equal(iccHelper.read8BitUnpackedToString(2), "zh");
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_LANGUAGE_SELECTION,
- language: "zh"
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
-
-/**
- * Verify Event Download Command : User Activity
- */
-add_test(function test_stk_event_download_user_activity() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 18 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3))
- equal(this.readInt32(), 18);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 7 = TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3)
- equal(pduHelper.readHexOctet(), 7);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_USER_ACTIVITY);
-
- // Device Identities, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_USER_ACTIVITY
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
-
-/**
- * Verify Event Download Command : Idle Screen Available
- */
-add_test(function test_stk_event_download_idle_screen_available() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 18 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3))
- equal(this.readInt32(), 18);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 7 = TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3)
- equal(pduHelper.readHexOctet(), 7);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE);
-
- // Device Identities, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_DISPLAY);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
-
-/**
- * Verify Event Downloaded Command :Browser Termination
- */
-add_test(function test_stk_event_download_browser_termination() {
- let worker = newUint8SupportOutgoingIndexWorker();
- let context = worker.ContextPool._contexts[0];
- let buf = context.Buf;
- let pduHelper = context.GsmPDUHelper;
-
- buf.sendParcel = function() {
- // Type
- equal(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
-
- // Token : we don't care
- this.readInt32();
-
- // Data Size, 24 = 2 * ( 2+TLV_DEVICE_ID(4)+TLV_EVENT_LIST_SIZE(3)
- // +TLV_BROWSER_TERMINATION_CAUSE(3) )
- equal(this.readInt32(), 24);
-
- // BER tag
- equal(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
-
- // BER length, 10 = TLV_DEVICE_ID(4)+TLV_EVENT_LIST_SIZE(3)
- // ++TLV_BROWSER_TERMINATION_CAUSE(3)
- equal(pduHelper.readHexOctet(), 10);
-
- // Event List, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_EVENT_TYPE_BROWSER_TERMINATION);
-
- // Device Identities, Type-Length-Value(Source ID-Destination ID)
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 2);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_ME);
- equal(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM);
-
- // Browser Termination Case, Type-Length-Value
- equal(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_BROWSER_TERMINATION_CAUSE |
- COMPREHENSIONTLV_FLAG_CR);
- equal(pduHelper.readHexOctet(), 1);
- equal(pduHelper.readHexOctet(), STK_BROWSER_TERMINATION_CAUSE_USER);
-
- run_next_test();
- };
-
- let event = {
- eventType: STK_EVENT_TYPE_BROWSER_TERMINATION,
- terminationCause: STK_BROWSER_TERMINATION_CAUSE_USER
- };
- context.RIL.sendStkEventDownload({
- event: event
- });
-});
diff --git a/dom/system/gonk/tests/test_ril_worker_voiceprivacy.js b/dom/system/gonk/tests/test_ril_worker_voiceprivacy.js
deleted file mode 100644
index 21829da22..000000000
--- a/dom/system/gonk/tests/test_ril_worker_voiceprivacy.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
- run_next_test();
-}
-
-add_test(function test_setVoicePrivacyMode_success() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setVoicePrivacyMode = function fakeSetVoicePrivacyMode(options) {
- context.RIL[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE](0, {});
- };
-
- context.RIL.setVoicePrivacyMode({
- enabled: true
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
-
- run_next_test();
-});
-
-add_test(function test_setVoicePrivacyMode_generic_failure() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.RIL.setVoicePrivacyMode = function fakeSetVoicePrivacyMode(options) {
- context.RIL[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE](0, {
- errorMsg: GECKO_ERROR_GENERIC_FAILURE
- });
- };
-
- context.RIL.setVoicePrivacyMode({
- enabled: true
- });
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
-
- run_next_test();
-});
-
-add_test(function test_queryVoicePrivacyMode_success_enabled_true() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32List = function fakeReadUint32List() {
- return [1];
- };
-
- context.RIL.queryVoicePrivacyMode = function fakeQueryVoicePrivacyMode(options) {
- context.RIL[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE](1, {});
- };
-
- context.RIL.queryVoicePrivacyMode();
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- ok(postedMessage.enabled);
- run_next_test();
-});
-
-add_test(function test_queryVoicePrivacyMode_success_enabled_false() {
- let workerHelper = newInterceptWorker();
- let worker = workerHelper.worker;
- let context = worker.ContextPool._contexts[0];
-
- context.Buf.readInt32List = function fakeReadUint32List() {
- return [0];
- };
-
- context.RIL.queryVoicePrivacyMode = function fakeQueryVoicePrivacyMode(options) {
- context.RIL[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE](1, {});
- };
-
- context.RIL.queryVoicePrivacyMode();
-
- let postedMessage = workerHelper.postedMessage;
-
- equal(postedMessage.errorMsg, undefined);
- ok(!postedMessage.enabled);
- run_next_test();
-});
diff --git a/dom/system/gonk/tests/xpcshell.ini b/dom/system/gonk/tests/xpcshell.ini
deleted file mode 100644
index 1e8b798a3..000000000
--- a/dom/system/gonk/tests/xpcshell.ini
+++ /dev/null
@@ -1,43 +0,0 @@
-[DEFAULT]
-head = header_helpers.js
-tail =
-
-[test_ril_worker_buf.js]
-[test_ril_worker_icc_CardLock.js]
-[test_ril_worker_icc_CardState.js]
-[test_ril_worker_icc_BerTlvHelper.js]
-[test_ril_worker_icc_GsmPDUHelper.js]
-[test_ril_worker_icc_ICCContactHelper.js]
-[test_ril_worker_icc_ICCIOHelper.js]
-[test_ril_worker_icc_ICCPDUHelper.js]
-[test_ril_worker_icc_ICCRecordHelper.js]
-[test_ril_worker_icc_IconLoader.js]
-[test_ril_worker_icc_ICCUtilsHelper.js]
-[test_ril_worker_icc_SimRecordHelper.js]
-[test_ril_worker_sms.js]
-# Bug 916067 - B2G RIL: test_ril_worker_sms.js takes too long to finish
-skip-if = true
-[test_ril_worker_sms_cdma.js]
-[test_ril_worker_sms_cdmapduhelper.js]
-[test_ril_worker_sms_nl_tables.js]
-[test_ril_worker_sms_gsmpduhelper.js]
-[test_ril_worker_sms_segment_info.js]
-[test_ril_worker_smsc_address.js]
-[test_ril_worker_cf.js]
-[test_ril_worker_cellbroadcast_config.js]
-[test_ril_worker_cellbroadcast_gsm.js]
-[test_ril_worker_cellbroadcast_umts.js]
-[test_ril_worker_ruim.js]
-[test_ril_worker_cw.js]
-[test_ril_worker_clir.js]
-[test_ril_worker_clip.js]
-[test_ril_worker_ssn.js]
-[test_ril_worker_voiceprivacy.js]
-[test_ril_worker_ecm.js]
-[test_ril_worker_stk.js]
-requesttimeoutfactor = 4
-[test_ril_worker_barring_password.js]
-[test_ril_worker_cdma_info_rec.js]
-[test_ril_system_messenger.js]
-# header_helpers.js is not needed for test_ril_system_messenger.js
-head =
diff --git a/dom/system/gonk/worker_buf.js b/dom/system/gonk/worker_buf.js
deleted file mode 100644
index 7064eeac5..000000000
--- a/dom/system/gonk/worker_buf.js
+++ /dev/null
@@ -1,623 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-/**
- * This object contains helpers buffering incoming data & deconstructing it
- * into parcels as well as buffering outgoing data & constructing parcels.
- * For that it maintains two buffers and corresponding uint8 views, indexes.
- *
- * The incoming buffer is a circular buffer where we store incoming data.
- * As soon as a complete parcel is received, it is processed right away, so
- * the buffer only needs to be large enough to hold one parcel.
- *
- * The outgoing buffer is to prepare outgoing parcels. The index is reset
- * every time a parcel is sent.
- */
-
-var Buf = {
- INT32_MAX: 2147483647,
- UINT8_SIZE: 1,
- UINT16_SIZE: 2,
- UINT32_SIZE: 4,
- PARCEL_SIZE_SIZE: 4,
- PDU_HEX_OCTET_SIZE: 4,
-
- incomingBufferLength: 1024,
- incomingBuffer: null,
- incomingBytes: null,
- incomingWriteIndex: 0,
- incomingReadIndex: 0,
- readIncoming: 0,
- readAvailable: 0,
- currentParcelSize: 0,
-
- outgoingBufferLength: 1024,
- outgoingBuffer: null,
- outgoingBytes: null,
- outgoingIndex: 0,
- outgoingBufferCalSizeQueue: null,
-
- _init: function() {
- this.incomingBuffer = new ArrayBuffer(this.incomingBufferLength);
- this.outgoingBuffer = new ArrayBuffer(this.outgoingBufferLength);
-
- this.incomingBytes = new Uint8Array(this.incomingBuffer);
- this.outgoingBytes = new Uint8Array(this.outgoingBuffer);
-
- // Track where incoming data is read from and written to.
- this.incomingWriteIndex = 0;
- this.incomingReadIndex = 0;
-
- // Leave room for the parcel size for outgoing parcels.
- this.outgoingIndex = this.PARCEL_SIZE_SIZE;
-
- // How many bytes we've read for this parcel so far.
- this.readIncoming = 0;
-
- // How many bytes available as parcel data.
- this.readAvailable = 0;
-
- // Size of the incoming parcel. If this is zero, we're expecting a new
- // parcel.
- this.currentParcelSize = 0;
-
- // Queue for storing outgoing override points
- this.outgoingBufferCalSizeQueue = [];
- },
-
- /**
- * Mark current outgoingIndex as start point for calculation length of data
- * written to outgoingBuffer.
- * Mark can be nested for here uses queue to remember marks.
- *
- * @param writeFunction
- * Function to write data length into outgoingBuffer, this function is
- * also used to allocate buffer for data length.
- * Raw data size(in Uint8) is provided as parameter calling writeFunction.
- * If raw data size is not in proper unit for writing, user can adjust
- * the length value in writeFunction before writing.
- **/
- startCalOutgoingSize: function(writeFunction) {
- let sizeInfo = {index: this.outgoingIndex,
- write: writeFunction};
-
- // Allocate buffer for data lemgtj.
- writeFunction.call(0);
-
- // Get size of data length buffer for it is not counted into data size.
- sizeInfo.size = this.outgoingIndex - sizeInfo.index;
-
- // Enqueue size calculation information.
- this.outgoingBufferCalSizeQueue.push(sizeInfo);
- },
-
- /**
- * Calculate data length since last mark, and write it into mark position.
- **/
- stopCalOutgoingSize: function() {
- let sizeInfo = this.outgoingBufferCalSizeQueue.pop();
-
- // Remember current outgoingIndex.
- let currentOutgoingIndex = this.outgoingIndex;
- // Calculate data length, in uint8.
- let writeSize = this.outgoingIndex - sizeInfo.index - sizeInfo.size;
-
- // Write data length to mark, use same function for allocating buffer to make
- // sure there is no buffer overloading.
- this.outgoingIndex = sizeInfo.index;
- sizeInfo.write(writeSize);
-
- // Restore outgoingIndex.
- this.outgoingIndex = currentOutgoingIndex;
- },
-
- /**
- * Grow the incoming buffer.
- *
- * @param min_size
- * Minimum new size. The actual new size will be the the smallest
- * power of 2 that's larger than this number.
- */
- growIncomingBuffer: function(min_size) {
- if (DEBUG) {
- debug("Current buffer of " + this.incomingBufferLength +
- " can't handle incoming " + min_size + " bytes.");
- }
- let oldBytes = this.incomingBytes;
- this.incomingBufferLength =
- 2 << Math.floor(Math.log(min_size)/Math.log(2));
- if (DEBUG) debug("New incoming buffer size: " + this.incomingBufferLength);
- this.incomingBuffer = new ArrayBuffer(this.incomingBufferLength);
- this.incomingBytes = new Uint8Array(this.incomingBuffer);
- if (this.incomingReadIndex <= this.incomingWriteIndex) {
- // Read and write index are in natural order, so we can just copy
- // the old buffer over to the bigger one without having to worry
- // about the indexes.
- this.incomingBytes.set(oldBytes, 0);
- } else {
- // The write index has wrapped around but the read index hasn't yet.
- // Write whatever the read index has left to read until it would
- // circle around to the beginning of the new buffer, and the rest
- // behind that.
- let head = oldBytes.subarray(this.incomingReadIndex);
- let tail = oldBytes.subarray(0, this.incomingReadIndex);
- this.incomingBytes.set(head, 0);
- this.incomingBytes.set(tail, head.length);
- this.incomingReadIndex = 0;
- this.incomingWriteIndex += head.length;
- }
- if (DEBUG) {
- debug("New incoming buffer size is " + this.incomingBufferLength);
- }
- },
-
- /**
- * Grow the outgoing buffer.
- *
- * @param min_size
- * Minimum new size. The actual new size will be the the smallest
- * power of 2 that's larger than this number.
- */
- growOutgoingBuffer: function(min_size) {
- if (DEBUG) {
- debug("Current buffer of " + this.outgoingBufferLength +
- " is too small.");
- }
- let oldBytes = this.outgoingBytes;
- this.outgoingBufferLength =
- 2 << Math.floor(Math.log(min_size)/Math.log(2));
- this.outgoingBuffer = new ArrayBuffer(this.outgoingBufferLength);
- this.outgoingBytes = new Uint8Array(this.outgoingBuffer);
- this.outgoingBytes.set(oldBytes, 0);
- if (DEBUG) {
- debug("New outgoing buffer size is " + this.outgoingBufferLength);
- }
- },
-
- /**
- * Functions for reading data from the incoming buffer.
- *
- * These are all little endian, apart from readParcelSize();
- */
-
- /**
- * Ensure position specified is readable.
- *
- * @param index
- * Data position in incoming parcel, valid from 0 to
- * currentParcelSize.
- */
- ensureIncomingAvailable: function(index) {
- if (index >= this.currentParcelSize) {
- throw new Error("Trying to read data beyond the parcel end!");
- } else if (index < 0) {
- throw new Error("Trying to read data before the parcel begin!");
- }
- },
-
- /**
- * Seek in current incoming parcel.
- *
- * @param offset
- * Seek offset in relative to current position.
- */
- seekIncoming: function(offset) {
- // Translate to 0..currentParcelSize
- let cur = this.currentParcelSize - this.readAvailable;
-
- let newIndex = cur + offset;
- this.ensureIncomingAvailable(newIndex);
-
- // ... incomingReadIndex -->|
- // 0 new cur currentParcelSize
- // |================|=======|====================|
- // |<-- cur -->|<- readAvailable ->|
- // |<-- newIndex -->|<-- new readAvailable -->|
- this.readAvailable = this.currentParcelSize - newIndex;
-
- // Translate back:
- if (this.incomingReadIndex < cur) {
- // The incomingReadIndex is wrapped.
- newIndex += this.incomingBufferLength;
- }
- newIndex += (this.incomingReadIndex - cur);
- newIndex %= this.incomingBufferLength;
- this.incomingReadIndex = newIndex;
- },
-
- readUint8Unchecked: function() {
- let value = this.incomingBytes[this.incomingReadIndex];
- this.incomingReadIndex = (this.incomingReadIndex + 1) %
- this.incomingBufferLength;
- return value;
- },
-
- readUint8: function() {
- // Translate to 0..currentParcelSize
- let cur = this.currentParcelSize - this.readAvailable;
- this.ensureIncomingAvailable(cur);
-
- this.readAvailable--;
- return this.readUint8Unchecked();
- },
-
- readUint8Array: function(length) {
- // Translate to 0..currentParcelSize
- let last = this.currentParcelSize - this.readAvailable;
- last += (length - 1);
- this.ensureIncomingAvailable(last);
-
- let array = new Uint8Array(length);
- for (let i = 0; i < length; i++) {
- array[i] = this.readUint8Unchecked();
- }
-
- this.readAvailable -= length;
- return array;
- },
-
- readUint16: function() {
- return this.readUint8() | this.readUint8() << 8;
- },
-
- readInt32: function() {
- return this.readUint8() | this.readUint8() << 8 |
- this.readUint8() << 16 | this.readUint8() << 24;
- },
-
- readInt64: function() {
- // Avoid using bitwise operators as the operands of all bitwise operators
- // are converted to signed 32-bit integers.
- return this.readUint8() +
- this.readUint8() * Math.pow(2, 8) +
- this.readUint8() * Math.pow(2, 16) +
- this.readUint8() * Math.pow(2, 24) +
- this.readUint8() * Math.pow(2, 32) +
- this.readUint8() * Math.pow(2, 40) +
- this.readUint8() * Math.pow(2, 48) +
- this.readUint8() * Math.pow(2, 56);
- },
-
- readInt32List: function() {
- let length = this.readInt32();
- let ints = [];
- for (let i = 0; i < length; i++) {
- ints.push(this.readInt32());
- }
- return ints;
- },
-
- readString: function() {
- let string_len = this.readInt32();
- if (string_len < 0 || string_len >= this.INT32_MAX) {
- return null;
- }
- let s = "";
- for (let i = 0; i < string_len; i++) {
- s += String.fromCharCode(this.readUint16());
- }
- // Strings are \0\0 delimited, but that isn't part of the length. And
- // if the string length is even, the delimiter is two characters wide.
- // It's insane, I know.
- this.readStringDelimiter(string_len);
- return s;
- },
-
- readStringList: function() {
- let num_strings = this.readInt32();
- let strings = [];
- for (let i = 0; i < num_strings; i++) {
- strings.push(this.readString());
- }
- return strings;
- },
-
- readStringDelimiter: function(length) {
- let delimiter = this.readUint16();
- if (!(length & 1)) {
- delimiter |= this.readUint16();
- }
- if (DEBUG) {
- if (delimiter !== 0) {
- debug("Something's wrong, found string delimiter: " + delimiter);
- }
- }
- },
-
- readParcelSize: function() {
- return this.readUint8Unchecked() << 24 |
- this.readUint8Unchecked() << 16 |
- this.readUint8Unchecked() << 8 |
- this.readUint8Unchecked();
- },
-
- /**
- * Functions for writing data to the outgoing buffer.
- */
-
- /**
- * Ensure position specified is writable.
- *
- * @param index
- * Data position in outgoing parcel, valid from 0 to
- * outgoingBufferLength.
- */
- ensureOutgoingAvailable: function(index) {
- if (index >= this.outgoingBufferLength) {
- this.growOutgoingBuffer(index + 1);
- }
- },
-
- writeUint8: function(value) {
- this.ensureOutgoingAvailable(this.outgoingIndex);
-
- this.outgoingBytes[this.outgoingIndex] = value;
- this.outgoingIndex++;
- },
-
- writeUint16: function(value) {
- this.writeUint8(value & 0xff);
- this.writeUint8((value >> 8) & 0xff);
- },
-
- writeInt32: function(value) {
- this.writeUint8(value & 0xff);
- this.writeUint8((value >> 8) & 0xff);
- this.writeUint8((value >> 16) & 0xff);
- this.writeUint8((value >> 24) & 0xff);
- },
-
- writeString: function(value) {
- if (value == null) {
- this.writeInt32(-1);
- return;
- }
- this.writeInt32(value.length);
- for (let i = 0; i < value.length; i++) {
- this.writeUint16(value.charCodeAt(i));
- }
- // Strings are \0\0 delimited, but that isn't part of the length. And
- // if the string length is even, the delimiter is two characters wide.
- // It's insane, I know.
- this.writeStringDelimiter(value.length);
- },
-
- writeStringList: function(strings) {
- this.writeInt32(strings.length);
- for (let i = 0; i < strings.length; i++) {
- this.writeString(strings[i]);
- }
- },
-
- writeStringDelimiter: function(length) {
- this.writeUint16(0);
- if (!(length & 1)) {
- this.writeUint16(0);
- }
- },
-
- writeParcelSize: function(value) {
- /**
- * Parcel size will always be the first thing in the parcel byte
- * array, but the last thing written. Store the current index off
- * to a temporary to be reset after we write the size.
- */
- let currentIndex = this.outgoingIndex;
- this.outgoingIndex = 0;
- this.writeUint8((value >> 24) & 0xff);
- this.writeUint8((value >> 16) & 0xff);
- this.writeUint8((value >> 8) & 0xff);
- this.writeUint8(value & 0xff);
- this.outgoingIndex = currentIndex;
- },
-
- copyIncomingToOutgoing: function(length) {
- if (!length || (length < 0)) {
- return;
- }
-
- let translatedReadIndexEnd =
- this.currentParcelSize - this.readAvailable + length - 1;
- this.ensureIncomingAvailable(translatedReadIndexEnd);
-
- let translatedWriteIndexEnd = this.outgoingIndex + length - 1;
- this.ensureOutgoingAvailable(translatedWriteIndexEnd);
-
- let newIncomingReadIndex = this.incomingReadIndex + length;
- if (newIncomingReadIndex < this.incomingBufferLength) {
- // Reading won't cause wrapping, go ahead with builtin copy.
- this.outgoingBytes
- .set(this.incomingBytes.subarray(this.incomingReadIndex,
- newIncomingReadIndex),
- this.outgoingIndex);
- } else {
- // Not so lucky.
- newIncomingReadIndex %= this.incomingBufferLength;
- this.outgoingBytes
- .set(this.incomingBytes.subarray(this.incomingReadIndex,
- this.incomingBufferLength),
- this.outgoingIndex);
- if (newIncomingReadIndex) {
- let firstPartLength = this.incomingBufferLength - this.incomingReadIndex;
- this.outgoingBytes.set(this.incomingBytes.subarray(0, newIncomingReadIndex),
- this.outgoingIndex + firstPartLength);
- }
- }
-
- this.incomingReadIndex = newIncomingReadIndex;
- this.readAvailable -= length;
- this.outgoingIndex += length;
- },
-
- /**
- * Parcel management
- */
-
- /**
- * Write incoming data to the circular buffer.
- *
- * @param incoming
- * Uint8Array containing the incoming data.
- */
- writeToIncoming: function(incoming) {
- // We don't have to worry about the head catching the tail since
- // we process any backlog in parcels immediately, before writing
- // new data to the buffer. So the only edge case we need to handle
- // is when the incoming data is larger than the buffer size.
- let minMustAvailableSize = incoming.length + this.readIncoming;
- if (minMustAvailableSize > this.incomingBufferLength) {
- this.growIncomingBuffer(minMustAvailableSize);
- }
-
- // We can let the typed arrays do the copying if the incoming data won't
- // wrap around the edges of the circular buffer.
- let remaining = this.incomingBufferLength - this.incomingWriteIndex;
- if (remaining >= incoming.length) {
- this.incomingBytes.set(incoming, this.incomingWriteIndex);
- } else {
- // The incoming data would wrap around it.
- let head = incoming.subarray(0, remaining);
- let tail = incoming.subarray(remaining);
- this.incomingBytes.set(head, this.incomingWriteIndex);
- this.incomingBytes.set(tail, 0);
- }
- this.incomingWriteIndex = (this.incomingWriteIndex + incoming.length) %
- this.incomingBufferLength;
- },
-
- /**
- * Process incoming data.
- *
- * @param incoming
- * Uint8Array containing the incoming data.
- */
- processIncoming: function(incoming) {
- if (DEBUG) {
- debug("Received " + incoming.length + " bytes.");
- debug("Already read " + this.readIncoming);
- }
-
- this.writeToIncoming(incoming);
- this.readIncoming += incoming.length;
- while (true) {
- if (!this.currentParcelSize) {
- // We're expecting a new parcel.
- if (this.readIncoming < this.PARCEL_SIZE_SIZE) {
- // We don't know how big the next parcel is going to be, need more
- // data.
- if (DEBUG) debug("Next parcel size unknown, going to sleep.");
- return;
- }
- this.currentParcelSize = this.readParcelSize();
- if (DEBUG) {
- debug("New incoming parcel of size " + this.currentParcelSize);
- }
- // The size itself is not included in the size.
- this.readIncoming -= this.PARCEL_SIZE_SIZE;
- }
-
- if (this.readIncoming < this.currentParcelSize) {
- // We haven't read enough yet in order to be able to process a parcel.
- if (DEBUG) debug("Read " + this.readIncoming + ", but parcel size is "
- + this.currentParcelSize + ". Going to sleep.");
- return;
- }
-
- // Alright, we have enough data to process at least one whole parcel.
- // Let's do that.
- let expectedAfterIndex = (this.incomingReadIndex + this.currentParcelSize)
- % this.incomingBufferLength;
-
- if (DEBUG) {
- let parcel;
- if (expectedAfterIndex < this.incomingReadIndex) {
- let head = this.incomingBytes.subarray(this.incomingReadIndex);
- let tail = this.incomingBytes.subarray(0, expectedAfterIndex);
- parcel = Array.slice(head).concat(Array.slice(tail));
- } else {
- parcel = Array.slice(this.incomingBytes.subarray(
- this.incomingReadIndex, expectedAfterIndex));
- }
- debug("Parcel (size " + this.currentParcelSize + "): " + parcel);
- }
-
- if (DEBUG) debug("We have at least one complete parcel.");
- try {
- this.readAvailable = this.currentParcelSize;
- this.processParcel();
- } catch (ex) {
- if (DEBUG) debug("Parcel handling threw " + ex + "\n" + ex.stack);
- }
-
- // Ensure that the whole parcel was consumed.
- if (this.incomingReadIndex != expectedAfterIndex) {
- if (DEBUG) {
- debug("Parcel handler didn't consume whole parcel, " +
- Math.abs(expectedAfterIndex - this.incomingReadIndex) +
- " bytes left over");
- }
- this.incomingReadIndex = expectedAfterIndex;
- }
- this.readIncoming -= this.currentParcelSize;
- this.readAvailable = 0;
- this.currentParcelSize = 0;
- }
- },
-
- /**
- * Communicate with the IPC thread.
- */
- sendParcel: function() {
- // Compute the size of the parcel and write it to the front of the parcel
- // where we left room for it. Note that he parcel size does not include
- // the size itself.
- let parcelSize = this.outgoingIndex - this.PARCEL_SIZE_SIZE;
- this.writeParcelSize(parcelSize);
-
- // This assumes that postRILMessage will make a copy of the ArrayBufferView
- // right away!
- let parcel = this.outgoingBytes.subarray(0, this.outgoingIndex);
- if (DEBUG) debug("Outgoing parcel: " + Array.slice(parcel));
- this.onSendParcel(parcel);
- this.outgoingIndex = this.PARCEL_SIZE_SIZE;
- },
-
- getCurrentParcelSize: function() {
- return this.currentParcelSize;
- },
-
- getReadAvailable: function() {
- return this.readAvailable;
- }
-
- /**
- * Process one parcel.
- *
- * |processParcel| is an implementation provided incoming parcel processing
- * function invoked when we have received a complete parcel. Implementation
- * may call multiple read functions to extract data from the incoming buffer.
- */
- //processParcel: function() {
- // let something = this.readInt32();
- // ...
- //},
-
- /**
- * Write raw data out to underlying channel.
- *
- * |onSendParcel| is an implementation provided stream output function
- * invoked when we're really going to write something out. We assume the
- * data are completely copied to some output buffer in this call and may
- * be destroyed when it's done.
- *
- * @param parcel
- * An array of numeric octet data.
- */
- //onSendParcel: function(parcel) {
- // ...
- //}
-};
-
-module.exports = { Buf: Buf };
diff --git a/dom/system/moz.build b/dom/system/moz.build
index 3cff531b5..fc8cf533b 100644
--- a/dom/system/moz.build
+++ b/dom/system/moz.build
@@ -12,8 +12,6 @@ elif toolkit == 'cocoa':
DIRS += ['mac']
elif toolkit == 'android':
DIRS += ['android']
-elif toolkit == 'gonk':
- DIRS += ['gonk']
elif toolkit in ('gtk2', 'gtk3'):
DIRS += ['linux']
diff --git a/hal/gonk/GonkDiskSpaceWatcher.cpp b/hal/gonk/GonkDiskSpaceWatcher.cpp
deleted file mode 100644
index cdc48ef89..000000000
--- a/hal/gonk/GonkDiskSpaceWatcher.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "Hal.h"
-#include <sys/syscall.h>
-#include <sys/vfs.h>
-#include <fcntl.h>
-#include <errno.h>
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "DiskSpaceWatcher.h"
-#include "fanotify.h"
-#include "nsIObserverService.h"
-#include "nsIDiskSpaceWatcher.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-#include "mozilla/ModuleUtils.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Services.h"
-
-using namespace mozilla;
-
-namespace mozilla { namespace hal_impl { class GonkDiskSpaceWatcher; } }
-
-using namespace mozilla::hal_impl;
-
-namespace mozilla {
-namespace hal_impl {
-
-// NOTE: this should be unnecessary once we no longer support ICS.
-#ifndef __NR_fanotify_init
-#if defined(__ARM_EABI__)
-#define __NR_fanotify_init 367
-#define __NR_fanotify_mark 368
-#elif defined(__i386__)
-#define __NR_fanotify_init 338
-#define __NR_fanotify_mark 339
-#else
-#error "Unhandled architecture"
-#endif
-#endif
-
-// fanotify_init and fanotify_mark functions are syscalls.
-// The user space bits are not part of bionic so we add them here
-// as well as fanotify.h
-int fanotify_init (unsigned int flags, unsigned int event_f_flags)
-{
- return syscall(__NR_fanotify_init, flags, event_f_flags);
-}
-
-// Add, remove, or modify an fanotify mark on a filesystem object.
-int fanotify_mark (int fanotify_fd, unsigned int flags,
- uint64_t mask, int dfd, const char *pathname)
-{
-
- // On 32 bits platforms we have to convert the 64 bits mask into
- // two 32 bits ints.
- if (sizeof(void *) == 4) {
- union {
- uint64_t _64;
- uint32_t _32[2];
- } _mask;
- _mask._64 = mask;
- return syscall(__NR_fanotify_mark, fanotify_fd, flags,
- _mask._32[0], _mask._32[1], dfd, pathname);
- }
-
- return syscall(__NR_fanotify_mark, fanotify_fd, flags, mask, dfd, pathname);
-}
-
-class GonkDiskSpaceWatcher final : public MessageLoopForIO::Watcher
-{
-public:
- GonkDiskSpaceWatcher();
- ~GonkDiskSpaceWatcher() {};
-
- virtual void OnFileCanReadWithoutBlocking(int aFd);
-
- // We should never write to the fanotify fd.
- virtual void OnFileCanWriteWithoutBlocking(int aFd)
- {
- MOZ_CRASH("Must not write to fanotify fd");
- }
-
- void DoStart();
- void DoStop();
-
-private:
- void NotifyUpdate();
-
- uint64_t mLowThreshold;
- uint64_t mHighThreshold;
- TimeDuration mTimeout;
- TimeStamp mLastTimestamp;
- uint64_t mLastFreeSpace;
- uint32_t mSizeDelta;
-
- bool mIsDiskFull;
- uint64_t mFreeSpace;
-
- int mFd;
- MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
-};
-
-static GonkDiskSpaceWatcher* gHalDiskSpaceWatcher = nullptr;
-
-#define WATCHER_PREF_LOW "disk_space_watcher.low_threshold"
-#define WATCHER_PREF_HIGH "disk_space_watcher.high_threshold"
-#define WATCHER_PREF_TIMEOUT "disk_space_watcher.timeout"
-#define WATCHER_PREF_SIZE_DELTA "disk_space_watcher.size_delta"
-
-static const char kWatchedPath[] = "/data";
-
-// Helper class to dispatch calls to xpcom on the main thread.
-class DiskSpaceNotifier : public Runnable
-{
-public:
- DiskSpaceNotifier(const bool aIsDiskFull, const uint64_t aFreeSpace) :
- mIsDiskFull(aIsDiskFull),
- mFreeSpace(aFreeSpace) {}
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- DiskSpaceWatcher::UpdateState(mIsDiskFull, mFreeSpace);
- return NS_OK;
- }
-
-private:
- bool mIsDiskFull;
- uint64_t mFreeSpace;
-};
-
-// Helper runnable to delete the watcher on the main thread.
-class DiskSpaceCleaner : public Runnable
-{
-public:
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- if (gHalDiskSpaceWatcher) {
- delete gHalDiskSpaceWatcher;
- gHalDiskSpaceWatcher = nullptr;
- }
- return NS_OK;
- }
-};
-
-GonkDiskSpaceWatcher::GonkDiskSpaceWatcher() :
- mLastFreeSpace(UINT64_MAX),
- mIsDiskFull(false),
- mFreeSpace(UINT64_MAX),
- mFd(-1)
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(gHalDiskSpaceWatcher == nullptr);
-
- // Default values: 5MB for low threshold, 10MB for high threshold, and
- // a timeout of 5 seconds.
- mLowThreshold = Preferences::GetInt(WATCHER_PREF_LOW, 5) * 1024 * 1024;
- mHighThreshold = Preferences::GetInt(WATCHER_PREF_HIGH, 10) * 1024 * 1024;
- mTimeout = TimeDuration::FromSeconds(Preferences::GetInt(WATCHER_PREF_TIMEOUT, 5));
- mSizeDelta = Preferences::GetInt(WATCHER_PREF_SIZE_DELTA, 1) * 1024 * 1024;
-}
-
-void
-GonkDiskSpaceWatcher::DoStart()
-{
- NS_ASSERTION(XRE_GetIOMessageLoop() == MessageLoopForIO::current(),
- "Not on the correct message loop");
-
- mFd = fanotify_init(FAN_CLASS_NOTIF, FAN_CLOEXEC | O_LARGEFILE);
- if (mFd == -1) {
- if (errno == ENOSYS) {
- // Don't change these printf_stderr since we need these logs even
- // in opt builds.
- printf_stderr("Warning: No fanotify support in this device's kernel.\n");
-#if ANDROID_VERSION >= 19
- MOZ_CRASH("Fanotify support must be enabled in the kernel.");
-#endif
- } else {
- printf_stderr("Error calling fanotify_init()");
- }
- return;
- }
-
- if (fanotify_mark(mFd, FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_CLOSE,
- 0, kWatchedPath) < 0) {
- NS_WARNING("Error calling fanotify_mark");
- close(mFd);
- mFd = -1;
- return;
- }
-
- if (!MessageLoopForIO::current()->WatchFileDescriptor(
- mFd, /* persistent = */ true,
- MessageLoopForIO::WATCH_READ,
- &mReadWatcher, gHalDiskSpaceWatcher)) {
- NS_WARNING("Unable to watch fanotify fd.");
- close(mFd);
- mFd = -1;
- }
-}
-
-void
-GonkDiskSpaceWatcher::DoStop()
-{
- NS_ASSERTION(XRE_GetIOMessageLoop() == MessageLoopForIO::current(),
- "Not on the correct message loop");
-
- if (mFd != -1) {
- mReadWatcher.StopWatchingFileDescriptor();
- fanotify_mark(mFd, FAN_MARK_FLUSH, 0, 0, kWatchedPath);
- close(mFd);
- mFd = -1;
- }
-
- // Dispatch the cleanup to the main thread.
- nsCOMPtr<nsIRunnable> runnable = new DiskSpaceCleaner();
- NS_DispatchToMainThread(runnable);
-}
-
-// We are called off the main thread, so we proxy first to the main thread
-// before calling the xpcom object.
-void
-GonkDiskSpaceWatcher::NotifyUpdate()
-{
- mLastTimestamp = TimeStamp::Now();
- mLastFreeSpace = mFreeSpace;
-
- nsCOMPtr<nsIRunnable> runnable =
- new DiskSpaceNotifier(mIsDiskFull, mFreeSpace);
- NS_DispatchToMainThread(runnable);
-}
-
-void
-GonkDiskSpaceWatcher::OnFileCanReadWithoutBlocking(int aFd)
-{
- struct fanotify_event_metadata* fem = nullptr;
- char buf[4096];
- struct statfs sfs;
- int32_t len, rc;
-
- do {
- len = read(aFd, buf, sizeof(buf));
- } while(len == -1 && errno == EINTR);
-
- // Bail out if the file is busy.
- if (len < 0 && errno == ETXTBSY) {
- return;
- }
-
- // We should get an exact multiple of fanotify_event_metadata
- if (len <= 0 || (len % FAN_EVENT_METADATA_LEN != 0)) {
- MOZ_CRASH("About to crash: fanotify_event_metadata read error.");
- }
-
- fem = reinterpret_cast<fanotify_event_metadata *>(buf);
-
- while (FAN_EVENT_OK(fem, len)) {
- rc = fstatfs(fem->fd, &sfs);
- if (rc < 0) {
- NS_WARNING("Unable to stat fan_notify fd");
- } else {
- bool firstRun = mFreeSpace == UINT64_MAX;
- mFreeSpace = sfs.f_bavail * sfs.f_bsize;
- // We change from full <-> free depending on the free space and the
- // low and high thresholds.
- // Once we are in 'full' mode we send updates for all size changes with
- // a minimum of time between messages or when we cross a size change
- // threshold.
- if (firstRun) {
- mIsDiskFull = mFreeSpace <= mLowThreshold;
- // Always notify the current state at first run.
- NotifyUpdate();
- } else if (!mIsDiskFull && (mFreeSpace <= mLowThreshold)) {
- mIsDiskFull = true;
- NotifyUpdate();
- } else if (mIsDiskFull && (mFreeSpace > mHighThreshold)) {
- mIsDiskFull = false;
- NotifyUpdate();
- } else if (mIsDiskFull) {
- if (mTimeout < TimeStamp::Now() - mLastTimestamp ||
- mSizeDelta < llabs(mFreeSpace - mLastFreeSpace)) {
- NotifyUpdate();
- }
- }
- }
- close(fem->fd);
- fem = FAN_EVENT_NEXT(fem, len);
- }
-}
-
-void
-StartDiskSpaceWatcher()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- // Bail out if called several times.
- if (gHalDiskSpaceWatcher != nullptr) {
- return;
- }
-
- gHalDiskSpaceWatcher = new GonkDiskSpaceWatcher();
-
- XRE_GetIOMessageLoop()->PostTask(
- NewNonOwningRunnableMethod(gHalDiskSpaceWatcher, &GonkDiskSpaceWatcher::DoStart));
-}
-
-void
-StopDiskSpaceWatcher()
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (!gHalDiskSpaceWatcher) {
- return;
- }
-
- XRE_GetIOMessageLoop()->PostTask(
- NewNonOwningRunnableMethod(gHalDiskSpaceWatcher, &GonkDiskSpaceWatcher::DoStop));
-}
-
-} // namespace hal_impl
-} // namespace mozilla
diff --git a/hal/gonk/GonkHal.cpp b/hal/gonk/GonkHal.cpp
deleted file mode 100644
index 05d9295a2..000000000
--- a/hal/gonk/GonkHal.cpp
+++ /dev/null
@@ -1,2045 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=8 et ft=cpp : */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/android_alarm.h>
-#include <math.h>
-#include <regex.h>
-#include <sched.h>
-#include <stdio.h>
-#include <sys/klog.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/resource.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "mozilla/DebugOnly.h"
-
-#include "android/log.h"
-#include "cutils/properties.h"
-#include "hardware/hardware.h"
-#include "hardware/lights.h"
-#include "hardware_legacy/uevent.h"
-#include "hardware_legacy/vibrator.h"
-#include "hardware_legacy/power.h"
-#include "libdisplay/GonkDisplay.h"
-#include "utils/threads.h"
-
-#include "base/message_loop.h"
-#include "base/task.h"
-
-#include "Hal.h"
-#include "HalImpl.h"
-#include "HalLog.h"
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/dom/battery/Constants.h"
-#include "mozilla/DebugOnly.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/Monitor.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticMutex.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/UniquePtrExtensions.h"
-#include "nsAlgorithm.h"
-#include "nsPrintfCString.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsIRecoveryService.h"
-#include "nsIRunnable.h"
-#include "nsScreenManagerGonk.h"
-#include "nsThreadUtils.h"
-#include "nsThreadUtils.h"
-#include "nsIThread.h"
-#include "nsXULAppAPI.h"
-#include "OrientationObserver.h"
-#include "UeventPoller.h"
-#include "nsIWritablePropertyBag2.h"
-#include <algorithm>
-
-#define NsecPerMsec 1000000LL
-#define NsecPerSec 1000000000
-
-// The header linux/oom.h is not available in bionic libc. We
-// redefine some of its constants here.
-
-#ifndef OOM_DISABLE
-#define OOM_DISABLE (-17)
-#endif
-
-#ifndef OOM_ADJUST_MIN
-#define OOM_ADJUST_MIN (-16)
-#endif
-
-#ifndef OOM_ADJUST_MAX
-#define OOM_ADJUST_MAX 15
-#endif
-
-#ifndef OOM_SCORE_ADJ_MIN
-#define OOM_SCORE_ADJ_MIN (-1000)
-#endif
-
-#ifndef OOM_SCORE_ADJ_MAX
-#define OOM_SCORE_ADJ_MAX 1000
-#endif
-
-#ifndef BATTERY_CHARGING_ARGB
-#define BATTERY_CHARGING_ARGB 0x00FF0000
-#endif
-#ifndef BATTERY_FULL_ARGB
-#define BATTERY_FULL_ARGB 0x0000FF00
-#endif
-
-using namespace mozilla;
-using namespace mozilla::hal;
-using namespace mozilla::dom;
-
-namespace mozilla {
-namespace hal_impl {
-
-/**
- * These are defined by libhardware, specifically, hardware/libhardware/include/hardware/lights.h
- * in the gonk subsystem.
- * If these change and are exposed to JS, make sure nsIHal.idl is updated as well.
- */
-enum LightType {
- eHalLightID_Backlight = 0,
- eHalLightID_Keyboard = 1,
- eHalLightID_Buttons = 2,
- eHalLightID_Battery = 3,
- eHalLightID_Notifications = 4,
- eHalLightID_Attention = 5,
- eHalLightID_Bluetooth = 6,
- eHalLightID_Wifi = 7,
- eHalLightID_Count // This should stay at the end
-};
-enum LightMode {
- eHalLightMode_User = 0, // brightness is managed by user setting
- eHalLightMode_Sensor = 1, // brightness is managed by a light sensor
- eHalLightMode_Count
-};
-enum FlashMode {
- eHalLightFlash_None = 0,
- eHalLightFlash_Timed = 1, // timed flashing. Use flashOnMS and flashOffMS for timing
- eHalLightFlash_Hardware = 2, // hardware assisted flashing
- eHalLightFlash_Count
-};
-
-struct LightConfiguration {
- LightType light;
- LightMode mode;
- FlashMode flash;
- uint32_t flashOnMS;
- uint32_t flashOffMS;
- uint32_t color;
-};
-
-static light_device_t* sLights[eHalLightID_Count]; // will be initialized to nullptr
-
-static light_device_t*
-GetDevice(hw_module_t* module, char const* name)
-{
- int err;
- hw_device_t* device;
- err = module->methods->open(module, name, &device);
- if (err == 0) {
- return (light_device_t*)device;
- } else {
- return nullptr;
- }
-}
-
-static void
-InitLights()
-{
- // assume that if backlight is nullptr, nothing has been set yet
- // if this is not true, the initialization will occur everytime a light is read or set!
- if (!sLights[eHalLightID_Backlight]) {
- int err;
- hw_module_t* module;
-
- err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
- if (err == 0) {
- sLights[eHalLightID_Backlight]
- = GetDevice(module, LIGHT_ID_BACKLIGHT);
- sLights[eHalLightID_Keyboard]
- = GetDevice(module, LIGHT_ID_KEYBOARD);
- sLights[eHalLightID_Buttons]
- = GetDevice(module, LIGHT_ID_BUTTONS);
- sLights[eHalLightID_Battery]
- = GetDevice(module, LIGHT_ID_BATTERY);
- sLights[eHalLightID_Notifications]
- = GetDevice(module, LIGHT_ID_NOTIFICATIONS);
- sLights[eHalLightID_Attention]
- = GetDevice(module, LIGHT_ID_ATTENTION);
- sLights[eHalLightID_Bluetooth]
- = GetDevice(module, LIGHT_ID_BLUETOOTH);
- sLights[eHalLightID_Wifi]
- = GetDevice(module, LIGHT_ID_WIFI);
- }
- }
-}
-
-/**
- * The state last set for the lights until liblights supports
- * getting the light state.
- */
-static light_state_t sStoredLightState[eHalLightID_Count];
-
-/**
-* Set the value of a light to a particular color, with a specific flash pattern.
-* light specifices which light. See Hal.idl for the list of constants
-* mode specifies user set or based on ambient light sensor
-* flash specifies whether or how to flash the light
-* flashOnMS and flashOffMS specify the pattern for XXX flash mode
-* color specifies the color. If the light doesn't support color, the given color is
-* transformed into a brightness, or just an on/off if that is all the light is capable of.
-* returns true if successful and false if failed.
-*/
-static bool
-SetLight(LightType light, const LightConfiguration& aConfig)
-{
- light_state_t state;
-
- InitLights();
-
- if (light < 0 || light >= eHalLightID_Count ||
- sLights[light] == nullptr) {
- return false;
- }
-
- memset(&state, 0, sizeof(light_state_t));
- state.color = aConfig.color;
- state.flashMode = aConfig.flash;
- state.flashOnMS = aConfig.flashOnMS;
- state.flashOffMS = aConfig.flashOffMS;
- state.brightnessMode = aConfig.mode;
-
- sLights[light]->set_light(sLights[light], &state);
- sStoredLightState[light] = state;
- return true;
-}
-
-/**
-* GET the value of a light returning a particular color, with a specific flash pattern.
-* returns true if successful and false if failed.
-*/
-static bool
-GetLight(LightType light, LightConfiguration* aConfig)
-{
- light_state_t state;
-
- if (light < 0 || light >= eHalLightID_Count ||
- sLights[light] == nullptr) {
- return false;
- }
-
- memset(&state, 0, sizeof(light_state_t));
- state = sStoredLightState[light];
-
- aConfig->light = light;
- aConfig->color = state.color;
- aConfig->flash = FlashMode(state.flashMode);
- aConfig->flashOnMS = state.flashOnMS;
- aConfig->flashOffMS = state.flashOffMS;
- aConfig->mode = LightMode(state.brightnessMode);
-
- return true;
-}
-
-namespace {
-
-/**
- * This runnable runs for the lifetime of the program, once started. It's
- * responsible for "playing" vibration patterns.
- */
-class VibratorRunnable final
- : public nsIRunnable
- , public nsIObserver
-{
-public:
- VibratorRunnable()
- : mMonitor("VibratorRunnable")
- , mIndex(0)
- {
- nsCOMPtr<nsIObserverService> os = services::GetObserverService();
- if (!os) {
- NS_WARNING("Could not get observer service!");
- return;
- }
-
- os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
- }
-
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIRUNNABLE
- NS_DECL_NSIOBSERVER
-
- // Run on the main thread, not the vibrator thread.
- void Vibrate(const nsTArray<uint32_t> &pattern);
- void CancelVibrate();
-
- static bool ShuttingDown() { return sShuttingDown; }
-
-protected:
- ~VibratorRunnable() {}
-
-private:
- Monitor mMonitor;
-
- // The currently-playing pattern.
- nsTArray<uint32_t> mPattern;
-
- // The index we're at in the currently-playing pattern. If mIndex >=
- // mPattern.Length(), then we're not currently playing anything.
- uint32_t mIndex;
-
- // Set to true in our shutdown observer. When this is true, we kill the
- // vibrator thread.
- static bool sShuttingDown;
-};
-
-NS_IMPL_ISUPPORTS(VibratorRunnable, nsIRunnable, nsIObserver);
-
-bool VibratorRunnable::sShuttingDown = false;
-
-static StaticRefPtr<VibratorRunnable> sVibratorRunnable;
-
-NS_IMETHODIMP
-VibratorRunnable::Run()
-{
- MonitorAutoLock lock(mMonitor);
-
- // We currently assume that mMonitor.Wait(X) waits for X milliseconds. But in
- // reality, the kernel might not switch to this thread for some time after the
- // wait expires. So there's potential for some inaccuracy here.
- //
- // This doesn't worry me too much. Note that we don't even start vibrating
- // immediately when VibratorRunnable::Vibrate is called -- we go through a
- // condvar onto another thread. Better just to be chill about small errors in
- // the timing here.
-
- while (!sShuttingDown) {
- if (mIndex < mPattern.Length()) {
- uint32_t duration = mPattern[mIndex];
- if (mIndex % 2 == 0) {
- vibrator_on(duration);
- }
- mIndex++;
- mMonitor.Wait(PR_MillisecondsToInterval(duration));
- }
- else {
- mMonitor.Wait();
- }
- }
- sVibratorRunnable = nullptr;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-VibratorRunnable::Observe(nsISupports *subject, const char *topic,
- const char16_t *data)
-{
- MOZ_ASSERT(strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
- MonitorAutoLock lock(mMonitor);
- sShuttingDown = true;
- mMonitor.Notify();
-
- return NS_OK;
-}
-
-void
-VibratorRunnable::Vibrate(const nsTArray<uint32_t> &pattern)
-{
- MonitorAutoLock lock(mMonitor);
- mPattern = pattern;
- mIndex = 0;
- mMonitor.Notify();
-}
-
-void
-VibratorRunnable::CancelVibrate()
-{
- MonitorAutoLock lock(mMonitor);
- mPattern.Clear();
- mPattern.AppendElement(0);
- mIndex = 0;
- mMonitor.Notify();
-}
-
-void
-EnsureVibratorThreadInitialized()
-{
- if (sVibratorRunnable) {
- return;
- }
-
- sVibratorRunnable = new VibratorRunnable();
- nsCOMPtr<nsIThread> thread;
- NS_NewThread(getter_AddRefs(thread), sVibratorRunnable);
-}
-
-} // namespace
-
-void
-Vibrate(const nsTArray<uint32_t> &pattern, const hal::WindowIdentifier &)
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (VibratorRunnable::ShuttingDown()) {
- return;
- }
- EnsureVibratorThreadInitialized();
- sVibratorRunnable->Vibrate(pattern);
-}
-
-void
-CancelVibrate(const hal::WindowIdentifier &)
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (VibratorRunnable::ShuttingDown()) {
- return;
- }
- EnsureVibratorThreadInitialized();
- sVibratorRunnable->CancelVibrate();
-}
-
-namespace {
-
-class BatteryUpdater : public Runnable {
-public:
- NS_IMETHOD Run() override
- {
- hal::BatteryInformation info;
- hal_impl::GetCurrentBatteryInformation(&info);
-
- // Control the battery indicator (led light) here using BatteryInformation
- // we just retrieved.
- uint32_t color = 0; // Format: 0x00rrggbb.
- if (info.charging() && (info.level() == 1)) {
- // Charging and battery full.
- color = BATTERY_FULL_ARGB;
- } else if (info.charging() && (info.level() < 1)) {
- // Charging but not full.
- color = BATTERY_CHARGING_ARGB;
- } // else turn off battery indicator.
-
- LightConfiguration aConfig;
- aConfig.light = eHalLightID_Battery;
- aConfig.mode = eHalLightMode_User;
- aConfig.flash = eHalLightFlash_None;
- aConfig.flashOnMS = aConfig.flashOffMS = 0;
- aConfig.color = color;
-
- SetLight(eHalLightID_Battery, aConfig);
-
- hal::NotifyBatteryChange(info);
-
- {
- // bug 975667
- // Gecko gonk hal is required to emit battery charging/level notification via nsIObserverService.
- // This is useful for XPCOM components that are not statically linked to Gecko and cannot call
- // hal::EnableBatteryNotifications
- nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
- nsCOMPtr<nsIWritablePropertyBag2> propbag =
- do_CreateInstance("@mozilla.org/hash-property-bag;1");
- if (obsService && propbag) {
- propbag->SetPropertyAsBool(NS_LITERAL_STRING("charging"),
- info.charging());
- propbag->SetPropertyAsDouble(NS_LITERAL_STRING("level"),
- info.level());
-
- obsService->NotifyObservers(propbag, "gonkhal-battery-notifier", nullptr);
- }
- }
-
- return NS_OK;
- }
-};
-
-} // namespace
-
-class BatteryObserver final : public IUeventObserver
-{
-public:
- NS_INLINE_DECL_REFCOUNTING(BatteryObserver)
-
- BatteryObserver()
- :mUpdater(new BatteryUpdater())
- {
- }
-
- virtual void Notify(const NetlinkEvent &aEvent)
- {
- // this will run on IO thread
- NetlinkEvent *event = const_cast<NetlinkEvent*>(&aEvent);
- const char *subsystem = event->getSubsystem();
- // e.g. DEVPATH=/devices/platform/sec-battery/power_supply/battery
- const char *devpath = event->findParam("DEVPATH");
- if (strcmp(subsystem, "power_supply") == 0 &&
- strstr(devpath, "battery")) {
- // aEvent will be valid only in this method.
- NS_DispatchToMainThread(mUpdater);
- }
- }
-
-protected:
- ~BatteryObserver() {}
-
-private:
- RefPtr<BatteryUpdater> mUpdater;
-};
-
-// sBatteryObserver is owned by the IO thread. Only the IO thread may
-// create or destroy it.
-static StaticRefPtr<BatteryObserver> sBatteryObserver;
-
-static void
-RegisterBatteryObserverIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(!sBatteryObserver);
-
- sBatteryObserver = new BatteryObserver();
- RegisterUeventListener(sBatteryObserver);
-}
-
-void
-EnableBatteryNotifications()
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(RegisterBatteryObserverIOThread));
-}
-
-static void
-UnregisterBatteryObserverIOThread()
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- MOZ_ASSERT(sBatteryObserver);
-
- UnregisterUeventListener(sBatteryObserver);
- sBatteryObserver = nullptr;
-}
-
-void
-DisableBatteryNotifications()
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(UnregisterBatteryObserverIOThread));
-}
-
-static bool
-GetCurrentBatteryCharge(int* aCharge)
-{
- bool success = ReadSysFile("/sys/class/power_supply/battery/capacity",
- aCharge);
- if (!success) {
- return false;
- }
-
- #ifdef DEBUG
- if ((*aCharge < 0) || (*aCharge > 100)) {
- HAL_LOG("charge level contains unknown value: %d", *aCharge);
- }
- #endif
-
- return (*aCharge >= 0) && (*aCharge <= 100);
-}
-
-static bool
-GetCurrentBatteryCharging(int* aCharging)
-{
- static const DebugOnly<int> BATTERY_NOT_CHARGING = 0;
- static const int BATTERY_CHARGING_USB = 1;
- static const int BATTERY_CHARGING_AC = 2;
-
- // Generic device support
-
- int chargingSrc;
- bool success =
- ReadSysFile("/sys/class/power_supply/battery/charging_source", &chargingSrc);
-
- if (success) {
- #ifdef DEBUG
- if (chargingSrc != BATTERY_NOT_CHARGING &&
- chargingSrc != BATTERY_CHARGING_USB &&
- chargingSrc != BATTERY_CHARGING_AC) {
- HAL_LOG("charging_source contained unknown value: %d", chargingSrc);
- }
- #endif
-
- *aCharging = (chargingSrc == BATTERY_CHARGING_USB ||
- chargingSrc == BATTERY_CHARGING_AC);
- return true;
- }
-
- // Otoro device support
-
- char chargingSrcString[16];
-
- success = ReadSysFile("/sys/class/power_supply/battery/status",
- chargingSrcString, sizeof(chargingSrcString));
- if (success) {
- *aCharging = strcmp(chargingSrcString, "Charging") == 0 ||
- strcmp(chargingSrcString, "Full") == 0;
- return true;
- }
-
- return false;
-}
-
-void
-GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
-{
- int charge;
- static bool previousCharging = false;
- static double previousLevel = 0.0, remainingTime = 0.0;
- static struct timespec lastLevelChange;
- struct timespec now;
- double dtime, dlevel;
-
- if (GetCurrentBatteryCharge(&charge)) {
- aBatteryInfo->level() = (double)charge / 100.0;
- } else {
- aBatteryInfo->level() = dom::battery::kDefaultLevel;
- }
-
- int charging;
-
- if (GetCurrentBatteryCharging(&charging)) {
- aBatteryInfo->charging() = charging;
- } else {
- aBatteryInfo->charging() = true;
- }
-
- if (aBatteryInfo->charging() != previousCharging){
- aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
- memset(&lastLevelChange, 0, sizeof(struct timespec));
- remainingTime = 0.0;
- }
-
- if (aBatteryInfo->charging()) {
- if (aBatteryInfo->level() == 1.0) {
- aBatteryInfo->remainingTime() = dom::battery::kDefaultRemainingTime;
- } else if (aBatteryInfo->level() != previousLevel){
- if (lastLevelChange.tv_sec != 0) {
- clock_gettime(CLOCK_MONOTONIC, &now);
- dtime = now.tv_sec - lastLevelChange.tv_sec;
- dlevel = aBatteryInfo->level() - previousLevel;
-
- if (dlevel <= 0.0) {
- aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
- } else {
- remainingTime = (double) round(dtime / dlevel * (1.0 - aBatteryInfo->level()));
- aBatteryInfo->remainingTime() = remainingTime;
- }
-
- lastLevelChange = now;
- } else { // lastLevelChange.tv_sec == 0
- clock_gettime(CLOCK_MONOTONIC, &lastLevelChange);
- aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
- }
-
- } else {
- clock_gettime(CLOCK_MONOTONIC, &now);
- dtime = now.tv_sec - lastLevelChange.tv_sec;
- if (dtime < remainingTime) {
- aBatteryInfo->remainingTime() = round(remainingTime - dtime);
- } else {
- aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
- }
-
- }
-
- } else {
- if (aBatteryInfo->level() == 0.0) {
- aBatteryInfo->remainingTime() = dom::battery::kDefaultRemainingTime;
- } else if (aBatteryInfo->level() != previousLevel){
- if (lastLevelChange.tv_sec != 0) {
- clock_gettime(CLOCK_MONOTONIC, &now);
- dtime = now.tv_sec - lastLevelChange.tv_sec;
- dlevel = previousLevel - aBatteryInfo->level();
-
- if (dlevel <= 0.0) {
- aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
- } else {
- remainingTime = (double) round(dtime / dlevel * aBatteryInfo->level());
- aBatteryInfo->remainingTime() = remainingTime;
- }
-
- lastLevelChange = now;
- } else { // lastLevelChange.tv_sec == 0
- clock_gettime(CLOCK_MONOTONIC, &lastLevelChange);
- aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
- }
-
- } else {
- clock_gettime(CLOCK_MONOTONIC, &now);
- dtime = now.tv_sec - lastLevelChange.tv_sec;
- if (dtime < remainingTime) {
- aBatteryInfo->remainingTime() = round(remainingTime - dtime);
- } else {
- aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
- }
-
- }
- }
-
- previousCharging = aBatteryInfo->charging();
- previousLevel = aBatteryInfo->level();
-}
-
-namespace {
-
-// We can write to screenEnabledFilename to enable/disable the screen, but when
-// we read, we always get "mem"! So we have to keep track ourselves whether
-// the screen is on or not.
-bool sScreenEnabled = true;
-
-// We can read wakeLockFilename to find out whether the cpu wake lock
-// is already acquired, but reading and parsing it is a lot more work
-// than tracking it ourselves, and it won't be accurate anyway (kernel
-// internal wake locks aren't counted here.)
-bool sCpuSleepAllowed = true;
-
-// Some CPU wake locks may be acquired internally in HAL. We use a counter to
-// keep track of these needs. Note we have to hold |sInternalLockCpuMutex|
-// when reading or writing this variable to ensure thread-safe.
-int32_t sInternalLockCpuCount = 0;
-
-} // namespace
-
-bool
-GetScreenEnabled()
-{
- return sScreenEnabled;
-}
-
-void
-SetScreenEnabled(bool aEnabled)
-{
- GetGonkDisplay()->SetEnabled(aEnabled);
- sScreenEnabled = aEnabled;
-}
-
-bool
-GetKeyLightEnabled()
-{
- LightConfiguration config;
- bool ok = GetLight(eHalLightID_Buttons, &config);
- if (ok) {
- return (config.color != 0x00000000);
- }
- return false;
-}
-
-void
-SetKeyLightEnabled(bool aEnabled)
-{
- LightConfiguration config;
- config.mode = eHalLightMode_User;
- config.flash = eHalLightFlash_None;
- config.flashOnMS = config.flashOffMS = 0;
- config.color = 0x00000000;
-
- if (aEnabled) {
- // Convert the value in [0, 1] to an int between 0 and 255 and then convert
- // it to a color. Note that the high byte is FF, corresponding to the alpha
- // channel.
- double brightness = GetScreenBrightness();
- uint32_t val = static_cast<int>(round(brightness * 255.0));
- uint32_t color = (0xff<<24) + (val<<16) + (val<<8) + val;
-
- config.color = color;
- }
-
- SetLight(eHalLightID_Buttons, config);
- SetLight(eHalLightID_Keyboard, config);
-}
-
-double
-GetScreenBrightness()
-{
- LightConfiguration config;
- LightType light = eHalLightID_Backlight;
-
- bool ok = GetLight(light, &config);
- if (ok) {
- // backlight is brightness only, so using one of the RGB elements as value.
- int brightness = config.color & 0xFF;
- return brightness / 255.0;
- }
- // If GetLight fails, it's because the light doesn't exist. So return
- // a value corresponding to "off".
- return 0;
-}
-
-void
-SetScreenBrightness(double brightness)
-{
- // Don't use De Morgan's law to push the ! into this expression; we want to
- // catch NaN too.
- if (!(0 <= brightness && brightness <= 1)) {
- HAL_LOG("SetScreenBrightness: Dropping illegal brightness %f.", brightness);
- return;
- }
-
- // Convert the value in [0, 1] to an int between 0 and 255 and convert to a color
- // note that the high byte is FF, corresponding to the alpha channel.
- uint32_t val = static_cast<int>(round(brightness * 255.0));
- uint32_t color = (0xff<<24) + (val<<16) + (val<<8) + val;
-
- LightConfiguration config;
- config.mode = eHalLightMode_User;
- config.flash = eHalLightFlash_None;
- config.flashOnMS = config.flashOffMS = 0;
- config.color = color;
- SetLight(eHalLightID_Backlight, config);
- if (GetKeyLightEnabled()) {
- SetLight(eHalLightID_Buttons, config);
- SetLight(eHalLightID_Keyboard, config);
- }
-}
-
-static StaticMutex sInternalLockCpuMutex;
-
-static void
-UpdateCpuSleepState()
-{
- const char *wakeLockFilename = "/sys/power/wake_lock";
- const char *wakeUnlockFilename = "/sys/power/wake_unlock";
-
- sInternalLockCpuMutex.AssertCurrentThreadOwns();
- bool allowed = sCpuSleepAllowed && !sInternalLockCpuCount;
- WriteSysFile(allowed ? wakeUnlockFilename : wakeLockFilename, "gecko");
-}
-
-static void
-InternalLockCpu() {
- StaticMutexAutoLock lock(sInternalLockCpuMutex);
- ++sInternalLockCpuCount;
- UpdateCpuSleepState();
-}
-
-static void
-InternalUnlockCpu() {
- StaticMutexAutoLock lock(sInternalLockCpuMutex);
- --sInternalLockCpuCount;
- UpdateCpuSleepState();
-}
-
-bool
-GetCpuSleepAllowed()
-{
- return sCpuSleepAllowed;
-}
-
-void
-SetCpuSleepAllowed(bool aAllowed)
-{
- StaticMutexAutoLock lock(sInternalLockCpuMutex);
- sCpuSleepAllowed = aAllowed;
- UpdateCpuSleepState();
-}
-
-void
-AdjustSystemClock(int64_t aDeltaMilliseconds)
-{
- int fd;
- struct timespec now;
-
- if (aDeltaMilliseconds == 0) {
- return;
- }
-
- // Preventing context switch before setting system clock
- sched_yield();
- clock_gettime(CLOCK_REALTIME, &now);
- now.tv_sec += (time_t)(aDeltaMilliseconds / 1000LL);
- now.tv_nsec += (long)((aDeltaMilliseconds % 1000LL) * NsecPerMsec);
- if (now.tv_nsec >= NsecPerSec) {
- now.tv_sec += 1;
- now.tv_nsec -= NsecPerSec;
- }
-
- if (now.tv_nsec < 0) {
- now.tv_nsec += NsecPerSec;
- now.tv_sec -= 1;
- }
-
- do {
- fd = open("/dev/alarm", O_RDWR);
- } while (fd == -1 && errno == EINTR);
- ScopedClose autoClose(fd);
- if (fd < 0) {
- HAL_LOG("Failed to open /dev/alarm: %s", strerror(errno));
- return;
- }
-
- if (ioctl(fd, ANDROID_ALARM_SET_RTC, &now) < 0) {
- HAL_LOG("ANDROID_ALARM_SET_RTC failed: %s", strerror(errno));
- }
-
- hal::NotifySystemClockChange(aDeltaMilliseconds);
-}
-
-int32_t
-GetTimezoneOffset()
-{
- PRExplodedTime prTime;
- PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prTime);
-
- // Daylight saving time (DST) will be taken into account.
- int32_t offset = prTime.tm_params.tp_gmt_offset;
- offset += prTime.tm_params.tp_dst_offset;
-
- // Returns the timezone offset relative to UTC in minutes.
- return -(offset / 60);
-}
-
-static int32_t sKernelTimezoneOffset = 0;
-
-static void
-UpdateKernelTimezone(int32_t timezoneOffset)
-{
- if (sKernelTimezoneOffset == timezoneOffset) {
- return;
- }
-
- // Tell the kernel about the new time zone as well, so that FAT filesystems
- // will get local timestamps rather than UTC timestamps.
- //
- // We assume that /init.rc has a sysclktz entry so that settimeofday has
- // already been called once before we call it (there is a side-effect in
- // the kernel the very first time settimeofday is called where it does some
- // special processing if you only set the timezone).
- struct timezone tz;
- memset(&tz, 0, sizeof(tz));
- tz.tz_minuteswest = timezoneOffset;
- settimeofday(nullptr, &tz);
- sKernelTimezoneOffset = timezoneOffset;
-}
-
-void
-SetTimezone(const nsCString& aTimezoneSpec)
-{
- if (aTimezoneSpec.Equals(GetTimezone())) {
- // Even though the timezone hasn't changed, we still need to tell the
- // kernel what the current timezone is. The timezone is persisted in
- // a property and doesn't change across reboots, but the kernel still
- // needs to be updated on every boot.
- UpdateKernelTimezone(GetTimezoneOffset());
- return;
- }
-
- int32_t oldTimezoneOffsetMinutes = GetTimezoneOffset();
- property_set("persist.sys.timezone", aTimezoneSpec.get());
- // This function is automatically called by the other time conversion
- // functions that depend on the timezone. To be safe, we call it manually.
- tzset();
- int32_t newTimezoneOffsetMinutes = GetTimezoneOffset();
- UpdateKernelTimezone(newTimezoneOffsetMinutes);
- hal::NotifySystemTimezoneChange(
- hal::SystemTimezoneChangeInformation(
- oldTimezoneOffsetMinutes, newTimezoneOffsetMinutes));
-}
-
-nsCString
-GetTimezone()
-{
- char timezone[32];
- property_get("persist.sys.timezone", timezone, "");
- return nsCString(timezone);
-}
-
-void
-EnableSystemClockChangeNotifications()
-{
-}
-
-void
-DisableSystemClockChangeNotifications()
-{
-}
-
-void
-EnableSystemTimezoneChangeNotifications()
-{
-}
-
-void
-DisableSystemTimezoneChangeNotifications()
-{
-}
-
-// Nothing to do here. Gonk widgetry always listens for screen
-// orientation changes.
-void
-EnableScreenConfigurationNotifications()
-{
-}
-
-void
-DisableScreenConfigurationNotifications()
-{
-}
-
-void
-GetCurrentScreenConfiguration(hal::ScreenConfiguration* aScreenConfiguration)
-{
- RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen();
- *aScreenConfiguration = screen->GetConfiguration();
-}
-
-bool
-LockScreenOrientation(const dom::ScreenOrientationInternal& aOrientation)
-{
- return OrientationObserver::GetInstance()->LockScreenOrientation(aOrientation);
-}
-
-void
-UnlockScreenOrientation()
-{
- OrientationObserver::GetInstance()->UnlockScreenOrientation();
-}
-
-// This thread will wait for the alarm firing by a blocking IO.
-static pthread_t sAlarmFireWatcherThread;
-
-// If |sAlarmData| is non-null, it's owned by the alarm-watcher thread.
-struct AlarmData {
-public:
- AlarmData(int aFd) : mFd(aFd),
- mGeneration(sNextGeneration++),
- mShuttingDown(false) {}
- ScopedClose mFd;
- int mGeneration;
- bool mShuttingDown;
-
- static int sNextGeneration;
-
-};
-
-int AlarmData::sNextGeneration = 0;
-
-AlarmData* sAlarmData = nullptr;
-
-class AlarmFiredEvent : public Runnable {
-public:
- AlarmFiredEvent(int aGeneration) : mGeneration(aGeneration) {}
-
- NS_IMETHOD Run() override {
- // Guard against spurious notifications caused by an alarm firing
- // concurrently with it being disabled.
- if (sAlarmData && !sAlarmData->mShuttingDown &&
- mGeneration == sAlarmData->mGeneration) {
- hal::NotifyAlarmFired();
- }
- // The fired alarm event has been delivered to the observer (if needed);
- // we can now release a CPU wake lock.
- InternalUnlockCpu();
- return NS_OK;
- }
-
-private:
- int mGeneration;
-};
-
-// Runs on alarm-watcher thread.
-static void
-DestroyAlarmData(void* aData)
-{
- AlarmData* alarmData = static_cast<AlarmData*>(aData);
- delete alarmData;
-}
-
-// Runs on alarm-watcher thread.
-void ShutDownAlarm(int aSigno)
-{
- if (aSigno == SIGUSR1 && sAlarmData) {
- sAlarmData->mShuttingDown = true;
- }
- return;
-}
-
-static void*
-WaitForAlarm(void* aData)
-{
- pthread_cleanup_push(DestroyAlarmData, aData);
-
- AlarmData* alarmData = static_cast<AlarmData*>(aData);
-
- while (!alarmData->mShuttingDown) {
- int alarmTypeFlags = 0;
-
- // ALARM_WAIT apparently will block even if an alarm hasn't been
- // programmed, although this behavior doesn't seem to be
- // documented. We rely on that here to avoid spinning the CPU
- // while awaiting an alarm to be programmed.
- do {
- alarmTypeFlags = ioctl(alarmData->mFd, ANDROID_ALARM_WAIT);
- } while (alarmTypeFlags < 0 && errno == EINTR &&
- !alarmData->mShuttingDown);
-
- if (!alarmData->mShuttingDown && alarmTypeFlags >= 0 &&
- (alarmTypeFlags & ANDROID_ALARM_RTC_WAKEUP_MASK)) {
- // To make sure the observer can get the alarm firing notification
- // *on time* (the system won't sleep during the process in any way),
- // we need to acquire a CPU wake lock before firing the alarm event.
- InternalLockCpu();
- RefPtr<AlarmFiredEvent> event =
- new AlarmFiredEvent(alarmData->mGeneration);
- NS_DispatchToMainThread(event);
- }
- }
-
- pthread_cleanup_pop(1);
- return nullptr;
-}
-
-bool
-EnableAlarm()
-{
- MOZ_ASSERT(!sAlarmData);
-
- int alarmFd = open("/dev/alarm", O_RDWR);
- if (alarmFd < 0) {
- HAL_LOG("Failed to open alarm device: %s.", strerror(errno));
- return false;
- }
-
- UniquePtr<AlarmData> alarmData = MakeUnique<AlarmData>(alarmFd);
-
- struct sigaction actions;
- memset(&actions, 0, sizeof(actions));
- sigemptyset(&actions.sa_mask);
- actions.sa_flags = 0;
- actions.sa_handler = ShutDownAlarm;
- if (sigaction(SIGUSR1, &actions, nullptr)) {
- HAL_LOG("Failed to set SIGUSR1 signal for alarm-watcher thread.");
- return false;
- }
-
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- int status = pthread_create(&sAlarmFireWatcherThread, &attr, WaitForAlarm,
- alarmData.get());
- if (status) {
- alarmData.reset();
- HAL_LOG("Failed to create alarm-watcher thread. Status: %d.", status);
- return false;
- }
-
- pthread_attr_destroy(&attr);
-
- // The thread owns this now. We only hold a pointer.
- sAlarmData = alarmData.release();
- return true;
-}
-
-void
-DisableAlarm()
-{
- MOZ_ASSERT(sAlarmData);
-
- // NB: this must happen-before the thread cancellation.
- sAlarmData = nullptr;
-
- // The cancel will interrupt the thread and destroy it, freeing the
- // data pointed at by sAlarmData.
- DebugOnly<int> err = pthread_kill(sAlarmFireWatcherThread, SIGUSR1);
- MOZ_ASSERT(!err);
-}
-
-bool
-SetAlarm(int32_t aSeconds, int32_t aNanoseconds)
-{
- if (!sAlarmData) {
- HAL_LOG("We should have enabled the alarm.");
- return false;
- }
-
- struct timespec ts;
- ts.tv_sec = aSeconds;
- ts.tv_nsec = aNanoseconds;
-
- // Currently we only support RTC wakeup alarm type.
- const int result = ioctl(sAlarmData->mFd,
- ANDROID_ALARM_SET(ANDROID_ALARM_RTC_WAKEUP), &ts);
-
- if (result < 0) {
- HAL_LOG("Unable to set alarm: %s.", strerror(errno));
- return false;
- }
-
- return true;
-}
-
-static int
-OomAdjOfOomScoreAdj(int aOomScoreAdj)
-{
- // Convert OOM adjustment from the domain of /proc/<pid>/oom_score_adj
- // to the domain of /proc/<pid>/oom_adj.
-
- int adj;
-
- if (aOomScoreAdj < 0) {
- adj = (OOM_DISABLE * aOomScoreAdj) / OOM_SCORE_ADJ_MIN;
- } else {
- adj = (OOM_ADJUST_MAX * aOomScoreAdj) / OOM_SCORE_ADJ_MAX;
- }
-
- return adj;
-}
-
-static void
-RoundOomScoreAdjUpWithLRU(int& aOomScoreAdj, uint32_t aLRU)
-{
- // We want to add minimum value to round OomScoreAdj up according to
- // the steps by aLRU.
- aOomScoreAdj +=
- ceil(((float)OOM_SCORE_ADJ_MAX / OOM_ADJUST_MAX) * aLRU);
-}
-
-#define OOM_LOG(level, args...) __android_log_print(level, "OomLogger", ##args)
-class OomVictimLogger final
- : public nsIObserver
-{
-public:
- OomVictimLogger()
- : mLastLineChecked(-1.0),
- mRegexes(nullptr)
- {
- // Enable timestamps in kernel's printk
- WriteSysFile("/sys/module/printk/parameters/time", "Y");
- }
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
-protected:
- ~OomVictimLogger() {}
-
-private:
- double mLastLineChecked;
- UniqueFreePtr<regex_t> mRegexes;
-};
-NS_IMPL_ISUPPORTS(OomVictimLogger, nsIObserver);
-
-NS_IMETHODIMP
-OomVictimLogger::Observe(
- nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- nsDependentCString event_type(aTopic);
- if (!event_type.EqualsLiteral("ipc:content-shutdown")) {
- return NS_OK;
- }
-
- // OOM message finding regexes
- const char* const regexes_raw[] = {
- ".*select.*to kill.*",
- ".*send sigkill to.*",
- ".*lowmem_shrink.*",
- ".*[Oo]ut of [Mm]emory.*",
- ".*[Kk]ill [Pp]rocess.*",
- ".*[Kk]illed [Pp]rocess.*",
- ".*oom-killer.*",
- // The regexes below are for the output of dump_task from oom_kill.c
- // 1st - title 2nd - body lines (8 ints and a string)
- // oom_adj and oom_score_adj can be negative
- "\\[ pid \\] uid tgid total_vm rss cpu oom_adj oom_score_adj name",
- "\\[.*[0-9][0-9]*\\][ ]*[0-9][0-9]*[ ]*[0-9][0-9]*[ ]*[0-9][0-9]*[ ]*[0-9][0-9]*[ ]*[0-9][0-9]*[ ]*.[0-9][0-9]*[ ]*.[0-9][0-9]*.*"
- };
- const size_t regex_count = ArrayLength(regexes_raw);
-
- // Compile our regex just in time
- if (!mRegexes) {
- UniqueFreePtr<regex_t> regexes(
- static_cast<regex_t*>(malloc(sizeof(regex_t) * regex_count))
- );
- mRegexes.swap(regexes);
- for (size_t i = 0; i < regex_count; i++) {
- int compilation_err =
- regcomp(&(mRegexes.get()[i]), regexes_raw[i], REG_NOSUB);
- if (compilation_err) {
- OOM_LOG(ANDROID_LOG_ERROR, "Cannot compile regex \"%s\"\n", regexes_raw[i]);
- return NS_OK;
- }
- }
- }
-
-#ifndef KLOG_SIZE_BUFFER
- // Upstream bionic in commit
- // e249b059637b49a285ed9f58a2a18bfd054e5d95
- // deprecated the old klog defs.
- // Our current bionic does not hit this
- // change yet so handle the future change.
- // (ICS doesn't have KLOG_SIZE_BUFFER but
- // JB and onwards does.)
- #define KLOG_SIZE_BUFFER KLOG_WRITE
-#endif
- // Retreive kernel log
- int msg_buf_size = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
- UniqueFreePtr<char> msg_buf(static_cast<char *>(malloc(msg_buf_size + 1)));
- int read_size = klogctl(KLOG_READ_ALL, msg_buf.get(), msg_buf_size);
-
- // Turn buffer into cstring
- read_size = read_size > msg_buf_size ? msg_buf_size : read_size;
- msg_buf.get()[read_size] = '\0';
-
- // Foreach line
- char* line_end;
- char* line_begin = msg_buf.get();
- for (; (line_end = strchr(line_begin, '\n')); line_begin = line_end + 1) {
- // make line into cstring
- *line_end = '\0';
-
- // Note: Kernel messages look like:
- // <5>[63648.286409] sd 35:0:0:0: Attached scsi generic sg1 type 0
- // 5 is the loging level
- // [*] is the time timestamp, seconds since boot
- // last comes the logged message
-
- // Since the logging level can be a string we must
- // skip it since scanf lacks wildcard matching
- char* timestamp_begin = strchr(line_begin, '[');
- char after_float;
- double lineTimestamp = -1;
- bool lineTimestampFound = false;
- if (timestamp_begin &&
- // Note: scanf treats a ' ' as [ ]*
- // Note: scanf treats [ %lf] as [ %lf thus we must check
- // for the closing bracket outselves.
- 2 == sscanf(timestamp_begin, "[ %lf%c", &lineTimestamp, &after_float) &&
- after_float == ']') {
- if (lineTimestamp <= mLastLineChecked) {
- continue;
- }
-
- lineTimestampFound = true;
- mLastLineChecked = lineTimestamp;
- }
-
- // Log interesting lines
- for (size_t i = 0; i < regex_count; i++) {
- int matching = !regexec(&(mRegexes.get()[i]), line_begin, 0, NULL, 0);
- if (matching) {
- // Log content of kernel message. We try to skip the ], but if for
- // some reason (most likely due to buffer overflow/wraparound), we
- // can't find the ] then we just log the entire line.
- char* endOfTimestamp = strchr(line_begin, ']');
- if (endOfTimestamp && endOfTimestamp[1] == ' ') {
- // skip the ] and the space that follows it
- line_begin = endOfTimestamp + 2;
- }
- if (!lineTimestampFound) {
- OOM_LOG(ANDROID_LOG_WARN, "following kill message may be a duplicate");
- }
- OOM_LOG(ANDROID_LOG_ERROR, "[Kill]: %s\n", line_begin);
- break;
- }
- }
- }
-
- return NS_OK;
-}
-
-/**
- * Wraps a particular ProcessPriority, giving us easy access to the prefs that
- * are relevant to it.
- *
- * Creating a PriorityClass also ensures that the control group is created.
- */
-class PriorityClass
-{
-public:
- /**
- * Create a PriorityClass for the given ProcessPriority. This implicitly
- * reads the relevant prefs and opens the cgroup.procs file of the relevant
- * control group caching its file descriptor for later use.
- */
- PriorityClass(ProcessPriority aPriority);
-
- /**
- * Closes the file descriptor for the cgroup.procs file of the associated
- * control group.
- */
- ~PriorityClass();
-
- PriorityClass(const PriorityClass& aOther);
- PriorityClass& operator=(const PriorityClass& aOther);
-
- ProcessPriority Priority()
- {
- return mPriority;
- }
-
- int32_t OomScoreAdj()
- {
- return clamped<int32_t>(mOomScoreAdj, OOM_SCORE_ADJ_MIN, OOM_SCORE_ADJ_MAX);
- }
-
- int32_t KillUnderKB()
- {
- return mKillUnderKB;
- }
-
- nsCString CGroup()
- {
- return mGroup;
- }
-
- /**
- * Adds a process to this priority class, this moves the process' PID into
- * the associated control group.
- *
- * @param aPid The PID of the process to be added.
- */
- void AddProcess(int aPid);
-
-private:
- ProcessPriority mPriority;
- int32_t mOomScoreAdj;
- int32_t mKillUnderKB;
- int mCpuCGroupProcsFd;
- int mMemCGroupProcsFd;
- nsCString mGroup;
-
- /**
- * Return a string that identifies where we can find the value of aPref
- * that's specific to mPriority. For example, we might return
- * "hal.processPriorityManager.gonk.FOREGROUND_HIGH.oomScoreAdjust".
- */
- nsCString PriorityPrefName(const char* aPref)
- {
- return nsPrintfCString("hal.processPriorityManager.gonk.%s.%s",
- ProcessPriorityToString(mPriority), aPref);
- }
-
- /**
- * Get the full path of the cgroup.procs file associated with the group.
- */
- nsCString CpuCGroupProcsFilename()
- {
- nsCString cgroupName = mGroup;
-
- /* If mGroup is empty, our cgroup.procs file is the root procs file,
- * located at /dev/cpuctl/cgroup.procs. Otherwise our procs file is
- * /dev/cpuctl/NAME/cgroup.procs. */
-
- if (!mGroup.IsEmpty()) {
- cgroupName.AppendLiteral("/");
- }
-
- return NS_LITERAL_CSTRING("/dev/cpuctl/") + cgroupName +
- NS_LITERAL_CSTRING("cgroup.procs");
- }
-
- nsCString MemCGroupProcsFilename()
- {
- nsCString cgroupName = mGroup;
-
- /* If mGroup is empty, our cgroup.procs file is the root procs file,
- * located at /sys/fs/cgroup/memory/cgroup.procs. Otherwise our procs
- * file is /sys/fs/cgroup/memory/NAME/cgroup.procs. */
-
- if (!mGroup.IsEmpty()) {
- cgroupName.AppendLiteral("/");
- }
-
- return NS_LITERAL_CSTRING("/sys/fs/cgroup/memory/") + cgroupName +
- NS_LITERAL_CSTRING("cgroup.procs");
- }
-
- int OpenCpuCGroupProcs()
- {
- return open(CpuCGroupProcsFilename().get(), O_WRONLY);
- }
-
- int OpenMemCGroupProcs()
- {
- return open(MemCGroupProcsFilename().get(), O_WRONLY);
- }
-};
-
-/**
- * Try to create the cgroup for the given PriorityClass, if it doesn't already
- * exist. This essentially implements mkdir -p; that is, we create parent
- * cgroups as necessary. The group parameters are also set according to
- * the corresponding preferences.
- *
- * @param aGroup The name of the group.
- * @return true if we successfully created the cgroup, or if it already
- * exists. Otherwise, return false.
- */
-static bool
-EnsureCpuCGroupExists(const nsACString &aGroup)
-{
- NS_NAMED_LITERAL_CSTRING(kDevCpuCtl, "/dev/cpuctl/");
- NS_NAMED_LITERAL_CSTRING(kSlash, "/");
-
- nsAutoCString groupName(aGroup);
- HAL_LOG("EnsureCpuCGroupExists for group '%s'", groupName.get());
-
- nsAutoCString prefPrefix("hal.processPriorityManager.gonk.cgroups.");
-
- /* If cgroup is not empty, append the cgroup name and a dot to obtain the
- * group specific preferences. */
- if (!aGroup.IsEmpty()) {
- prefPrefix += aGroup + NS_LITERAL_CSTRING(".");
- }
-
- nsAutoCString cpuSharesPref(prefPrefix + NS_LITERAL_CSTRING("cpu_shares"));
- int cpuShares = Preferences::GetInt(cpuSharesPref.get());
-
- nsAutoCString cpuNotifyOnMigratePref(prefPrefix
- + NS_LITERAL_CSTRING("cpu_notify_on_migrate"));
- int cpuNotifyOnMigrate = Preferences::GetInt(cpuNotifyOnMigratePref.get());
-
- // Create mCGroup and its parent directories, as necessary.
- nsCString cgroupIter = aGroup + kSlash;
-
- int32_t offset = 0;
- while ((offset = cgroupIter.FindChar('/', offset)) != -1) {
- nsAutoCString path = kDevCpuCtl + Substring(cgroupIter, 0, offset);
- int rv = mkdir(path.get(), 0744);
-
- if (rv == -1 && errno != EEXIST) {
- HAL_LOG("Could not create the %s control group.", path.get());
- return false;
- }
-
- offset++;
- }
- HAL_LOG("EnsureCpuCGroupExists created group '%s'", groupName.get());
-
- nsAutoCString pathPrefix(kDevCpuCtl + aGroup + kSlash);
- nsAutoCString cpuSharesPath(pathPrefix + NS_LITERAL_CSTRING("cpu.shares"));
- if (cpuShares && !WriteSysFile(cpuSharesPath.get(),
- nsPrintfCString("%d", cpuShares).get())) {
- HAL_LOG("Could not set the cpu share for group %s", cpuSharesPath.get());
- return false;
- }
-
- nsAutoCString notifyOnMigratePath(pathPrefix
- + NS_LITERAL_CSTRING("cpu.notify_on_migrate"));
- if (!WriteSysFile(notifyOnMigratePath.get(),
- nsPrintfCString("%d", cpuNotifyOnMigrate).get())) {
- HAL_LOG("Could not set the cpu migration notification flag for group %s",
- notifyOnMigratePath.get());
- return false;
- }
-
- return true;
-}
-
-static bool
-EnsureMemCGroupExists(const nsACString &aGroup)
-{
- NS_NAMED_LITERAL_CSTRING(kMemCtl, "/sys/fs/cgroup/memory/");
- NS_NAMED_LITERAL_CSTRING(kSlash, "/");
-
- nsAutoCString groupName(aGroup);
- HAL_LOG("EnsureMemCGroupExists for group '%s'", groupName.get());
-
- nsAutoCString prefPrefix("hal.processPriorityManager.gonk.cgroups.");
-
- /* If cgroup is not empty, append the cgroup name and a dot to obtain the
- * group specific preferences. */
- if (!aGroup.IsEmpty()) {
- prefPrefix += aGroup + NS_LITERAL_CSTRING(".");
- }
-
- nsAutoCString memSwappinessPref(prefPrefix + NS_LITERAL_CSTRING("memory_swappiness"));
- int memSwappiness = Preferences::GetInt(memSwappinessPref.get());
-
- // Create mCGroup and its parent directories, as necessary.
- nsCString cgroupIter = aGroup + kSlash;
-
- int32_t offset = 0;
- while ((offset = cgroupIter.FindChar('/', offset)) != -1) {
- nsAutoCString path = kMemCtl + Substring(cgroupIter, 0, offset);
- int rv = mkdir(path.get(), 0744);
-
- if (rv == -1 && errno != EEXIST) {
- HAL_LOG("Could not create the %s control group.", path.get());
- return false;
- }
-
- offset++;
- }
- HAL_LOG("EnsureMemCGroupExists created group '%s'", groupName.get());
-
- nsAutoCString pathPrefix(kMemCtl + aGroup + kSlash);
- nsAutoCString memSwappinessPath(pathPrefix + NS_LITERAL_CSTRING("memory.swappiness"));
- if (!WriteSysFile(memSwappinessPath.get(),
- nsPrintfCString("%d", memSwappiness).get())) {
- HAL_LOG("Could not set the memory.swappiness for group %s", memSwappinessPath.get());
- return false;
- }
- HAL_LOG("Set memory.swappiness for group %s to %d", memSwappinessPath.get(), memSwappiness);
-
- return true;
-}
-
-PriorityClass::PriorityClass(ProcessPriority aPriority)
- : mPriority(aPriority)
- , mOomScoreAdj(0)
- , mKillUnderKB(0)
- , mCpuCGroupProcsFd(-1)
- , mMemCGroupProcsFd(-1)
-{
- DebugOnly<nsresult> rv;
-
- rv = Preferences::GetInt(PriorityPrefName("OomScoreAdjust").get(),
- &mOomScoreAdj);
- MOZ_ASSERT(NS_SUCCEEDED(rv), "Missing oom_score_adj preference");
-
- rv = Preferences::GetInt(PriorityPrefName("KillUnderKB").get(),
- &mKillUnderKB);
-
- rv = Preferences::GetCString(PriorityPrefName("cgroup").get(), &mGroup);
- MOZ_ASSERT(NS_SUCCEEDED(rv), "Missing control group preference");
-
- if (EnsureCpuCGroupExists(mGroup)) {
- mCpuCGroupProcsFd = OpenCpuCGroupProcs();
- }
- if (EnsureMemCGroupExists(mGroup)) {
- mMemCGroupProcsFd = OpenMemCGroupProcs();
- }
-}
-
-PriorityClass::~PriorityClass()
-{
- if (mCpuCGroupProcsFd != -1) {
- close(mCpuCGroupProcsFd);
- }
- if (mMemCGroupProcsFd != -1) {
- close(mMemCGroupProcsFd);
- }
-}
-
-PriorityClass::PriorityClass(const PriorityClass& aOther)
- : mPriority(aOther.mPriority)
- , mOomScoreAdj(aOther.mOomScoreAdj)
- , mKillUnderKB(aOther.mKillUnderKB)
- , mGroup(aOther.mGroup)
-{
- mCpuCGroupProcsFd = OpenCpuCGroupProcs();
- mMemCGroupProcsFd = OpenMemCGroupProcs();
-}
-
-PriorityClass& PriorityClass::operator=(const PriorityClass& aOther)
-{
- mPriority = aOther.mPriority;
- mOomScoreAdj = aOther.mOomScoreAdj;
- mKillUnderKB = aOther.mKillUnderKB;
- mGroup = aOther.mGroup;
- mCpuCGroupProcsFd = OpenCpuCGroupProcs();
- mMemCGroupProcsFd = OpenMemCGroupProcs();
- return *this;
-}
-
-void PriorityClass::AddProcess(int aPid)
-{
- if (mCpuCGroupProcsFd >= 0) {
- nsPrintfCString str("%d", aPid);
-
- if (write(mCpuCGroupProcsFd, str.get(), strlen(str.get())) < 0) {
- HAL_ERR("Couldn't add PID %d to the %s cpu control group", aPid, mGroup.get());
- }
- }
- if (mMemCGroupProcsFd >= 0) {
- nsPrintfCString str("%d", aPid);
-
- if (write(mMemCGroupProcsFd, str.get(), strlen(str.get())) < 0) {
- HAL_ERR("Couldn't add PID %d to the %s memory control group", aPid, mGroup.get());
- }
- }
-}
-
-/**
- * Get the PriorityClass associated with the given ProcessPriority.
- *
- * If you pass an invalid ProcessPriority value, we return null.
- *
- * The pointers returned here are owned by GetPriorityClass (don't free them
- * yourself). They are guaranteed to stick around until shutdown.
- */
-PriorityClass*
-GetPriorityClass(ProcessPriority aPriority)
-{
- static StaticAutoPtr<nsTArray<PriorityClass>> priorityClasses;
-
- // Initialize priorityClasses if this is the first time we're running this
- // method.
- if (!priorityClasses) {
- priorityClasses = new nsTArray<PriorityClass>();
- ClearOnShutdown(&priorityClasses);
-
- for (int32_t i = 0; i < NUM_PROCESS_PRIORITY; i++) {
- priorityClasses->AppendElement(PriorityClass(ProcessPriority(i)));
- }
- }
-
- if (aPriority < 0 ||
- static_cast<uint32_t>(aPriority) >= priorityClasses->Length()) {
- return nullptr;
- }
-
- return &(*priorityClasses)[aPriority];
-}
-
-static void
-EnsureKernelLowMemKillerParamsSet()
-{
- static bool kernelLowMemKillerParamsSet;
- if (kernelLowMemKillerParamsSet) {
- return;
- }
- kernelLowMemKillerParamsSet = true;
-
- HAL_LOG("Setting kernel's low-mem killer parameters.");
-
- // Set /sys/module/lowmemorykiller/parameters/{adj,minfree,notify_trigger}
- // according to our prefs. These files let us tune when the kernel kills
- // processes when we're low on memory, and when it notifies us that we're
- // running low on available memory.
- //
- // adj and minfree are both comma-separated lists of integers. If adj="A,B"
- // and minfree="X,Y", then the kernel will kill processes with oom_adj
- // A or higher once we have fewer than X pages of memory free, and will kill
- // processes with oom_adj B or higher once we have fewer than Y pages of
- // memory free.
- //
- // notify_trigger is a single integer. If we set notify_trigger=Z, then
- // we'll get notified when there are fewer than Z pages of memory free. (See
- // GonkMemoryPressureMonitoring.cpp.)
-
- // Build the adj and minfree strings.
- nsAutoCString adjParams;
- nsAutoCString minfreeParams;
-
- DebugOnly<int32_t> lowerBoundOfNextOomScoreAdj = OOM_SCORE_ADJ_MIN - 1;
- DebugOnly<int32_t> lowerBoundOfNextKillUnderKB = 0;
- int32_t countOfLowmemorykillerParametersSets = 0;
-
- long page_size = sysconf(_SC_PAGESIZE);
-
- for (int i = NUM_PROCESS_PRIORITY - 1; i >= 0; i--) {
- // The system doesn't function correctly if we're missing these prefs, so
- // crash loudly.
-
- PriorityClass* pc = GetPriorityClass(static_cast<ProcessPriority>(i));
-
- int32_t oomScoreAdj = pc->OomScoreAdj();
- int32_t killUnderKB = pc->KillUnderKB();
-
- if (killUnderKB == 0) {
- // ProcessPriority values like PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
- // which has only OomScoreAdjust but lacks KillUnderMB value, will not
- // create new LMK parameters.
- continue;
- }
-
- // The LMK in kernel silently malfunctions if we assign the parameters
- // in non-increasing order, so we add this assertion here. See bug 887192.
- MOZ_ASSERT(oomScoreAdj > lowerBoundOfNextOomScoreAdj);
- MOZ_ASSERT(killUnderKB > lowerBoundOfNextKillUnderKB);
-
- // The LMK in kernel only accept 6 sets of LMK parameters. See bug 914728.
- MOZ_ASSERT(countOfLowmemorykillerParametersSets < 6);
-
- // adj is in oom_adj units.
- adjParams.AppendPrintf("%d,", OomAdjOfOomScoreAdj(oomScoreAdj));
-
- // minfree is in pages.
- minfreeParams.AppendPrintf("%ld,", killUnderKB * 1024 / page_size);
-
- lowerBoundOfNextOomScoreAdj = oomScoreAdj;
- lowerBoundOfNextKillUnderKB = killUnderKB;
- countOfLowmemorykillerParametersSets++;
- }
-
- // Strip off trailing commas.
- adjParams.Cut(adjParams.Length() - 1, 1);
- minfreeParams.Cut(minfreeParams.Length() - 1, 1);
- if (!adjParams.IsEmpty() && !minfreeParams.IsEmpty()) {
- WriteSysFile("/sys/module/lowmemorykiller/parameters/adj", adjParams.get());
- WriteSysFile("/sys/module/lowmemorykiller/parameters/minfree",
- minfreeParams.get());
- }
-
- // Set the low-memory-notification threshold.
- int32_t lowMemNotifyThresholdKB;
- if (NS_SUCCEEDED(Preferences::GetInt(
- "hal.processPriorityManager.gonk.notifyLowMemUnderKB",
- &lowMemNotifyThresholdKB))) {
-
- // notify_trigger is in pages.
- WriteSysFile("/sys/module/lowmemorykiller/parameters/notify_trigger",
- nsPrintfCString("%ld", lowMemNotifyThresholdKB * 1024 / page_size).get());
- }
-
- // Ensure OOM events appear in logcat
- RefPtr<OomVictimLogger> oomLogger = new OomVictimLogger();
- nsCOMPtr<nsIObserverService> os = services::GetObserverService();
- if (os) {
- os->AddObserver(oomLogger, "ipc:content-shutdown", false);
- }
-}
-
-void
-SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
-{
- HAL_LOG("SetProcessPriority(pid=%d, priority=%d, LRU=%u)",
- aPid, aPriority, aLRU);
-
- // If this is the first time SetProcessPriority was called, set the kernel's
- // OOM parameters according to our prefs.
- //
- // We could/should do this on startup instead of waiting for the first
- // SetProcessPriorityCall. But in practice, the master process needs to set
- // its priority early in the game, so we can reasonably rely on
- // SetProcessPriority being called early in startup.
- EnsureKernelLowMemKillerParamsSet();
-
- PriorityClass* pc = GetPriorityClass(aPriority);
-
- int oomScoreAdj = pc->OomScoreAdj();
-
- RoundOomScoreAdjUpWithLRU(oomScoreAdj, aLRU);
-
- // We try the newer interface first, and fall back to the older interface
- // on failure.
- if (!WriteSysFile(nsPrintfCString("/proc/%d/oom_score_adj", aPid).get(),
- nsPrintfCString("%d", oomScoreAdj).get()))
- {
- WriteSysFile(nsPrintfCString("/proc/%d/oom_adj", aPid).get(),
- nsPrintfCString("%d", OomAdjOfOomScoreAdj(oomScoreAdj)).get());
- }
-
- HAL_LOG("Assigning pid %d to cgroup %s", aPid, pc->CGroup().get());
- pc->AddProcess(aPid);
-}
-
-static bool
-IsValidRealTimePriority(int aValue, int aSchedulePolicy)
-{
- return (aValue >= sched_get_priority_min(aSchedulePolicy)) &&
- (aValue <= sched_get_priority_max(aSchedulePolicy));
-}
-
-static void
-SetThreadNiceValue(pid_t aTid, ThreadPriority aThreadPriority, int aValue)
-{
- MOZ_ASSERT(aThreadPriority < NUM_THREAD_PRIORITY);
- MOZ_ASSERT(aThreadPriority >= 0);
-
- HAL_LOG("Setting thread %d to priority level %s; nice level %d",
- aTid, ThreadPriorityToString(aThreadPriority), aValue);
- int rv = setpriority(PRIO_PROCESS, aTid, aValue);
-
- if (rv) {
- HAL_LOG("Failed to set thread %d to priority level %s; error %s", aTid,
- ThreadPriorityToString(aThreadPriority), strerror(errno));
- }
-}
-
-static void
-SetRealTimeThreadPriority(pid_t aTid,
- ThreadPriority aThreadPriority,
- int aValue)
-{
- int policy = SCHED_FIFO;
-
- MOZ_ASSERT(aThreadPriority < NUM_THREAD_PRIORITY);
- MOZ_ASSERT(aThreadPriority >= 0);
- MOZ_ASSERT(IsValidRealTimePriority(aValue, policy), "Invalid real time priority");
-
- // Setting real time priorities requires using sched_setscheduler
- HAL_LOG("Setting thread %d to priority level %s; Real Time priority %d, "
- "Schedule FIFO", aTid, ThreadPriorityToString(aThreadPriority),
- aValue);
- sched_param schedParam;
- schedParam.sched_priority = aValue;
- int rv = sched_setscheduler(aTid, policy, &schedParam);
-
- if (rv) {
- HAL_LOG("Failed to set thread %d to real time priority level %s; error %s",
- aTid, ThreadPriorityToString(aThreadPriority), strerror(errno));
- }
-}
-
-/*
- * Used to store the nice value adjustments and real time priorities for the
- * various thread priority levels.
- */
-struct ThreadPriorityPrefs {
- bool initialized;
- struct {
- int nice;
- int realTime;
- } priorities[NUM_THREAD_PRIORITY];
-};
-
-/*
- * Reads the preferences for the various process priority levels and sets up
- * watchers so that if they're dynamically changed the change is reflected on
- * the appropriate variables.
- */
-void
-EnsureThreadPriorityPrefs(ThreadPriorityPrefs* prefs)
-{
- if (prefs->initialized) {
- return;
- }
-
- for (int i = THREAD_PRIORITY_COMPOSITOR; i < NUM_THREAD_PRIORITY; i++) {
- ThreadPriority priority = static_cast<ThreadPriority>(i);
-
- // Read the nice values
- const char* threadPriorityStr = ThreadPriorityToString(priority);
- nsPrintfCString niceStr("hal.gonk.%s.nice", threadPriorityStr);
- Preferences::AddIntVarCache(&prefs->priorities[i].nice, niceStr.get());
-
- // Read the real-time priorities
- nsPrintfCString realTimeStr("hal.gonk.%s.rt_priority", threadPriorityStr);
- Preferences::AddIntVarCache(&prefs->priorities[i].realTime,
- realTimeStr.get());
- }
-
- prefs->initialized = true;
-}
-
-static void
-DoSetThreadPriority(pid_t aTid, hal::ThreadPriority aThreadPriority)
-{
- // See bug 999115, we can only read preferences on the main thread otherwise
- // we create a race condition in HAL
- MOZ_ASSERT(NS_IsMainThread(), "Can only set thread priorities on main thread");
- MOZ_ASSERT(aThreadPriority >= 0);
-
- static ThreadPriorityPrefs prefs = { 0 };
- EnsureThreadPriorityPrefs(&prefs);
-
- switch (aThreadPriority) {
- case THREAD_PRIORITY_COMPOSITOR:
- break;
- default:
- HAL_ERR("Unrecognized thread priority %d; Doing nothing",
- aThreadPriority);
- return;
- }
-
- int realTimePriority = prefs.priorities[aThreadPriority].realTime;
-
- if (IsValidRealTimePriority(realTimePriority, SCHED_FIFO)) {
- SetRealTimeThreadPriority(aTid, aThreadPriority, realTimePriority);
- return;
- }
-
- SetThreadNiceValue(aTid, aThreadPriority,
- prefs.priorities[aThreadPriority].nice);
-}
-
-namespace {
-
-/**
- * This class sets the priority of threads given the kernel thread's id and a
- * value taken from hal::ThreadPriority.
- *
- * This runnable must always be dispatched to the main thread otherwise it will fail.
- * We have to run this from the main thread since preferences can only be read on
- * main thread.
- */
-class SetThreadPriorityRunnable : public Runnable
-{
-public:
- SetThreadPriorityRunnable(pid_t aThreadId, hal::ThreadPriority aThreadPriority)
- : mThreadId(aThreadId)
- , mThreadPriority(aThreadPriority)
- { }
-
- NS_IMETHOD Run() override
- {
- NS_ASSERTION(NS_IsMainThread(), "Can only set thread priorities on main thread");
- hal_impl::DoSetThreadPriority(mThreadId, mThreadPriority);
- return NS_OK;
- }
-
-private:
- pid_t mThreadId;
- hal::ThreadPriority mThreadPriority;
-};
-
-} // namespace
-
-void
-SetCurrentThreadPriority(ThreadPriority aThreadPriority)
-{
- pid_t threadId = gettid();
- hal_impl::SetThreadPriority(threadId, aThreadPriority);
-}
-
-void
-SetThreadPriority(PlatformThreadId aThreadId,
- ThreadPriority aThreadPriority)
-{
- switch (aThreadPriority) {
- case THREAD_PRIORITY_COMPOSITOR: {
- nsCOMPtr<nsIRunnable> runnable =
- new SetThreadPriorityRunnable(aThreadId, aThreadPriority);
- NS_DispatchToMainThread(runnable);
- break;
- }
- default:
- HAL_LOG("Unrecognized thread priority %d; Doing nothing",
- aThreadPriority);
- return;
- }
-}
-
-void
-FactoryReset(FactoryResetReason& aReason)
-{
- nsCOMPtr<nsIRecoveryService> recoveryService =
- do_GetService("@mozilla.org/recovery-service;1");
- if (!recoveryService) {
- NS_WARNING("Could not get recovery service!");
- return;
- }
-
- if (aReason == FactoryResetReason::Wipe) {
- recoveryService->FactoryReset("wipe");
- } else if (aReason == FactoryResetReason::Root) {
- recoveryService->FactoryReset("root");
- } else {
- recoveryService->FactoryReset("normal");
- }
-}
-
-} // hal_impl
-} // mozilla
diff --git a/hal/gonk/GonkSensor.cpp b/hal/gonk/GonkSensor.cpp
deleted file mode 100644
index 7bd2d3c9b..000000000
--- a/hal/gonk/GonkSensor.cpp
+++ /dev/null
@@ -1,861 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <pthread.h>
-#include <stdio.h>
-
-#include "mozilla/DebugOnly.h"
-#include "mozilla/Saturate.h"
-
-#include "base/basictypes.h"
-#include "base/thread.h"
-#include "base/task.h"
-
-#include "GonkSensorsInterface.h"
-#include "GonkSensorsPollInterface.h"
-#include "GonkSensorsRegistryInterface.h"
-#include "Hal.h"
-#include "HalLog.h"
-#include "HalSensor.h"
-#include "hardware/sensors.h"
-#include "nsThreadUtils.h"
-
-using namespace mozilla::hal;
-
-namespace mozilla {
-
-//
-// Internal implementation
-//
-
-// The value from SensorDevice.h (Android)
-#define DEFAULT_DEVICE_POLL_RATE 200000000 /*200ms*/
-// ProcessOrientation.cpp needs smaller poll rate to detect delay between
-// different orientation angles
-#define ACCELEROMETER_POLL_RATE 66667000 /*66.667ms*/
-
-// This is present in Android from API level 18 onwards, which is 4.3. We might
-// be building on something before 4.3, so use a local define for its value
-#define MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR 15
-
-double radToDeg(double a) {
- return a * (180.0 / M_PI);
-}
-
-static SensorType
-HardwareSensorToHalSensor(int type)
-{
- switch(type) {
- case SENSOR_TYPE_ORIENTATION:
- return SENSOR_ORIENTATION;
- case SENSOR_TYPE_ACCELEROMETER:
- return SENSOR_ACCELERATION;
- case SENSOR_TYPE_PROXIMITY:
- return SENSOR_PROXIMITY;
- case SENSOR_TYPE_LIGHT:
- return SENSOR_LIGHT;
- case SENSOR_TYPE_GYROSCOPE:
- return SENSOR_GYROSCOPE;
- case SENSOR_TYPE_LINEAR_ACCELERATION:
- return SENSOR_LINEAR_ACCELERATION;
- case SENSOR_TYPE_ROTATION_VECTOR:
- return SENSOR_ROTATION_VECTOR;
- case MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR:
- return SENSOR_GAME_ROTATION_VECTOR;
- default:
- return SENSOR_UNKNOWN;
- }
-}
-
-static SensorAccuracyType
-HardwareStatusToHalAccuracy(int status) {
- return static_cast<SensorAccuracyType>(status);
-}
-
-static int
-HalSensorToHardwareSensor(SensorType type)
-{
- switch(type) {
- case SENSOR_ORIENTATION:
- return SENSOR_TYPE_ORIENTATION;
- case SENSOR_ACCELERATION:
- return SENSOR_TYPE_ACCELEROMETER;
- case SENSOR_PROXIMITY:
- return SENSOR_TYPE_PROXIMITY;
- case SENSOR_LIGHT:
- return SENSOR_TYPE_LIGHT;
- case SENSOR_GYROSCOPE:
- return SENSOR_TYPE_GYROSCOPE;
- case SENSOR_LINEAR_ACCELERATION:
- return SENSOR_TYPE_LINEAR_ACCELERATION;
- case SENSOR_ROTATION_VECTOR:
- return SENSOR_TYPE_ROTATION_VECTOR;
- case SENSOR_GAME_ROTATION_VECTOR:
- return MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR;
- default:
- return -1;
- }
-}
-
-static int
-SensorseventStatus(const sensors_event_t& data)
-{
- int type = data.type;
- switch(type) {
- case SENSOR_ORIENTATION:
- return data.orientation.status;
- case SENSOR_LINEAR_ACCELERATION:
- case SENSOR_ACCELERATION:
- return data.acceleration.status;
- case SENSOR_GYROSCOPE:
- return data.gyro.status;
- }
-
- return SENSOR_STATUS_UNRELIABLE;
-}
-
-class SensorRunnable : public Runnable
-{
-public:
- SensorRunnable(const sensors_event_t& data, const sensor_t* sensors, ssize_t size)
- {
- mSensorData.sensor() = HardwareSensorToHalSensor(data.type);
- mSensorData.accuracy() = HardwareStatusToHalAccuracy(SensorseventStatus(data));
- mSensorData.timestamp() = data.timestamp;
- if (mSensorData.sensor() == SENSOR_GYROSCOPE) {
- // libhardware returns gyro as rad. convert.
- mSensorValues.AppendElement(radToDeg(data.data[0]));
- mSensorValues.AppendElement(radToDeg(data.data[1]));
- mSensorValues.AppendElement(radToDeg(data.data[2]));
- } else if (mSensorData.sensor() == SENSOR_PROXIMITY) {
- mSensorValues.AppendElement(data.data[0]);
- mSensorValues.AppendElement(0);
-
- // Determine the maxRange for this sensor.
- for (ssize_t i = 0; i < size; i++) {
- if (sensors[i].type == SENSOR_TYPE_PROXIMITY) {
- mSensorValues.AppendElement(sensors[i].maxRange);
- }
- }
- } else if (mSensorData.sensor() == SENSOR_LIGHT) {
- mSensorValues.AppendElement(data.data[0]);
- } else if (mSensorData.sensor() == SENSOR_ROTATION_VECTOR) {
- mSensorValues.AppendElement(data.data[0]);
- mSensorValues.AppendElement(data.data[1]);
- mSensorValues.AppendElement(data.data[2]);
- if (data.data[3] == 0.0) {
- // data.data[3] was optional in Android <= API level 18. It can be computed from 012,
- // but it's better to take the actual value if one is provided. The computation is
- // v = 1 - d[0]*d[0] - d[1]*d[1] - d[2]*d[2]
- // d[3] = v > 0 ? sqrt(v) : 0;
- // I'm assuming that it will be 0 if it's not passed in. (The values form a unit
- // quaternion, so the angle can be computed from the direction vector.)
- float sx = data.data[0], sy = data.data[1], sz = data.data[2];
- float v = 1.0f - sx*sx - sy*sy - sz*sz;
- mSensorValues.AppendElement(v > 0.0f ? sqrt(v) : 0.0f);
- } else {
- mSensorValues.AppendElement(data.data[3]);
- }
- } else if (mSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) {
- mSensorValues.AppendElement(data.data[0]);
- mSensorValues.AppendElement(data.data[1]);
- mSensorValues.AppendElement(data.data[2]);
- mSensorValues.AppendElement(data.data[3]);
- } else {
- mSensorValues.AppendElement(data.data[0]);
- mSensorValues.AppendElement(data.data[1]);
- mSensorValues.AppendElement(data.data[2]);
- }
- mSensorData.values() = mSensorValues;
- }
-
- ~SensorRunnable() {}
-
- NS_IMETHOD Run() override
- {
- NotifySensorChange(mSensorData);
- return NS_OK;
- }
-
-private:
- SensorData mSensorData;
- AutoTArray<float, 4> mSensorValues;
-};
-
-namespace hal_impl {
-
-static DebugOnly<int> sSensorRefCount[NUM_SENSOR_TYPE];
-static base::Thread* sPollingThread;
-static sensors_poll_device_t* sSensorDevice;
-static sensors_module_t* sSensorModule;
-
-static void
-PollSensors()
-{
- const size_t numEventMax = 16;
- sensors_event_t buffer[numEventMax];
- const sensor_t* sensors;
- int size = sSensorModule->get_sensors_list(sSensorModule, &sensors);
-
- do {
- // didn't check sSensorDevice because already be done on creating pollingThread.
- int n = sSensorDevice->poll(sSensorDevice, buffer, numEventMax);
- if (n < 0) {
- HAL_ERR("Error polling for sensor data (err=%d)", n);
- break;
- }
-
- for (int i = 0; i < n; ++i) {
- // FIXME: bug 802004, add proper support for the magnetic field sensor.
- if (buffer[i].type == SENSOR_TYPE_MAGNETIC_FIELD)
- continue;
-
- // Bug 938035, transfer HAL data for orientation sensor to meet w3c spec
- // ex: HAL report alpha=90 means East but alpha=90 means West in w3c spec
- if (buffer[i].type == SENSOR_TYPE_ORIENTATION) {
- buffer[i].orientation.azimuth = 360 - buffer[i].orientation.azimuth;
- buffer[i].orientation.pitch = -buffer[i].orientation.pitch;
- buffer[i].orientation.roll = -buffer[i].orientation.roll;
- }
-
- if (HardwareSensorToHalSensor(buffer[i].type) == SENSOR_UNKNOWN) {
- // Emulator is broken and gives us events without types set
- int index;
- for (index = 0; index < size; index++) {
- if (sensors[index].handle == buffer[i].sensor) {
- break;
- }
- }
- if (index < size &&
- HardwareSensorToHalSensor(sensors[index].type) != SENSOR_UNKNOWN) {
- buffer[i].type = sensors[index].type;
- } else {
- HAL_LOG("Could not determine sensor type of event");
- continue;
- }
- }
-
- NS_DispatchToMainThread(new SensorRunnable(buffer[i], sensors, size));
- }
- } while (true);
-}
-
-static void
-SwitchSensor(bool aActivate, sensor_t aSensor, pthread_t aThreadId)
-{
- int index = HardwareSensorToHalSensor(aSensor.type);
-
- MOZ_ASSERT(sSensorRefCount[index] || aActivate);
-
- sSensorDevice->activate(sSensorDevice, aSensor.handle, aActivate);
-
- if (aActivate) {
- if (aSensor.type == SENSOR_TYPE_ACCELEROMETER) {
- sSensorDevice->setDelay(sSensorDevice, aSensor.handle,
- ACCELEROMETER_POLL_RATE);
- } else {
- sSensorDevice->setDelay(sSensorDevice, aSensor.handle,
- DEFAULT_DEVICE_POLL_RATE);
- }
- }
-
- if (aActivate) {
- sSensorRefCount[index]++;
- } else {
- sSensorRefCount[index]--;
- }
-}
-
-static void
-SetSensorState(SensorType aSensor, bool activate)
-{
- int type = HalSensorToHardwareSensor(aSensor);
- const sensor_t* sensors = nullptr;
-
- int size = sSensorModule->get_sensors_list(sSensorModule, &sensors);
- for (ssize_t i = 0; i < size; i++) {
- if (sensors[i].type == type) {
- SwitchSensor(activate, sensors[i], pthread_self());
- break;
- }
- }
-}
-
-static void
-EnableSensorNotificationsInternal(SensorType aSensor)
-{
- if (!sSensorModule) {
- hw_get_module(SENSORS_HARDWARE_MODULE_ID,
- (hw_module_t const**)&sSensorModule);
- if (!sSensorModule) {
- HAL_ERR("Can't get sensor HAL module\n");
- return;
- }
-
- sensors_open(&sSensorModule->common, &sSensorDevice);
- if (!sSensorDevice) {
- sSensorModule = nullptr;
- HAL_ERR("Can't get sensor poll device from module \n");
- return;
- }
-
- sensor_t const* sensors;
- int count = sSensorModule->get_sensors_list(sSensorModule, &sensors);
- for (size_t i=0 ; i<size_t(count) ; i++) {
- sSensorDevice->activate(sSensorDevice, sensors[i].handle, 0);
- }
- }
-
- if (!sPollingThread) {
- sPollingThread = new base::Thread("GonkSensors");
- MOZ_ASSERT(sPollingThread);
- // sPollingThread never terminates because poll may never return
- sPollingThread->Start();
- sPollingThread->message_loop()->PostTask(
- NewRunnableFunction(PollSensors));
- }
-
- SetSensorState(aSensor, true);
-}
-
-static void
-DisableSensorNotificationsInternal(SensorType aSensor)
-{
- if (!sSensorModule) {
- return;
- }
- SetSensorState(aSensor, false);
-}
-
-//
-// Daemon
-//
-
-typedef detail::SaturateOp<uint32_t> SaturateOpUint32;
-
-/**
- * The poll notification handler receives all events about sensors and
- * sensor events.
- */
-class SensorsPollNotificationHandler final
- : public GonkSensorsPollNotificationHandler
-{
-public:
- SensorsPollNotificationHandler(GonkSensorsPollInterface* aPollInterface)
- : mPollInterface(aPollInterface)
- {
- MOZ_ASSERT(mPollInterface);
-
- mPollInterface->SetNotificationHandler(this);
- }
-
- void EnableSensorsByType(SensorsType aType)
- {
- if (SaturateOpUint32(mClasses[aType].mActivated)++) {
- return;
- }
-
- SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType);
-
- // Old ref-count for the sensor type was 0, so we
- // activate all sensors of the type.
- for (size_t i = 0; i < mSensors.Length(); ++i) {
- if (mSensors[i].mType == aType &&
- mSensors[i].mDeliveryMode == deliveryMode) {
- mPollInterface->EnableSensor(mSensors[i].mId, nullptr);
- mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType),
- nullptr);
- }
- }
- }
-
- void DisableSensorsByType(SensorsType aType)
- {
- if (SaturateOpUint32(mClasses[aType].mActivated)-- != 1) {
- return;
- }
-
- SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType);
-
- // Old ref-count for the sensor type was 1, so we
- // deactivate all sensors of the type.
- for (size_t i = 0; i < mSensors.Length(); ++i) {
- if (mSensors[i].mType == aType &&
- mSensors[i].mDeliveryMode == deliveryMode) {
- mPollInterface->DisableSensor(mSensors[i].mId, nullptr);
- }
- }
- }
-
- void ClearSensorClasses()
- {
- for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mClasses); ++i) {
- mClasses[i] = SensorsSensorClass();
- }
- }
-
- void ClearSensors()
- {
- mSensors.Clear();
- }
-
- // Methods for SensorsPollNotificationHandler
- //
-
- void ErrorNotification(SensorsError aError) override
- {
- // XXX: Bug 1206056: Try to repair some of the errors or restart cleanly.
- }
-
- void SensorDetectedNotification(int32_t aId, SensorsType aType,
- float aRange, float aResolution,
- float aPower, int32_t aMinPeriod,
- int32_t aMaxPeriod,
- SensorsTriggerMode aTriggerMode,
- SensorsDeliveryMode aDeliveryMode) override
- {
- auto i = FindSensorIndexById(aId);
- if (i == -1) {
- // Add a new sensor...
- i = mSensors.Length();
- mSensors.AppendElement(SensorsSensor(aId, aType, aRange, aResolution,
- aPower, aMinPeriod, aMaxPeriod,
- aTriggerMode, aDeliveryMode));
- } else {
- // ...or update an existing one.
- mSensors[i] = SensorsSensor(aId, aType, aRange, aResolution, aPower,
- aMinPeriod, aMaxPeriod, aTriggerMode,
- aDeliveryMode);
- }
-
- mClasses[aType].UpdateFromSensor(mSensors[i]);
-
- if (mClasses[aType].mActivated &&
- mSensors[i].mDeliveryMode == DefaultSensorsDeliveryMode(aType)) {
- // The new sensor's type is enabled, so enable sensor.
- mPollInterface->EnableSensor(aId, nullptr);
- mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType),
- nullptr);
- }
- }
-
- void SensorLostNotification(int32_t aId) override
- {
- auto i = FindSensorIndexById(aId);
- if (i != -1) {
- mSensors.RemoveElementAt(i);
- }
- }
-
- void EventNotification(int32_t aId, const SensorsEvent& aEvent) override
- {
- auto i = FindSensorIndexById(aId);
- if (i == -1) {
- HAL_ERR("Sensor %d not registered", aId);
- return;
- }
-
- SensorData sensorData;
- auto rv = CreateSensorData(aEvent, mClasses[mSensors[i].mType],
- sensorData);
- if (NS_FAILED(rv)) {
- return;
- }
-
- NotifySensorChange(sensorData);
- }
-
-private:
- ssize_t FindSensorIndexById(int32_t aId) const
- {
- for (size_t i = 0; i < mSensors.Length(); ++i) {
- if (mSensors[i].mId == aId) {
- return i;
- }
- }
- return -1;
- }
-
- uint64_t DefaultSensorPeriod(SensorsType aType) const
- {
- return aType == SENSORS_TYPE_ACCELEROMETER ? ACCELEROMETER_POLL_RATE
- : DEFAULT_DEVICE_POLL_RATE;
- }
-
- SensorsDeliveryMode DefaultSensorsDeliveryMode(SensorsType aType) const
- {
- if (aType == SENSORS_TYPE_PROXIMITY ||
- aType == SENSORS_TYPE_SIGNIFICANT_MOTION) {
- return SENSORS_DELIVERY_MODE_IMMEDIATE;
- }
- return SENSORS_DELIVERY_MODE_BEST_EFFORT;
- }
-
- SensorType HardwareSensorToHalSensor(SensorsType aType) const
- {
- // FIXME: bug 802004, add proper support for the magnetic-field sensor.
- switch (aType) {
- case SENSORS_TYPE_ORIENTATION:
- return SENSOR_ORIENTATION;
- case SENSORS_TYPE_ACCELEROMETER:
- return SENSOR_ACCELERATION;
- case SENSORS_TYPE_PROXIMITY:
- return SENSOR_PROXIMITY;
- case SENSORS_TYPE_LIGHT:
- return SENSOR_LIGHT;
- case SENSORS_TYPE_GYROSCOPE:
- return SENSOR_GYROSCOPE;
- case SENSORS_TYPE_LINEAR_ACCELERATION:
- return SENSOR_LINEAR_ACCELERATION;
- case SENSORS_TYPE_ROTATION_VECTOR:
- return SENSOR_ROTATION_VECTOR;
- case SENSORS_TYPE_GAME_ROTATION_VECTOR:
- return SENSOR_GAME_ROTATION_VECTOR;
- default:
- NS_NOTREACHED("Invalid sensors type");
- }
- return SENSOR_UNKNOWN;
- }
-
- SensorAccuracyType HardwareStatusToHalAccuracy(SensorsStatus aStatus) const
- {
- return static_cast<SensorAccuracyType>(aStatus - 1);
- }
-
- nsresult CreateSensorData(const SensorsEvent& aEvent,
- const SensorsSensorClass& aSensorClass,
- SensorData& aSensorData) const
- {
- AutoTArray<float, 4> sensorValues;
-
- auto sensor = HardwareSensorToHalSensor(aEvent.mType);
-
- if (sensor == SENSOR_UNKNOWN) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
-
- aSensorData.sensor() = sensor;
- aSensorData.accuracy() = HardwareStatusToHalAccuracy(aEvent.mStatus);
- aSensorData.timestamp() = aEvent.mTimestamp;
-
- if (aSensorData.sensor() == SENSOR_ORIENTATION) {
- // Bug 938035: transfer HAL data for orientation sensor to meet W3C spec
- // ex: HAL report alpha=90 means East but alpha=90 means West in W3C spec
- sensorValues.AppendElement(360.0 - radToDeg(aEvent.mData.mFloat[0]));
- sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[1]));
- sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[2]));
- } else if (aSensorData.sensor() == SENSOR_ACCELERATION) {
- sensorValues.AppendElement(aEvent.mData.mFloat[0]);
- sensorValues.AppendElement(aEvent.mData.mFloat[1]);
- sensorValues.AppendElement(aEvent.mData.mFloat[2]);
- } else if (aSensorData.sensor() == SENSOR_PROXIMITY) {
- sensorValues.AppendElement(aEvent.mData.mFloat[0]);
- sensorValues.AppendElement(aSensorClass.mMinValue);
- sensorValues.AppendElement(aSensorClass.mMaxValue);
- } else if (aSensorData.sensor() == SENSOR_LINEAR_ACCELERATION) {
- sensorValues.AppendElement(aEvent.mData.mFloat[0]);
- sensorValues.AppendElement(aEvent.mData.mFloat[1]);
- sensorValues.AppendElement(aEvent.mData.mFloat[2]);
- } else if (aSensorData.sensor() == SENSOR_GYROSCOPE) {
- sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[0]));
- sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[1]));
- sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[2]));
- } else if (aSensorData.sensor() == SENSOR_LIGHT) {
- sensorValues.AppendElement(aEvent.mData.mFloat[0]);
- } else if (aSensorData.sensor() == SENSOR_ROTATION_VECTOR) {
- sensorValues.AppendElement(aEvent.mData.mFloat[0]);
- sensorValues.AppendElement(aEvent.mData.mFloat[1]);
- sensorValues.AppendElement(aEvent.mData.mFloat[2]);
- sensorValues.AppendElement(aEvent.mData.mFloat[3]);
- } else if (aSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) {
- sensorValues.AppendElement(aEvent.mData.mFloat[0]);
- sensorValues.AppendElement(aEvent.mData.mFloat[1]);
- sensorValues.AppendElement(aEvent.mData.mFloat[2]);
- sensorValues.AppendElement(aEvent.mData.mFloat[3]);
- }
-
- aSensorData.values() = sensorValues;
-
- return NS_OK;
- }
-
- GonkSensorsPollInterface* mPollInterface;
- nsTArray<SensorsSensor> mSensors;
- SensorsSensorClass mClasses[SENSORS_NUM_TYPES];
-};
-
-static StaticAutoPtr<SensorsPollNotificationHandler> sPollNotificationHandler;
-
-/**
- * This is the notifiaction handler for the Sensors interface. If the backend
- * crashes, we can restart it from here.
- */
-class SensorsNotificationHandler final : public GonkSensorsNotificationHandler
-{
-public:
- SensorsNotificationHandler(GonkSensorsInterface* aInterface)
- : mInterface(aInterface)
- {
- MOZ_ASSERT(mInterface);
-
- mInterface->SetNotificationHandler(this);
- }
-
- void BackendErrorNotification(bool aCrashed) override
- {
- // XXX: Bug 1206056: restart sensorsd
- }
-
-private:
- GonkSensorsInterface* mInterface;
-};
-
-static StaticAutoPtr<SensorsNotificationHandler> sNotificationHandler;
-
-/**
- * |SensorsRegisterModuleResultHandler| implements the result-handler
- * callback for registering the Poll service and activating the first
- * sensors. If an error occures during the process, the result handler
- * disconnects and closes the backend.
- */
-class SensorsRegisterModuleResultHandler final
- : public GonkSensorsRegistryResultHandler
-{
-public:
- SensorsRegisterModuleResultHandler(
- uint32_t* aSensorsTypeActivated,
- GonkSensorsInterface* aInterface)
- : mSensorsTypeActivated(aSensorsTypeActivated)
- , mInterface(aInterface)
- {
- MOZ_ASSERT(mSensorsTypeActivated);
- MOZ_ASSERT(mInterface);
- }
- void OnError(SensorsError aError) override
- {
- GonkSensorsRegistryResultHandler::OnError(aError); // print error message
- Disconnect(); // Registering failed, so close the connection completely
- }
- void RegisterModule(uint32_t aProtocolVersion) override
- {
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!sPollNotificationHandler);
-
- // Init, step 3: set notification handler for poll service and vice versa
- auto pollInterface = mInterface->GetSensorsPollInterface();
- if (!pollInterface) {
- Disconnect();
- return;
- }
- if (NS_FAILED(pollInterface->SetProtocolVersion(aProtocolVersion))) {
- Disconnect();
- return;
- }
-
- sPollNotificationHandler =
- new SensorsPollNotificationHandler(pollInterface);
-
- // Init, step 4: activate sensors
- for (int i = 0; i < SENSORS_NUM_TYPES; ++i) {
- while (mSensorsTypeActivated[i]) {
- sPollNotificationHandler->EnableSensorsByType(
- static_cast<SensorsType>(i));
- --mSensorsTypeActivated[i];
- }
- }
- }
-public:
- void Disconnect()
- {
- class DisconnectResultHandler final : public GonkSensorsResultHandler
- {
- public:
- void OnError(SensorsError aError)
- {
- GonkSensorsResultHandler::OnError(aError); // print error message
- sNotificationHandler = nullptr;
- }
- void Disconnect() override
- {
- sNotificationHandler = nullptr;
- }
- };
- mInterface->Disconnect(new DisconnectResultHandler());
- }
-private:
- uint32_t* mSensorsTypeActivated;
- GonkSensorsInterface* mInterface;
-};
-
-/**
- * |SensorsConnectResultHandler| implements the result-handler
- * callback for starting the Sensors backend.
- */
-class SensorsConnectResultHandler final : public GonkSensorsResultHandler
-{
-public:
- SensorsConnectResultHandler(
- uint32_t* aSensorsTypeActivated,
- GonkSensorsInterface* aInterface)
- : mSensorsTypeActivated(aSensorsTypeActivated)
- , mInterface(aInterface)
- {
- MOZ_ASSERT(mSensorsTypeActivated);
- MOZ_ASSERT(mInterface);
- }
- void OnError(SensorsError aError) override
- {
- GonkSensorsResultHandler::OnError(aError); // print error message
- sNotificationHandler = nullptr;
- }
- void Connect() override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- // Init, step 2: register poll service
- auto registryInterface = mInterface->GetSensorsRegistryInterface();
- if (!registryInterface) {
- return;
- }
- registryInterface->RegisterModule(
- GonkSensorsPollModule::SERVICE_ID,
- new SensorsRegisterModuleResultHandler(mSensorsTypeActivated,
- mInterface));
- }
-private:
- uint32_t* mSensorsTypeActivated;
- GonkSensorsInterface* mInterface;
-};
-
-static uint32_t sSensorsTypeActivated[SENSORS_NUM_TYPES];
-
-static const SensorsType sSensorsType[] = {
- [SENSOR_ORIENTATION] = SENSORS_TYPE_ORIENTATION,
- [SENSOR_ACCELERATION] = SENSORS_TYPE_ACCELEROMETER,
- [SENSOR_PROXIMITY] = SENSORS_TYPE_PROXIMITY,
- [SENSOR_LINEAR_ACCELERATION] = SENSORS_TYPE_LINEAR_ACCELERATION,
- [SENSOR_GYROSCOPE] = SENSORS_TYPE_GYROSCOPE,
- [SENSOR_LIGHT] = SENSORS_TYPE_LIGHT,
- [SENSOR_ROTATION_VECTOR] = SENSORS_TYPE_ROTATION_VECTOR,
- [SENSOR_GAME_ROTATION_VECTOR] = SENSORS_TYPE_GAME_ROTATION_VECTOR
-};
-
-void
-EnableSensorNotificationsDaemon(SensorType aSensor)
-{
- if ((aSensor < 0) ||
- (aSensor > static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sSensorsType)))) {
- HAL_ERR("Sensor type %d not known", aSensor);
- return; // Unsupported sensor type
- }
-
- auto interface = GonkSensorsInterface::GetInstance();
- if (!interface) {
- return;
- }
-
- if (sPollNotificationHandler) {
- // Everythings already up and running; enable sensor type.
- sPollNotificationHandler->EnableSensorsByType(sSensorsType[aSensor]);
- return;
- }
-
- ++SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]);
-
- if (sNotificationHandler) {
- // We are in the middle of a pending start up; nothing else to do.
- return;
- }
-
- // Start up
-
- MOZ_ASSERT(!sPollNotificationHandler);
- MOZ_ASSERT(!sNotificationHandler);
-
- sNotificationHandler = new SensorsNotificationHandler(interface);
-
- // Init, step 1: connect to Sensors backend
- interface->Connect(
- sNotificationHandler,
- new SensorsConnectResultHandler(sSensorsTypeActivated, interface));
-}
-
-void
-DisableSensorNotificationsDaemon(SensorType aSensor)
-{
- if ((aSensor < 0) ||
- (aSensor > static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sSensorsType)))) {
- HAL_ERR("Sensor type %d not known", aSensor);
- return; // Unsupported sensor type
- }
-
- if (sPollNotificationHandler) {
- // Everthings up and running; disable sensors type
- sPollNotificationHandler->DisableSensorsByType(sSensorsType[aSensor]);
- return;
- }
-
- // We might be in the middle of a startup; decrement type's ref-counter.
- --SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]);
-
- // TODO: stop sensorsd if all sensors are disabled
-}
-
-//
-// Public interface
-//
-
-// TODO: Remove in-Gecko sensors code. Until all devices' base
-// images come with sensorsd installed, we have to support the
-// in-Gecko implementation as well. So we test for the existance
-// of the binary. If it's there, we use it. Otherwise we run the
-// old code.
-static bool
-HasDaemon()
-{
- static bool tested;
- static bool hasDaemon;
-
- if (MOZ_UNLIKELY(!tested)) {
- hasDaemon = !access("/system/bin/sensorsd", X_OK);
- tested = true;
- }
-
- return hasDaemon;
-}
-
-void
-EnableSensorNotifications(SensorType aSensor)
-{
- if (HasDaemon()) {
- EnableSensorNotificationsDaemon(aSensor);
- } else {
- EnableSensorNotificationsInternal(aSensor);
- }
-}
-
-void
-DisableSensorNotifications(SensorType aSensor)
-{
- if (HasDaemon()) {
- DisableSensorNotificationsDaemon(aSensor);
- } else {
- DisableSensorNotificationsInternal(aSensor);
- }
-}
-
-} // hal_impl
-} // mozilla
diff --git a/hal/gonk/GonkSensorsHelpers.cpp b/hal/gonk/GonkSensorsHelpers.cpp
deleted file mode 100644
index ccc940c7c..000000000
--- a/hal/gonk/GonkSensorsHelpers.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GonkSensorsHelpers.h"
-
-namespace mozilla {
-namespace hal {
-
-//
-// Unpacking
-//
-
-nsresult
-UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut)
-{
- nsresult rv = UnpackPDU(aPDU, aOut.mType);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = UnpackPDU(aPDU, aOut.mTimestamp);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = UnpackPDU(aPDU, aOut.mStatus);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- size_t i = 0;
-
- switch (aOut.mType) {
- case SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
- case SENSORS_TYPE_GYROSCOPE_UNCALIBRATED:
- /* 6 data values */
- rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
- if (NS_FAILED(rv)) {
- return rv;
- }
- /* fall through */
- case SENSORS_TYPE_ROTATION_VECTOR:
- case SENSORS_TYPE_GAME_ROTATION_VECTOR:
- case SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
- /* 5 data values */
- rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
- if (NS_FAILED(rv)) {
- return rv;
- }
- /* fall through */
- case SENSORS_TYPE_ACCELEROMETER:
- case SENSORS_TYPE_GEOMAGNETIC_FIELD:
- case SENSORS_TYPE_ORIENTATION:
- case SENSORS_TYPE_GYROSCOPE:
- case SENSORS_TYPE_GRAVITY:
- case SENSORS_TYPE_LINEAR_ACCELERATION:
- /* 3 data values */
- rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
- if (NS_FAILED(rv)) {
- return rv;
- }
- /* fall through */
- case SENSORS_TYPE_LIGHT:
- case SENSORS_TYPE_PRESSURE:
- case SENSORS_TYPE_TEMPERATURE:
- case SENSORS_TYPE_PROXIMITY:
- case SENSORS_TYPE_RELATIVE_HUMIDITY:
- case SENSORS_TYPE_AMBIENT_TEMPERATURE:
- case SENSORS_TYPE_HEART_RATE:
- case SENSORS_TYPE_TILT_DETECTOR:
- case SENSORS_TYPE_WAKE_GESTURE:
- case SENSORS_TYPE_GLANCE_GESTURE:
- case SENSORS_TYPE_PICK_UP_GESTURE:
- case SENSORS_TYPE_WRIST_TILT_GESTURE:
- case SENSORS_TYPE_SIGNIFICANT_MOTION:
- case SENSORS_TYPE_STEP_DETECTED:
- /* 1 data value */
- rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
- if (NS_FAILED(rv)) {
- return rv;
- }
- break;
- case SENSORS_TYPE_STEP_COUNTER:
- /* 1 data value */
- rv = UnpackPDU(aPDU, aOut.mData.mUint[0]);
- if (NS_FAILED(rv)) {
- return rv;
- }
- break;
- default:
- if (MOZ_HAL_IPC_UNPACK_WARN_IF(true, SensorsEvent)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- }
- rv = UnpackPDU(aPDU, aOut.mDeliveryMode);
- if (NS_FAILED(rv)) {
- return rv;
- }
- return NS_OK;
-}
-
-} // namespace hal
-} // namespace mozilla
diff --git a/hal/gonk/GonkSensorsHelpers.h b/hal/gonk/GonkSensorsHelpers.h
deleted file mode 100644
index 5218af53a..000000000
--- a/hal/gonk/GonkSensorsHelpers.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef hal_gonk_GonkSensorsHelpers_h
-#define hal_gonk_GonkSensorsHelpers_h
-
-#include <mozilla/ipc/DaemonSocketPDU.h>
-#include <mozilla/ipc/DaemonSocketPDUHelpers.h>
-#include "SensorsTypes.h"
-
-namespace mozilla {
-namespace hal {
-
-using mozilla::ipc::DaemonSocketPDU;
-using mozilla::ipc::DaemonSocketPDUHeader;
-using mozilla::ipc::DaemonSocketPDUHelpers::Convert;
-using mozilla::ipc::DaemonSocketPDUHelpers::PackPDU;
-using mozilla::ipc::DaemonSocketPDUHelpers::UnpackPDU;
-
-using namespace mozilla::ipc::DaemonSocketPDUHelpers;
-
-//
-// Conversion
-//
-// The functions below convert the input value to the output value's
-// type and perform extension tests on the validity of the result. On
-// success the output value will be returned in |aOut|. The functions
-// return NS_OK on success, or an XPCOM error code otherwise.
-//
-// See the documentation of the HAL IPC framework for more information
-// on conversion functions.
-//
-
-nsresult
-Convert(int32_t aIn, SensorsStatus& aOut)
-{
- static const uint8_t sStatus[] = {
- [0] = SENSORS_STATUS_NO_CONTACT, // '-1'
- [1] = SENSORS_STATUS_UNRELIABLE, // '0'
- [2] = SENSORS_STATUS_ACCURACY_LOW, // '1'
- [3] = SENSORS_STATUS_ACCURACY_MEDIUM, // '2'
- [4] = SENSORS_STATUS_ACCURACY_HIGH // '3'
- };
- static const int8_t sOffset = -1; // '-1' is the lower bound of the status
-
- if (MOZ_HAL_IPC_CONVERT_WARN_IF(aIn < sOffset, int32_t, SensorsStatus) ||
- MOZ_HAL_IPC_CONVERT_WARN_IF(
- aIn >= (static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sStatus)) + sOffset),
- int32_t, SensorsStatus)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = static_cast<SensorsStatus>(sStatus[aIn - sOffset]);
- return NS_OK;
-}
-
-nsresult
-Convert(uint8_t aIn, SensorsDeliveryMode& aOut)
-{
- static const uint8_t sMode[] = {
- [0x00] = SENSORS_DELIVERY_MODE_BEST_EFFORT,
- [0x01] = SENSORS_DELIVERY_MODE_IMMEDIATE
- };
- if (MOZ_HAL_IPC_CONVERT_WARN_IF(
- aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsDeliveryMode)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = static_cast<SensorsDeliveryMode>(sMode[aIn]);
- return NS_OK;
-}
-
-nsresult
-Convert(uint8_t aIn, SensorsError& aOut)
-{
- static const uint8_t sError[] = {
- [0x00] = SENSORS_ERROR_NONE,
- [0x01] = SENSORS_ERROR_FAIL,
- [0x02] = SENSORS_ERROR_NOT_READY,
- [0x03] = SENSORS_ERROR_NOMEM,
- [0x04] = SENSORS_ERROR_BUSY,
- [0x05] = SENSORS_ERROR_DONE,
- [0x06] = SENSORS_ERROR_UNSUPPORTED,
- [0x07] = SENSORS_ERROR_PARM_INVALID
- };
- if (MOZ_HAL_IPC_CONVERT_WARN_IF(
- aIn >= MOZ_ARRAY_LENGTH(sError), uint8_t, SensorsError)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = static_cast<SensorsError>(sError[aIn]);
- return NS_OK;
-}
-
-nsresult
-Convert(uint8_t aIn, SensorsTriggerMode& aOut)
-{
- static const uint8_t sMode[] = {
- [0x00] = SENSORS_TRIGGER_MODE_CONTINUOUS,
- [0x01] = SENSORS_TRIGGER_MODE_ON_CHANGE,
- [0x02] = SENSORS_TRIGGER_MODE_ONE_SHOT,
- [0x03] = SENSORS_TRIGGER_MODE_SPECIAL
- };
- if (MOZ_HAL_IPC_CONVERT_WARN_IF(
- aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsTriggerMode)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = static_cast<SensorsTriggerMode>(sMode[aIn]);
- return NS_OK;
-}
-
-nsresult
-Convert(uint32_t aIn, SensorsType& aOut)
-{
- static const uint8_t sType[] = {
- [0x00] = 0, // invalid, required by gcc
- [0x01] = SENSORS_TYPE_ACCELEROMETER,
- [0x02] = SENSORS_TYPE_GEOMAGNETIC_FIELD,
- [0x03] = SENSORS_TYPE_ORIENTATION,
- [0x04] = SENSORS_TYPE_GYROSCOPE,
- [0x05] = SENSORS_TYPE_LIGHT,
- [0x06] = SENSORS_TYPE_PRESSURE,
- [0x07] = SENSORS_TYPE_TEMPERATURE,
- [0x08] = SENSORS_TYPE_PROXIMITY,
- [0x09] = SENSORS_TYPE_GRAVITY,
- [0x0a] = SENSORS_TYPE_LINEAR_ACCELERATION,
- [0x0b] = SENSORS_TYPE_ROTATION_VECTOR,
- [0x0c] = SENSORS_TYPE_RELATIVE_HUMIDITY,
- [0x0d] = SENSORS_TYPE_AMBIENT_TEMPERATURE,
- [0x0e] = SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
- [0x0f] = SENSORS_TYPE_GAME_ROTATION_VECTOR,
- [0x10] = SENSORS_TYPE_GYROSCOPE_UNCALIBRATED,
- [0x11] = SENSORS_TYPE_SIGNIFICANT_MOTION,
- [0x12] = SENSORS_TYPE_STEP_DETECTED,
- [0x13] = SENSORS_TYPE_STEP_COUNTER,
- [0x14] = SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR,
- [0x15] = SENSORS_TYPE_HEART_RATE,
- [0x16] = SENSORS_TYPE_TILT_DETECTOR,
- [0x17] = SENSORS_TYPE_WAKE_GESTURE,
- [0x18] = SENSORS_TYPE_GLANCE_GESTURE,
- [0x19] = SENSORS_TYPE_PICK_UP_GESTURE,
- [0x1a] = SENSORS_TYPE_WRIST_TILT_GESTURE
- };
- if (MOZ_HAL_IPC_CONVERT_WARN_IF(
- !aIn, uint32_t, SensorsType) ||
- MOZ_HAL_IPC_CONVERT_WARN_IF(
- aIn >= MOZ_ARRAY_LENGTH(sType), uint32_t, SensorsType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = static_cast<SensorsType>(sType[aIn]);
- return NS_OK;
-}
-
-nsresult
-Convert(nsresult aIn, SensorsError& aOut)
-{
- if (NS_SUCCEEDED(aIn)) {
- aOut = SENSORS_ERROR_NONE;
- } else if (aIn == NS_ERROR_OUT_OF_MEMORY) {
- aOut = SENSORS_ERROR_NOMEM;
- } else if (aIn == NS_ERROR_ILLEGAL_VALUE) {
- aOut = SENSORS_ERROR_PARM_INVALID;
- } else {
- aOut = SENSORS_ERROR_FAIL;
- }
- return NS_OK;
-}
-
-//
-// Packing
-//
-// Pack functions store a value in PDU. See the documentation of the
-// HAL IPC framework for more information.
-//
-// There are currently no sensor-specific pack functions necessary. If
-// you add one, put it below.
-//
-
-//
-// Unpacking
-//
-// Unpack function retrieve a value from a PDU. The functions return
-// NS_OK on success, or an XPCOM error code otherwise. On sucess, the
-// returned value is stored in the second argument |aOut|.
-//
-// See the documentation of the HAL IPC framework for more information
-// on unpack functions.
-//
-
-nsresult
-UnpackPDU(DaemonSocketPDU& aPDU, SensorsDeliveryMode& aOut)
-{
- return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsDeliveryMode>(aOut));
-}
-
-nsresult
-UnpackPDU(DaemonSocketPDU& aPDU, SensorsError& aOut)
-{
- return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsError>(aOut));
-}
-
-nsresult
-UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut);
-
-nsresult
-UnpackPDU(DaemonSocketPDU& aPDU, SensorsStatus& aOut)
-{
- return UnpackPDU(aPDU, UnpackConversion<int32_t, SensorsStatus>(aOut));
-}
-
-nsresult
-UnpackPDU(DaemonSocketPDU& aPDU, SensorsTriggerMode& aOut)
-{
- return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsTriggerMode>(aOut));
-}
-
-nsresult
-UnpackPDU(DaemonSocketPDU& aPDU, SensorsType& aOut)
-{
- return UnpackPDU(aPDU, UnpackConversion<uint32_t, SensorsType>(aOut));
-}
-
-} // namespace hal
-} // namespace mozilla
-
-#endif // hal_gonk_GonkSensorsHelpers_h
diff --git a/hal/gonk/GonkSensorsInterface.cpp b/hal/gonk/GonkSensorsInterface.cpp
deleted file mode 100644
index 51e1ff50c..000000000
--- a/hal/gonk/GonkSensorsInterface.cpp
+++ /dev/null
@@ -1,494 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GonkSensorsInterface.h"
-#include "GonkSensorsPollInterface.h"
-#include "GonkSensorsRegistryInterface.h"
-#include "HalLog.h"
-#include <mozilla/ipc/DaemonSocket.h>
-#include <mozilla/ipc/DaemonSocketConnector.h>
-#include <mozilla/ipc/ListenSocket.h>
-
-namespace mozilla {
-namespace hal {
-
-using namespace mozilla::ipc;
-
-//
-// GonkSensorsResultHandler
-//
-
-void
-GonkSensorsResultHandler::OnError(SensorsError aError)
-{
- HAL_ERR("Received error code %d", static_cast<int>(aError));
-}
-
-void
-GonkSensorsResultHandler::Connect()
-{ }
-
-void
-GonkSensorsResultHandler::Disconnect()
-{ }
-
-GonkSensorsResultHandler::~GonkSensorsResultHandler()
-{ }
-
-//
-// GonkSensorsNotificationHandler
-//
-
-void
-GonkSensorsNotificationHandler::BackendErrorNotification(bool aCrashed)
-{
- if (aCrashed) {
- HAL_ERR("Sensors backend crashed");
- } else {
- HAL_ERR("Error in sensors backend");
- }
-}
-
-GonkSensorsNotificationHandler::~GonkSensorsNotificationHandler()
-{ }
-
-//
-// GonkSensorsProtocol
-//
-
-class GonkSensorsProtocol final
- : public DaemonSocketIOConsumer
- , public GonkSensorsRegistryModule
- , public GonkSensorsPollModule
-{
-public:
- GonkSensorsProtocol();
-
- void SetConnection(DaemonSocket* aConnection);
-
- already_AddRefed<DaemonSocketResultHandler> FetchResultHandler(
- const DaemonSocketPDUHeader& aHeader);
-
- // Methods for |SensorsRegistryModule| and |SensorsPollModule|
- //
-
- nsresult Send(DaemonSocketPDU* aPDU,
- DaemonSocketResultHandler* aRes) override;
-
- // Methods for |DaemonSocketIOConsumer|
- //
-
- void Handle(DaemonSocketPDU& aPDU) override;
- void StoreResultHandler(const DaemonSocketPDU& aPDU) override;
-
-private:
- void HandleRegistrySvc(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes);
- void HandlePollSvc(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes);
-
- DaemonSocket* mConnection;
- nsTArray<RefPtr<DaemonSocketResultHandler>> mResultHandlerQ;
-};
-
-GonkSensorsProtocol::GonkSensorsProtocol()
-{ }
-
-void
-GonkSensorsProtocol::SetConnection(DaemonSocket* aConnection)
-{
- mConnection = aConnection;
-}
-
-already_AddRefed<DaemonSocketResultHandler>
-GonkSensorsProtocol::FetchResultHandler(const DaemonSocketPDUHeader& aHeader)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- if (aHeader.mOpcode & 0x80) {
- return nullptr; // Ignore notifications
- }
-
- RefPtr<DaemonSocketResultHandler> res = mResultHandlerQ.ElementAt(0);
- mResultHandlerQ.RemoveElementAt(0);
-
- return res.forget();
-}
-
-void
-GonkSensorsProtocol::HandleRegistrySvc(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes)
-{
- GonkSensorsRegistryModule::HandleSvc(aHeader, aPDU, aRes);
-}
-
-void
-GonkSensorsProtocol::HandlePollSvc(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes)
-{
- GonkSensorsPollModule::HandleSvc(aHeader, aPDU, aRes);
-}
-
-// |SensorsRegistryModule|, |SensorsPollModule|
-
-nsresult
-GonkSensorsProtocol::Send(DaemonSocketPDU* aPDU,
- DaemonSocketResultHandler* aRes)
-{
- MOZ_ASSERT(mConnection);
- MOZ_ASSERT(aPDU);
-
- aPDU->SetConsumer(this);
- aPDU->SetResultHandler(aRes);
- aPDU->UpdateHeader();
-
- if (mConnection->GetConnectionStatus() == SOCKET_DISCONNECTED) {
- HAL_ERR("Sensors socket is disconnected");
- return NS_ERROR_FAILURE;
- }
-
- mConnection->SendSocketData(aPDU); // Forward PDU to data channel
-
- return NS_OK;
-}
-
-// |DaemonSocketIOConsumer|
-
-void
-GonkSensorsProtocol::Handle(DaemonSocketPDU& aPDU)
-{
- static void (GonkSensorsProtocol::* const HandleSvc[])(
- const DaemonSocketPDUHeader&, DaemonSocketPDU&,
- DaemonSocketResultHandler*) = {
- [GonkSensorsRegistryModule::SERVICE_ID] =
- &GonkSensorsProtocol::HandleRegistrySvc,
- [GonkSensorsPollModule::SERVICE_ID] =
- &GonkSensorsProtocol::HandlePollSvc
- };
-
- DaemonSocketPDUHeader header;
-
- if (NS_FAILED(UnpackPDU(aPDU, header))) {
- return;
- }
- if (!(header.mService < MOZ_ARRAY_LENGTH(HandleSvc)) ||
- !HandleSvc[header.mService]) {
- HAL_ERR("Sensors service %d unknown", header.mService);
- return;
- }
-
- RefPtr<DaemonSocketResultHandler> res = FetchResultHandler(header);
-
- (this->*(HandleSvc[header.mService]))(header, aPDU, res);
-}
-
-void
-GonkSensorsProtocol::StoreResultHandler(const DaemonSocketPDU& aPDU)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- mResultHandlerQ.AppendElement(aPDU.GetResultHandler());
-}
-
-//
-// GonkSensorsInterface
-//
-
-GonkSensorsInterface*
-GonkSensorsInterface::GetInstance()
-{
- static GonkSensorsInterface* sGonkSensorsInterface;
-
- if (sGonkSensorsInterface) {
- return sGonkSensorsInterface;
- }
-
- sGonkSensorsInterface = new GonkSensorsInterface();
-
- return sGonkSensorsInterface;
-}
-
-void
-GonkSensorsInterface::SetNotificationHandler(
- GonkSensorsNotificationHandler* aNotificationHandler)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mNotificationHandler = aNotificationHandler;
-}
-
-/*
- * The connect procedure consists of several steps.
- *
- * (1) Start listening for the command channel's socket connection: We
- * do this before anything else, so that we don't miss connection
- * requests from the Sensors daemon. This step will create a listen
- * socket.
- *
- * (2) Start the Sensors daemon: When the daemon starts up it will open
- * a socket connection to Gecko and thus create the data channel.
- * Gecko already opened the listen socket in step (1). Step (2) ends
- * with the creation of the data channel.
- *
- * (3) Signal success to the caller.
- *
- * If any step fails, we roll-back the procedure and signal an error to the
- * caller.
- */
-void
-GonkSensorsInterface::Connect(GonkSensorsNotificationHandler* aNotificationHandler,
- GonkSensorsResultHandler* aRes)
-{
-#define BASE_SOCKET_NAME "sensorsd"
- static unsigned long POSTFIX_LENGTH = 16;
-
- // If we could not cleanup properly before and an old
- // instance of the daemon is still running, we kill it
- // here.
- mozilla::hal::StopSystemService("sensorsd");
-
- mNotificationHandler = aNotificationHandler;
-
- mResultHandlerQ.AppendElement(aRes);
-
- if (!mProtocol) {
- mProtocol = MakeUnique<GonkSensorsProtocol>();
- }
-
- if (!mListenSocket) {
- mListenSocket = new ListenSocket(this, LISTEN_SOCKET);
- }
-
- // Init, step 1: Listen for data channel... */
-
- if (!mDataSocket) {
- mDataSocket = new DaemonSocket(mProtocol.get(), this, DATA_SOCKET);
- } else if (mDataSocket->GetConnectionStatus() == SOCKET_CONNECTED) {
- // Command channel should not be open; let's close it.
- mDataSocket->Close();
- }
-
- // The listen socket's name is generated with a random postfix. This
- // avoids naming collisions if we still have a listen socket from a
- // previously failed cleanup. It also makes it hard for malicious
- // external programs to capture the socket name or connect before
- // the daemon can do so. If no random postfix can be generated, we
- // simply use the base name as-is.
- nsresult rv = DaemonSocketConnector::CreateRandomAddressString(
- NS_LITERAL_CSTRING(BASE_SOCKET_NAME), POSTFIX_LENGTH, mListenSocketName);
- if (NS_FAILED(rv)) {
- mListenSocketName.AssignLiteral(BASE_SOCKET_NAME);
- }
-
- rv = mListenSocket->Listen(new DaemonSocketConnector(mListenSocketName),
- mDataSocket);
- if (NS_FAILED(rv)) {
- OnConnectError(DATA_SOCKET);
- return;
- }
-
- // The protocol implementation needs a data channel for
- // sending commands to the daemon. We set it here, because
- // this is the earliest time when it's available.
- mProtocol->SetConnection(mDataSocket);
-}
-
-/*
- * Disconnecting is inverse to connecting.
- *
- * (1) Close data socket: We close the data channel and the daemon will
- * will notice. Once we see the socket's disconnect, we continue with
- * the cleanup.
- *
- * (2) Close listen socket: The listen socket is not active any longer
- * and we simply close it.
- *
- * (3) Signal success to the caller.
- *
- * We don't have to stop the daemon explicitly. It will cleanup and quit
- * after it noticed the closing of the data channel
- *
- * Rolling back half-completed cleanups is not possible. In the case of
- * an error, we simply push forward and try to recover during the next
- * initialization.
- */
-void
-GonkSensorsInterface::Disconnect(GonkSensorsResultHandler* aRes)
-{
- mNotificationHandler = nullptr;
-
- // Cleanup, step 1: Close data channel
- mDataSocket->Close();
-
- mResultHandlerQ.AppendElement(aRes);
-}
-
-GonkSensorsRegistryInterface*
-GonkSensorsInterface::GetSensorsRegistryInterface()
-{
- if (mRegistryInterface) {
- return mRegistryInterface.get();
- }
-
- mRegistryInterface = MakeUnique<GonkSensorsRegistryInterface>(mProtocol.get());
-
- return mRegistryInterface.get();
-}
-
-GonkSensorsPollInterface*
-GonkSensorsInterface::GetSensorsPollInterface()
-{
- if (mPollInterface) {
- return mPollInterface.get();
- }
-
- mPollInterface = MakeUnique<GonkSensorsPollInterface>(mProtocol.get());
-
- return mPollInterface.get();
-}
-
-GonkSensorsInterface::GonkSensorsInterface()
- : mNotificationHandler(nullptr)
-{ }
-
-GonkSensorsInterface::~GonkSensorsInterface()
-{ }
-
-void
-GonkSensorsInterface::DispatchError(GonkSensorsResultHandler* aRes,
- SensorsError aError)
-{
- DaemonResultRunnable1<GonkSensorsResultHandler, void,
- SensorsError, SensorsError>::Dispatch(
- aRes, &GonkSensorsResultHandler::OnError,
- ConstantInitOp1<SensorsError>(aError));
-}
-
-void
-GonkSensorsInterface::DispatchError(
- GonkSensorsResultHandler* aRes, nsresult aRv)
-{
- SensorsError error;
-
- if (NS_FAILED(Convert(aRv, error))) {
- error = SENSORS_ERROR_FAIL;
- }
- DispatchError(aRes, error);
-}
-
-// |DaemonSocketConsumer|, |ListenSocketConsumer|
-
-void
-GonkSensorsInterface::OnConnectSuccess(int aIndex)
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
-
- switch (aIndex) {
- case LISTEN_SOCKET: {
- // Init, step 2: Start Sensors daemon
- nsCString args("-a ");
- args.Append(mListenSocketName);
- mozilla::hal::StartSystemService("sensorsd", args.get());
- }
- break;
- case DATA_SOCKET:
- if (!mResultHandlerQ.IsEmpty()) {
- // Init, step 3: Signal success
- RefPtr<GonkSensorsResultHandler> res = mResultHandlerQ.ElementAt(0);
- mResultHandlerQ.RemoveElementAt(0);
- if (res) {
- res->Connect();
- }
- }
- break;
- }
-}
-
-void
-GonkSensorsInterface::OnConnectError(int aIndex)
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
-
- switch (aIndex) {
- case DATA_SOCKET:
- // Stop daemon and close listen socket
- mozilla::hal::StopSystemService("sensorsd");
- mListenSocket->Close();
- // fall through
- case LISTEN_SOCKET:
- if (!mResultHandlerQ.IsEmpty()) {
- // Signal error to caller
- RefPtr<GonkSensorsResultHandler> res = mResultHandlerQ.ElementAt(0);
- mResultHandlerQ.RemoveElementAt(0);
- if (res) {
- DispatchError(res, SENSORS_ERROR_FAIL);
- }
- }
- break;
- }
-}
-
-/*
- * Disconnects can happend
- *
- * (a) during startup,
- * (b) during regular service, or
- * (c) during shutdown.
- *
- * For cases (a) and (c), |mResultHandlerQ| contains an element. For
- * case (b) |mResultHandlerQ| will be empty. This distinguishes a crash in
- * the daemon. The following procedure to recover from crashes consists of
- * several steps for case (b).
- *
- * (1) Close listen socket.
- * (2) Wait for all sockets to be disconnected and inform caller about
- * the crash.
- * (3) After all resources have been cleaned up, let the caller restart
- * the daemon.
- */
-void
-GonkSensorsInterface::OnDisconnect(int aIndex)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- switch (aIndex) {
- case DATA_SOCKET:
- // Cleanup, step 2 (Recovery, step 1): Close listen socket
- mListenSocket->Close();
- break;
- case LISTEN_SOCKET:
- // Cleanup, step 3: Signal success to caller
- if (!mResultHandlerQ.IsEmpty()) {
- RefPtr<GonkSensorsResultHandler> res = mResultHandlerQ.ElementAt(0);
- mResultHandlerQ.RemoveElementAt(0);
- if (res) {
- res->Disconnect();
- }
- }
- break;
- }
-
- /* For recovery make sure all sockets disconnected, in order to avoid
- * the remaining disconnects interfere with the restart procedure.
- */
- if (mNotificationHandler && mResultHandlerQ.IsEmpty()) {
- if (mListenSocket->GetConnectionStatus() == SOCKET_DISCONNECTED &&
- mDataSocket->GetConnectionStatus() == SOCKET_DISCONNECTED) {
- // Recovery, step 2: Notify the caller to prepare the restart procedure.
- mNotificationHandler->BackendErrorNotification(true);
- mNotificationHandler = nullptr;
- }
- }
-}
-
-} // namespace hal
-} // namespace mozilla
diff --git a/hal/gonk/GonkSensorsInterface.h b/hal/gonk/GonkSensorsInterface.h
deleted file mode 100644
index 6e356dc36..000000000
--- a/hal/gonk/GonkSensorsInterface.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * The sensors interface gives you access to the low-level sensors code
- * in a platform-independent manner. The interfaces in this file allow
- * for starting an stopping the sensors driver. Specific functionality
- * is implemented in sub-interfaces.
- */
-
-#ifndef hal_gonk_GonkSensorsInterface_h
-#define hal_gonk_GonkSensorsInterface_h
-
-#include <mozilla/ipc/DaemonSocketConsumer.h>
-#include <mozilla/ipc/DaemonSocketMessageHandlers.h>
-#include <mozilla/ipc/ListenSocketConsumer.h>
-#include <mozilla/UniquePtr.h>
-#include "SensorsTypes.h"
-
-namespace mozilla {
-namespace ipc {
-
-class DaemonSocket;
-class ListenSocket;
-
-}
-}
-
-namespace mozilla {
-namespace hal {
-
-class GonkSensorsPollInterface;
-class GonkSensorsProtocol;
-class GonkSensorsRegistryInterface;
-
-/**
- * This class is the result-handler interface for the Sensors
- * interface. Methods always run on the main thread.
- */
-class GonkSensorsResultHandler
- : public mozilla::ipc::DaemonSocketResultHandler
-{
-public:
-
- /**
- * Called if a command failed.
- *
- * @param aError The error code.
- */
- virtual void OnError(SensorsError aError);
-
- /**
- * The callback method for |GonkSensorsInterface::Connect|.
- */
- virtual void Connect();
-
- /**
- * The callback method for |GonkSensorsInterface::Connect|.
- */
- virtual void Disconnect();
-
-protected:
- virtual ~GonkSensorsResultHandler();
-};
-
-/**
- * This is the notification-handler interface. Implement this classes
- * methods to handle event and notifications from the sensors daemon.
- * All methods run on the main thread.
- */
-class GonkSensorsNotificationHandler
-{
-public:
-
- /**
- * This notification is called when the backend code fails
- * unexpectedly. Save state in the high-level code and restart
- * the driver.
- *
- * @param aCrash True is the sensors driver crashed.
- */
- virtual void BackendErrorNotification(bool aCrashed);
-
-protected:
- virtual ~GonkSensorsNotificationHandler();
-};
-
-/**
- * This class implements the public interface to the Sensors functionality
- * and driver. Use |GonkSensorsInterface::GetInstance| to retrieve an instance.
- * All methods run on the main thread.
- */
-class GonkSensorsInterface final
- : public mozilla::ipc::DaemonSocketConsumer
- , public mozilla::ipc::ListenSocketConsumer
-{
-public:
- /**
- * Returns an instance of the Sensors backend. This code can return
- * |nullptr| if no Sensors backend is available.
- *
- * @return An instance of |GonkSensorsInterface|.
- */
- static GonkSensorsInterface* GetInstance();
-
- /**
- * This method sets the notification handler for sensor notifications. Call
- * this method immediately after retreiving an instance of the class, or you
- * won't be able able to receive notifications. You may not free the handler
- * class while the Sensors backend is connected.
- *
- * @param aNotificationHandler An instance of a notification handler.
- */
- void SetNotificationHandler(
- GonkSensorsNotificationHandler* aNotificationHandler);
-
- /**
- * This method starts the Sensors backend and establishes ad connection
- * with Gecko. This is a multi-step process and errors are signalled by
- * |GonkSensorsNotificationHandler::BackendErrorNotification|. If you see
- * this notification before the connection has been established, it's
- * certainly best to assume the Sensors backend to be not evailable.
- *
- * @param aRes The result handler.
- */
- void Connect(GonkSensorsNotificationHandler* aNotificationHandler,
- GonkSensorsResultHandler* aRes);
-
- /**
- * This method disconnects Gecko from the Sensors backend and frees
- * the backend's resources. This will invalidate all interfaces and
- * state. Don't use any sensors functionality without reconnecting
- * first.
- *
- * @param aRes The result handler.
- */
- void Disconnect(GonkSensorsResultHandler* aRes);
-
- /**
- * Returns the Registry interface for the connected Sensors backend.
- *
- * @return An instance of the Sensors Registry interface.
- */
- GonkSensorsRegistryInterface* GetSensorsRegistryInterface();
-
- /**
- * Returns the Poll interface for the connected Sensors backend.
- *
- * @return An instance of the Sensors Poll interface.
- */
- GonkSensorsPollInterface* GetSensorsPollInterface();
-
-private:
- enum Channel {
- LISTEN_SOCKET,
- DATA_SOCKET
- };
-
- GonkSensorsInterface();
- ~GonkSensorsInterface();
-
- void DispatchError(GonkSensorsResultHandler* aRes, SensorsError aError);
- void DispatchError(GonkSensorsResultHandler* aRes, nsresult aRv);
-
- // Methods for |DaemonSocketConsumer| and |ListenSocketConsumer|
- //
-
- void OnConnectSuccess(int aIndex) override;
- void OnConnectError(int aIndex) override;
- void OnDisconnect(int aIndex) override;
-
- nsCString mListenSocketName;
- RefPtr<mozilla::ipc::ListenSocket> mListenSocket;
- RefPtr<mozilla::ipc::DaemonSocket> mDataSocket;
- UniquePtr<GonkSensorsProtocol> mProtocol;
-
- nsTArray<RefPtr<GonkSensorsResultHandler> > mResultHandlerQ;
-
- GonkSensorsNotificationHandler* mNotificationHandler;
-
- UniquePtr<GonkSensorsRegistryInterface> mRegistryInterface;
- UniquePtr<GonkSensorsPollInterface> mPollInterface;
-};
-
-} // namespace hal
-} // namespace mozilla
-
-#endif // hal_gonk_GonkSensorsInterface_h
diff --git a/hal/gonk/GonkSensorsPollInterface.cpp b/hal/gonk/GonkSensorsPollInterface.cpp
deleted file mode 100644
index d4edc2e7a..000000000
--- a/hal/gonk/GonkSensorsPollInterface.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GonkSensorsPollInterface.h"
-#include "HalLog.h"
-#include <mozilla/UniquePtr.h>
-
-namespace mozilla {
-namespace hal {
-
-using namespace mozilla::ipc;
-
-//
-// GonkSensorsPollResultHandler
-//
-
-void
-GonkSensorsPollResultHandler::OnError(SensorsError aError)
-{
- HAL_ERR("Received error code %d", static_cast<int>(aError));
-}
-
-void
-GonkSensorsPollResultHandler::EnableSensor()
-{ }
-
-void
-GonkSensorsPollResultHandler::DisableSensor()
-{ }
-
-void
-GonkSensorsPollResultHandler::SetPeriod()
-{ }
-
-GonkSensorsPollResultHandler::~GonkSensorsPollResultHandler()
-{ }
-
-//
-// GonkSensorsPollNotificationHandler
-//
-
-void
-GonkSensorsPollNotificationHandler::ErrorNotification(SensorsError aError)
-{
- HAL_ERR("Received error code %d", static_cast<int>(aError));
-}
-
-void
-GonkSensorsPollNotificationHandler::SensorDetectedNotification(
- int32_t aId,
- SensorsType aType,
- float aRange,
- float aResolution,
- float aPower,
- int32_t aMinPeriod,
- int32_t aMaxPeriod,
- SensorsTriggerMode aTriggerMode,
- SensorsDeliveryMode aDeliveryMode)
-{ }
-
-void
-GonkSensorsPollNotificationHandler::SensorLostNotification(int32_t aId)
-{ }
-
-void
-GonkSensorsPollNotificationHandler::EventNotification(int32_t aId,
- const SensorsEvent& aEvent)
-{ }
-
-GonkSensorsPollNotificationHandler::~GonkSensorsPollNotificationHandler()
-{ }
-
-//
-// GonkSensorsPollModule
-//
-
-GonkSensorsPollModule::GonkSensorsPollModule()
- : mProtocolVersion(0)
-{ }
-
-GonkSensorsPollModule::~GonkSensorsPollModule()
-{ }
-
-nsresult
-GonkSensorsPollModule::SetProtocolVersion(unsigned long aProtocolVersion)
-{
- if ((aProtocolVersion < MIN_PROTOCOL_VERSION) ||
- (aProtocolVersion > MAX_PROTOCOL_VERSION)) {
- HAL_ERR("Sensors Poll protocol version %lu not supported",
- aProtocolVersion);
- return NS_ERROR_ILLEGAL_VALUE;
- }
- mProtocolVersion = aProtocolVersion;
- return NS_OK;
-}
-
-void
-GonkSensorsPollModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes)
-{
- static void (GonkSensorsPollModule::* const HandleOp[])(
- const DaemonSocketPDUHeader&, DaemonSocketPDU&,
- DaemonSocketResultHandler*) = {
- [0] = &GonkSensorsPollModule::HandleRsp,
- [1] = &GonkSensorsPollModule::HandleNtf
- };
-
- MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
-
- // Negate twice to map bit to 0/1
- unsigned long isNtf = !!(aHeader.mOpcode & 0x80);
-
- (this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes);
-}
-
-// Commands
-//
-
-nsresult
-GonkSensorsPollModule::EnableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- UniquePtr<DaemonSocketPDU> pdu =
- MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_ENABLE_SENSOR, 0);
-
- nsresult rv = PackPDU(aId, *pdu);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = Send(pdu.get(), aRes);
- if (NS_FAILED(rv)) {
- return rv;
- }
- Unused << pdu.release();
- return NS_OK;
-}
-
-nsresult
-GonkSensorsPollModule::DisableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- UniquePtr<DaemonSocketPDU> pdu =
- MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DISABLE_SENSOR, 0);
-
- nsresult rv = PackPDU(aId, *pdu);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = Send(pdu.get(), aRes);
- if (NS_FAILED(rv)) {
- return rv;
- }
- Unused << pdu.release();
- return NS_OK;
-}
-
-nsresult
-GonkSensorsPollModule::SetPeriodCmd(int32_t aId, uint64_t aPeriod,
- GonkSensorsPollResultHandler* aRes)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- UniquePtr<DaemonSocketPDU> pdu =
- MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_PERIOD, 0);
-
- nsresult rv = PackPDU(aId, *pdu);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = PackPDU(aPeriod, *pdu);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = Send(pdu.get(), aRes);
- if (NS_FAILED(rv)) {
- return rv;
- }
- Unused << pdu.release();
- return NS_OK;
-}
-
-// Responses
-//
-
-void
-GonkSensorsPollModule::ErrorRsp(
- const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU, GonkSensorsPollResultHandler* aRes)
-{
- ErrorRunnable::Dispatch(
- aRes, &GonkSensorsPollResultHandler::OnError, UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsPollModule::EnableSensorRsp(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
- GonkSensorsPollResultHandler* aRes)
-{
- ResultRunnable::Dispatch(
- aRes, &GonkSensorsPollResultHandler::EnableSensor, UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsPollModule::DisableSensorRsp(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
- GonkSensorsPollResultHandler* aRes)
-{
- ResultRunnable::Dispatch(
- aRes, &GonkSensorsPollResultHandler::DisableSensor, UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsPollModule::SetPeriodRsp(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
- GonkSensorsPollResultHandler* aRes)
-{
- ResultRunnable::Dispatch(
- aRes, &GonkSensorsPollResultHandler::SetPeriod, UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsPollModule::HandleRsp(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes)
-{
- static void (GonkSensorsPollModule::* const sHandleRsp[])(
- const DaemonSocketPDUHeader&, DaemonSocketPDU&,
- GonkSensorsPollResultHandler*) = {
- [OPCODE_ERROR] = &GonkSensorsPollModule::ErrorRsp,
- [OPCODE_ENABLE_SENSOR] = &GonkSensorsPollModule::EnableSensorRsp,
- [OPCODE_DISABLE_SENSOR] = &GonkSensorsPollModule::DisableSensorRsp,
- [OPCODE_SET_PERIOD] = &GonkSensorsPollModule::SetPeriodRsp,
- };
-
- MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
-
- if (!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(sHandleRsp)) ||
- !sHandleRsp[aHeader.mOpcode]) {
- HAL_ERR("Sensors poll response opcode %d unknown", aHeader.mOpcode);
- return;
- }
-
- RefPtr<GonkSensorsPollResultHandler> res =
- static_cast<GonkSensorsPollResultHandler*>(aRes);
-
- if (!res) {
- return; // Return early if no result handler has been set for response
- }
-
- (this->*(sHandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res);
-}
-
-// Notifications
-//
-
-// Returns the current notification handler to a notification runnable
-class GonkSensorsPollModule::NotificationHandlerWrapper final
-{
-public:
- typedef GonkSensorsPollNotificationHandler ObjectType;
-
- static ObjectType* GetInstance()
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- return sNotificationHandler;
- }
-
- static GonkSensorsPollNotificationHandler* sNotificationHandler;
-};
-
-GonkSensorsPollNotificationHandler*
- GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler;
-
-void
-GonkSensorsPollModule::ErrorNtf(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
-{
- ErrorNotification::Dispatch(
- &GonkSensorsPollNotificationHandler::ErrorNotification,
- UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsPollModule::SensorDetectedNtf(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
-{
- SensorDetectedNotification::Dispatch(
- &GonkSensorsPollNotificationHandler::SensorDetectedNotification,
- UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsPollModule::SensorLostNtf(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
-{
- SensorLostNotification::Dispatch(
- &GonkSensorsPollNotificationHandler::SensorLostNotification,
- UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsPollModule::EventNtf(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
-{
- EventNotification::Dispatch(
- &GonkSensorsPollNotificationHandler::EventNotification,
- UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsPollModule::HandleNtf(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes)
-{
- static void (GonkSensorsPollModule::* const sHandleNtf[])(
- const DaemonSocketPDUHeader&, DaemonSocketPDU&) = {
- [0] = &GonkSensorsPollModule::ErrorNtf,
- [1] = &GonkSensorsPollModule::SensorDetectedNtf,
- [2] = &GonkSensorsPollModule::SensorLostNtf,
- [3] = &GonkSensorsPollModule::EventNtf
- };
-
- MOZ_ASSERT(!NS_IsMainThread());
-
- uint8_t index = aHeader.mOpcode - 0x80;
-
- if (!(index < MOZ_ARRAY_LENGTH(sHandleNtf)) || !sHandleNtf[index]) {
- HAL_ERR("Sensors poll notification opcode %d unknown", aHeader.mOpcode);
- return;
- }
-
- (this->*(sHandleNtf[index]))(aHeader, aPDU);
-}
-
-//
-// GonkSensorsPollInterface
-//
-
-GonkSensorsPollInterface::GonkSensorsPollInterface(
- GonkSensorsPollModule* aModule)
- : mModule(aModule)
-{ }
-
-GonkSensorsPollInterface::~GonkSensorsPollInterface()
-{ }
-
-void
-GonkSensorsPollInterface::SetNotificationHandler(
- GonkSensorsPollNotificationHandler* aNotificationHandler)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler =
- aNotificationHandler;
-}
-
-nsresult
-GonkSensorsPollInterface::SetProtocolVersion(unsigned long aProtocolVersion)
-{
- MOZ_ASSERT(mModule);
-
- return mModule->SetProtocolVersion(aProtocolVersion);
-}
-
-void
-GonkSensorsPollInterface::EnableSensor(int32_t aId,
- GonkSensorsPollResultHandler* aRes)
-{
- MOZ_ASSERT(mModule);
-
- nsresult rv = mModule->EnableSensorCmd(aId, aRes);
- if (NS_FAILED(rv)) {
- DispatchError(aRes, rv);
- }
-}
-
-void
-GonkSensorsPollInterface::DisableSensor(int32_t aId,
- GonkSensorsPollResultHandler* aRes)
-{
- MOZ_ASSERT(mModule);
-
- nsresult rv = mModule->DisableSensorCmd(aId, aRes);
- if (NS_FAILED(rv)) {
- DispatchError(aRes, rv);
- }
-}
-
-void
-GonkSensorsPollInterface::SetPeriod(int32_t aId, uint64_t aPeriod,
- GonkSensorsPollResultHandler* aRes)
-{
- MOZ_ASSERT(mModule);
-
- nsresult rv = mModule->SetPeriodCmd(aId, aPeriod, aRes);
- if (NS_FAILED(rv)) {
- DispatchError(aRes, rv);
- }
-}
-
-void
-GonkSensorsPollInterface::DispatchError(
- GonkSensorsPollResultHandler* aRes, SensorsError aError)
-{
- DaemonResultRunnable1<GonkSensorsPollResultHandler, void,
- SensorsError, SensorsError>::Dispatch(
- aRes, &GonkSensorsPollResultHandler::OnError,
- ConstantInitOp1<SensorsError>(aError));
-}
-
-void
-GonkSensorsPollInterface::DispatchError(
- GonkSensorsPollResultHandler* aRes, nsresult aRv)
-{
- SensorsError error;
-
- if (NS_FAILED(Convert(aRv, error))) {
- error = SENSORS_ERROR_FAIL;
- }
- DispatchError(aRes, error);
-}
-
-} // namespace hal
-} // namespace mozilla
diff --git a/hal/gonk/GonkSensorsPollInterface.h b/hal/gonk/GonkSensorsPollInterface.h
deleted file mode 100644
index 89381a9bd..000000000
--- a/hal/gonk/GonkSensorsPollInterface.h
+++ /dev/null
@@ -1,340 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * The poll interface gives yo access to the Sensors daemon's Poll service,
- * which handles sensors. The poll service will inform you when sensors are
- * detected or removed from the system. You can activate (or deactivate)
- * existing sensors and poll will deliver the sensors' events.
- *
- * All public methods and callback methods run on the main thread.
- */
-
-#ifndef hal_gonk_GonkSensorsPollInterface_h
-#define hal_gonk_GonkSensorsPollInterface_h
-
-#include <mozilla/ipc/DaemonRunnables.h>
-#include <mozilla/ipc/DaemonSocketMessageHandlers.h>
-#include "SensorsTypes.h"
-
-namespace mozilla {
-namespace ipc {
-
-class DaemonSocketPDU;
-class DaemonSocketPDUHeader;
-
-}
-}
-
-namespace mozilla {
-namespace hal {
-
-class SensorsInterface;
-
-using mozilla::ipc::DaemonSocketPDU;
-using mozilla::ipc::DaemonSocketPDUHeader;
-using mozilla::ipc::DaemonSocketResultHandler;
-
-/**
- * This class is the result-handler interface for the Sensors
- * Poll interface. Methods always run on the main thread.
- */
-class GonkSensorsPollResultHandler : public DaemonSocketResultHandler
-{
-public:
-
- /**
- * Called if a poll command failed.
- *
- * @param aError The error code.
- */
- virtual void OnError(SensorsError aError);
-
- /**
- * The callback method for |GonkSensorsPollInterface::EnableSensor|.
- */
- virtual void EnableSensor();
-
- /**
- * The callback method for |GonkSensorsPollInterface::DisableSensor|.
- */
- virtual void DisableSensor();
-
- /**
- * The callback method for |GonkSensorsPollInterface::SetPeriod|.
- */
- virtual void SetPeriod();
-
-protected:
- virtual ~GonkSensorsPollResultHandler();
-};
-
-/**
- * This is the notification-handler interface. Implement this classes
- * methods to handle event and notifications from the sensors daemon.
- */
-class GonkSensorsPollNotificationHandler
-{
-public:
-
- /**
- * The notification handler for errors. You'll receive this call if
- * there's been a critical error in the daemon. Either try to handle
- * the error, or restart the daemon.
- *
- * @param aError The error code.
- */
- virtual void ErrorNotification(SensorsError aError);
-
- /**
- * This methods gets call when a new sensor has been detected.
- *
- * @param aId The sensor's id.
- * @param aType The sensor's type.
- * @param aRange The sensor's maximum value.
- * @param aResolution The minimum difference between two consecutive values.
- * @param aPower The sensor's power consumption (in mA).
- * @param aMinPeriod The minimum time between two events (in ns).
- * @param aMaxPeriod The maximum time between two events (in ns).
- * @param aTriggerMode The sensor's mode for triggering events.
- * @param aDeliveryMode The sensor's urgency for event delivery.
- */
- virtual void SensorDetectedNotification(int32_t aId, SensorsType aType,
- float aRange, float aResolution,
- float aPower, int32_t aMinPeriod,
- int32_t aMaxPeriod,
- SensorsTriggerMode aTriggerMode,
- SensorsDeliveryMode aDeliveryMode);
-
- /**
- * This methods gets call when an existing sensor has been removed.
- *
- * @param aId The sensor's id.
- */
- virtual void SensorLostNotification(int32_t aId);
-
- /**
- * This is the callback methods for sensor events. Only activated sensors
- * generate events. All sensors are disabled by default. The actual data
- * of the event depends on the sensor type.
- *
- * @param aId The sensor's id.
- * @param aEvent The event's data.
- */
- virtual void EventNotification(int32_t aId, const SensorsEvent& aEvent);
-
-protected:
- virtual ~GonkSensorsPollNotificationHandler();
-};
-
-/**
- * This is the module class for the Sensors poll component. It handles PDU
- * packing and unpacking. Methods are either executed on the main thread or
- * the I/O thread.
- *
- * This is an internal class, use |GonkSensorsPollInterface| instead.
- */
-class GonkSensorsPollModule
-{
-public:
- class NotificationHandlerWrapper;
-
- enum {
- SERVICE_ID = 0x01
- };
-
- enum {
- OPCODE_ERROR = 0x00,
- OPCODE_ENABLE_SENSOR = 0x01,
- OPCODE_DISABLE_SENSOR = 0x02,
- OPCODE_SET_PERIOD = 0x03
- };
-
- enum {
- MIN_PROTOCOL_VERSION = 1,
- MAX_PROTOCOL_VERSION = 1
- };
-
- virtual nsresult Send(DaemonSocketPDU* aPDU,
- DaemonSocketResultHandler* aRes) = 0;
-
- nsresult SetProtocolVersion(unsigned long aProtocolVersion);
-
- //
- // Commands
- //
-
- nsresult EnableSensorCmd(int32_t aId,
- GonkSensorsPollResultHandler* aRes);
-
- nsresult DisableSensorCmd(int32_t aId,
- GonkSensorsPollResultHandler* aRes);
-
- nsresult SetPeriodCmd(int32_t aId, uint64_t aPeriod,
- GonkSensorsPollResultHandler* aRes);
-
-protected:
- GonkSensorsPollModule();
- virtual ~GonkSensorsPollModule();
-
- void HandleSvc(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes);
-
-private:
-
- //
- // Responses
- //
-
- typedef mozilla::ipc::DaemonResultRunnable0<
- GonkSensorsPollResultHandler, void>
- ResultRunnable;
-
- typedef mozilla::ipc::DaemonResultRunnable1<
- GonkSensorsPollResultHandler, void, SensorsError, SensorsError>
- ErrorRunnable;
-
- void ErrorRsp(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- GonkSensorsPollResultHandler* aRes);
-
- void EnableSensorRsp(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- GonkSensorsPollResultHandler* aRes);
-
- void DisableSensorRsp(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- GonkSensorsPollResultHandler* aRes);
-
- void SetPeriodRsp(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- GonkSensorsPollResultHandler* aRes);
-
- void HandleRsp(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes);
-
- //
- // Notifications
- //
-
- typedef mozilla::ipc::DaemonNotificationRunnable1<
- NotificationHandlerWrapper, void, SensorsError>
- ErrorNotification;
-
- typedef mozilla::ipc::DaemonNotificationRunnable9<
- NotificationHandlerWrapper, void, int32_t, SensorsType,
- float, float, float, int32_t, int32_t, SensorsTriggerMode,
- SensorsDeliveryMode>
- SensorDetectedNotification;
-
- typedef mozilla::ipc::DaemonNotificationRunnable1<
- NotificationHandlerWrapper, void, int32_t>
- SensorLostNotification;
-
- typedef mozilla::ipc::DaemonNotificationRunnable2<
- NotificationHandlerWrapper, void, int32_t, SensorsEvent, int32_t,
- const SensorsEvent&>
- EventNotification;
-
- class SensorDetectedInitOp;
- class SensorLostInitOp;
- class EventInitOp;
-
- void ErrorNtf(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU);
-
- void SensorDetectedNtf(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU);
-
- void SensorLostNtf(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU);
-
- void EventNtf(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU);
-
- void HandleNtf(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes);
-
-private:
- unsigned long mProtocolVersion;
-};
-
-/**
- * This class implements the public interface to the Sensors poll
- * component. Use |SensorsInterface::GetPollInterface| to retrieve
- * an instance. All methods run on the main thread.
- */
-class GonkSensorsPollInterface final
-{
-public:
- GonkSensorsPollInterface(GonkSensorsPollModule* aModule);
- ~GonkSensorsPollInterface();
-
- /**
- * This method sets the notification handler for poll notifications. Call
- * this method immediately after registering the module. Otherwise you won't
- * be able able to receive poll notifications. You may not free the handler
- * class while the poll component is regsitered.
- *
- * @param aNotificationHandler An instance of a poll notification handler.
- */
- void SetNotificationHandler(
- GonkSensorsPollNotificationHandler* aNotificationHandler);
-
- /**
- * This method sets the protocol version. You should set it to the
- * value that has been returned from the backend when registering the
- * Poll service. You cannot send or receive messages before setting
- * the protocol version.
- *
- * @param aProtocolVersion
- * @return NS_OK for supported versions, or an XPCOM error code otherwise.
- */
- nsresult SetProtocolVersion(unsigned long aProtocolVersion);
-
- /**
- * Enables an existing sensor. The sensor id will have been delivered in
- * a SensorDetectedNotification.
- *
- * @param aId The sensor's id.
- * @param aRes The result handler.
- */
- void EnableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes);
-
- /**
- * Disables an existing sensor. The sensor id will have been delivered in
- * a SensorDetectedNotification.
- *
- * @param aId The sensor's id.
- * @param aRes The result handler.
- */
- void DisableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes);
-
- /**
- * Sets the period for a sensor. The sensor id will have been delivered in
- * a SensorDetectedNotification. The value for the period should be between
- * the sensor's minimum and maximum period.
- *
- * @param aId The sensor's id.
- * @param aPeriod The sensor's new period.
- * @param aRes The result handler.
- */
- void SetPeriod(int32_t aId, uint64_t aPeriod, GonkSensorsPollResultHandler* aRes);
-
-private:
- void DispatchError(GonkSensorsPollResultHandler* aRes, SensorsError aError);
- void DispatchError(GonkSensorsPollResultHandler* aRes, nsresult aRv);
-
- GonkSensorsPollModule* mModule;
-};
-
-} // hal
-} // namespace mozilla
-
-#endif // hal_gonk_GonkSensorsPollInterface_h
diff --git a/hal/gonk/GonkSensorsRegistryInterface.cpp b/hal/gonk/GonkSensorsRegistryInterface.cpp
deleted file mode 100644
index 601dc7a2a..000000000
--- a/hal/gonk/GonkSensorsRegistryInterface.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GonkSensorsRegistryInterface.h"
-#include "GonkSensorsHelpers.h"
-#include "HalLog.h"
-#include <mozilla/UniquePtr.h>
-
-namespace mozilla {
-namespace hal {
-
-using namespace mozilla::ipc;
-
-//
-// GonkSensorsRegistryResultHandler
-//
-
-void
-GonkSensorsRegistryResultHandler::OnError(SensorsError aError)
-{
- HAL_ERR("Received error code %d", static_cast<int>(aError));
-}
-
-void
-GonkSensorsRegistryResultHandler::RegisterModule(uint32_t aProtocolVersion)
-{ }
-
-void
-GonkSensorsRegistryResultHandler::UnregisterModule()
-{ }
-
-GonkSensorsRegistryResultHandler::~GonkSensorsRegistryResultHandler()
-{ }
-
-//
-// GonkSensorsRegistryModule
-//
-
-GonkSensorsRegistryModule::~GonkSensorsRegistryModule()
-{ }
-
-void
-GonkSensorsRegistryModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- DaemonSocketResultHandler* aRes)
-{
- static void (GonkSensorsRegistryModule::* const HandleRsp[])(
- const DaemonSocketPDUHeader&,
- DaemonSocketPDU&,
- GonkSensorsRegistryResultHandler*) = {
- [OPCODE_ERROR] = &GonkSensorsRegistryModule::ErrorRsp,
- [OPCODE_REGISTER_MODULE] = &GonkSensorsRegistryModule::RegisterModuleRsp,
- [OPCODE_UNREGISTER_MODULE] = &GonkSensorsRegistryModule::UnregisterModuleRsp
- };
-
- if ((aHeader.mOpcode >= MOZ_ARRAY_LENGTH(HandleRsp)) ||
- !HandleRsp[aHeader.mOpcode]) {
- HAL_ERR("Sensors registry response opcode %d unknown", aHeader.mOpcode);
- return;
- }
-
- RefPtr<GonkSensorsRegistryResultHandler> res =
- static_cast<GonkSensorsRegistryResultHandler*>(aRes);
-
- if (!res) {
- return; // Return early if no result handler has been set
- }
-
- (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res);
-}
-
-// Commands
-//
-
-nsresult
-GonkSensorsRegistryModule::RegisterModuleCmd(
- uint8_t aId, GonkSensorsRegistryResultHandler* aRes)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- UniquePtr<DaemonSocketPDU> pdu =
- MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_REGISTER_MODULE, 0);
-
- nsresult rv = PackPDU(aId, *pdu);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = Send(pdu.get(), aRes);
- if (NS_FAILED(rv)) {
- return rv;
- }
- Unused << pdu.release();
- return NS_OK;
-}
-
-nsresult
-GonkSensorsRegistryModule::UnregisterModuleCmd(
- uint8_t aId, GonkSensorsRegistryResultHandler* aRes)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- UniquePtr<DaemonSocketPDU> pdu =
- MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_UNREGISTER_MODULE, 0);
-
- nsresult rv = PackPDU(aId, *pdu);
- if (NS_FAILED(rv)) {
- return rv;
- }
- rv = Send(pdu.get(), aRes);
- if (NS_FAILED(rv)) {
- return rv;
- }
- Unused << pdu.release();
- return NS_OK;
-}
-
-// Responses
-//
-
-void
-GonkSensorsRegistryModule::ErrorRsp(
- const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU, GonkSensorsRegistryResultHandler* aRes)
-{
- ErrorRunnable::Dispatch(
- aRes, &GonkSensorsRegistryResultHandler::OnError, UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsRegistryModule::RegisterModuleRsp(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
- GonkSensorsRegistryResultHandler* aRes)
-{
- Uint32ResultRunnable::Dispatch(
- aRes,
- &GonkSensorsRegistryResultHandler::RegisterModule,
- UnpackPDUInitOp(aPDU));
-}
-
-void
-GonkSensorsRegistryModule::UnregisterModuleRsp(
- const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
- GonkSensorsRegistryResultHandler* aRes)
-{
- ResultRunnable::Dispatch(
- aRes,
- &GonkSensorsRegistryResultHandler::UnregisterModule,
- UnpackPDUInitOp(aPDU));
-}
-
-//
-// GonkSensorsRegistryInterface
-//
-
-GonkSensorsRegistryInterface::GonkSensorsRegistryInterface(
- GonkSensorsRegistryModule* aModule)
- : mModule(aModule)
-{ }
-
-GonkSensorsRegistryInterface::~GonkSensorsRegistryInterface()
-{ }
-
-void
-GonkSensorsRegistryInterface::RegisterModule(
- uint8_t aId, GonkSensorsRegistryResultHandler* aRes)
-{
- MOZ_ASSERT(mModule);
-
- nsresult rv = mModule->RegisterModuleCmd(aId, aRes);
- if (NS_FAILED(rv)) {
- DispatchError(aRes, rv);
- }
-}
-
-void
-GonkSensorsRegistryInterface::UnregisterModule(
- uint8_t aId, GonkSensorsRegistryResultHandler* aRes)
-{
- MOZ_ASSERT(mModule);
-
- nsresult rv = mModule->UnregisterModuleCmd(aId, aRes);
- if (NS_FAILED(rv)) {
- DispatchError(aRes, rv);
- }
-}
-
-void
-GonkSensorsRegistryInterface::DispatchError(
- GonkSensorsRegistryResultHandler* aRes, SensorsError aError)
-{
- DaemonResultRunnable1<GonkSensorsRegistryResultHandler, void,
- SensorsError, SensorsError>::Dispatch(
- aRes, &GonkSensorsRegistryResultHandler::OnError,
- ConstantInitOp1<SensorsError>(aError));
-}
-
-void
-GonkSensorsRegistryInterface::DispatchError(
- GonkSensorsRegistryResultHandler* aRes, nsresult aRv)
-{
- SensorsError error;
-
- if (NS_FAILED(Convert(aRv, error))) {
- error = SENSORS_ERROR_FAIL;
- }
- DispatchError(aRes, error);
-}
-
-} // namespace hal
-} // namespace mozilla
diff --git a/hal/gonk/GonkSensorsRegistryInterface.h b/hal/gonk/GonkSensorsRegistryInterface.h
deleted file mode 100644
index a9d98d653..000000000
--- a/hal/gonk/GonkSensorsRegistryInterface.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * The registry interface gives yo access to the Sensors daemon's Registry
- * service. The purpose of the service is to register and setup all other
- * services, and make them available.
- *
- * All public methods and callback methods run on the main thread.
- */
-
-#ifndef hal_gonk_GonkSensorsRegistryInterface_h
-#define hal_gonk_GonkSensorsRegistryInterface_h
-
-#include <mozilla/ipc/DaemonRunnables.h>
-#include <mozilla/ipc/DaemonSocketMessageHandlers.h>
-#include "SensorsTypes.h"
-
-namespace mozilla {
-namespace ipc {
-
-class DaemonSocketPDU;
-class DaemonSocketPDUHeader;
-
-}
-}
-
-namespace mozilla {
-namespace hal {
-
-class SensorsInterface;
-
-using mozilla::ipc::DaemonSocketPDU;
-using mozilla::ipc::DaemonSocketPDUHeader;
-using mozilla::ipc::DaemonSocketResultHandler;
-
-/**
- * This class is the result-handler interface for the Sensors
- * Registry interface. Methods always run on the main thread.
- */
-class GonkSensorsRegistryResultHandler : public DaemonSocketResultHandler
-{
-public:
-
- /**
- * Called if a registry command failed.
- *
- * @param aError The error code.
- */
- virtual void OnError(SensorsError aError);
-
- /**
- * The callback method for |GonkSensorsRegistryInterface::RegisterModule|.
- *
- * @param aProtocolVersion The daemon's protocol version. Make sure it's
- * compatible with Gecko's implementation.
- */
- virtual void RegisterModule(uint32_t aProtocolVersion);
-
- /**
- * The callback method for |SensorsRegsitryInterface::UnregisterModule|.
- */
- virtual void UnregisterModule();
-
-protected:
- virtual ~GonkSensorsRegistryResultHandler();
-};
-
-/**
- * This is the module class for the Sensors registry component. It handles
- * PDU packing and unpacking. Methods are either executed on the main thread
- * or the I/O thread.
- *
- * This is an internal class, use |GonkSensorsRegistryInterface| instead.
- */
-class GonkSensorsRegistryModule
-{
-public:
- enum {
- SERVICE_ID = 0x00
- };
-
- enum {
- OPCODE_ERROR = 0x00,
- OPCODE_REGISTER_MODULE = 0x01,
- OPCODE_UNREGISTER_MODULE = 0x02
- };
-
- virtual nsresult Send(DaemonSocketPDU* aPDU,
- DaemonSocketResultHandler* aRes) = 0;
-
- //
- // Commands
- //
-
- nsresult RegisterModuleCmd(uint8_t aId,
- GonkSensorsRegistryResultHandler* aRes);
-
- nsresult UnregisterModuleCmd(uint8_t aId,
- GonkSensorsRegistryResultHandler* aRes);
-
-protected:
- virtual ~GonkSensorsRegistryModule();
-
- void HandleSvc(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes);
-
- //
- // Responses
- //
-
- typedef mozilla::ipc::DaemonResultRunnable0<
- GonkSensorsRegistryResultHandler, void>
- ResultRunnable;
-
- typedef mozilla::ipc::DaemonResultRunnable1<
- GonkSensorsRegistryResultHandler, void, uint32_t, uint32_t>
- Uint32ResultRunnable;
-
- typedef mozilla::ipc::DaemonResultRunnable1<
- GonkSensorsRegistryResultHandler, void, SensorsError, SensorsError>
- ErrorRunnable;
-
- void ErrorRsp(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- GonkSensorsRegistryResultHandler* aRes);
-
- void RegisterModuleRsp(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- GonkSensorsRegistryResultHandler* aRes);
-
- void UnregisterModuleRsp(const DaemonSocketPDUHeader& aHeader,
- DaemonSocketPDU& aPDU,
- GonkSensorsRegistryResultHandler* aRes);
-};
-
-/**
- * This class implements the public interface to the Sensors Registry
- * component. Use |SensorsInterface::GetRegistryInterface| to retrieve
- * an instance. All methods run on the main thread.
- */
-class GonkSensorsRegistryInterface final
-{
-public:
- GonkSensorsRegistryInterface(GonkSensorsRegistryModule* aModule);
- ~GonkSensorsRegistryInterface();
-
- /**
- * Sends a RegisterModule command to the Sensors daemon. When the
- * result handler's |RegisterModule| method gets called, the service
- * has been registered successfully and can be used.
- *
- * @param aId The id of the service that is to be registered.
- * @param aRes The result handler.
- */
- void RegisterModule(uint8_t aId, GonkSensorsRegistryResultHandler* aRes);
-
- /**
- * Sends an UnregisterModule command to the Sensors daemon. The service
- * should not be used afterwards until it has been registered again.
- *
- * @param aId The id of the service that is to be unregistered.
- * @param aRes The result handler.
- */
- void UnregisterModule(uint8_t aId, GonkSensorsRegistryResultHandler* aRes);
-
-private:
- void DispatchError(GonkSensorsRegistryResultHandler* aRes,
- SensorsError aError);
- void DispatchError(GonkSensorsRegistryResultHandler* aRes,
- nsresult aRv);
-
- GonkSensorsRegistryModule* mModule;
-};
-
-} // namespace hal
-} // namespace mozilla
-
-#endif // hal_gonk_GonkSensorsRegistryInterface_h
diff --git a/hal/gonk/GonkSwitch.cpp b/hal/gonk/GonkSwitch.cpp
deleted file mode 100644
index b2c31c973..000000000
--- a/hal/gonk/GonkSwitch.cpp
+++ /dev/null
@@ -1,479 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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 <sysutils/NetlinkEvent.h>
-
-#include "base/message_loop.h"
-#include "base/task.h"
-
-#include "Hal.h"
-#include "HalLog.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/Monitor.h"
-#include "nsPrintfCString.h"
-#include "nsXULAppAPI.h"
-#include "nsThreadUtils.h"
-#include "UeventPoller.h"
-
-using namespace mozilla::hal;
-
-#define SWITCH_HEADSET_DEVPATH "/devices/virtual/switch/h2w"
-#define SWITCH_USB_DEVPATH_GB "/devices/virtual/switch/usb_configuration"
-#define SWITCH_USB_DEVPATH_ICS "/devices/virtual/android_usb/android0"
-
-namespace mozilla {
-namespace hal_impl {
-/**
- * The uevent for a usb on GB insertion looks like:
- *
- * change@/devices/virtual/switch/usb_configuration
- * ACTION=change
- * DEVPATH=/devices/virtual/switch/usb_configuration
- * SUBSYSTEM=switch
- * SWITCH_NAME=usb_configuration
- * SWITCH_STATE=0
- * SEQNUM=5038
- */
-class SwitchHandler
-{
-public:
- NS_INLINE_DECL_REFCOUNTING(SwitchHandler)
-
- SwitchHandler(const char* aDevPath, SwitchDevice aDevice)
- : mDevPath(aDevPath),
- mState(SWITCH_STATE_UNKNOWN),
- mDevice(aDevice)
- {
- GetInitialState();
- }
-
- bool CheckEvent(NetlinkEvent* aEvent)
- {
- if (strcmp(GetSubsystem(), aEvent->getSubsystem()) ||
- strcmp(mDevPath, aEvent->findParam("DEVPATH"))) {
- return false;
- }
-
- mState = ConvertState(GetStateString(aEvent));
- return mState != SWITCH_STATE_UNKNOWN;
- }
-
- SwitchState GetState()
- {
- return mState;
- }
-
- SwitchDevice GetType()
- {
- return mDevice;
- }
-protected:
- virtual ~SwitchHandler()
- {
- }
-
- virtual const char* GetSubsystem()
- {
- return "switch";
- }
-
- virtual const char* GetStateString(NetlinkEvent* aEvent)
- {
- return aEvent->findParam("SWITCH_STATE");
- }
-
- void GetInitialState()
- {
- nsPrintfCString statePath("/sys%s/state", mDevPath);
- int fd = open(statePath.get(), O_RDONLY);
- if (fd <= 0) {
- return;
- }
-
- ScopedClose autoClose(fd);
- char state[16];
- ssize_t bytesRead = read(fd, state, sizeof(state));
- if (bytesRead < 0) {
- HAL_ERR("Read data from %s fails", statePath.get());
- return;
- }
-
- if (state[bytesRead - 1] == '\n') {
- bytesRead--;
- }
-
- state[bytesRead] = '\0';
- mState = ConvertState(state);
- }
-
- virtual SwitchState ConvertState(const char* aState)
- {
- MOZ_ASSERT(aState);
- return aState[0] == '0' ? SWITCH_STATE_OFF : SWITCH_STATE_ON;
- }
-
- const char* mDevPath;
- SwitchState mState;
- SwitchDevice mDevice;
-};
-
-/**
- * The uevent delivered for the USB configuration under ICS looks like,
- *
- * change@/devices/virtual/android_usb/android0
- * ACTION=change
- * DEVPATH=/devices/virtual/android_usb/android0
- * SUBSYSTEM=android_usb
- * USB_STATE=CONFIGURED
- * SEQNUM=1802
- */
-class SwitchHandlerUsbIcs: public SwitchHandler
-{
-public:
- SwitchHandlerUsbIcs(const char* aDevPath) : SwitchHandler(aDevPath, SWITCH_USB)
- {
- SwitchHandler::GetInitialState();
- }
-
- virtual ~SwitchHandlerUsbIcs() { }
-
-protected:
- virtual const char* GetSubsystem()
- {
- return "android_usb";
- }
-
- virtual const char* GetStateString(NetlinkEvent* aEvent)
- {
- return aEvent->findParam("USB_STATE");
- }
-
- SwitchState ConvertState(const char* aState)
- {
- MOZ_ASSERT(aState);
- return strcmp(aState, "CONFIGURED") == 0 ? SWITCH_STATE_ON : SWITCH_STATE_OFF;
- }
-};
-
-/**
- * The uevent delivered for the headset under ICS looks like,
- *
- * change@/devices/virtual/switch/h2w
- * ACTION=change
- * DEVPATH=/devices/virtual/switch/h2w
- * SUBSYSTEM=switch
- * SWITCH_NAME=h2w
- * SWITCH_STATE=2 // Headset with no mic
- * SEQNUM=2581
- * On Otoro, SWITCH_NAME could be Headset/No Device when plug/unplug.
- * change@/devices/virtual/switch/h2w
- * ACTION=change
- * DEVPATH=/devices/virtual/switch/h2w
- * SUBSYSTEM=switch
- * SWITCH_NAME=Headset
- * SWITCH_STATE=1 // Headset with mic
- * SEQNUM=1602
- */
-class SwitchHandlerHeadphone: public SwitchHandler
-{
-public:
- SwitchHandlerHeadphone(const char* aDevPath) :
- SwitchHandler(aDevPath, SWITCH_HEADPHONES)
- {
- SwitchHandler::GetInitialState();
- }
-
- virtual ~SwitchHandlerHeadphone() { }
-
-protected:
- SwitchState ConvertState(const char* aState)
- {
- MOZ_ASSERT(aState);
-
- return aState[0] == '0' ? SWITCH_STATE_OFF :
- (aState[0] == '1' ? SWITCH_STATE_HEADSET : SWITCH_STATE_HEADPHONE);
- }
-};
-
-
-typedef nsTArray<RefPtr<SwitchHandler> > SwitchHandlerArray;
-
-class SwitchEventRunnable : public Runnable
-{
-public:
- SwitchEventRunnable(SwitchEvent& aEvent) : mEvent(aEvent)
- {
- }
-
- NS_IMETHOD Run() override
- {
- NotifySwitchChange(mEvent);
- return NS_OK;
- }
-private:
- SwitchEvent mEvent;
-};
-
-class SwitchEventObserver final : public IUeventObserver
-{
- ~SwitchEventObserver()
- {
- mHandler.Clear();
- }
-
-public:
- NS_INLINE_DECL_REFCOUNTING(SwitchEventObserver)
- SwitchEventObserver()
- : mEnableCount(0),
- mHeadphonesFromInputDev(false)
- {
- Init();
- }
-
- int GetEnableCount()
- {
- return mEnableCount;
- }
-
- void EnableSwitch(SwitchDevice aDevice)
- {
- mEventInfo[aDevice].mEnabled = true;
- mEnableCount++;
- }
-
- void DisableSwitch(SwitchDevice aDevice)
- {
- mEventInfo[aDevice].mEnabled = false;
- mEnableCount--;
- }
-
- void Notify(const NetlinkEvent& aEvent)
- {
- SwitchState currState;
-
- SwitchDevice device = GetEventInfo(aEvent, currState);
- if (device == SWITCH_DEVICE_UNKNOWN) {
- return;
- }
-
- EventInfo& info = mEventInfo[device];
- if (currState == info.mEvent.status()) {
- return;
- }
-
- info.mEvent.status() = currState;
-
- if (info.mEnabled) {
- NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent));
- }
- }
-
- void Notify(SwitchDevice aDevice, SwitchState aState)
- {
- EventInfo& info = mEventInfo[aDevice];
- if (aState == info.mEvent.status()) {
- return;
- }
-
- info.mEvent.status() = aState;
-
- if (info.mEnabled) {
- NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent));
- }
- }
-
- SwitchState GetCurrentInformation(SwitchDevice aDevice)
- {
- return mEventInfo[aDevice].mEvent.status();
- }
-
- void NotifyAnEvent(SwitchDevice aDevice)
- {
- EventInfo& info = mEventInfo[aDevice];
- if (info.mEvent.status() != SWITCH_STATE_UNKNOWN) {
- NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent));
- }
- }
-
- bool GetHeadphonesFromInputDev()
- {
- return mHeadphonesFromInputDev;
- }
-
-private:
- class EventInfo
- {
- public:
- EventInfo() : mEnabled(false)
- {
- mEvent.status() = SWITCH_STATE_UNKNOWN;
- mEvent.device() = SWITCH_DEVICE_UNKNOWN;
- }
- SwitchEvent mEvent;
- bool mEnabled;
- };
-
- EventInfo mEventInfo[NUM_SWITCH_DEVICE];
- size_t mEnableCount;
- SwitchHandlerArray mHandler;
- bool mHeadphonesFromInputDev;
-
- // This function might also get called on the main thread
- // (from IsHeadphoneEventFromInputDev)
- void Init()
- {
- RefPtr<SwitchHandlerHeadphone> switchHeadPhone =
- new SwitchHandlerHeadphone(SWITCH_HEADSET_DEVPATH);
-
- // If the initial state is unknown, it means the headphone event is from input dev
- mHeadphonesFromInputDev = switchHeadPhone->GetState() == SWITCH_STATE_UNKNOWN ? true : false;
-
- if (!mHeadphonesFromInputDev) {
- mHandler.AppendElement(switchHeadPhone);
- } else {
- // If headphone status will be notified from input dev then initialize
- // status to "off" and wait for event notification.
- mEventInfo[SWITCH_HEADPHONES].mEvent.device() = SWITCH_HEADPHONES;
- mEventInfo[SWITCH_HEADPHONES].mEvent.status() = SWITCH_STATE_OFF;
- }
- mHandler.AppendElement(new SwitchHandler(SWITCH_USB_DEVPATH_GB, SWITCH_USB));
- mHandler.AppendElement(new SwitchHandlerUsbIcs(SWITCH_USB_DEVPATH_ICS));
-
- SwitchHandlerArray::index_type handlerIndex;
- SwitchHandlerArray::size_type numHandlers = mHandler.Length();
-
- for (handlerIndex = 0; handlerIndex < numHandlers; handlerIndex++) {
- SwitchState state = mHandler[handlerIndex]->GetState();
- if (state == SWITCH_STATE_UNKNOWN) {
- continue;
- }
-
- SwitchDevice device = mHandler[handlerIndex]->GetType();
- mEventInfo[device].mEvent.device() = device;
- mEventInfo[device].mEvent.status() = state;
- }
- }
-
- SwitchDevice GetEventInfo(const NetlinkEvent& aEvent, SwitchState& aState)
- {
- //working around the android code not being const-correct
- NetlinkEvent *e = const_cast<NetlinkEvent*>(&aEvent);
-
- for (size_t i = 0; i < mHandler.Length(); i++) {
- if (mHandler[i]->CheckEvent(e)) {
- aState = mHandler[i]->GetState();
- return mHandler[i]->GetType();
- }
- }
- return SWITCH_DEVICE_UNKNOWN;
- }
-};
-
-static RefPtr<SwitchEventObserver> sSwitchObserver;
-
-static void
-InitializeResourceIfNeed()
-{
- if (!sSwitchObserver) {
- sSwitchObserver = new SwitchEventObserver();
- RegisterUeventListener(sSwitchObserver);
- }
-}
-
-static void
-ReleaseResourceIfNeed()
-{
- if (sSwitchObserver->GetEnableCount() == 0) {
- UnregisterUeventListener(sSwitchObserver);
- sSwitchObserver = nullptr;
- }
-}
-
-static void
-EnableSwitchNotificationsIOThread(SwitchDevice aDevice, Monitor *aMonitor)
-{
- InitializeResourceIfNeed();
- sSwitchObserver->EnableSwitch(aDevice);
- {
- MonitorAutoLock lock(*aMonitor);
- lock.Notify();
- }
-
- // Notify the latest state if IO thread has the information.
- if (sSwitchObserver->GetEnableCount() > 1) {
- sSwitchObserver->NotifyAnEvent(aDevice);
- }
-}
-
-void
-EnableSwitchNotifications(SwitchDevice aDevice)
-{
- Monitor monitor("EnableSwitch.monitor");
- {
- MonitorAutoLock lock(monitor);
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(EnableSwitchNotificationsIOThread, aDevice, &monitor));
- lock.Wait();
- }
-}
-
-static void
-DisableSwitchNotificationsIOThread(SwitchDevice aDevice)
-{
- MOZ_ASSERT(sSwitchObserver->GetEnableCount());
- sSwitchObserver->DisableSwitch(aDevice);
- ReleaseResourceIfNeed();
-}
-
-void
-DisableSwitchNotifications(SwitchDevice aDevice)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(DisableSwitchNotificationsIOThread, aDevice));
-}
-
-SwitchState
-GetCurrentSwitchState(SwitchDevice aDevice)
-{
- MOZ_ASSERT(sSwitchObserver && sSwitchObserver->GetEnableCount());
- return sSwitchObserver->GetCurrentInformation(aDevice);
-}
-
-static void
-NotifySwitchStateIOThread(SwitchDevice aDevice, SwitchState aState)
-{
- InitializeResourceIfNeed();
- sSwitchObserver->Notify(aDevice, aState);
-}
-
-void NotifySwitchStateFromInputDevice(SwitchDevice aDevice, SwitchState aState)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(NotifySwitchStateIOThread, aDevice, aState));
-}
-
-bool IsHeadphoneEventFromInputDev()
-{
- // Instead of calling InitializeResourceIfNeed, create new SwitchEventObserver
- // to prevent calling RegisterUeventListener in main thread.
- RefPtr<SwitchEventObserver> switchObserver = new SwitchEventObserver();
- return switchObserver->GetHeadphonesFromInputDev();
-}
-
-} // hal_impl
-} //mozilla
diff --git a/hal/gonk/SensorsTypes.h b/hal/gonk/SensorsTypes.h
deleted file mode 100644
index 35c852f5a..000000000
--- a/hal/gonk/SensorsTypes.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef hal_gonk_SensorsTypes_h
-#define hal_gonk_SensorsTypes_h
-
-namespace mozilla {
-namespace hal {
-
-enum SensorsDeliveryMode {
- SENSORS_DELIVERY_MODE_BEST_EFFORT,
- SENSORS_DELIVERY_MODE_IMMEDIATE
-};
-
-enum SensorsError {
- SENSORS_ERROR_NONE,
- SENSORS_ERROR_FAIL,
- SENSORS_ERROR_NOT_READY,
- SENSORS_ERROR_NOMEM,
- SENSORS_ERROR_BUSY,
- SENSORS_ERROR_DONE,
- SENSORS_ERROR_UNSUPPORTED,
- SENSORS_ERROR_PARM_INVALID
-};
-
-enum SensorsStatus {
- SENSORS_STATUS_NO_CONTACT,
- SENSORS_STATUS_UNRELIABLE,
- SENSORS_STATUS_ACCURACY_LOW,
- SENSORS_STATUS_ACCURACY_MEDIUM,
- SENSORS_STATUS_ACCURACY_HIGH
-};
-
-enum SensorsTriggerMode {
- SENSORS_TRIGGER_MODE_CONTINUOUS,
- SENSORS_TRIGGER_MODE_ON_CHANGE,
- SENSORS_TRIGGER_MODE_ONE_SHOT,
- SENSORS_TRIGGER_MODE_SPECIAL
-};
-
-enum SensorsType {
- SENSORS_TYPE_ACCELEROMETER,
- SENSORS_TYPE_GEOMAGNETIC_FIELD,
- SENSORS_TYPE_ORIENTATION,
- SENSORS_TYPE_GYROSCOPE,
- SENSORS_TYPE_LIGHT,
- SENSORS_TYPE_PRESSURE,
- SENSORS_TYPE_TEMPERATURE,
- SENSORS_TYPE_PROXIMITY,
- SENSORS_TYPE_GRAVITY,
- SENSORS_TYPE_LINEAR_ACCELERATION,
- SENSORS_TYPE_ROTATION_VECTOR,
- SENSORS_TYPE_RELATIVE_HUMIDITY,
- SENSORS_TYPE_AMBIENT_TEMPERATURE,
- SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
- SENSORS_TYPE_GAME_ROTATION_VECTOR,
- SENSORS_TYPE_GYROSCOPE_UNCALIBRATED,
- SENSORS_TYPE_SIGNIFICANT_MOTION,
- SENSORS_TYPE_STEP_DETECTED,
- SENSORS_TYPE_STEP_COUNTER,
- SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR,
- SENSORS_TYPE_HEART_RATE,
- SENSORS_TYPE_TILT_DETECTOR,
- SENSORS_TYPE_WAKE_GESTURE,
- SENSORS_TYPE_GLANCE_GESTURE,
- SENSORS_TYPE_PICK_UP_GESTURE,
- SENSORS_TYPE_WRIST_TILT_GESTURE,
- SENSORS_NUM_TYPES
-};
-
-struct SensorsEvent {
- SensorsType mType;
- SensorsStatus mStatus;
- SensorsDeliveryMode mDeliveryMode;
- int64_t mTimestamp;
- union {
- float mFloat[6];
- uint64_t mUint[1];
- } mData;
-};
-
-/**
- * |SensorsSensor| represents a device sensor; either single or composite.
- */
-struct SensorsSensor {
- SensorsSensor(int32_t aId, SensorsType aType,
- float aRange, float aResolution,
- float aPower, int32_t aMinPeriod,
- int32_t aMaxPeriod,
- SensorsTriggerMode aTriggerMode,
- SensorsDeliveryMode aDeliveryMode)
- : mId(aId)
- , mType(aType)
- , mRange(aRange)
- , mResolution(aResolution)
- , mPower(aPower)
- , mMinPeriod(aMinPeriod)
- , mMaxPeriod(aMaxPeriod)
- , mTriggerMode(aTriggerMode)
- , mDeliveryMode(aDeliveryMode)
- { }
-
- int32_t mId;
- SensorsType mType;
- float mRange;
- float mResolution;
- float mPower;
- int32_t mMinPeriod;
- int32_t mMaxPeriod;
- SensorsTriggerMode mTriggerMode;
- SensorsDeliveryMode mDeliveryMode;
-};
-
-/**
- * |SensorClass| represents the status of a specific sensor type.
- */
-struct SensorsSensorClass {
- SensorsSensorClass()
- : mActivated(0)
- , mMinValue(0)
- , mMaxValue(0)
- { }
-
- void UpdateFromSensor(const SensorsSensor& aSensor)
- {
- mMaxValue = std::max(aSensor.mRange, mMaxValue);
- }
-
- uint32_t mActivated;
- float mMinValue;
- float mMaxValue;
-};
-
-} // namespace hal
-} // namespace mozilla
-
-#endif // hal_gonk_SensorsTypes_h
diff --git a/hal/gonk/SystemService.cpp b/hal/gonk/SystemService.cpp
deleted file mode 100644
index 2b98f5fdd..000000000
--- a/hal/gonk/SystemService.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=8 et ft=cpp : */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "Hal.h"
-
-#include <cutils/properties.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "HalLog.h"
-#include "nsITimer.h"
-#include "mozilla/Unused.h"
-
-namespace mozilla {
-namespace hal_impl {
-
-static const int sRetryInterval = 100; // ms
-
-bool
-SystemServiceIsRunning(const char* aSvcName)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- char key[PROPERTY_KEY_MAX];
- auto res = snprintf(key, sizeof(key), "init.svc.%s", aSvcName);
-
- if (res < 0) {
- HAL_ERR("snprintf: %s", strerror(errno));
- return false;
- } else if (static_cast<size_t>(res) >= sizeof(key)) {
- HAL_ERR("snprintf: trunctated service name %s", aSvcName);
- return false;
- }
-
- char value[PROPERTY_VALUE_MAX];
- Unused << NS_WARN_IF(property_get(key, value, "") < 0);
-
- return !strcmp(value, "running");
-}
-
-class StartSystemServiceTimerCallback final : public nsITimerCallback
-{
- NS_DECL_THREADSAFE_ISUPPORTS;
-
-public:
- StartSystemServiceTimerCallback(const char* aSvcName, const char* aArgs)
- : mSvcName(aSvcName)
- , mArgs(aArgs)
- {
- MOZ_COUNT_CTOR_INHERITED(StartSystemServiceTimerCallback,
- nsITimerCallback);
- }
-
- NS_IMETHOD Notify(nsITimer* aTimer) override
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- return StartSystemService(mSvcName.get(), mArgs.get());
- }
-
-protected:
- ~StartSystemServiceTimerCallback()
- {
- MOZ_COUNT_DTOR_INHERITED(StartSystemServiceTimerCallback,
- nsITimerCallback);
- }
-
-private:
- nsCString mSvcName;
- nsCString mArgs;
-};
-
-NS_IMPL_ISUPPORTS0(StartSystemServiceTimerCallback);
-
-nsresult
-StartSystemService(const char* aSvcName, const char* aArgs)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- char value[PROPERTY_VALUE_MAX];
- auto res = snprintf(value, sizeof(value), "%s:%s", aSvcName, aArgs);
-
- if (res < 0) {
- HAL_ERR("snprintf: %s", strerror(errno));
- return NS_ERROR_FAILURE;
- } else if (static_cast<size_t>(res) >= sizeof(value)) {
- HAL_ERR("snprintf: trunctated service name %s", aSvcName);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- if (NS_WARN_IF(property_set("ctl.start", value) < 0)) {
- return NS_ERROR_FAILURE;
- }
-
- /* If the system service is not running, re-try later to start it.
- *
- * This condition happens when we restart a service immediately
- * after it crashed, as the service state remains 'stopping'
- * instead of 'stopped'. Due to the limitation of property service,
- * hereby add delay. See Bug 1143925 Comment 41.
- */
- if (!SystemServiceIsRunning(aSvcName)) {
- nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
- if (!timer) {
- return NS_ERROR_FAILURE;
- }
-
- RefPtr<StartSystemServiceTimerCallback> timerCallback =
- new StartSystemServiceTimerCallback(aSvcName, aArgs);
-
- timer->InitWithCallback(timerCallback,
- sRetryInterval,
- nsITimer::TYPE_ONE_SHOT);
- }
-
- return NS_OK;
-}
-
-void
-StopSystemService(const char* aSvcName)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- Unused << NS_WARN_IF(property_set("ctl.stop", aSvcName));
-}
-
-} // namespace hal_impl
-} // namespace mozilla
diff --git a/hal/gonk/UeventPoller.cpp b/hal/gonk/UeventPoller.cpp
deleted file mode 100644
index 3fbe850ed..000000000
--- a/hal/gonk/UeventPoller.cpp
+++ /dev/null
@@ -1,312 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <signal.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-
-#include <arpa/inet.h>
-#include <linux/types.h>
-#include <linux/netlink.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-#include "HalLog.h"
-#include "nsDebug.h"
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/Monitor.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-
-#include "UeventPoller.h"
-
-using namespace mozilla;
-
-namespace mozilla {
-namespace hal_impl {
-
-static void ShutdownUevent();
-
-class NetlinkPoller : public MessageLoopForIO::Watcher
-{
-public:
- NetlinkPoller() : mSocket(-1),
- mIOLoop(MessageLoopForIO::current())
- {
- }
-
- virtual ~NetlinkPoller() {}
-
- bool OpenSocket();
-
- virtual void OnFileCanReadWithoutBlocking(int fd);
-
- // no writing to the netlink socket
- virtual void OnFileCanWriteWithoutBlocking(int fd)
- {
- MOZ_CRASH("Must not write to netlink socket");
- }
-
- MessageLoopForIO *GetIOLoop () const { return mIOLoop; }
- void RegisterObserver(IUeventObserver *aObserver)
- {
- mUeventObserverList.AddObserver(aObserver);
- }
-
- void UnregisterObserver(IUeventObserver *aObserver)
- {
- mUeventObserverList.RemoveObserver(aObserver);
- if (mUeventObserverList.Length() == 0) {
- ShutdownUevent(); // this will destroy self
- }
- }
-
-private:
- ScopedClose mSocket;
- MessageLoopForIO* mIOLoop;
- MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
-
- const static int kBuffsize = 64 * 1024;
- uint8_t mBuffer [kBuffsize];
-
- typedef ObserverList<NetlinkEvent> UeventObserverList;
- UeventObserverList mUeventObserverList;
-};
-
-bool
-NetlinkPoller::OpenSocket()
-{
- mSocket.rwget() = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
- if (mSocket.get() < 0) {
- return false;
- }
-
- int sz = kBuffsize;
-
- if (setsockopt(mSocket.get(), SOL_SOCKET, SO_RCVBUFFORCE, &sz,
- sizeof(sz)) < 0) {
- return false;
- }
-
- // add FD_CLOEXEC flag
- int flags = fcntl(mSocket.get(), F_GETFD);
- if (flags == -1) {
- return false;
- }
- flags |= FD_CLOEXEC;
- if (fcntl(mSocket.get(), F_SETFD, flags) == -1) {
- return false;
- }
-
- // set non-blocking
- if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) {
- return false;
- }
-
- struct sockaddr_nl saddr;
- bzero(&saddr, sizeof(saddr));
- saddr.nl_family = AF_NETLINK;
- saddr.nl_groups = 1;
- saddr.nl_pid = gettid();
-
- do {
- if (bind(mSocket.get(), (struct sockaddr *)&saddr, sizeof(saddr)) == 0) {
- break;
- }
-
- if (errno != EADDRINUSE) {
- return false;
- }
-
- if (saddr.nl_pid == 0) {
- return false;
- }
-
- // Once there was any other place in the same process assigning saddr.nl_pid by
- // gettid(), we can detect it and print warning message.
- HAL_LOG("The netlink socket address saddr.nl_pid=%u is in use. "
- "Let the kernel re-assign.\n", saddr.nl_pid);
- saddr.nl_pid = 0;
- } while (true);
-
- if (!mIOLoop->WatchFileDescriptor(mSocket.get(),
- true,
- MessageLoopForIO::WATCH_READ,
- &mReadWatcher,
- this)) {
- return false;
- }
-
- return true;
-}
-
-static StaticAutoPtr<NetlinkPoller> sPoller;
-
-class UeventInitTask : public Runnable
-{
- NS_IMETHOD Run() override
- {
- if (!sPoller) {
- return NS_OK;
- }
- if (sPoller->OpenSocket()) {
- return NS_OK;
- }
- sPoller->GetIOLoop()->PostDelayedTask(MakeAndAddRef<UeventInitTask>(),
- 1000);
- return NS_OK;
- }
-};
-
-void
-NetlinkPoller::OnFileCanReadWithoutBlocking(int fd)
-{
- MOZ_ASSERT(fd == mSocket.get());
- while (true) {
- int ret = read(fd, mBuffer, kBuffsize);
- if (ret == -1) {
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- return;
- }
- if (errno == EINTR) {
- continue;
- }
- }
- if (ret <= 0) {
- // fatal error on netlink socket which should not happen
- _exit(1);
- }
- NetlinkEvent netlinkEvent;
- netlinkEvent.decode(reinterpret_cast<char*>(mBuffer), ret);
- mUeventObserverList.Broadcast(netlinkEvent);
- }
-}
-
-static bool sShutdown = false;
-
-class ShutdownNetlinkPoller;
-static StaticAutoPtr<ShutdownNetlinkPoller> sShutdownPoller;
-static Monitor* sMonitor = nullptr;
-
-class ShutdownNetlinkPoller {
-public:
- ~ShutdownNetlinkPoller()
- {
- // This is called from KillClearOnShutdown() on the main thread.
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(XRE_GetIOMessageLoop());
-
- {
- MonitorAutoLock lock(*sMonitor);
-
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(ShutdownUeventIOThread));
-
- while (!sShutdown) {
- lock.Wait();
- }
- }
-
- sShutdown = true;
- delete sMonitor;
- }
-
- static void MaybeInit()
- {
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- if (sShutdown || sMonitor) {
- // Don't init twice or init after shutdown.
- return;
- }
-
- sMonitor = new Monitor("ShutdownNetlinkPoller.monitor");
- {
- ShutdownNetlinkPoller* shutdownPoller = new ShutdownNetlinkPoller();
-
- nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=] () -> void
- {
- sShutdownPoller = shutdownPoller;
- ClearOnShutdown(&sShutdownPoller); // Must run on the main thread.
- });
- MOZ_ASSERT(runnable);
- MOZ_ALWAYS_SUCCEEDS(
- NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL));
- }
- }
-private:
- ShutdownNetlinkPoller() = default;
- static void ShutdownUeventIOThread()
- {
- MonitorAutoLock l(*sMonitor);
- ShutdownUevent(); // Must run on the IO thread.
- sShutdown = true;
- l.NotifyAll();
- }
-};
-
-static void
-InitializeUevent()
-{
- MOZ_ASSERT(!sPoller);
- sPoller = new NetlinkPoller();
- sPoller->GetIOLoop()->PostTask(MakeAndAddRef<UeventInitTask>());
-
- ShutdownNetlinkPoller::MaybeInit();
-}
-
-static void
-ShutdownUevent()
-{
- sPoller = nullptr;
-}
-
-void
-RegisterUeventListener(IUeventObserver *aObserver)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (sShutdown) {
- return;
- }
-
- if (!sPoller) {
- InitializeUevent();
- }
- sPoller->RegisterObserver(aObserver);
-}
-
-void
-UnregisterUeventListener(IUeventObserver *aObserver)
-{
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
- if (sShutdown) {
- return;
- }
-
- sPoller->UnregisterObserver(aObserver);
-}
-
-} // hal_impl
-} // mozilla
-
diff --git a/hal/gonk/UeventPoller.h b/hal/gonk/UeventPoller.h
deleted file mode 100644
index ba121cec2..000000000
--- a/hal/gonk/UeventPoller.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 _mozilla_uevent_poller_h_
-#define _mozilla_uevent_poller_h_
-
-#include <sysutils/NetlinkEvent.h>
-#include "mozilla/Observer.h"
-
-class NetlinkEvent;
-
-namespace mozilla {
-namespace hal_impl {
-
-typedef mozilla::Observer<NetlinkEvent> IUeventObserver;
-
-/**
- * Register for uevent notification. Note that the method should run on the
- * <b> IO Thread </b>
- * @aObserver the observer to be added. The observer's Notify() is only called
- * on the <b> IO Thread </b>
- */
-void RegisterUeventListener(IUeventObserver *aObserver);
-
-/**
- * Unregister for uevent notification. Note that the method should run on the
- * <b> IO Thread </b>
- * @aObserver the observer to be removed
- */
-void UnregisterUeventListener(IUeventObserver *aObserver);
-
-}
-}
-
-#endif
-
diff --git a/hal/gonk/fanotify.h b/hal/gonk/fanotify.h
deleted file mode 100644
index e715d3bf9..000000000
--- a/hal/gonk/fanotify.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#ifndef _LINUX_FANOTIFY_H
-#define _LINUX_FANOTIFY_H
-
-/* This is a Linux header generated by "make headers_install" */
-
-#include <linux/types.h>
-
-/* the following events that user-space can register for */
-#define FAN_ACCESS 0x00000001 /* File was accessed */
-#define FAN_MODIFY 0x00000002 /* File was modified */
-#define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */
-#define FAN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
-#define FAN_OPEN 0x00000020 /* File was opened */
-
-#define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
-
-#define FAN_OPEN_PERM 0x00010000 /* File open in perm check */
-#define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */
-
-#define FAN_ONDIR 0x40000000 /* event occurred against dir */
-
-#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */
-
-/* helper events */
-#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */
-
-/* flags used for fanotify_init() */
-#define FAN_CLOEXEC 0x00000001
-#define FAN_NONBLOCK 0x00000002
-
-/* These are NOT bitwise flags. Both bits are used togther. */
-#define FAN_CLASS_NOTIF 0x00000000
-#define FAN_CLASS_CONTENT 0x00000004
-#define FAN_CLASS_PRE_CONTENT 0x00000008
-#define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \
- FAN_CLASS_PRE_CONTENT)
-
-#define FAN_UNLIMITED_QUEUE 0x00000010
-#define FAN_UNLIMITED_MARKS 0x00000020
-
-#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \
- FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\
- FAN_UNLIMITED_MARKS)
-
-/* flags used for fanotify_modify_mark() */
-#define FAN_MARK_ADD 0x00000001
-#define FAN_MARK_REMOVE 0x00000002
-#define FAN_MARK_DONT_FOLLOW 0x00000004
-#define FAN_MARK_ONLYDIR 0x00000008
-#define FAN_MARK_MOUNT 0x00000010
-#define FAN_MARK_IGNORED_MASK 0x00000020
-#define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040
-#define FAN_MARK_FLUSH 0x00000080
-
-#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\
- FAN_MARK_REMOVE |\
- FAN_MARK_DONT_FOLLOW |\
- FAN_MARK_ONLYDIR |\
- FAN_MARK_MOUNT |\
- FAN_MARK_IGNORED_MASK |\
- FAN_MARK_IGNORED_SURV_MODIFY |\
- FAN_MARK_FLUSH)
-
-/*
- * All of the events - we build the list by hand so that we can add flags in
- * the future and not break backward compatibility. Apps will get only the
- * events that they originally wanted. Be sure to add new events here!
- */
-#define FAN_ALL_EVENTS (FAN_ACCESS |\
- FAN_MODIFY |\
- FAN_CLOSE |\
- FAN_OPEN)
-
-/*
- * All events which require a permission response from userspace
- */
-#define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM |\
- FAN_ACCESS_PERM)
-
-#define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS |\
- FAN_ALL_PERM_EVENTS |\
- FAN_Q_OVERFLOW)
-
-#define FANOTIFY_METADATA_VERSION 3
-
-struct fanotify_event_metadata {
- __u32 event_len;
- __u8 vers;
- __u8 reserved;
- __u16 metadata_len;
- __u64 mask;
- __s32 fd;
- __s32 pid;
-};
-
-struct fanotify_response {
- __s32 fd;
- __u32 response;
-};
-
-/* Legit userspace responses to a _PERM event */
-#define FAN_ALLOW 0x01
-#define FAN_DENY 0x02
-/* No fd set in event */
-#define FAN_NOFD -1
-
-/* Helper functions to deal with fanotify_event_metadata buffers */
-#define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
-
-#define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, \
- (struct fanotify_event_metadata*)(((char *)(meta)) + \
- (meta)->event_len))
-
-#define FAN_EVENT_OK(meta, len) ((long)(len) >= (long)FAN_EVENT_METADATA_LEN && \
- (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \
- (long)(meta)->event_len <= (long)(len))
-
-#endif /* _LINUX_FANOTIFY_H */
diff --git a/hal/gonk/nsIRecoveryService.idl b/hal/gonk/nsIRecoveryService.idl
deleted file mode 100644
index ecbb39c0e..000000000
--- a/hal/gonk/nsIRecoveryService.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(bc24fb33-a0c1-49ca-aa43-05f167e02fb6)]
-interface nsIRecoveryService : nsISupports
-{
- /**
- * Possible values of fotaStatus.result. These should stay in sync with
- * librecovery/librecovery.h
- */
- const long FOTA_UPDATE_UNKNOWN = 0;
- const long FOTA_UPDATE_FAIL = 1;
- const long FOTA_UPDATE_SUCCESS = 2;
-
- /**
- * Uses recovery to wipe the data and cache partitions. If this call is
- * successful, the device should reboot before the function call ever returns.
- *
- * @throws NS_ERROR_FAILURE when rebooting into recovery fails for some reason.
- */
- void factoryReset(in string reason);
-
- /**
- * Use recovery to install an OTA update.zip. If this call is
- * successful, the device should reboot before the function call ever returns.
- *
- * @throws NS_ERROR_FAILURE when rebooting into recovery fails for some reason.
- */
- void installFotaUpdate(in string updatePath);
-
- /**
- * @return The status of the last FOTA update. One of FOTA_UPDATE_UNKNOWN,
- * FOTA_UPDATE_FAIL, FOTA_UPDATE_SUCCESS.
- */
- long getFotaUpdateStatus();
-};
diff --git a/hal/gonk/tavarua.h b/hal/gonk/tavarua.h
deleted file mode 100644
index 4eb3483a8..000000000
--- a/hal/gonk/tavarua.h
+++ /dev/null
@@ -1,484 +0,0 @@
-#ifndef __LINUX_TAVARUA_H
-#define __LINUX_TAVARUA_H
-
-/* This is a Linux header generated by "make headers_install" */
-
-#include <stdint.h>
-#include <linux/ioctl.h>
-#include <linux/videodev2.h>
-
-
-#undef FM_DEBUG
-
-/* constants */
-#define RDS_BLOCKS_NUM (4)
-#define BYTES_PER_BLOCK (3)
-#define MAX_PS_LENGTH (96)
-#define MAX_RT_LENGTH (64)
-
-#define XFRDAT0 (0x20)
-#define XFRDAT1 (0x21)
-#define XFRDAT2 (0x22)
-
-#define INTDET_PEEK_MSB (0x88)
-#define INTDET_PEEK_LSB (0x26)
-
-#define RMSSI_PEEK_MSB (0x88)
-#define RMSSI_PEEK_LSB (0xA8)
-
-#define MPX_DCC_BYPASS_POKE_MSB (0x88)
-#define MPX_DCC_BYPASS_POKE_LSB (0xC0)
-
-#define MPX_DCC_PEEK_MSB_REG1 (0x88)
-#define MPX_DCC_PEEK_LSB_REG1 (0xC2)
-
-#define MPX_DCC_PEEK_MSB_REG2 (0x88)
-#define MPX_DCC_PEEK_LSB_REG2 (0xC3)
-
-#define MPX_DCC_PEEK_MSB_REG3 (0x88)
-#define MPX_DCC_PEEK_LSB_REG3 (0xC4)
-
-#define ON_CHANNEL_TH_MSB (0x0B)
-#define ON_CHANNEL_TH_LSB (0xA8)
-
-#define OFF_CHANNEL_TH_MSB (0x0B)
-#define OFF_CHANNEL_TH_LSB (0xAC)
-
-#define ENF_200Khz (1)
-#define SRCH200KHZ_OFFSET (7)
-#define SRCH_MASK (1 << SRCH200KHZ_OFFSET)
-
-/* Standard buffer size */
-#define STD_BUF_SIZE (128)
-/* Search direction */
-#define SRCH_DIR_UP (0)
-#define SRCH_DIR_DOWN (1)
-
-/* control options */
-#define CTRL_ON (1)
-#define CTRL_OFF (0)
-
-#define US_LOW_BAND (87.5)
-#define US_HIGH_BAND (108)
-
-/* constant for Tx */
-
-#define MASK_PI (0x0000FFFF)
-#define MASK_PI_MSB (0x0000FF00)
-#define MASK_PI_LSB (0x000000FF)
-#define MASK_PTY (0x0000001F)
-#define MASK_TXREPCOUNT (0x0000000F)
-
-#undef FMDBG
-#ifdef FM_DEBUG
- #define FMDBG(fmt, args...) printk(KERN_INFO "tavarua_radio: " fmt, ##args)
-#else
- #define FMDBG(fmt, args...)
-#endif
-
-#undef FMDERR
-#define FMDERR(fmt, args...) printk(KERN_INFO "tavarua_radio: " fmt, ##args)
-
-#undef FMDBG_I2C
-#ifdef FM_DEBUG_I2C
- #define FMDBG_I2C(fmt, args...) printk(KERN_INFO "fm_i2c: " fmt, ##args)
-#else
- #define FMDBG_I2C(fmt, args...)
-#endif
-
-/* function declarations */
-/* FM Core audio paths. */
-#define TAVARUA_AUDIO_OUT_ANALOG_OFF (0)
-#define TAVARUA_AUDIO_OUT_ANALOG_ON (1)
-#define TAVARUA_AUDIO_OUT_DIGITAL_OFF (0)
-#define TAVARUA_AUDIO_OUT_DIGITAL_ON (1)
-
-int tavarua_set_audio_path(int digital_on, int analog_on);
-
-/* defines and enums*/
-
-#define MARIMBA_A0 0x01010013
-#define MARIMBA_2_1 0x02010204
-#define BAHAMA_1_0 0x0302010A
-#define BAHAMA_2_0 0x04020205
-#define WAIT_TIMEOUT 2000
-#define RADIO_INIT_TIME 15
-#define TAVARUA_DELAY 10
-/*
- * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
- * 62.5 kHz otherwise.
- * The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
- * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW
- * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000
- */
-#define FREQ_MUL (1000000 / 62.5)
-
-enum v4l2_cid_private_tavarua_t {
- V4L2_CID_PRIVATE_TAVARUA_SRCHMODE = (V4L2_CID_PRIVATE_BASE + 1),
- V4L2_CID_PRIVATE_TAVARUA_SCANDWELL,
- V4L2_CID_PRIVATE_TAVARUA_SRCHON,
- V4L2_CID_PRIVATE_TAVARUA_STATE,
- V4L2_CID_PRIVATE_TAVARUA_TRANSMIT_MODE,
- V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_MASK,
- V4L2_CID_PRIVATE_TAVARUA_REGION,
- V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH,
- V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY,
- V4L2_CID_PRIVATE_TAVARUA_SRCH_PI,
- V4L2_CID_PRIVATE_TAVARUA_SRCH_CNT,
- V4L2_CID_PRIVATE_TAVARUA_EMPHASIS,
- V4L2_CID_PRIVATE_TAVARUA_RDS_STD,
- V4L2_CID_PRIVATE_TAVARUA_SPACING,
- V4L2_CID_PRIVATE_TAVARUA_RDSON,
- V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_PROC,
- V4L2_CID_PRIVATE_TAVARUA_LP_MODE,
- V4L2_CID_PRIVATE_TAVARUA_ANTENNA,
- V4L2_CID_PRIVATE_TAVARUA_RDSD_BUF,
- V4L2_CID_PRIVATE_TAVARUA_PSALL,
- /*v4l2 Tx controls*/
- V4L2_CID_PRIVATE_TAVARUA_TX_SETPSREPEATCOUNT,
- V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_PS_NAME,
- V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_RT,
- V4L2_CID_PRIVATE_TAVARUA_IOVERC,
- V4L2_CID_PRIVATE_TAVARUA_INTDET,
- V4L2_CID_PRIVATE_TAVARUA_MPX_DCC,
- V4L2_CID_PRIVATE_TAVARUA_AF_JUMP,
- V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA,
- V4L2_CID_PRIVATE_TAVARUA_HLSI,
-
- /*
- * Here we have IOCTl's that are specific to IRIS
- * (V4L2_CID_PRIVATE_BASE + 0x1E to V4L2_CID_PRIVATE_BASE + 0x28)
- */
- V4L2_CID_PRIVATE_SOFT_MUTE,/* 0x800001E*/
- V4L2_CID_PRIVATE_RIVA_ACCS_ADDR,
- V4L2_CID_PRIVATE_RIVA_ACCS_LEN,
- V4L2_CID_PRIVATE_RIVA_PEEK,
- V4L2_CID_PRIVATE_RIVA_POKE,
- V4L2_CID_PRIVATE_SSBI_ACCS_ADDR,
- V4L2_CID_PRIVATE_SSBI_PEEK,
- V4L2_CID_PRIVATE_SSBI_POKE,
- V4L2_CID_PRIVATE_TX_TONE,
- V4L2_CID_PRIVATE_RDS_GRP_COUNTERS,
- V4L2_CID_PRIVATE_SET_NOTCH_FILTER,/* 0x8000028 */
-
- V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH,/* 0x8000029 */
- V4L2_CID_PRIVATE_TAVARUA_DO_CALIBRATION,/* 0x800002A : IRIS */
- V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM,/* 0x800002B */
- V4L2_CID_PRIVATE_IRIS_GET_SINR, /* 0x800002C : IRIS */
- V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD, /* 0x800002D */
- V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD, /* 0x800002E */
- V4L2_CID_PRIVATE_SINR_THRESHOLD, /* 0x800002F : IRIS */
- V4L2_CID_PRIVATE_SINR_SAMPLES, /* 0x8000030 : IRIS */
-
-};
-
-enum tavarua_buf_t {
- TAVARUA_BUF_SRCH_LIST,
- TAVARUA_BUF_EVENTS,
- TAVARUA_BUF_RT_RDS,
- TAVARUA_BUF_PS_RDS,
- TAVARUA_BUF_RAW_RDS,
- TAVARUA_BUF_AF_LIST,
- TAVARUA_BUF_MAX
-};
-
-enum tavarua_xfr_t {
- TAVARUA_XFR_SYNC,
- TAVARUA_XFR_ERROR,
- TAVARUA_XFR_SRCH_LIST,
- TAVARUA_XFR_RT_RDS,
- TAVARUA_XFR_PS_RDS,
- TAVARUA_XFR_AF_LIST,
- TAVARUA_XFR_MAX
-};
-
-enum channel_spacing {
- FM_CH_SPACE_200KHZ,
- FM_CH_SPACE_100KHZ,
- FM_CH_SPACE_50KHZ
-};
-
-enum step_size {
- NO_SRCH200khz,
- ENF_SRCH200khz
-};
-
-enum emphasis {
- EMP_75,
- EMP_50
-};
-
-enum rds_std {
- RBDS_STD,
- RDS_STD
-};
-
-/* offsets */
-#define RAW_RDS 0x0F
-#define RDS_BLOCK 3
-
-/* registers*/
-#define MARIMBA_XO_BUFF_CNTRL 0x07
-#define RADIO_REGISTERS 0x30
-#define XFR_REG_NUM 16
-#define STATUS_REG_NUM 3
-
-/* TX constants */
-#define HEADER_SIZE 4
-#define TX_ON 0x80
-#define TAVARUA_TX_RT RDS_RT_0
-#define TAVARUA_TX_PS RDS_PS_0
-
-enum register_t {
- STATUS_REG1 = 0,
- STATUS_REG2,
- STATUS_REG3,
- RDCTRL,
- FREQ,
- TUNECTRL,
- SRCHRDS1,
- SRCHRDS2,
- SRCHCTRL,
- IOCTRL,
- RDSCTRL,
- ADVCTRL,
- AUDIOCTRL,
- RMSSI,
- IOVERC,
- AUDIOIND = 0x1E,
- XFRCTRL,
- FM_CTL0 = 0xFF,
- LEAKAGE_CNTRL = 0xFE,
-};
-#define BAHAMA_RBIAS_CTL1 0x07
-#define BAHAMA_FM_MODE_REG 0xFD
-#define BAHAMA_FM_CTL1_REG 0xFE
-#define BAHAMA_FM_CTL0_REG 0xFF
-#define BAHAMA_FM_MODE_NORMAL 0x00
-#define BAHAMA_LDO_DREG_CTL0 0xF0
-#define BAHAMA_LDO_AREG_CTL0 0xF4
-
-/* Radio Control */
-#define RDCTRL_STATE_OFFSET 0
-#define RDCTRL_STATE_MASK (3 << RDCTRL_STATE_OFFSET)
-#define RDCTRL_BAND_OFFSET 2
-#define RDCTRL_BAND_MASK (1 << RDCTRL_BAND_OFFSET)
-#define RDCTRL_CHSPACE_OFFSET 3
-#define RDCTRL_CHSPACE_MASK (3 << RDCTRL_CHSPACE_OFFSET)
-#define RDCTRL_DEEMPHASIS_OFFSET 5
-#define RDCTRL_DEEMPHASIS_MASK (1 << RDCTRL_DEEMPHASIS_OFFSET)
-#define RDCTRL_HLSI_OFFSET 6
-#define RDCTRL_HLSI_MASK (3 << RDCTRL_HLSI_OFFSET)
-#define RDSAF_OFFSET 6
-#define RDSAF_MASK (1 << RDSAF_OFFSET)
-
-/* Tune Control */
-#define TUNE_STATION 0x01
-#define ADD_OFFSET (1 << 1)
-#define SIGSTATE (1 << 5)
-#define MOSTSTATE (1 << 6)
-#define RDSSYNC (1 << 7)
-/* Search Control */
-#define SRCH_MODE_OFFSET 0
-#define SRCH_MODE_MASK (7 << SRCH_MODE_OFFSET)
-#define SRCH_DIR_OFFSET 3
-#define SRCH_DIR_MASK (1 << SRCH_DIR_OFFSET)
-#define SRCH_DWELL_OFFSET 4
-#define SRCH_DWELL_MASK (7 << SRCH_DWELL_OFFSET)
-#define SRCH_STATE_OFFSET 7
-#define SRCH_STATE_MASK (1 << SRCH_STATE_OFFSET)
-
-/* I/O Control */
-#define IOC_HRD_MUTE 0x03
-#define IOC_SFT_MUTE (1 << 2)
-#define IOC_MON_STR (1 << 3)
-#define IOC_SIG_BLND (1 << 4)
-#define IOC_INTF_BLND (1 << 5)
-#define IOC_ANTENNA (1 << 6)
-#define IOC_ANTENNA_OFFSET 6
-#define IOC_ANTENNA_MASK (1 << IOC_ANTENNA_OFFSET)
-
-/* RDS Control */
-#define RDS_ON 0x01
-#define RDSCTRL_STANDARD_OFFSET 1
-#define RDSCTRL_STANDARD_MASK (1 << RDSCTRL_STANDARD_OFFSET)
-
-/* Advanced features controls */
-#define RDSRTEN (1 << 3)
-#define RDSPSEN (1 << 4)
-
-/* Audio path control */
-#define AUDIORX_ANALOG_OFFSET 0
-#define AUDIORX_ANALOG_MASK (1 << AUDIORX_ANALOG_OFFSET)
-#define AUDIORX_DIGITAL_OFFSET 1
-#define AUDIORX_DIGITAL_MASK (1 << AUDIORX_DIGITAL_OFFSET)
-#define AUDIOTX_OFFSET 2
-#define AUDIOTX_MASK (1 << AUDIOTX_OFFSET)
-#define I2SCTRL_OFFSET 3
-#define I2SCTRL_MASK (1 << I2SCTRL_OFFSET)
-
-/* Search options */
-enum search_t {
- SEEK,
- SCAN,
- SCAN_FOR_STRONG,
- SCAN_FOR_WEAK,
- RDS_SEEK_PTY,
- RDS_SCAN_PTY,
- RDS_SEEK_PI,
- RDS_AF_JUMP,
-};
-
-enum audio_path {
- FM_DIGITAL_PATH,
- FM_ANALOG_PATH
-};
-#define SRCH_MODE 0x07
-#define SRCH_DIR 0x08 /* 0-up 1-down */
-#define SCAN_DWELL 0x70
-#define SRCH_ON 0x80
-
-/* RDS CONFIG */
-#define RDS_CONFIG_PSALL 0x01
-
-#define FM_ENABLE 0x22
-#define SET_REG_FIELD(reg, val, offset, mask) \
- (reg = (reg & ~mask) | (((val) << offset) & mask))
-#define GET_REG_FIELD(reg, offset, mask) ((reg & mask) >> offset)
-#define RSH_DATA(val, offset) ((val) >> (offset))
-#define LSH_DATA(val, offset) ((val) << (offset))
-#define GET_ABS_VAL(val) ((val) & (0xFF))
-
-enum radio_state_t {
- FM_OFF,
- FM_RECV,
- FM_TRANS,
- FM_RESET,
-};
-
-#define XFRCTRL_WRITE (1 << 7)
-
-/* Interrupt status */
-
-/* interrupt register 1 */
-#define READY (1 << 0) /* Radio ready after powerup or reset */
-#define TUNE (1 << 1) /* Tune completed */
-#define SEARCH (1 << 2) /* Search completed (read FREQ) */
-#define SCANNEXT (1 << 3) /* Scanning for next station */
-#define SIGNAL (1 << 4) /* Signal indicator change (read SIGSTATE) */
-#define INTF (1 << 5) /* Interference cnt has fallen outside range */
-#define SYNC (1 << 6) /* RDS sync state change (read RDSSYNC) */
-#define AUDIO (1 << 7) /* Audio Control indicator (read AUDIOIND) */
-
-/* interrupt register 2 */
-#define RDSDAT (1 << 0) /* New unread RDS data group available */
-#define BLOCKB (1 << 1) /* Block-B match condition exists */
-#define PROGID (1 << 2) /* Block-A or Block-C matched stored PI value*/
-#define RDSPS (1 << 3) /* New RDS Program Service Table available */
-#define RDSRT (1 << 4) /* New RDS Radio Text available */
-#define RDSAF (1 << 5) /* New RDS AF List available */
-#define TXRDSDAT (1 << 6) /* Transmitted an RDS group */
-#define TXRDSDONE (1 << 7) /* RDS raw group one-shot transmit completed */
-
-/* interrupt register 3 */
-#define TRANSFER (1 << 0) /* Data transfer (XFR) completed */
-#define RDSPROC (1 << 1) /* Dynamic RDS Processing complete */
-#define ERROR (1 << 7) /* Err occurred.Read code to determine cause */
-
-
-#define FM_TX_PWR_LVL_0 0 /* Lowest power lvl that can be set for Tx */
-#define FM_TX_PWR_LVL_MAX 7 /* Max power lvl for Tx */
-/* Transfer */
-enum tavarua_xfr_ctrl_t {
- RDS_PS_0 = 0x01,
- RDS_PS_1,
- RDS_PS_2,
- RDS_PS_3,
- RDS_PS_4,
- RDS_PS_5,
- RDS_PS_6,
- RDS_RT_0,
- RDS_RT_1,
- RDS_RT_2,
- RDS_RT_3,
- RDS_RT_4,
- RDS_AF_0,
- RDS_AF_1,
- RDS_CONFIG,
- RDS_TX_GROUPS,
- RDS_COUNT_0,
- RDS_COUNT_1,
- RDS_COUNT_2,
- RADIO_CONFIG,
- RX_CONFIG,
- RX_TIMERS,
- RX_STATIONS_0,
- RX_STATIONS_1,
- INT_CTRL,
- ERROR_CODE,
- CHIPID,
- CAL_DAT_0 = 0x20,
- CAL_DAT_1,
- CAL_DAT_2,
- CAL_DAT_3,
- CAL_CFG_0,
- CAL_CFG_1,
- DIG_INTF_0,
- DIG_INTF_1,
- DIG_AGC_0,
- DIG_AGC_1,
- DIG_AGC_2,
- DIG_AUDIO_0,
- DIG_AUDIO_1,
- DIG_AUDIO_2,
- DIG_AUDIO_3,
- DIG_AUDIO_4,
- DIG_RXRDS,
- DIG_DCC,
- DIG_SPUR,
- DIG_MPXDCC,
- DIG_PILOT,
- DIG_DEMOD,
- DIG_MOST,
- DIG_TX_0,
- DIG_TX_1,
- PHY_TXGAIN = 0x3B,
- PHY_CONFIG,
- PHY_TXBLOCK,
- PHY_TCB,
- XFR_PEEK_MODE = 0x40,
- XFR_POKE_MODE = 0xC0,
- TAVARUA_XFR_CTRL_MAX
-};
-
-enum tavarua_evt_t {
- TAVARUA_EVT_RADIO_READY,
- TAVARUA_EVT_TUNE_SUCC,
- TAVARUA_EVT_SEEK_COMPLETE,
- TAVARUA_EVT_SCAN_NEXT,
- TAVARUA_EVT_NEW_RAW_RDS,
- TAVARUA_EVT_NEW_RT_RDS,
- TAVARUA_EVT_NEW_PS_RDS,
- TAVARUA_EVT_ERROR,
- TAVARUA_EVT_BELOW_TH,
- TAVARUA_EVT_ABOVE_TH,
- TAVARUA_EVT_STEREO,
- TAVARUA_EVT_MONO,
- TAVARUA_EVT_RDS_AVAIL,
- TAVARUA_EVT_RDS_NOT_AVAIL,
- TAVARUA_EVT_NEW_SRCH_LIST,
- TAVARUA_EVT_NEW_AF_LIST,
- TAVARUA_EVT_TXRDSDAT,
- TAVARUA_EVT_TXRDSDONE,
- TAVARUA_EVT_RADIO_DISABLED
-};
-
-enum tavarua_region_t {
- TAVARUA_REGION_US,
- TAVARUA_REGION_EU,
- TAVARUA_REGION_JAPAN,
- TAVARUA_REGION_JAPAN_WIDE,
- TAVARUA_REGION_OTHER
-};
-
-#endif /* __LINUX_TAVARUA_H */
diff --git a/hal/moz.build b/hal/moz.build
index c17379f22..235994273 100644
--- a/hal/moz.build
+++ b/hal/moz.build
@@ -45,24 +45,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
SOURCES += [
'android/AndroidHal.cpp',
]
-elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- UNIFIED_SOURCES += [
- 'gonk/GonkDiskSpaceWatcher.cpp',
- 'gonk/GonkSensor.cpp',
- 'gonk/GonkSensorsHelpers.cpp',
- 'gonk/GonkSensorsInterface.cpp',
- 'gonk/GonkSensorsPollInterface.cpp',
- 'gonk/GonkSensorsRegistryInterface.cpp',
- 'gonk/GonkSwitch.cpp',
- 'gonk/SystemService.cpp',
- 'gonk/UeventPoller.cpp',
- 'linux/LinuxMemory.cpp',
- 'linux/LinuxPower.cpp',
- ]
- # GonkHal.cpp cannot be built in unified mode because it relies on HalImpl.h.
- SOURCES += [
- 'gonk/GonkHal.cpp',
- ]
elif CONFIG['OS_TARGET'] == 'Linux':
UNIFIED_SOURCES += [
'fallback/FallbackAlarm.cpp',
@@ -130,19 +112,17 @@ else:
'fallback/FallbackVibration.cpp',
]
-# Fallbacks for backends implemented on Gonk only.
-if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
- UNIFIED_SOURCES += [
- 'fallback/FallbackDiskSpaceWatcher.cpp',
- 'fallback/FallbackFactoryReset.cpp',
- 'fallback/FallbackProcessPriority.cpp',
- 'fallback/FallbackScreenPower.cpp',
- 'fallback/FallbackSwitch.cpp',
- 'fallback/FallbackSystemService.cpp',
- 'fallback/FallbackThreadPriority.cpp',
- 'fallback/FallbackTime.cpp',
- 'fallback/FallbackWakeLocks.cpp',
- ]
+UNIFIED_SOURCES += [
+ 'fallback/FallbackDiskSpaceWatcher.cpp',
+ 'fallback/FallbackFactoryReset.cpp',
+ 'fallback/FallbackProcessPriority.cpp',
+ 'fallback/FallbackScreenPower.cpp',
+ 'fallback/FallbackSwitch.cpp',
+ 'fallback/FallbackSystemService.cpp',
+ 'fallback/FallbackThreadPriority.cpp',
+ 'fallback/FallbackTime.cpp',
+ 'fallback/FallbackWakeLocks.cpp',
+]
# Fallbacks for backends implemented on Android only.
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
@@ -169,16 +149,6 @@ if CONFIG['MOZ_GAMEPAD']:
'/dom/base',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- # So that we can call nsScreenManagerGonk::GetConfiguration().
- LOCAL_INCLUDES += [
- '/widget',
- '/widget/gonk',
- ]
-
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- LOCAL_INCLUDES += ['%' + '%s/hardware/libhardware_legacy/include' % CONFIG['ANDROID_SOURCE']]
-
CFLAGS += CONFIG['GLIB_CFLAGS']
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
CXXFLAGS += CONFIG['GLIB_CFLAGS']
diff --git a/testing/marionette/harness/marionette_harness/tests/webapi-tests.ini b/testing/marionette/harness/marionette_harness/tests/webapi-tests.ini
index 2c9dd1dce..66a72ae4d 100644
--- a/testing/marionette/harness/marionette_harness/tests/webapi-tests.ini
+++ b/testing/marionette/harness/marionette_harness/tests/webapi-tests.ini
@@ -1,4 +1,3 @@
-[include:../../../../../dom/system/gonk/tests/marionette/manifest.ini]
[include:../../../../../dom/system/tests/marionette/manifest.ini]
skip-if = android_version > '15' # Bug 1203072
[include:../../../../../dom/events/test/marionette/manifest.ini]
diff --git a/uriloader/exthandler/gonk/nsOSHelperAppService.cpp b/uriloader/exthandler/gonk/nsOSHelperAppService.cpp
deleted file mode 100644
index d1342ec18..000000000
--- a/uriloader/exthandler/gonk/nsOSHelperAppService.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "nsOSHelperAppService.h"
-#include "nsMIMEInfoImpl.h"
-
-class nsGonkMIMEInfo : public nsMIMEInfoImpl {
-public:
- nsGonkMIMEInfo(const nsACString& aMIMEType) : nsMIMEInfoImpl(aMIMEType) { }
-
-protected:
- virtual nsresult LoadUriInternal(nsIURI *aURI) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-};
-
-nsOSHelperAppService::nsOSHelperAppService() : nsExternalHelperAppService()
-{
-}
-
-nsOSHelperAppService::~nsOSHelperAppService()
-{
-}
-
-already_AddRefed<nsIMIMEInfo>
-nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
- const nsACString& aFileExt,
- bool* aFound)
-{
- *aFound = false;
- // Even if we return false for aFound, we need to return a working
- // nsIMIMEInfo implementation that will be used by the caller.
- RefPtr<nsGonkMIMEInfo> mimeInfo = new nsGonkMIMEInfo(aMIMEType);
- return mimeInfo.forget();
-}
-
-nsresult
-nsOSHelperAppService::OSProtocolHandlerExists(const char* aScheme,
- bool* aExists)
-{
- *aExists = false;
- return NS_OK;
-}
diff --git a/uriloader/exthandler/gonk/nsOSHelperAppService.h b/uriloader/exthandler/gonk/nsOSHelperAppService.h
deleted file mode 100644
index 99a280bfc..000000000
--- a/uriloader/exthandler/gonk/nsOSHelperAppService.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 nsOSHelperAppService_h
-#define nsOSHelperAppService_h
-
-#include "nsCExternalHandlerService.h"
-#include "nsExternalHelperAppService.h"
-
-class nsOSHelperAppService : public nsExternalHelperAppService
-{
-public:
- nsOSHelperAppService();
- virtual ~nsOSHelperAppService();
-
- virtual already_AddRefed<nsIMIMEInfo>
- GetMIMEInfoFromOS(const nsACString& aMIMEType,
- const nsACString& aFileExt,
- bool* aFound);
-
- virtual MOZ_MUST_USE nsresult
- OSProtocolHandlerExists(const char* aScheme,
- bool* aExists);
-};
-
-#endif /* nsOSHelperAppService_h */
diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build
index 6a3ca08af..714b275f1 100644
--- a/uriloader/exthandler/moz.build
+++ b/uriloader/exthandler/moz.build
@@ -24,7 +24,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
LOCAL_INCLUDES += ['win']
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
osdir = 'mac'
-elif CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk', 'uikit'):
+elif CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'uikit'):
osdir = CONFIG['MOZ_WIDGET_TOOLKIT']
else:
osdir = 'unix'
diff --git a/widget/gonk/GeckoTouchDispatcher.cpp b/widget/gonk/GeckoTouchDispatcher.cpp
deleted file mode 100644
index 0b18c91a1..000000000
--- a/widget/gonk/GeckoTouchDispatcher.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* Copyright 2014 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "FrameMetrics.h"
-#include "GeckoProfiler.h"
-#include "GeckoTouchDispatcher.h"
-#include "InputData.h"
-#include "ProfilerMarkers.h"
-#include "base/basictypes.h"
-#include "gfxPrefs.h"
-#include "libui/Input.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/Mutex.h"
-#include "mozilla/TimeStamp.h"
-#include "mozilla/TouchEvents.h"
-#include "mozilla/dom/Touch.h"
-#include "mozilla/layers/APZThreadUtils.h"
-#include "mozilla/layers/CompositorBridgeParent.h"
-#include "nsAppShell.h"
-#include "nsDebug.h"
-#include "nsThreadUtils.h"
-#include "nsWindow.h"
-#include <sys/types.h>
-#include <unistd.h>
-#include <utils/Timers.h>
-
-#undef LOG
-#define LOG(args...) \
- __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
-
-// uncomment to print log resample data
-// #define LOG_RESAMPLE_DATA 1
-
-namespace mozilla {
-
-// Amount of time in MS before an input is considered expired.
-static const uint64_t kInputExpirationThresholdMs = 1000;
-
-static StaticRefPtr<GeckoTouchDispatcher> sTouchDispatcher;
-
-/* static */ GeckoTouchDispatcher*
-GeckoTouchDispatcher::GetInstance()
-{
- if (!sTouchDispatcher) {
- sTouchDispatcher = new GeckoTouchDispatcher();
- ClearOnShutdown(&sTouchDispatcher);
- }
- return sTouchDispatcher;
-}
-
-GeckoTouchDispatcher::GeckoTouchDispatcher()
- : mTouchQueueLock("GeckoTouchDispatcher::mTouchQueueLock")
- , mHavePendingTouchMoves(false)
- , mInflightNonMoveEvents(0)
- , mTouchEventsFiltered(false)
-{
- // Since GeckoTouchDispatcher is initialized when input is initialized
- // and reads gfxPrefs, it is the first thing to touch gfxPrefs.
- // The first thing to touch gfxPrefs MUST occur on the main thread and init
- // the singleton
- MOZ_ASSERT(sTouchDispatcher == nullptr);
- MOZ_ASSERT(NS_IsMainThread());
- gfxPrefs::GetSingleton();
-
- mEnabledUniformityInfo = gfxPrefs::UniformityInfo();
- mVsyncAdjust = TimeDuration::FromMilliseconds(gfxPrefs::TouchVsyncSampleAdjust());
- mMaxPredict = TimeDuration::FromMilliseconds(gfxPrefs::TouchResampleMaxPredict());
- mMinDelta = TimeDuration::FromMilliseconds(gfxPrefs::TouchResampleMinDelta());
- mOldTouchThreshold = TimeDuration::FromMilliseconds(gfxPrefs::TouchResampleOldTouchThreshold());
- mDelayedVsyncThreshold = TimeDuration::FromMilliseconds(gfxPrefs::TouchResampleVsyncDelayThreshold());
-}
-
-void
-GeckoTouchDispatcher::SetCompositorVsyncScheduler(mozilla::layers::CompositorVsyncScheduler *aObserver)
-{
- MOZ_ASSERT(NS_IsMainThread());
- // We assume on b2g that there is only 1 CompositorBridgeParent
- MOZ_ASSERT(mCompositorVsyncScheduler == nullptr);
- mCompositorVsyncScheduler = aObserver;
-}
-
-void
-GeckoTouchDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
-{
- layers::APZThreadUtils::AssertOnControllerThread();
- DispatchTouchMoveEvents(aVsyncTimestamp);
-}
-
-// Touch data timestamps are in milliseconds, aEventTime is in nanoseconds
-void
-GeckoTouchDispatcher::NotifyTouch(MultiTouchInput& aTouch, TimeStamp aEventTime)
-{
- if (mCompositorVsyncScheduler) {
- mCompositorVsyncScheduler->SetNeedsComposite();
- }
-
- if (aTouch.mType == MultiTouchInput::MULTITOUCH_MOVE) {
- MutexAutoLock lock(mTouchQueueLock);
- if (mInflightNonMoveEvents > 0) {
- // If we have any pending non-move events, we shouldn't resample the
- // move events because we might end up dispatching events out of order.
- // Instead, fall back to a non-resampling in-order dispatch until we're
- // done processing the non-move events.
- layers::APZThreadUtils::RunOnControllerThread(NewRunnableMethod<MultiTouchInput>(
- this, &GeckoTouchDispatcher::DispatchTouchEvent, aTouch));
- return;
- }
-
- mTouchMoveEvents.push_back(aTouch);
- mHavePendingTouchMoves = true;
- } else {
- { // scope lock
- MutexAutoLock lock(mTouchQueueLock);
- mInflightNonMoveEvents++;
- }
- layers::APZThreadUtils::RunOnControllerThread(NewRunnableMethod<MultiTouchInput>(
- this, &GeckoTouchDispatcher::DispatchTouchNonMoveEvent, aTouch));
- }
-}
-
-void
-GeckoTouchDispatcher::DispatchTouchNonMoveEvent(MultiTouchInput aInput)
-{
- layers::APZThreadUtils::AssertOnControllerThread();
-
- // Flush pending touch move events, if there are any
- // (DispatchTouchMoveEvents will check the mHavePendingTouchMoves flag and
- // bail out if there's nothing to be done).
- NotifyVsync(TimeStamp::Now());
- DispatchTouchEvent(aInput);
-
- { // scope lock
- MutexAutoLock lock(mTouchQueueLock);
- mInflightNonMoveEvents--;
- MOZ_ASSERT(mInflightNonMoveEvents >= 0);
- }
-}
-
-void
-GeckoTouchDispatcher::DispatchTouchMoveEvents(TimeStamp aVsyncTime)
-{
- MultiTouchInput touchMove;
-
- {
- MutexAutoLock lock(mTouchQueueLock);
- if (!mHavePendingTouchMoves) {
- return;
- }
- mHavePendingTouchMoves = false;
-
- int touchCount = mTouchMoveEvents.size();
- TimeDuration vsyncTouchDiff = aVsyncTime - mTouchMoveEvents.back().mTimeStamp;
- // The delay threshold is a positive pref, but we're testing to see if the
- // vsync time is delayed from the touch, so add a negative sign.
- bool isDelayedVsyncEvent = vsyncTouchDiff < -mDelayedVsyncThreshold;
- bool isOldTouch = vsyncTouchDiff > mOldTouchThreshold;
- bool resample = (touchCount > 1) && !isDelayedVsyncEvent && !isOldTouch;
-
- if (!resample) {
- touchMove = mTouchMoveEvents.back();
- mTouchMoveEvents.clear();
- if (!isDelayedVsyncEvent && !isOldTouch) {
- mTouchMoveEvents.push_back(touchMove);
- }
- } else {
- ResampleTouchMoves(touchMove, aVsyncTime);
- }
- }
-
- DispatchTouchEvent(touchMove);
-}
-
-static int
-Interpolate(int start, int end, TimeDuration aFrameDiff, TimeDuration aTouchDiff)
-{
- return start + (((end - start) * aFrameDiff.ToMicroseconds()) / aTouchDiff.ToMicroseconds());
-}
-
-static const SingleTouchData&
-GetTouchByID(const SingleTouchData& aCurrentTouch, MultiTouchInput& aOtherTouch)
-{
- int32_t index = aOtherTouch.IndexOfTouch(aCurrentTouch.mIdentifier);
- if (index < 0) {
- // We can have situations where a previous touch event had 2 fingers
- // and we lift 1 finger off. In those cases, we won't find the touch event
- // with given id, so just return the current touch, which will be resampled
- // without modification and dispatched.
- return aCurrentTouch;
- }
- return aOtherTouch.mTouches[index];
-}
-
-
-// aTouchDiff is the duration between the base and current touch times
-// aFrameDiff is the duration between the base and the time we're resampling to
-static void
-ResampleTouch(MultiTouchInput& aOutTouch,
- MultiTouchInput& aBase, MultiTouchInput& aCurrent,
- TimeDuration aFrameDiff, TimeDuration aTouchDiff)
-{
- aOutTouch = aCurrent;
-
- // Make sure we only resample the correct finger.
- for (size_t i = 0; i < aOutTouch.mTouches.Length(); i++) {
- const SingleTouchData& current = aCurrent.mTouches[i];
- const SingleTouchData& base = GetTouchByID(current, aBase);
-
- const ScreenIntPoint& baseTouchPoint = base.mScreenPoint;
- const ScreenIntPoint& currentTouchPoint = current.mScreenPoint;
-
- ScreenIntPoint newSamplePoint;
- newSamplePoint.x = Interpolate(baseTouchPoint.x, currentTouchPoint.x, aFrameDiff, aTouchDiff);
- newSamplePoint.y = Interpolate(baseTouchPoint.y, currentTouchPoint.y, aFrameDiff, aTouchDiff);
-
- aOutTouch.mTouches[i].mScreenPoint = newSamplePoint;
-
-#ifdef LOG_RESAMPLE_DATA
- const char* type = "extrapolate";
- if (aFrameDiff < aTouchDiff) {
- type = "interpolate";
- }
-
- float alpha = aFrameDiff / aTouchDiff;
- LOG("%s base (%d, %d), current (%d, %d) to (%d, %d) alpha %f, touch diff %d, frame diff %d\n",
- type,
- baseTouchPoint.x, baseTouchPoint.y,
- currentTouchPoint.x, currentTouchPoint.y,
- newSamplePoint.x, newSamplePoint.y,
- alpha, (int)aTouchDiff.ToMilliseconds(), (int)aFrameDiff.ToMilliseconds());
-#endif
- }
-}
-
-/*
- * +> Base touch (The touch before current touch)
- * |
- * | +> Current touch (Latest touch)
- * | |
- * | | +> Maximum resample time
- * | | |
- * +-----+------+--------------------> Time
- * ^ ^
- * | |
- * +------+--> Potential vsync events which the touches are resampled to
- * | |
- * | +> Extrapolation
- * |
- * +> Interpolation
- */
-
-void
-GeckoTouchDispatcher::ResampleTouchMoves(MultiTouchInput& aOutTouch, TimeStamp aVsyncTime)
-{
- MOZ_RELEASE_ASSERT(mTouchMoveEvents.size() >= 2);
- mTouchQueueLock.AssertCurrentThreadOwns();
-
- MultiTouchInput currentTouch = mTouchMoveEvents.back();
- mTouchMoveEvents.pop_back();
- MultiTouchInput baseTouch = mTouchMoveEvents.back();
- mTouchMoveEvents.clear();
- mTouchMoveEvents.push_back(currentTouch);
-
- TimeStamp sampleTime = aVsyncTime - mVsyncAdjust;
- TimeDuration touchDiff = currentTouch.mTimeStamp - baseTouch.mTimeStamp;
-
- if (touchDiff < mMinDelta) {
- aOutTouch = currentTouch;
- #ifdef LOG_RESAMPLE_DATA
- LOG("The touches are too close, skip resampling\n");
- #endif
- return;
- }
-
- if (currentTouch.mTimeStamp < sampleTime) {
- TimeDuration maxResampleTime = std::min(touchDiff / int64_t(2), mMaxPredict);
- TimeStamp maxTimestamp = currentTouch.mTimeStamp + maxResampleTime;
- if (sampleTime > maxTimestamp) {
- sampleTime = maxTimestamp;
- #ifdef LOG_RESAMPLE_DATA
- LOG("Overshot extrapolation time, adjusting sample time\n");
- #endif
- }
- }
-
- ResampleTouch(aOutTouch, baseTouch, currentTouch, sampleTime - baseTouch.mTimeStamp, touchDiff);
-
- // Both mTimeStamp and mTime are being updated to sampleTime here.
- // mTime needs to be updated using a delta since TimeStamp doesn't
- // provide a way to obtain a raw value.
- aOutTouch.mTime += (sampleTime - aOutTouch.mTimeStamp).ToMilliseconds();
- aOutTouch.mTimeStamp = sampleTime;
-}
-
-static bool
-IsExpired(const MultiTouchInput& aTouch)
-{
- // No pending events, the filter state can be updated.
- uint64_t timeNowMs = systemTime(SYSTEM_TIME_MONOTONIC) / 1000000;
- return (timeNowMs - aTouch.mTime) > kInputExpirationThresholdMs;
-}
-void
-GeckoTouchDispatcher::DispatchTouchEvent(MultiTouchInput aMultiTouch)
-{
- if ((aMultiTouch.mType == MultiTouchInput::MULTITOUCH_END ||
- aMultiTouch.mType == MultiTouchInput::MULTITOUCH_CANCEL) &&
- aMultiTouch.mTouches.Length() == 1) {
- MutexAutoLock lock(mTouchQueueLock);
- mTouchMoveEvents.clear();
- } else if (aMultiTouch.mType == MultiTouchInput::MULTITOUCH_START &&
- aMultiTouch.mTouches.Length() == 1) {
- mTouchEventsFiltered = IsExpired(aMultiTouch);
- }
-
- if (mTouchEventsFiltered) {
- return;
- }
-
- nsWindow::DispatchTouchInput(aMultiTouch);
-
- if (mEnabledUniformityInfo && profiler_is_active()) {
- const char* touchAction = "Invalid";
- switch (aMultiTouch.mType) {
- case MultiTouchInput::MULTITOUCH_START:
- touchAction = "Touch_Event_Down";
- break;
- case MultiTouchInput::MULTITOUCH_MOVE:
- touchAction = "Touch_Event_Move";
- break;
- case MultiTouchInput::MULTITOUCH_END:
- case MultiTouchInput::MULTITOUCH_CANCEL:
- touchAction = "Touch_Event_Up";
- break;
- case MultiTouchInput::MULTITOUCH_SENTINEL:
- MOZ_ASSERT_UNREACHABLE("Invalid MultTouchInput.");
- break;
- }
-
- const ScreenIntPoint& touchPoint = aMultiTouch.mTouches[0].mScreenPoint;
- TouchDataPayload* payload = new TouchDataPayload(touchPoint);
- PROFILER_MARKER_PAYLOAD(touchAction, payload);
- }
-}
-
-} // namespace mozilla
diff --git a/widget/gonk/GeckoTouchDispatcher.h b/widget/gonk/GeckoTouchDispatcher.h
deleted file mode 100644
index 3c7acd0e3..000000000
--- a/widget/gonk/GeckoTouchDispatcher.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sts=2 et sw=2 tw=80: */
-/* Copyright 2014 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 GECKO_TOUCH_INPUT_DISPATCHER_h
-#define GECKO_TOUCH_INPUT_DISPATCHER_h
-
-#include "InputData.h"
-#include "Units.h"
-#include "mozilla/Mutex.h"
-#include <vector>
-#include "mozilla/RefPtr.h"
-
-class nsIWidget;
-
-namespace mozilla {
-namespace layers {
-class CompositorVsyncScheduler;
-}
-
-// Used to resample touch events whenever a vsync event occurs. It batches
-// touch moves and on every vsync, resamples the touch position to create smooth
-// scrolls. We use the Android touch resample algorithm. It uses a combination of
-// extrapolation and interpolation. The algorithm takes the vsync time and
-// subtracts mVsyncAdjust time in ms and creates a sample time. All touch events are
-// relative to this sample time. If the last touch event occurs AFTER this
-// sample time, interpolate the last two touch events. If the last touch event occurs BEFORE
-// this sample time, we extrapolate the last two touch events to the sample
-// time. The magic numbers defined as constants are taken from android
-// InputTransport.cpp.
-class GeckoTouchDispatcher final
-{
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GeckoTouchDispatcher)
-
-public:
- static GeckoTouchDispatcher* GetInstance();
- void NotifyTouch(MultiTouchInput& aTouch, TimeStamp aEventTime);
- void DispatchTouchEvent(MultiTouchInput aMultiTouch);
- void DispatchTouchNonMoveEvent(MultiTouchInput aInput);
- void DispatchTouchMoveEvents(TimeStamp aVsyncTime);
- void NotifyVsync(TimeStamp aVsyncTimestamp);
- void SetCompositorVsyncScheduler(layers::CompositorVsyncScheduler* aObserver);
-
-protected:
- ~GeckoTouchDispatcher() {}
-
-private:
- GeckoTouchDispatcher();
- void ResampleTouchMoves(MultiTouchInput& aOutTouch, TimeStamp vsyncTime);
- void SendTouchEvent(MultiTouchInput& aData);
- void DispatchMouseEvent(MultiTouchInput& aMultiTouch,
- bool aForwardToChildren);
-
- // mTouchQueueLock is used to protect the vector and state below
- // as it is accessed on multiple threads.
- Mutex mTouchQueueLock;
- std::vector<MultiTouchInput> mTouchMoveEvents;
- bool mHavePendingTouchMoves;
- int mInflightNonMoveEvents;
- // end stuff protected by mTouchQueueLock
-
- bool mResamplingEnabled;
- bool mTouchEventsFiltered;
- bool mEnabledUniformityInfo;
-
- // All times below are in nanoseconds
- TimeDuration mVsyncAdjust; // Time from vsync we create sample times from
- TimeDuration mMaxPredict; // How far into the future we're allowed to extrapolate
- TimeDuration mMinDelta; // Minimal time difference between touches for resampling
-
- // Amount of time between vsync and the last event that is required before we
- // resample
- TimeDuration mMinResampleTime;
-
- // Threshold if a vsync event runs too far behind touch events
- TimeDuration mDelayedVsyncThreshold;
-
- // How far ahead can vsync events get ahead of touch events.
- TimeDuration mOldTouchThreshold;
-
- RefPtr<layers::CompositorVsyncScheduler> mCompositorVsyncScheduler;
-};
-
-} // namespace mozilla
-
-#endif // GECKO_TOUCH_INPUT_DISPATCHER_h
diff --git a/widget/gonk/GfxInfo.cpp b/widget/gonk/GfxInfo.cpp
deleted file mode 100644
index 7ddd39038..000000000
--- a/widget/gonk/GfxInfo.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GfxInfo.h"
-
-using namespace mozilla::widget;
-
-/* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after gfxPlatform initialization
- * has occurred because they depend on it for information. (See bug 591561) */
-nsresult
-GfxInfo::GetD2DEnabled(bool *aEnabled)
-{
- return NS_ERROR_FAILURE;
-}
-
-nsresult
-GfxInfo::GetDWriteEnabled(bool *aEnabled)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
-{
- aAdapterDescription.Truncate();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
-{
- aAdapterRAM.Truncate();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
-{
- aAdapterDriver.Truncate();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
-{
- aAdapterDriverVersion.Truncate();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
-{
- aAdapterDriverDate.Truncate();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
-{
- aAdapterVendorID.Truncate();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
-{
- aAdapterDeviceID.Truncate();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterSubsysID(nsAString & aAdapterSubsysID)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetAdapterSubsysID2(nsAString & aAdapterSubsysID)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
-{
- return NS_ERROR_FAILURE;
-}
-
-const nsTArray<GfxDriverInfo>&
-GfxInfo::GetGfxDriverInfo()
-{
- return *mDriverInfo;
-}
-
-uint32_t GfxInfo::OperatingSystemVersion()
-{
- return 0;
-}
-
-nsresult
-GfxInfo::GetFeatureStatusImpl(int32_t /*aFeature*/,
- int32_t *aStatus,
- nsAString & /*aSuggestedDriverVersion*/,
- const nsTArray<GfxDriverInfo>& /*aDriverInfo*/,
- nsACString& aFailureId,
- OperatingSystem* /*aOS*/ /* = nullptr */)
-{
- NS_ENSURE_ARG_POINTER(aStatus);
- *aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
-
- return NS_OK;
-}
-
-#ifdef DEBUG
-
-// Implement nsIGfxInfoDebug
-
-NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString &)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString &)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString &)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t)
-{
- return NS_OK;
-}
-
-#endif
diff --git a/widget/gonk/GfxInfo.h b/widget/gonk/GfxInfo.h
deleted file mode 100644
index 61494713f..000000000
--- a/widget/gonk/GfxInfo.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* vim: se cin sw=2 ts=2 et : */
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __mozilla_widget_GfxInfo_h__
-#define __mozilla_widget_GfxInfo_h__
-
-#include "GfxInfoBase.h"
-#include "GfxDriverInfo.h"
-
-#include "nsString.h"
-
-namespace mozilla {
-namespace widget {
-
-class GfxInfo : public GfxInfoBase
-{
-public:
- // We only declare the subset of nsIGfxInfo that we actually implement. The
- // rest is brought forward from GfxInfoBase.
- NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
- NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
- NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
- NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
- NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
- NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver);
- NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID);
- NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID);
- NS_IMETHOD GetAdapterSubsysID(nsAString & aAdapterSubsysID);
- NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM);
- NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion);
- NS_IMETHOD GetAdapterDriverDate(nsAString & aAdapterDriverDate);
- NS_IMETHOD GetAdapterDescription2(nsAString & aAdapterDescription);
- NS_IMETHOD GetAdapterDriver2(nsAString & aAdapterDriver);
- NS_IMETHOD GetAdapterVendorID2(nsAString & aAdapterVendorID);
- NS_IMETHOD GetAdapterDeviceID2(nsAString & aAdapterDeviceID);
- NS_IMETHOD GetAdapterSubsysID2(nsAString & aAdapterSubsysID);
- NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM);
- NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion);
- NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate);
- NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active);
- using GfxInfoBase::GetFeatureStatus;
- using GfxInfoBase::GetFeatureSuggestedDriverVersion;
- using GfxInfoBase::GetWebGLParameter;
-
- virtual uint32_t OperatingSystemVersion() override;
-
-#ifdef DEBUG
- NS_DECL_NSIGFXINFODEBUG
-#endif
-
-protected:
-
- virtual nsresult GetFeatureStatusImpl(int32_t aFeature,
- int32_t *aStatus,
- nsAString & aSuggestedDriverVersion,
- const nsTArray<GfxDriverInfo>& aDriverInfo,
- nsACString& aFailureId,
- OperatingSystem* aOS = nullptr);
- virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo();
-};
-
-} // namespace widget
-} // namespace mozilla
-
-#endif /* __mozilla_widget_GfxInfo_h__ */
diff --git a/widget/gonk/GonkClipboardData.cpp b/widget/gonk/GonkClipboardData.cpp
deleted file mode 100644
index ced6422a5..000000000
--- a/widget/gonk/GonkClipboardData.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GonkClipboardData.h"
-#include "mozilla/gfx/DataSurfaceHelpers.h"
-
-namespace mozilla {
-
-void
-GonkClipboardData::SetText(const nsAString &aText)
-{
- mPlain = aText;
-}
-
-bool
-GonkClipboardData::HasText() const
-{
- return !mPlain.IsEmpty();
-}
-
-const nsAString&
-GonkClipboardData::GetText() const
-{
- return mPlain;
-}
-
-void
-GonkClipboardData::SetHTML(const nsAString &aHTML)
-{
- mHTML = aHTML;
-}
-
-bool
-GonkClipboardData::HasHTML() const
-{
- return !mHTML.IsEmpty();
-}
-
-const nsAString&
-GonkClipboardData::GetHTML() const
-{
- return mHTML;
-}
-
-void
-GonkClipboardData::SetImage(gfx::DataSourceSurface* aDataSource)
-{
- // Clone a new DataSourceSurface and store it.
- mImage = gfx::CreateDataSourceSurfaceByCloning(aDataSource);
-}
-
-bool
-GonkClipboardData::HasImage() const
-{
- return static_cast<bool>(mImage);
-}
-
-already_AddRefed<gfx::DataSourceSurface>
-GonkClipboardData::GetImage() const
-{
- // Return cloned DataSourceSurface.
- RefPtr<gfx::DataSourceSurface> cloned = gfx::CreateDataSourceSurfaceByCloning(mImage);
- return cloned.forget();
-}
-
-void
-GonkClipboardData::Clear()
-{
- mPlain.Truncate(0);
- mHTML.Truncate(0);
- mImage = nullptr;
-}
-
-} // namespace mozilla
diff --git a/widget/gonk/GonkClipboardData.h b/widget/gonk/GonkClipboardData.h
deleted file mode 100644
index 8bc1f1c9c..000000000
--- a/widget/gonk/GonkClipboardData.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_GonkClipboardData
-#define mozilla_GonkClipboardData
-
-#include "mozilla/RefPtr.h"
-#include "nsString.h"
-
-namespace mozilla {
-
-namespace gfx {
-class DataSourceSurface;
-}
-
-class GonkClipboardData final
-{
-public:
- explicit GonkClipboardData() = default;
- ~GonkClipboardData() = default;
-
- // For text/plain
- void SetText(const nsAString &aText);
- bool HasText() const;
- const nsAString& GetText() const;
-
- // For text/html
- void SetHTML(const nsAString &aHTML);
- bool HasHTML() const;
- const nsAString& GetHTML() const;
-
- // For images
- void SetImage(gfx::DataSourceSurface* aDataSource);
- bool HasImage() const;
- already_AddRefed<gfx::DataSourceSurface> GetImage() const;
-
- // For other APIs
- void Clear();
-
-private:
- nsAutoString mPlain;
- nsAutoString mHTML;
- RefPtr<gfx::DataSourceSurface> mImage;
-};
-
-} // namespace mozilla
-
-#endif // mozilla_GonkClipboardData
diff --git a/widget/gonk/GonkKeyMapping.h b/widget/gonk/GonkKeyMapping.h
deleted file mode 100644
index d5d4e7a0b..000000000
--- a/widget/gonk/GonkKeyMapping.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 GONKKEYMAPPING_H
-#define GONKKEYMAPPING_H
-
-#include "libui/android_keycodes.h"
-#include "mozilla/EventForwards.h"
-
-namespace mozilla {
-namespace widget {
-
-/* See libui/KeycodeLabels.h for the mapping */
-static const unsigned long kKeyMapping[] = {
- 0,
- 0, // SOFT_LEFT
- 0, // SOFT_RIGHT
- NS_VK_HOME, // HOME
- NS_VK_ESCAPE, // BACK
- 0, // CALL
- NS_VK_SLEEP, // ENDCALL
- NS_VK_0,
- NS_VK_1,
- NS_VK_2,
- NS_VK_3,
- NS_VK_4,
- NS_VK_5,
- NS_VK_6,
- NS_VK_7,
- NS_VK_8,
- NS_VK_9,
- NS_VK_ASTERISK,
- NS_VK_HASH,
- NS_VK_UP,
- NS_VK_DOWN,
- NS_VK_LEFT,
- NS_VK_RIGHT,
- NS_VK_RETURN,
- NS_VK_VOLUME_UP,
- NS_VK_VOLUME_DOWN,
- NS_VK_SLEEP, // POWER
- NS_VK_PRINTSCREEN, // CAMERA
- NS_VK_CLEAR,
- NS_VK_A,
- NS_VK_B,
- NS_VK_C,
- NS_VK_D,
- NS_VK_E,
- NS_VK_F,
- NS_VK_G,
- NS_VK_H,
- NS_VK_I,
- NS_VK_J,
- NS_VK_K,
- NS_VK_L,
- NS_VK_M,
- NS_VK_N,
- NS_VK_O,
- NS_VK_P,
- NS_VK_Q,
- NS_VK_R,
- NS_VK_S,
- NS_VK_T,
- NS_VK_U,
- NS_VK_V,
- NS_VK_W,
- NS_VK_X,
- NS_VK_Y,
- NS_VK_Z,
- NS_VK_COMMA,
- NS_VK_PERIOD,
- 0,
- 0,
- 0,
- 0,
- NS_VK_TAB,
- NS_VK_SPACE,
- NS_VK_META, // SYM
- 0, // EXPLORER
- 0, // ENVELOPE
- NS_VK_RETURN, // ENTER
- NS_VK_BACK,
- NS_VK_BACK_QUOTE, // GRAVE
- NS_VK_HYPHEN_MINUS,
- NS_VK_EQUALS,
- NS_VK_OPEN_BRACKET,
- NS_VK_CLOSE_BRACKET,
- NS_VK_BACK_SLASH,
- NS_VK_SEMICOLON,
- NS_VK_QUOTE,
- NS_VK_SLASH,
- NS_VK_AT,
- 0, // NUM
- NS_VK_F1, // HEADSETHOOK
- 0, // FOCUS
- NS_VK_PLUS,
- NS_VK_CONTEXT_MENU,
- 0, // NOTIFICATION
- NS_VK_F5, // SEARCH
- 0, // MEDIA_PLAY_PAUSE
- 0, // MEDIA_STOP
- 0, // MEDIA_NEXT
- 0, // MEDIA_PREVIOUS
- 0, // MEDIA_REWIND
- 0, // MEDIA_FAST_FORWARD
- 0, // MUTE
- NS_VK_PAGE_UP,
- NS_VK_PAGE_DOWN,
- 0, // PICTSYMBOLS
- 0, // SWITCH_CHARSET
- 0, // BUTTON_A
- 0, // BUTTON_B
- 0, // BUTTON_C
- 0, // BUTTON_X
- 0, // BUTTON_Y
- 0, // BUTTON_Z
- 0, // BUTTON_L1
- 0, // BUTTON_R1
- 0, // BUTTON_L2
- 0, // BUTTON_R2
- 0, // BUTTON_THUMBL
- 0, // BUTTON_THUMBR
- 0, // BUTTON_START
- 0, // BUTTON_SELECT
- 0, // BUTTON_MODE
- NS_VK_ESCAPE,
- NS_VK_DELETE,
- 0, // CTRL_LEFT
- 0, // CTRL_RIGHT
- NS_VK_CAPS_LOCK,
- NS_VK_SCROLL_LOCK,
- 0, // META_LEFT
- 0, // META_RIGHT
- 0, // FUNCTION
- 0, // SYSRQ
- 0, // BREAK
- NS_VK_HOME, // MOVE_HOME
- NS_VK_END,
- NS_VK_INSERT,
- 0, // FORWARD
- 0, // MEDIA_PLAY
- 0, // MEDIA_PAUSE
- 0, // MEDIA_CLOSE
- 0, // MEDIA_EJECT
- 0, // MEDIA_RECORD
- NS_VK_F1,
- NS_VK_F2,
- NS_VK_F3,
- NS_VK_F4,
- NS_VK_F5,
- NS_VK_F6,
- NS_VK_F7,
- NS_VK_F8,
- NS_VK_F9,
- NS_VK_F10,
- NS_VK_F11,
- NS_VK_F12,
- NS_VK_NUM_LOCK,
- NS_VK_NUMPAD0,
- NS_VK_NUMPAD1,
- NS_VK_NUMPAD2,
- NS_VK_NUMPAD3,
- NS_VK_NUMPAD4,
- NS_VK_NUMPAD5,
- NS_VK_NUMPAD6,
- NS_VK_NUMPAD7,
- NS_VK_NUMPAD8,
- NS_VK_NUMPAD9,
- NS_VK_DIVIDE,
- NS_VK_MULTIPLY,
- NS_VK_SUBTRACT,
- NS_VK_ADD,
- NS_VK_PERIOD,
- NS_VK_COMMA,
- NS_VK_RETURN,
- NS_VK_EQUALS,
- 0, // NUMPAD_LEFT_PAREN
- 0, // NUMPAD_RIGHT_PAREN
- NS_VK_VOLUME_MUTE,
- // There are more but we don't map them
-};
-
-static KeyNameIndex GetKeyNameIndex(int aKeyCode)
-{
- switch (aKeyCode) {
-#define NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex) \
- case aNativeKey: return aKeyNameIndex;
-
-#include "NativeKeyToDOMKeyName.h"
-
-#undef NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
-
- case AKEYCODE_0:
- case AKEYCODE_1:
- case AKEYCODE_2:
- case AKEYCODE_3:
- case AKEYCODE_4:
- case AKEYCODE_5:
- case AKEYCODE_6:
- case AKEYCODE_7:
- case AKEYCODE_8:
- case AKEYCODE_9:
- case AKEYCODE_STAR:
- case AKEYCODE_POUND:
- case AKEYCODE_A:
- case AKEYCODE_B:
- case AKEYCODE_C:
- case AKEYCODE_D:
- case AKEYCODE_E:
- case AKEYCODE_F:
- case AKEYCODE_G:
- case AKEYCODE_H:
- case AKEYCODE_I:
- case AKEYCODE_J:
- case AKEYCODE_K:
- case AKEYCODE_L:
- case AKEYCODE_M:
- case AKEYCODE_N:
- case AKEYCODE_O:
- case AKEYCODE_P:
- case AKEYCODE_Q:
- case AKEYCODE_R:
- case AKEYCODE_S:
- case AKEYCODE_T:
- case AKEYCODE_U:
- case AKEYCODE_V:
- case AKEYCODE_W:
- case AKEYCODE_X:
- case AKEYCODE_Y:
- case AKEYCODE_Z:
- case AKEYCODE_COMMA:
- case AKEYCODE_PERIOD:
- case AKEYCODE_SPACE:
- case AKEYCODE_GRAVE:
- case AKEYCODE_MINUS:
- case AKEYCODE_EQUALS:
- case AKEYCODE_LEFT_BRACKET:
- case AKEYCODE_RIGHT_BRACKET:
- case AKEYCODE_BACKSLASH:
- case AKEYCODE_SEMICOLON:
- case AKEYCODE_APOSTROPHE:
- case AKEYCODE_SLASH:
- case AKEYCODE_AT:
- case AKEYCODE_PLUS:
- case AKEYCODE_NUMPAD_0:
- case AKEYCODE_NUMPAD_1:
- case AKEYCODE_NUMPAD_2:
- case AKEYCODE_NUMPAD_3:
- case AKEYCODE_NUMPAD_4:
- case AKEYCODE_NUMPAD_5:
- case AKEYCODE_NUMPAD_6:
- case AKEYCODE_NUMPAD_7:
- case AKEYCODE_NUMPAD_8:
- case AKEYCODE_NUMPAD_9:
- case AKEYCODE_NUMPAD_DIVIDE:
- case AKEYCODE_NUMPAD_MULTIPLY:
- case AKEYCODE_NUMPAD_SUBTRACT:
- case AKEYCODE_NUMPAD_ADD:
- case AKEYCODE_NUMPAD_DOT:
- case AKEYCODE_NUMPAD_COMMA:
- case AKEYCODE_NUMPAD_EQUALS:
- case AKEYCODE_NUMPAD_LEFT_PAREN:
- case AKEYCODE_NUMPAD_RIGHT_PAREN:
- return KEY_NAME_INDEX_USE_STRING;
-
- default:
- return KEY_NAME_INDEX_Unidentified;
- }
-}
-
-static CodeNameIndex GetCodeNameIndex(int aScanCode)
-{
- switch (aScanCode) {
-#define NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, aCodeNameIndex) \
- case aNativeKey: return aCodeNameIndex;
-
-#include "NativeKeyToDOMCodeName.h"
-
-#undef NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX
-
- default:
- return CODE_NAME_INDEX_UNKNOWN;
- }
-}
-
-} // namespace widget
-} // namespace mozilla
-
-#endif /* GONKKEYMAPPING_H */
diff --git a/widget/gonk/GonkMemoryPressureMonitoring.cpp b/widget/gonk/GonkMemoryPressureMonitoring.cpp
deleted file mode 100644
index 0fafb37cf..000000000
--- a/widget/gonk/GonkMemoryPressureMonitoring.cpp
+++ /dev/null
@@ -1,359 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <android/log.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <sys/sysinfo.h>
-
-#include "GonkMemoryPressureMonitoring.h"
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/Monitor.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/ProcessPriorityManager.h"
-#include "mozilla/Services.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsMemoryPressure.h"
-#include "nsPrintfCString.h"
-#include "nsThreadUtils.h"
-
-#define LOG(args...) \
- __android_log_print(ANDROID_LOG_INFO, "GonkMemoryPressure" , ## args)
-
-using namespace mozilla;
-
-namespace {
-
-/**
- * MemoryPressureWatcher watches sysfs from its own thread to notice when the
- * system is under memory pressure. When we observe memory pressure, we use
- * MemoryPressureRunnable to notify observers that they should release memory.
- *
- * When the system is under memory pressure, we don't want to constantly fire
- * memory-pressure events. So instead, we try to detect when sysfs indicates
- * that we're no longer under memory pressure, and only then start firing events
- * again.
- *
- * (This is a bit problematic because we can't poll() to detect when we're no
- * longer under memory pressure; instead we have to periodically read the sysfs
- * node. If we remain under memory pressure for a long time, this means we'll
- * continue waking up to read from the node for a long time, potentially wasting
- * battery life. Hopefully we don't hit this case in practice! We write to
- * logcat each time we go around this loop so it's at least noticable.)
- *
- * Shutting down safely is a bit of a chore. XPCOM won't shut down until all
- * threads exit, so we need to exit the Run() method below on shutdown. But our
- * thread might be blocked in one of two situations: We might be poll()'ing the
- * sysfs node waiting for memory pressure to occur, or we might be asleep
- * waiting to read() the sysfs node to see if we're no longer under memory
- * pressure.
- *
- * To let us wake up from the poll(), we poll() not just the sysfs node but also
- * a pipe, which we write to on shutdown. To let us wake up from sleeping
- * between read()s, we sleep by Wait()'ing on a monitor, which we notify on
- * shutdown.
- */
-class MemoryPressureWatcher final
- : public nsIRunnable
- , public nsIObserver
-{
-public:
- MemoryPressureWatcher()
- : mMonitor("MemoryPressureWatcher")
- , mLowMemTriggerKB(0)
- , mPageSize(0)
- , mShuttingDown(false)
- , mTriggerFd(-1)
- , mShutdownPipeRead(-1)
- , mShutdownPipeWrite(-1)
- {
- }
-
- NS_DECL_THREADSAFE_ISUPPORTS
-
- nsresult Init()
- {
- nsCOMPtr<nsIObserverService> os = services::GetObserverService();
- NS_ENSURE_STATE(os);
-
- // The observer service holds us alive.
- os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, /* ownsWeak */ false);
-
- // Initialize the internal state
- mPageSize = sysconf(_SC_PAGESIZE);
- ReadPrefs();
- nsresult rv = OpenFiles();
- NS_ENSURE_SUCCESS(rv, rv);
- SetLowMemTrigger(mSoftLowMemTriggerKB);
-
- return NS_OK;
- }
-
- NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
- const char16_t* aData)
- {
- MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
- LOG("Observed XPCOM shutdown.");
-
- MonitorAutoLock lock(mMonitor);
- mShuttingDown = true;
- mMonitor.Notify();
-
- int rv;
- do {
- // Write something to the pipe; doesn't matter what.
- uint32_t dummy = 0;
- rv = write(mShutdownPipeWrite, &dummy, sizeof(dummy));
- } while(rv == -1 && errno == EINTR);
-
- return NS_OK;
- }
-
- NS_IMETHOD Run() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- int triggerResetTimeout = -1;
- bool memoryPressure;
- nsresult rv = CheckForMemoryPressure(&memoryPressure);
- NS_ENSURE_SUCCESS(rv, rv);
-
- while (true) {
- // Wait for a notification on mTriggerFd or for data to be written to
- // mShutdownPipeWrite. (poll(mTriggerFd, POLLPRI) blocks until we're
- // under memory pressure or until we time out, the time out is used
- // to adjust the trigger level after a memory pressure event.)
- struct pollfd pollfds[2];
- pollfds[0].fd = mTriggerFd;
- pollfds[0].events = POLLPRI;
- pollfds[1].fd = mShutdownPipeRead;
- pollfds[1].events = POLLIN;
-
- int pollRv = MOZ_TEMP_FAILURE_RETRY(
- poll(pollfds, ArrayLength(pollfds), triggerResetTimeout)
- );
-
- if (pollRv == 0) {
- // Timed out, adjust the trigger and update the timeout.
- triggerResetTimeout = AdjustTrigger(triggerResetTimeout);
- continue;
- }
-
- if (pollfds[1].revents) {
- // Something was written to our shutdown pipe; we're outta here.
- LOG("shutting down (1)");
- return NS_OK;
- }
-
- // If pollfds[1] isn't happening, pollfds[0] ought to be!
- if (!(pollfds[0].revents & POLLPRI)) {
- LOG("Unexpected revents value after poll(): %d. "
- "Shutting down GonkMemoryPressureMonitoring.", pollfds[0].revents);
- return NS_ERROR_FAILURE;
- }
-
- // POLLPRI on mTriggerFd indicates that we're in a low-memory situation.
- // We could read lowMemFd to double-check, but we've observed that the
- // read sometimes completes after the memory-pressure event is over, so
- // let's just believe the result of poll().
- rv = DispatchMemoryPressure(MemPressure_New);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Move to the hard level if we're on the soft one.
- if (mLowMemTriggerKB > mHardLowMemTriggerKB) {
- SetLowMemTrigger(mHardLowMemTriggerKB);
- }
-
- // Manually check mTriggerFd until we observe that memory pressure is
- // over. We won't fire any more low-memory events until we observe that
- // we're no longer under pressure. Instead, we fire low-memory-ongoing
- // events, which cause processes to keep flushing caches but will not
- // trigger expensive GCs and other attempts to save memory that are
- // likely futile at this point.
- do {
- {
- MonitorAutoLock lock(mMonitor);
-
- // We need to check mShuttingDown before we wait here, in order to
- // catch a shutdown signal sent after we poll()'ed mShutdownPipeRead
- // above but before we started waiting on the monitor. But we don't
- // need to check after we wait, because we'll either do another
- // iteration of this inner loop, in which case we'll check
- // mShuttingDown, or we'll exit this loop and do another iteration
- // of the outer loop, in which case we'll check the shutdown pipe.
- if (mShuttingDown) {
- LOG("shutting down (2)");
- return NS_OK;
- }
- mMonitor.Wait(PR_MillisecondsToInterval(mPollMS));
- }
-
- LOG("Checking to see if memory pressure is over.");
- rv = CheckForMemoryPressure(&memoryPressure);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (memoryPressure) {
- rv = DispatchMemoryPressure(MemPressure_Ongoing);
- NS_ENSURE_SUCCESS(rv, rv);
- continue;
- }
- } while (false);
-
- if (XRE_IsParentProcess()) {
- // The main process will try to adjust the trigger.
- triggerResetTimeout = mPollMS * 2;
- }
-
- LOG("Memory pressure is over.");
- }
-
- return NS_OK;
- }
-
-protected:
- ~MemoryPressureWatcher() {}
-
-private:
- void ReadPrefs() {
- // While we're under memory pressure, we periodically read()
- // notify_trigger_active to try and see when we're no longer under memory
- // pressure. mPollMS indicates how many milliseconds we wait between those
- // read()s.
- Preferences::AddUintVarCache(&mPollMS,
- "gonk.systemMemoryPressureRecoveryPollMS", /* default */ 5000);
-
- // We have two values for the notify trigger, a soft one which is triggered
- // before we start killing background applications and an hard one which is
- // after we've killed background applications but before we start killing
- // foreground ones.
- Preferences::AddUintVarCache(&mSoftLowMemTriggerKB,
- "gonk.notifySoftLowMemUnderKB", /* default */ 43008);
- Preferences::AddUintVarCache(&mHardLowMemTriggerKB,
- "gonk.notifyHardLowMemUnderKB", /* default */ 14336);
- }
-
- nsresult OpenFiles() {
- mTriggerFd = open("/sys/kernel/mm/lowmemkiller/notify_trigger_active",
- O_RDONLY | O_CLOEXEC);
- NS_ENSURE_STATE(mTriggerFd != -1);
-
- int pipes[2];
- NS_ENSURE_STATE(!pipe(pipes));
- mShutdownPipeRead = pipes[0];
- mShutdownPipeWrite = pipes[1];
- return NS_OK;
- }
-
- /**
- * Set the low memory trigger to the specified value, this can be done by
- * the main process alone.
- */
- void SetLowMemTrigger(uint32_t aValue) {
- if (XRE_IsParentProcess()) {
- nsPrintfCString str("%ld", (aValue * 1024) / mPageSize);
- if (WriteSysFile("/sys/module/lowmemorykiller/parameters/notify_trigger",
- str.get())) {
- mLowMemTriggerKB = aValue;
- }
- }
- }
-
- /**
- * Read from the trigger file descriptor and determine whether we're
- * currently under memory pressure.
- *
- * We don't expect this method to block.
- */
- nsresult CheckForMemoryPressure(bool* aOut)
- {
- *aOut = false;
-
- lseek(mTriggerFd, 0, SEEK_SET);
-
- char buf[2];
- int nread = MOZ_TEMP_FAILURE_RETRY(read(mTriggerFd, buf, sizeof(buf)));
- NS_ENSURE_STATE(nread == 2);
-
- // The notify_trigger_active sysfs node should contain either "0\n" or
- // "1\n". The latter indicates memory pressure.
- *aOut = (buf[0] == '1');
- return NS_OK;
- }
-
- int AdjustTrigger(int timeout)
- {
- if (!XRE_IsParentProcess()) {
- return -1; // Only the main process can adjust the trigger.
- }
-
- struct sysinfo info;
- int rv = sysinfo(&info);
- if (rv < 0) {
- return -1; // Without system information we're blind, bail out.
- }
-
- size_t freeMemory = (info.freeram * info.mem_unit) / 1024;
-
- if (freeMemory > mSoftLowMemTriggerKB) {
- SetLowMemTrigger(mSoftLowMemTriggerKB);
- return -1; // Trigger adjusted, wait indefinitely.
- }
-
- // Wait again but double the duration, max once per day.
- return std::min(86400000, timeout * 2);
- }
-
- /**
- * Dispatch the specified memory pressure event unless a high-priority
- * process is present. If a high-priority process is present then it's likely
- * responding to an urgent event (an incoming call or message for example) so
- * avoid wasting CPU time responding to low-memory events.
- */
- nsresult DispatchMemoryPressure(MemoryPressureState state)
- {
- if (ProcessPriorityManager::AnyProcessHasHighPriority()) {
- return NS_OK;
- }
-
- return NS_DispatchMemoryPressure(state);
- }
-
- Monitor mMonitor;
- uint32_t mPollMS; // Ongoing pressure poll delay
- uint32_t mSoftLowMemTriggerKB; // Soft memory pressure level
- uint32_t mHardLowMemTriggerKB; // Hard memory pressure level
- uint32_t mLowMemTriggerKB; // Current value of the trigger
- size_t mPageSize;
- bool mShuttingDown;
-
- ScopedClose mTriggerFd;
- ScopedClose mShutdownPipeRead;
- ScopedClose mShutdownPipeWrite;
-};
-
-NS_IMPL_ISUPPORTS(MemoryPressureWatcher, nsIRunnable, nsIObserver);
-
-} // namespace
-
-namespace mozilla {
-
-void
-InitGonkMemoryPressureMonitoring()
-{
- // memoryPressureWatcher is held alive by the observer service.
- RefPtr<MemoryPressureWatcher> memoryPressureWatcher =
- new MemoryPressureWatcher();
- NS_ENSURE_SUCCESS_VOID(memoryPressureWatcher->Init());
-
- nsCOMPtr<nsIThread> thread;
- NS_NewNamedThread("MemoryPressure", getter_AddRefs(thread),
- memoryPressureWatcher);
-}
-
-} // namespace mozilla
diff --git a/widget/gonk/GonkMemoryPressureMonitoring.h b/widget/gonk/GonkMemoryPressureMonitoring.h
deleted file mode 100644
index 4d5149cd6..000000000
--- a/widget/gonk/GonkMemoryPressureMonitoring.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_GonkMemoryPressureMonitoring_h_
-#define mozilla_GonkMemoryPressureMonitoring_h_
-
-namespace mozilla {
-void InitGonkMemoryPressureMonitoring();
-}
-
-#endif /* mozilla_GonkMemoryPressureMonitoring_h_ */
diff --git a/widget/gonk/GonkPermission.cpp b/widget/gonk/GonkPermission.cpp
deleted file mode 100644
index 8ebc43de8..000000000
--- a/widget/gonk/GonkPermission.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "GonkPermission.h"
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <binder/IPermissionController.h>
-
-#ifndef HAVE_ANDROID_OS
-#define HAVE_ANDROID_OS 1
-#endif
-#include <private/android_filesystem_config.h>
-
-#include "mozilla/dom/ContentParent.h"
-#include "mozilla/dom/TabParent.h"
-#include "mozilla/SyncRunnable.h"
-#include "nsIAppsService.h"
-#include "mozIApplication.h"
-#include "nsThreadUtils.h"
-
-#undef LOG
-#include <android/log.h>
-#undef ALOGE
-#define ALOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "gonkperm" , ## args)
-
-using namespace android;
-using namespace mozilla;
-
-// Checking permissions needs to happen on the main thread, but the
-// binder callback is called on a special binder thread, so we use
-// this runnable for that.
-class GonkPermissionChecker : public Runnable {
- int32_t mPid;
- bool mCanUseCamera;
-
- explicit GonkPermissionChecker(int32_t pid)
- : mPid(pid)
- , mCanUseCamera(false)
- {
- }
-
-public:
- static already_AddRefed<GonkPermissionChecker> Inspect(int32_t pid)
- {
- RefPtr<GonkPermissionChecker> that = new GonkPermissionChecker(pid);
- nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
- MOZ_ASSERT(mainThread);
- SyncRunnable::DispatchToThread(mainThread, that);
- return that.forget();
- }
-
- bool CanUseCamera()
- {
- return mCanUseCamera;
- }
-
- NS_IMETHOD Run();
-};
-
-NS_IMETHODIMP
-GonkPermissionChecker::Run()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- // Find our ContentParent.
- dom::ContentParent *contentParent = nullptr;
- {
- nsTArray<dom::ContentParent*> parents;
- dom::ContentParent::GetAll(parents);
- for (uint32_t i = 0; i < parents.Length(); ++i) {
- if (parents[i]->Pid() == mPid) {
- contentParent = parents[i];
- break;
- }
- }
- }
- if (!contentParent) {
- ALOGE("pid=%d denied: can't find ContentParent", mPid);
- return NS_OK;
- }
-
- // Now iterate its apps...
- const ManagedContainer<dom::PBrowserParent>& browsers =
- contentParent->ManagedPBrowserParent();
- for (auto iter = browsers.ConstIter(); !iter.Done(); iter.Next()) {
- dom::TabParent *tabParent =
- static_cast<dom::TabParent*>(iter.Get()->GetKey());
- nsCOMPtr<mozIApplication> mozApp = tabParent->GetOwnOrContainingApp();
- if (!mozApp) {
- continue;
- }
-
- // ...and check if any of them has camera access.
- bool appCanUseCamera;
- nsresult rv = mozApp->HasPermission("camera", &appCanUseCamera);
- if (NS_SUCCEEDED(rv) && appCanUseCamera) {
- mCanUseCamera = true;
- return NS_OK;
- }
- }
- return NS_OK;
-}
-
-bool
-GonkPermissionService::checkPermission(const String16& permission, int32_t pid,
- int32_t uid)
-{
- // root can do anything.
- if (0 == uid) {
- return true;
- }
-
- String8 perm8(permission);
-
- // Some ril implementations need android.permission.MODIFY_AUDIO_SETTINGS
- if ((uid == AID_SYSTEM || uid == AID_RADIO || uid == AID_BLUETOOTH) &&
- perm8 == "android.permission.MODIFY_AUDIO_SETTINGS") {
- return true;
- }
-
- // No other permissions apply to non-app processes.
- if (uid < AID_APP) {
- ALOGE("%s for pid=%d,uid=%d denied: not an app",
- String8(permission).string(), pid, uid);
- return false;
- }
-
- // Only these permissions can be granted to apps through this service.
- if (perm8 != "android.permission.CAMERA" &&
- perm8 != "android.permission.RECORD_AUDIO") {
- ALOGE("%s for pid=%d,uid=%d denied: unsupported permission",
- String8(permission).string(), pid, uid);
- return false;
- }
-
- // Users granted the permission through a prompt dialog.
- // Before permission managment of gUM is done, app cannot remember the
- // permission.
- PermissionGrant permGrant(perm8.string(), pid);
- if (nsTArray<PermissionGrant>::NoIndex != mGrantArray.IndexOf(permGrant)) {
- mGrantArray.RemoveElement(permGrant);
- return true;
- }
-
- // Camera/audio record permissions are allowed for apps with the
- // "camera" permission.
- RefPtr<GonkPermissionChecker> checker =
- GonkPermissionChecker::Inspect(pid);
- bool canUseCamera = checker->CanUseCamera();
- if (!canUseCamera) {
- ALOGE("%s for pid=%d,uid=%d denied: not granted by user or app manifest",
- String8(permission).string(), pid, uid);
- }
- return canUseCamera;
-}
-
-static GonkPermissionService* gGonkPermissionService = NULL;
-
-/* static */
-void
-GonkPermissionService::instantiate()
-{
- defaultServiceManager()->addService(String16(getServiceName()),
- GetInstance());
-}
-
-/* static */
-GonkPermissionService*
-GonkPermissionService::GetInstance()
-{
- if (!gGonkPermissionService) {
- gGonkPermissionService = new GonkPermissionService();
- }
- return gGonkPermissionService;
-}
-
-void
-GonkPermissionService::addGrantInfo(const char* permission, int32_t pid)
-{
- mGrantArray.AppendElement(PermissionGrant(permission, pid));
-}
diff --git a/widget/gonk/GonkPermission.h b/widget/gonk/GonkPermission.h
deleted file mode 100644
index d34fcd8ac..000000000
--- a/widget/gonk/GonkPermission.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 GONKPERMISSION_H
-#define GONKPERMISSION_H
-
-#include <binder/BinderService.h>
-#include "nsString.h"
-#include "nsTArray.h"
-
-namespace mozilla {
-class PermissionGrant
-{
-public:
- PermissionGrant(const char* perm, int32_t p) : mPid(p)
- {
- mPermission.Assign(perm);
- }
-
- PermissionGrant(const nsACString& permission, int32_t pid) : mPid(pid),
- mPermission(permission)
- {
- }
-
- bool operator==(const PermissionGrant& other) const
- {
- return (mPid == other.pid() && mPermission.Equals(other.permission()));
- }
-
- int32_t pid() const
- {
- return mPid;
- }
-
- const nsACString& permission() const
- {
- return mPermission;
- }
-
-private:
- int32_t mPid;
- nsCString mPermission;
-};
-
-class PermissionGrant;
-
-class GonkPermissionService :
- public android::BinderService<GonkPermissionService>,
- public android::BnPermissionController
-{
-public:
- virtual ~GonkPermissionService() {}
- static GonkPermissionService* GetInstance();
- static const char *getServiceName() {
- return "permission";
- }
-
- static void instantiate();
-
- virtual android::status_t dump(int fd, const android::Vector<android::String16>& args) {
- return android::NO_ERROR;
- }
- virtual bool checkPermission(const android::String16& permission, int32_t pid,
- int32_t uid);
-
- void addGrantInfo(const char* permission, int32_t pid);
-private:
- GonkPermissionService(): android::BnPermissionController() {}
- nsTArray<PermissionGrant> mGrantArray;
-};
-
-} // namespace mozilla
-
-#endif // GONKPERMISSION_H
diff --git a/widget/gonk/HwcComposer2D.cpp b/widget/gonk/HwcComposer2D.cpp
deleted file mode 100644
index 6b4c7a1cc..000000000
--- a/widget/gonk/HwcComposer2D.cpp
+++ /dev/null
@@ -1,971 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim:set ts=4 sw=4 sts=4 et: */
-/*
- * Copyright (c) 2012, 2013 The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/log.h>
-#include <string.h>
-
-#include "gfxPrefs.h"
-#include "ImageLayers.h"
-#include "libdisplay/GonkDisplay.h"
-#include "HwcComposer2D.h"
-#include "LayerScope.h"
-#include "Units.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/layers/CompositorBridgeParent.h"
-#include "mozilla/layers/LayerManagerComposite.h"
-#include "mozilla/layers/PLayerTransaction.h"
-#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
-#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
-#include "mozilla/StaticPtr.h"
-#include "nsThreadUtils.h"
-#include "cutils/properties.h"
-#include "gfx2DGlue.h"
-#include "gfxPlatform.h"
-#include "VsyncSource.h"
-#include "nsScreenManagerGonk.h"
-#include "nsWindow.h"
-
-#if ANDROID_VERSION >= 17
-#include "libdisplay/DisplaySurface.h"
-#endif
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "HWComposer"
-
-/*
- * By default the debug message of hwcomposer (LOG_DEBUG level) are undefined,
- * but can be enabled by uncommenting HWC_DEBUG below.
- */
-//#define HWC_DEBUG
-
-#ifdef HWC_DEBUG
-#define LOGD(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, ## args)
-#else
-#define LOGD(args...) ((void)0)
-#endif
-
-#define LOGI(args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, ## args)
-#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, ## args)
-
-#define LAYER_COUNT_INCREMENTS 5
-
-using namespace android;
-using namespace mozilla::gfx;
-using namespace mozilla::layers;
-
-namespace mozilla {
-
-static void
-HookInvalidate(const struct hwc_procs* aProcs)
-{
- HwcComposer2D::GetInstance()->Invalidate();
-}
-
-static void
-HookVsync(const struct hwc_procs* aProcs, int aDisplay,
- int64_t aTimestamp)
-{
- HwcComposer2D::GetInstance()->Vsync(aDisplay, aTimestamp);
-}
-
-static void
-HookHotplug(const struct hwc_procs* aProcs, int aDisplay,
- int aConnected)
-{
- HwcComposer2D::GetInstance()->Hotplug(aDisplay, aConnected);
-}
-
-static StaticRefPtr<HwcComposer2D> sInstance;
-
-HwcComposer2D::HwcComposer2D()
- : mList(nullptr)
- , mMaxLayerCount(0)
- , mColorFill(false)
- , mRBSwapSupport(false)
- , mPrepared(false)
- , mHasHWVsync(false)
- , mLock("mozilla.HwcComposer2D.mLock")
-{
- mHal = HwcHALBase::CreateHwcHAL();
- if (!mHal->HasHwc()) {
- LOGD("no hwc support");
- return;
- }
-
- RegisterHwcEventCallback();
-
- nsIntSize screenSize;
-
- GonkDisplay::NativeData data = GetGonkDisplay()->GetNativeData(GonkDisplay::DISPLAY_PRIMARY);
- ANativeWindow *win = data.mNativeWindow.get();
- win->query(win, NATIVE_WINDOW_WIDTH, &screenSize.width);
- win->query(win, NATIVE_WINDOW_HEIGHT, &screenSize.height);
- mScreenRect = gfx::IntRect(gfx::IntPoint(0, 0), screenSize);
-
- mColorFill = mHal->Query(HwcHALBase::QueryType::COLOR_FILL);
- mRBSwapSupport = mHal->Query(HwcHALBase::QueryType::RB_SWAP);
-}
-
-HwcComposer2D::~HwcComposer2D()
-{
- free(mList);
-}
-
-HwcComposer2D*
-HwcComposer2D::GetInstance()
-{
- if (!sInstance) {
-#ifdef HWC_DEBUG
- // Make sure only create once
- static int timesCreated = 0;
- ++timesCreated;
- MOZ_ASSERT(timesCreated == 1);
-#endif
- LOGI("Creating new instance");
- sInstance = new HwcComposer2D();
-
- // If anyone uses the compositor thread to create HwcComposer2D,
- // we just skip this function.
- // If ClearOnShutdown() can handle objects in other threads
- // in the future, we can remove this check.
- if (NS_IsMainThread()) {
- // If we create HwcComposer2D by the main thread, we can use
- // ClearOnShutdown() to make sure it will be nullified properly.
- ClearOnShutdown(&sInstance);
- }
- }
- return sInstance;
-}
-
-bool
-HwcComposer2D::EnableVsync(bool aEnable)
-{
- MOZ_ASSERT(NS_IsMainThread());
- if (!mHasHWVsync) {
- return false;
- }
- return mHal->EnableVsync(aEnable) && aEnable;
-}
-
-bool
-HwcComposer2D::RegisterHwcEventCallback()
-{
- const HwcHALProcs_t cHWCProcs = {
- &HookInvalidate, // 1st: void (*invalidate)(...)
- &HookVsync, // 2nd: void (*vsync)(...)
- &HookHotplug // 3rd: void (*hotplug)(...)
- };
- mHasHWVsync = mHal->RegisterHwcEventCallback(cHWCProcs);
- return mHasHWVsync;
-}
-
-void
-HwcComposer2D::Vsync(int aDisplay, nsecs_t aVsyncTimestamp)
-{
- // Only support hardware vsync on kitkat, L and up due to inaccurate timings
- // with JellyBean.
-#if (ANDROID_VERSION == 19 || ANDROID_VERSION >= 21)
- TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(aVsyncTimestamp);
- gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().NotifyVsync(vsyncTime);
-#else
- // If this device doesn't support vsync, this function should not be used.
- MOZ_ASSERT(false);
-#endif
-}
-
-// Called on the "invalidator" thread (run from HAL).
-void
-HwcComposer2D::Invalidate()
-{
- if (!mHal->HasHwc()) {
- LOGE("HwcComposer2D::Invalidate failed!");
- return;
- }
-
- MutexAutoLock lock(mLock);
- if (mCompositorBridgeParent) {
- mCompositorBridgeParent->ScheduleRenderOnCompositorThread();
- }
-}
-
-namespace {
-class HotplugEvent : public Runnable {
-public:
- HotplugEvent(GonkDisplay::DisplayType aType, bool aConnected)
- : mType(aType)
- , mConnected(aConnected)
- {
- }
-
- NS_IMETHOD Run() override
- {
- RefPtr<nsScreenManagerGonk> screenManager =
- nsScreenManagerGonk::GetInstance();
- if (mConnected) {
- screenManager->AddScreen(mType);
- } else {
- screenManager->RemoveScreen(mType);
- }
- return NS_OK;
- }
-private:
- GonkDisplay::DisplayType mType;
- bool mConnected;
-};
-} // namespace
-
-void
-HwcComposer2D::Hotplug(int aDisplay, int aConnected)
-{
- NS_DispatchToMainThread(new HotplugEvent(GonkDisplay::DISPLAY_EXTERNAL,
- aConnected));
-}
-
-void
-HwcComposer2D::SetCompositorBridgeParent(CompositorBridgeParent* aCompositorBridgeParent)
-{
- MutexAutoLock lock(mLock);
- mCompositorBridgeParent = aCompositorBridgeParent;
-}
-
-bool
-HwcComposer2D::ReallocLayerList()
-{
- int size = sizeof(HwcList) +
- ((mMaxLayerCount + LAYER_COUNT_INCREMENTS) * sizeof(HwcLayer));
-
- HwcList* listrealloc = (HwcList*)realloc(mList, size);
-
- if (!listrealloc) {
- return false;
- }
-
- if (!mList) {
- //first alloc, initialize
- listrealloc->numHwLayers = 0;
- listrealloc->flags = 0;
- }
-
- mList = listrealloc;
- mMaxLayerCount += LAYER_COUNT_INCREMENTS;
- return true;
-}
-
-bool
-HwcComposer2D::PrepareLayerList(Layer* aLayer,
- const nsIntRect& aClip,
- const Matrix& aParentTransform,
- bool aFindSidebandStreams)
-{
- // NB: we fall off this path whenever there are container layers
- // that require intermediate surfaces. That means all the
- // GetEffective*() coordinates are relative to the framebuffer.
-
- bool fillColor = false;
-
- const nsIntRegion visibleRegion = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
- if (visibleRegion.IsEmpty()) {
- return true;
- }
-
- uint8_t opacity = std::min(0xFF, (int)(aLayer->GetEffectiveOpacity() * 256.0));
- if (opacity == 0) {
- LOGD("%s Layer has zero opacity; skipping", aLayer->Name());
- return true;
- }
-
- if (!mHal->SupportTransparency() && opacity < 0xFF && !aFindSidebandStreams) {
- LOGD("%s Layer has planar semitransparency which is unsupported by hwcomposer", aLayer->Name());
- return false;
- }
-
- if (aLayer->GetMaskLayer() && !aFindSidebandStreams) {
- LOGD("%s Layer has MaskLayer which is unsupported by hwcomposer", aLayer->Name());
- return false;
- }
-
- nsIntRect clip;
- nsIntRect layerClip = aLayer->GetLocalClipRect().valueOr(ParentLayerIntRect()).ToUnknownRect();
- nsIntRect* layerClipPtr = aLayer->GetLocalClipRect() ? &layerClip : nullptr;
- if (!HwcUtils::CalculateClipRect(aParentTransform,
- layerClipPtr,
- aClip,
- &clip))
- {
- LOGD("%s Clip rect is empty. Skip layer", aLayer->Name());
- return true;
- }
-
- // HWC supports only the following 2D transformations:
- //
- // Scaling via the sourceCrop and displayFrame in HwcLayer
- // Translation via the sourceCrop and displayFrame in HwcLayer
- // Rotation (in square angles only) via the HWC_TRANSFORM_ROT_* flags
- // Reflection (horizontal and vertical) via the HWC_TRANSFORM_FLIP_* flags
- //
- // A 2D transform with PreservesAxisAlignedRectangles() has all the attributes
- // above
- Matrix layerTransform;
- if (!aLayer->GetEffectiveTransform().Is2D(&layerTransform) ||
- !layerTransform.PreservesAxisAlignedRectangles()) {
- LOGD("Layer EffectiveTransform has a 3D transform or a non-square angle rotation");
- return false;
- }
-
- Matrix layerBufferTransform;
- if (!aLayer->GetEffectiveTransformForBuffer().Is2D(&layerBufferTransform) ||
- !layerBufferTransform.PreservesAxisAlignedRectangles()) {
- LOGD("Layer EffectiveTransformForBuffer has a 3D transform or a non-square angle rotation");
- return false;
- }
-
- if (ContainerLayer* container = aLayer->AsContainerLayer()) {
- if (container->UseIntermediateSurface() && !aFindSidebandStreams) {
- LOGD("Container layer needs intermediate surface");
- return false;
- }
- AutoTArray<Layer*, 12> children;
- container->SortChildrenBy3DZOrder(children);
-
- for (uint32_t i = 0; i < children.Length(); i++) {
- if (!PrepareLayerList(children[i], clip, layerTransform, aFindSidebandStreams) &&
- !aFindSidebandStreams) {
- return false;
- }
- }
- return true;
- }
-
- LayerRenderState state = aLayer->GetRenderState();
-
-#if ANDROID_VERSION >= 21
- if (!state.GetGrallocBuffer() && !state.GetSidebandStream().IsValid()) {
-#else
- if (!state.GetGrallocBuffer()) {
-#endif
- if (aLayer->AsColorLayer() && mColorFill) {
- fillColor = true;
- } else {
- LOGD("%s Layer doesn't have a gralloc buffer", aLayer->Name());
- return false;
- }
- }
-
- nsIntRect visibleRect = visibleRegion.GetBounds();
-
- nsIntRect bufferRect;
- if (fillColor) {
- bufferRect = nsIntRect(visibleRect);
- } else {
- nsIntRect layerRect;
- if (state.mHasOwnOffset) {
- bufferRect = nsIntRect(state.mOffset.x, state.mOffset.y,
- state.mSize.width, state.mSize.height);
- layerRect = bufferRect;
- } else {
- //Since the buffer doesn't have its own offset, assign the whole
- //surface size as its buffer bounds
- bufferRect = nsIntRect(0, 0, state.mSize.width, state.mSize.height);
- layerRect = bufferRect;
- if (aLayer->GetType() == Layer::TYPE_IMAGE) {
- ImageLayer* imageLayer = static_cast<ImageLayer*>(aLayer);
- if(imageLayer->GetScaleMode() != ScaleMode::SCALE_NONE) {
- layerRect = nsIntRect(0, 0, imageLayer->GetScaleToSize().width, imageLayer->GetScaleToSize().height);
- }
- }
- }
- // In some cases the visible rect assigned to the layer can be larger
- // than the layer's surface, e.g., an ImageLayer with a small Image
- // in it.
- visibleRect.IntersectRect(visibleRect, layerRect);
- }
-
- // Buffer rotation is not to be confused with the angled rotation done by a transform matrix
- // It's a fancy PaintedLayer feature used for scrolling
- if (state.BufferRotated()) {
- LOGD("%s Layer has a rotated buffer", aLayer->Name());
- return false;
- }
-
- const bool needsYFlip = state.OriginBottomLeft() ? true
- : false;
-
- hwc_rect_t sourceCrop, displayFrame;
- if(!HwcUtils::PrepareLayerRects(visibleRect,
- layerTransform,
- layerBufferTransform,
- clip,
- bufferRect,
- needsYFlip,
- &(sourceCrop),
- &(displayFrame)))
- {
- return true;
- }
-
- // OK! We can compose this layer with hwc.
- int current = mList ? mList->numHwLayers : 0;
-
- // Do not compose any layer below full-screen Opaque layer
- // Note: It can be generalized to non-fullscreen Opaque layers.
- bool isOpaque = opacity == 0xFF &&
- (state.mFlags & LayerRenderStateFlags::OPAQUE);
- // Currently we perform opacity calculation using the *bounds* of the layer.
- // We can only make this assumption if we're not dealing with a complex visible region.
- bool isSimpleVisibleRegion = visibleRegion.Contains(visibleRect);
- if (current && isOpaque && isSimpleVisibleRegion) {
- nsIntRect displayRect = nsIntRect(displayFrame.left, displayFrame.top,
- displayFrame.right - displayFrame.left, displayFrame.bottom - displayFrame.top);
- if (displayRect.Contains(mScreenRect)) {
- // In z-order, all previous layers are below
- // the current layer. We can ignore them now.
- mList->numHwLayers = current = 0;
- mHwcLayerMap.Clear();
- }
- }
-
- if (!mList || current >= mMaxLayerCount) {
- if (!ReallocLayerList() || current >= mMaxLayerCount) {
- LOGE("PrepareLayerList failed! Could not increase the maximum layer count");
- return false;
- }
- }
-
- HwcLayer& hwcLayer = mList->hwLayers[current];
- hwcLayer.displayFrame = displayFrame;
- mHal->SetCrop(hwcLayer, sourceCrop);
- buffer_handle_t handle = nullptr;
-#if ANDROID_VERSION >= 21
- if (state.GetSidebandStream().IsValid()) {
- handle = state.GetSidebandStream().GetRawNativeHandle();
- } else if (state.GetGrallocBuffer()) {
- handle = state.GetGrallocBuffer()->getNativeBuffer()->handle;
- }
-#else
- if (state.GetGrallocBuffer()) {
- handle = state.GetGrallocBuffer()->getNativeBuffer()->handle;
- }
-#endif
- hwcLayer.handle = handle;
-
- hwcLayer.flags = 0;
- hwcLayer.hints = 0;
- hwcLayer.blending = isOpaque ? HWC_BLENDING_NONE : HWC_BLENDING_PREMULT;
-#if ANDROID_VERSION >= 17
- hwcLayer.compositionType = HWC_FRAMEBUFFER;
-#if ANDROID_VERSION >= 21
- if (state.GetSidebandStream().IsValid()) {
- hwcLayer.compositionType = HWC_SIDEBAND;
- }
-#endif
- hwcLayer.acquireFenceFd = -1;
- hwcLayer.releaseFenceFd = -1;
-#if ANDROID_VERSION >= 18
- hwcLayer.planeAlpha = opacity;
-#endif
-#else
- hwcLayer.compositionType = HwcUtils::HWC_USE_COPYBIT;
-#endif
-
- if (!fillColor) {
- if (state.FormatRBSwapped()) {
- if (!mRBSwapSupport) {
- LOGD("No R/B swap support in H/W Composer");
- return false;
- }
- hwcLayer.flags |= HwcUtils::HWC_FORMAT_RB_SWAP;
- }
-
- // Translation and scaling have been addressed in PrepareLayerRects().
- // Given the above and that we checked for PreservesAxisAlignedRectangles()
- // the only possible transformations left to address are
- // square angle rotation and horizontal/vertical reflection.
- //
- // The rotation and reflection permutations total 16 but can be
- // reduced to 8 transformations after eliminating redundancies.
- //
- // All matrices represented here are in the form
- //
- // | xx xy |
- // | yx yy |
- //
- // And ignore scaling.
- //
- // Reflection is applied before rotation
- gfx::Matrix rotation = layerTransform;
- // Compute fuzzy zero like PreservesAxisAlignedRectangles()
- if (fabs(rotation._11) < 1e-6) {
- if (rotation._21 < 0) {
- if (rotation._12 > 0) {
- // 90 degree rotation
- //
- // | 0 -1 |
- // | 1 0 |
- //
- hwcLayer.transform = HWC_TRANSFORM_ROT_90;
- LOGD("Layer rotated 90 degrees");
- }
- else {
- // Horizontal reflection then 90 degree rotation
- //
- // | 0 -1 | | -1 0 | = | 0 -1 |
- // | 1 0 | | 0 1 | | -1 0 |
- //
- // same as vertical reflection then 270 degree rotation
- //
- // | 0 1 | | 1 0 | = | 0 -1 |
- // | -1 0 | | 0 -1 | | -1 0 |
- //
- hwcLayer.transform = HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_FLIP_H;
- LOGD("Layer vertically reflected then rotated 270 degrees");
- }
- } else {
- if (rotation._12 < 0) {
- // 270 degree rotation
- //
- // | 0 1 |
- // | -1 0 |
- //
- hwcLayer.transform = HWC_TRANSFORM_ROT_270;
- LOGD("Layer rotated 270 degrees");
- }
- else {
- // Vertical reflection then 90 degree rotation
- //
- // | 0 1 | | -1 0 | = | 0 1 |
- // | -1 0 | | 0 1 | | 1 0 |
- //
- // Same as horizontal reflection then 270 degree rotation
- //
- // | 0 -1 | | 1 0 | = | 0 1 |
- // | 1 0 | | 0 -1 | | 1 0 |
- //
- hwcLayer.transform = HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_FLIP_V;
- LOGD("Layer horizontally reflected then rotated 270 degrees");
- }
- }
- } else if (rotation._11 < 0) {
- if (rotation._22 > 0) {
- // Horizontal reflection
- //
- // | -1 0 |
- // | 0 1 |
- //
- hwcLayer.transform = HWC_TRANSFORM_FLIP_H;
- LOGD("Layer rotated 180 degrees");
- }
- else {
- // 180 degree rotation
- //
- // | -1 0 |
- // | 0 -1 |
- //
- // Same as horizontal and vertical reflection
- //
- // | -1 0 | | 1 0 | = | -1 0 |
- // | 0 1 | | 0 -1 | | 0 -1 |
- //
- hwcLayer.transform = HWC_TRANSFORM_ROT_180;
- LOGD("Layer rotated 180 degrees");
- }
- } else {
- if (rotation._22 < 0) {
- // Vertical reflection
- //
- // | 1 0 |
- // | 0 -1 |
- //
- hwcLayer.transform = HWC_TRANSFORM_FLIP_V;
- LOGD("Layer rotated 180 degrees");
- }
- else {
- // No rotation or reflection
- //
- // | 1 0 |
- // | 0 1 |
- //
- hwcLayer.transform = 0;
- }
- }
-
- const bool needsYFlip = state.OriginBottomLeft() ? true
- : false;
-
- if (needsYFlip) {
- // Invert vertical reflection flag if it was already set
- hwcLayer.transform ^= HWC_TRANSFORM_FLIP_V;
- }
- hwc_region_t region;
- if (visibleRegion.GetNumRects() > 1) {
- mVisibleRegions.push_back(HwcUtils::RectVector());
- HwcUtils::RectVector* visibleRects = &(mVisibleRegions.back());
- bool isVisible = false;
- if(!HwcUtils::PrepareVisibleRegion(visibleRegion,
- layerTransform,
- layerBufferTransform,
- clip,
- bufferRect,
- visibleRects,
- isVisible)) {
- LOGD("A region of layer is too small to be rendered by HWC");
- return false;
- }
- if (!isVisible) {
- // Layer is not visible, no need to render it
- return true;
- }
- region.numRects = visibleRects->size();
- region.rects = &((*visibleRects)[0]);
- } else {
- region.numRects = 1;
- region.rects = &(hwcLayer.displayFrame);
- }
- hwcLayer.visibleRegionScreen = region;
- } else {
- hwcLayer.flags |= HwcUtils::HWC_COLOR_FILL;
- ColorLayer* colorLayer = aLayer->AsColorLayer();
- if (colorLayer->GetColor().a < 1.0) {
- LOGD("Color layer has semitransparency which is unsupported");
- return false;
- }
- hwcLayer.transform = colorLayer->GetColor().ToABGR();
- }
-
-#if ANDROID_VERSION >= 21
- if (aFindSidebandStreams && hwcLayer.compositionType == HWC_SIDEBAND) {
- mCachedSidebandLayers.AppendElement(hwcLayer);
- }
-#endif
-
- mHwcLayerMap.AppendElement(static_cast<LayerComposite*>(aLayer->ImplData()));
- mList->numHwLayers++;
- return true;
-}
-
-
-#if ANDROID_VERSION >= 17
-bool
-HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen)
-{
- DisplaySurface* dispSurface = aScreen->GetDisplaySurface();
-
- if (!(dispSurface && dispSurface->lastHandle)) {
- LOGD("H/W Composition failed. DispSurface not initialized.");
- return false;
- }
-
- // Add FB layer
- int idx = mList->numHwLayers++;
- if (idx >= mMaxLayerCount) {
- if (!ReallocLayerList() || idx >= mMaxLayerCount) {
- LOGE("TryHwComposition failed! Could not add FB layer");
- return false;
- }
- }
-
- Prepare(dispSurface->lastHandle, -1, aScreen);
-
- /* Possible composition paths, after hwc prepare:
- 1. GPU Composition
- 2. BLIT Composition
- 3. Full OVERLAY Composition
- 4. Partial OVERLAY Composition (GPU + OVERLAY) */
-
- bool gpuComposite = false;
- bool blitComposite = false;
- bool overlayComposite = true;
-
- for (int j=0; j < idx; j++) {
- if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER ||
- mList->hwLayers[j].compositionType == HWC_BLIT) {
- // Full OVERLAY composition is not possible on this frame
- // It is either GPU / BLIT / partial OVERLAY composition.
- overlayComposite = false;
- break;
- }
- }
-
- if (!overlayComposite) {
- for (int k=0; k < idx; k++) {
- switch (mList->hwLayers[k].compositionType) {
- case HWC_FRAMEBUFFER:
- gpuComposite = true;
- break;
- case HWC_BLIT:
- blitComposite = true;
- break;
-#if ANDROID_VERSION >= 21
- case HWC_SIDEBAND:
-#endif
- case HWC_OVERLAY: {
- // HWC will compose HWC_OVERLAY layers in partial
- // Overlay Composition, set layer composition flag
- // on mapped LayerComposite to skip GPU composition
- mHwcLayerMap[k]->SetLayerComposited(true);
-
- uint8_t opacity = std::min(0xFF, (int)(mHwcLayerMap[k]->GetLayer()->GetEffectiveOpacity() * 256.0));
- if ((mList->hwLayers[k].hints & HWC_HINT_CLEAR_FB) &&
- (opacity == 0xFF)) {
- // Clear visible rect on FB with transparent pixels.
- hwc_rect_t r = mList->hwLayers[k].displayFrame;
- mHwcLayerMap[k]->SetClearRect(nsIntRect(r.left, r.top,
- r.right - r.left,
- r.bottom - r.top));
- }
- break;
- }
- default:
- break;
- }
- }
-
- if (gpuComposite) {
- // GPU or partial OVERLAY Composition
- return false;
- } else if (blitComposite) {
- // BLIT Composition, flip DispSurface target
- GetGonkDisplay()->UpdateDispSurface(aScreen->GetEGLDisplay(), aScreen->GetEGLSurface());
- DisplaySurface* dispSurface = aScreen->GetDisplaySurface();
- if (!dispSurface) {
- LOGE("H/W Composition failed. NULL DispSurface.");
- return false;
- }
- mList->hwLayers[idx].handle = dispSurface->lastHandle;
- mList->hwLayers[idx].acquireFenceFd = dispSurface->GetPrevDispAcquireFd();
- }
- }
-
- // BLIT or full OVERLAY Composition
- return Commit(aScreen);
-}
-
-bool
-HwcComposer2D::Render(nsIWidget* aWidget)
-{
- nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
-
- // HWC module does not exist or mList is not created yet.
- if (!mHal->HasHwc() || !mList) {
- return GetGonkDisplay()->SwapBuffers(screen->GetEGLDisplay(), screen->GetEGLSurface());
- } else if (!mList && !ReallocLayerList()) {
- LOGE("Cannot realloc layer list");
- return false;
- }
-
- DisplaySurface* dispSurface = screen->GetDisplaySurface();
- if (!dispSurface) {
- LOGE("H/W Composition failed. DispSurface not initialized.");
- return false;
- }
-
- if (mPrepared) {
- // No mHwc prepare, if already prepared in current draw cycle
- mList->hwLayers[mList->numHwLayers - 1].handle = dispSurface->lastHandle;
- mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = dispSurface->GetPrevDispAcquireFd();
- } else {
- // Update screen rect to handle a case that TryRenderWithHwc() is not called.
- mScreenRect = screen->GetNaturalBounds().ToUnknownRect();
-
- mList->flags = HWC_GEOMETRY_CHANGED;
- mList->numHwLayers = 2;
- mList->hwLayers[0].hints = 0;
- mList->hwLayers[0].compositionType = HWC_FRAMEBUFFER;
- mList->hwLayers[0].flags = HWC_SKIP_LAYER;
- mList->hwLayers[0].backgroundColor = {0};
- mList->hwLayers[0].acquireFenceFd = -1;
- mList->hwLayers[0].releaseFenceFd = -1;
- mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height};
-
-#if ANDROID_VERSION >= 21
- // Prepare layers for sideband streams
- const uint32_t len = mCachedSidebandLayers.Length();
- for (uint32_t i = 0; i < len; ++i) {
- ++mList->numHwLayers;
- mList->hwLayers[i+1] = mCachedSidebandLayers[i];
- }
-#endif
- Prepare(dispSurface->lastHandle, dispSurface->GetPrevDispAcquireFd(), screen);
- }
-
- // GPU or partial HWC Composition
- return Commit(screen);
-}
-
-void
-HwcComposer2D::Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* screen)
-{
- if (mPrepared) {
- LOGE("Multiple hwc prepare calls!");
- }
- hwc_rect_t dispRect = {0, 0, mScreenRect.width, mScreenRect.height};
- mHal->Prepare(mList, screen->GetDisplayType(), dispRect, dispHandle, fence);
- mPrepared = true;
-}
-
-bool
-HwcComposer2D::Commit(nsScreenGonk* aScreen)
-{
- for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) {
- mList->hwLayers[j].acquireFenceFd = -1;
- if (mHwcLayerMap.IsEmpty() ||
- (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER)) {
- continue;
- }
- LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState();
- if (!state.mTexture) {
- continue;
- }
- FenceHandle fence = state.mTexture->GetAndResetAcquireFenceHandle();
- if (fence.IsValid()) {
- RefPtr<FenceHandle::FdObj> fdObj = fence.GetAndResetFdObj();
- mList->hwLayers[j].acquireFenceFd = fdObj->GetAndResetFd();
- }
- }
-
- int err = mHal->Set(mList, aScreen->GetDisplayType());
-
- mPrevRetireFence.TransferToAnotherFenceHandle(mPrevDisplayFence);
-
- for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) {
- if (mList->hwLayers[j].releaseFenceFd >= 0) {
- int fd = mList->hwLayers[j].releaseFenceFd;
- mList->hwLayers[j].releaseFenceFd = -1;
- RefPtr<FenceHandle::FdObj> fdObj = new FenceHandle::FdObj(fd);
- FenceHandle fence(fdObj);
-
- LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState();
- if (!state.mTexture) {
- continue;
- }
- state.mTexture->SetReleaseFenceHandle(fence);
- }
- }
-
- if (mList->retireFenceFd >= 0) {
- mPrevRetireFence = FenceHandle(new FenceHandle::FdObj(mList->retireFenceFd));
- }
-
- // Set DisplaySurface layer fence
- DisplaySurface* displaySurface = aScreen->GetDisplaySurface();
- displaySurface->setReleaseFenceFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
- mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd = -1;
-
- mPrepared = false;
- return !err;
-}
-#else
-bool
-HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen)
-{
- mHal->SetEGLInfo(aScreen->GetEGLDisplay(), aScreen->GetEGLSurface());
- return !mHal->Set(mList, aScreen->GetDisplayType());
-}
-
-bool
-HwcComposer2D::Render(nsIWidget* aWidget)
-{
- nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
- return GetGonkDisplay()->SwapBuffers(screen->GetEGLDisplay(), screen->GetEGLSurface());
-}
-#endif
-
-bool
-HwcComposer2D::TryRenderWithHwc(Layer* aRoot,
- nsIWidget* aWidget,
- bool aGeometryChanged,
- bool aHasImageHostOverlays)
-{
- if (!mHal->HasHwc()) {
- return false;
- }
-
- nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
-
- if (mList) {
- mList->flags = mHal->GetGeometryChangedFlag(aGeometryChanged);
- mList->numHwLayers = 0;
- mHwcLayerMap.Clear();
- }
-
- if (mPrepared) {
- mHal->ResetHwc();
- mPrepared = false;
- }
-
- // XXX: The clear() below means all rect vectors will be have to be
- // reallocated. We may want to avoid this if possible
- mVisibleRegions.clear();
-
- mScreenRect = screen->GetNaturalBounds().ToUnknownRect();
- MOZ_ASSERT(mHwcLayerMap.IsEmpty());
- mCachedSidebandLayers.Clear();
- if (!PrepareLayerList(aRoot,
- mScreenRect,
- gfx::Matrix(),
- /* aFindSidebandStreams */ false))
- {
- mHwcLayerMap.Clear();
- LOGD("Render aborted. Fallback to GPU Composition");
- if (aHasImageHostOverlays) {
- LOGD("Prepare layers of SidebandStreams");
- // Failed to create a layer list for hwc. But we need the list
- // only for handling sideband streams. Traverse layer tree without
- // some early returns to make sure we can find all the layers.
- // It is the best wrong thing that we can do.
- PrepareLayerList(aRoot,
- mScreenRect,
- gfx::Matrix(),
- /* aFindSidebandStreams */ true);
- // Reset mPrepared to false, since we already fell back to
- // gpu composition.
- mPrepared = false;
- }
- return false;
- }
-
- // Send data to LayerScope for debugging
- SendtoLayerScope();
-
- if (!TryHwComposition(screen)) {
- LOGD("Full HWC Composition failed. Fallback to GPU Composition or partial OVERLAY Composition");
- LayerScope::CleanLayer();
- return false;
- }
-
- LOGD("Frame rendered");
- return true;
-}
-
-void
-HwcComposer2D::SendtoLayerScope()
-{
- if (!LayerScope::CheckSendable()) {
- return;
- }
-
- const int len = mList->numHwLayers;
- for (int i = 0; i < len; ++i) {
- LayerComposite* layer = mHwcLayerMap[i];
- const hwc_rect_t r = mList->hwLayers[i].displayFrame;
- LayerScope::SendLayer(layer, r.right - r.left, r.bottom - r.top);
- }
-}
-
-} // namespace mozilla
diff --git a/widget/gonk/HwcComposer2D.h b/widget/gonk/HwcComposer2D.h
deleted file mode 100644
index 56c1d1ec1..000000000
--- a/widget/gonk/HwcComposer2D.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim:set ts=4 sw=4 sts=4 et: */
-/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef mozilla_HwcComposer2D
-#define mozilla_HwcComposer2D
-
-#include "Composer2D.h"
-#include "hwchal/HwcHALBase.h" // for HwcHAL
-#include "HwcUtils.h" // for RectVector
-#include "Layers.h"
-#include "mozilla/Mutex.h"
-#include "mozilla/layers/FenceUtils.h" // for FenceHandle
-#include "mozilla/UniquePtr.h" // for HwcHAL
-
-#include <vector>
-#include <list>
-
-#include <utils/Timers.h>
-
-class nsScreenGonk;
-
-namespace mozilla {
-
-namespace gl {
- class GLContext;
-}
-
-namespace layers {
-class CompositorBridgeParent;
-class Layer;
-}
-
-/*
- * HwcComposer2D provides a way for gecko to render frames
- * using hwcomposer.h in the AOSP HAL.
- *
- * hwcomposer.h defines an interface for display composition
- * using dedicated hardware. This hardware is usually faster
- * or more power efficient than the GPU. However, in exchange
- * for better performance, generality has to be sacrificed:
- * no 3d transforms, no intermediate surfaces, no special shader effects,
- * and loss of other goodies depending on the platform.
- *
- * In general, when hwc is enabled gecko tries to compose
- * its frames using HwcComposer2D first. Then if HwcComposer2D is
- * unable to compose a frame then it falls back to compose it
- * using the GPU with OpenGL.
- *
- */
-class HwcComposer2D : public mozilla::layers::Composer2D {
-public:
- HwcComposer2D();
- virtual ~HwcComposer2D();
-
- static HwcComposer2D* GetInstance();
-
- // Returns TRUE if the container has been succesfully rendered
- // Returns FALSE if the container cannot be fully rendered
- // by this composer so nothing was rendered at all
- virtual bool TryRenderWithHwc(layers::Layer* aRoot,
- nsIWidget* aWidget,
- bool aGeometryChanged,
- bool aHasImageHostOverlays) override;
-
- virtual bool Render(nsIWidget* aWidget) override;
-
- virtual bool HasHwc() override { return mHal->HasHwc(); }
-
- bool EnableVsync(bool aEnable);
- bool RegisterHwcEventCallback();
- void Vsync(int aDisplay, int64_t aTimestamp);
- void Invalidate();
- void Hotplug(int aDisplay, int aConnected);
- void SetCompositorBridgeParent(layers::CompositorBridgeParent* aCompositorBridgeParent);
-
-private:
- void Reset();
- void Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* screen);
- bool Commit(nsScreenGonk* aScreen);
- bool TryHwComposition(nsScreenGonk* aScreen);
- bool ReallocLayerList();
- bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,
- const gfx::Matrix& aParentTransform,
- bool aFindSidebandStreams);
- void SendtoLayerScope();
-
- UniquePtr<HwcHALBase> mHal;
- HwcList* mList;
- nsIntRect mScreenRect;
- int mMaxLayerCount;
- bool mColorFill;
- bool mRBSwapSupport;
- //Holds all the dynamically allocated RectVectors needed
- //to render the current frame
- std::list<HwcUtils::RectVector> mVisibleRegions;
- layers::FenceHandle mPrevRetireFence;
- layers::FenceHandle mPrevDisplayFence;
- nsTArray<HwcLayer> mCachedSidebandLayers;
- nsTArray<layers::LayerComposite*> mHwcLayerMap;
- bool mPrepared;
- bool mHasHWVsync;
- layers::CompositorBridgeParent* mCompositorBridgeParent;
- Mutex mLock;
-};
-
-} // namespace mozilla
-
-#endif // mozilla_HwcComposer2D
diff --git a/widget/gonk/HwcUtils.cpp b/widget/gonk/HwcUtils.cpp
deleted file mode 100644
index a8f030f3c..000000000
--- a/widget/gonk/HwcUtils.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2013 The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/log.h>
-#include "HwcUtils.h"
-#include "gfxUtils.h"
-#include "gfx2DGlue.h"
-
-#define LOG_TAG "HwcUtils"
-
-#if (LOG_NDEBUG == 0)
-#define LOGD(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, ## args)
-#else
-#define LOGD(args...) ((void)0)
-#endif
-
-#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, ## args)
-
-
-namespace mozilla {
-
-/* Utility functions for HwcComposer */
-
-
-
-/* static */ bool
-HwcUtils::PrepareLayerRects(nsIntRect aVisible,
- const gfx::Matrix& aLayerTransform,
- const gfx::Matrix& aLayerBufferTransform,
- nsIntRect aClip, nsIntRect aBufferRect,
- bool aYFlipped,
- hwc_rect_t* aSourceCrop, hwc_rect_t* aVisibleRegionScreen) {
-
- gfxMatrix aTransform = gfx::ThebesMatrix(aLayerTransform);
- gfxRect visibleRect(ThebesRect(aVisible));
- gfxRect clip(ThebesRect(aClip));
- gfxRect visibleRectScreen = aTransform.TransformBounds(visibleRect);
- // |clip| is guaranteed to be integer
- visibleRectScreen.IntersectRect(visibleRectScreen, clip);
-
- if (visibleRectScreen.IsEmpty()) {
- return false;
- }
-
- gfxMatrix inverse = gfx::ThebesMatrix(aLayerBufferTransform);
- inverse.Invert();
- gfxRect crop = inverse.TransformBounds(visibleRectScreen);
-
- //clip to buffer size
- crop.IntersectRect(crop, ThebesRect(aBufferRect));
- crop.Round();
-
- if (crop.IsEmpty()) {
- return false;
- }
-
- //propagate buffer clipping back to visible rect
- gfxMatrix layerBufferTransform = gfx::ThebesMatrix(aLayerBufferTransform);
- visibleRectScreen = layerBufferTransform.TransformBounds(crop);
- visibleRectScreen.Round();
-
- // Map from layer space to buffer space
- crop -= aBufferRect.TopLeft();
- if (aYFlipped) {
- crop.y = aBufferRect.height - (crop.y + crop.height);
- }
-
- aSourceCrop->left = crop.x;
- aSourceCrop->top = crop.y;
- aSourceCrop->right = crop.x + crop.width;
- aSourceCrop->bottom = crop.y + crop.height;
-
- aVisibleRegionScreen->left = visibleRectScreen.x;
- aVisibleRegionScreen->top = visibleRectScreen.y;
- aVisibleRegionScreen->right = visibleRectScreen.x + visibleRectScreen.width;
- aVisibleRegionScreen->bottom = visibleRectScreen.y + visibleRectScreen.height;
-
- return true;
-}
-
-/* static */ bool
-HwcUtils::PrepareVisibleRegion(const nsIntRegion& aVisible,
- const gfx::Matrix& aLayerTransform,
- const gfx::Matrix& aLayerBufferTransform,
- nsIntRect aClip, nsIntRect aBufferRect,
- RectVector* aVisibleRegionScreen,
- bool& aIsVisible) {
- const float MIN_SRC_WIDTH = 2.f;
- const float MIN_SRC_HEIGHT = 2.f;
-
- gfxMatrix layerTransform = gfx::ThebesMatrix(aLayerTransform);
- gfxMatrix layerBufferTransform = gfx::ThebesMatrix(aLayerBufferTransform);
- gfxRect bufferRect =
- layerBufferTransform.TransformBounds(ThebesRect(aBufferRect));
- gfxMatrix inverse = gfx::ThebesMatrix(aLayerBufferTransform);
- inverse.Invert();
- aIsVisible = false;
-
- for (auto iter = aVisible.RectIter(); !iter.Done(); iter.Next()) {
- gfxRect screenRect =
- layerTransform.TransformBounds(ThebesRect(iter.Get()));
- screenRect.IntersectRect(screenRect, bufferRect);
- screenRect.IntersectRect(screenRect, ThebesRect(aClip));
- screenRect.Round();
- if (screenRect.IsEmpty()) {
- continue;
- }
-
- hwc_rect_t visibleRectScreen;
- visibleRectScreen.left = screenRect.x;
- visibleRectScreen.top = screenRect.y;
- visibleRectScreen.right = screenRect.XMost();
- visibleRectScreen.bottom = screenRect.YMost();
-
- gfxRect srcCrop = inverse.TransformBounds(screenRect);
- // When src crop is very small, HWC could not render correctly in some cases.
- // See Bug 1169093
- if(srcCrop.Width() < MIN_SRC_WIDTH || srcCrop.Height() < MIN_SRC_HEIGHT) {
- return false;
- }
-
- aVisibleRegionScreen->push_back(visibleRectScreen);
- aIsVisible = true;
- }
-
- return true;
-}
-
-/* static */ bool
-HwcUtils::CalculateClipRect(const gfx::Matrix& transform,
- const nsIntRect* aLayerClip,
- nsIntRect aParentClip, nsIntRect* aRenderClip) {
-
- gfxMatrix aTransform = gfx::ThebesMatrix(transform);
- *aRenderClip = aParentClip;
-
- if (!aLayerClip) {
- return true;
- }
-
- if (aLayerClip->IsEmpty()) {
- return false;
- }
-
- nsIntRect clip = *aLayerClip;
-
- gfxRect r = ThebesRect(clip);
- gfxRect trClip = aTransform.TransformBounds(r);
- trClip.Round();
- gfxUtils::GfxRectToIntRect(trClip, &clip);
-
- aRenderClip->IntersectRect(*aRenderClip, clip);
- return true;
-}
-
-} // namespace mozilla
diff --git a/widget/gonk/HwcUtils.h b/widget/gonk/HwcUtils.h
deleted file mode 100644
index 876ff8e99..000000000
--- a/widget/gonk/HwcUtils.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef mozilla_HwcUtils
-#define mozilla_HwcUtils
-
-#include "Layers.h"
-#include <vector>
-#include "hardware/hwcomposer.h"
-
-namespace mozilla {
-
-namespace gfx {
-class Matrix;
-}
-
-class HwcUtils {
-public:
-
-enum {
- HWC_USE_GPU = HWC_FRAMEBUFFER,
- HWC_USE_OVERLAY = HWC_OVERLAY,
- HWC_USE_COPYBIT
-};
-
-// HWC layer flags
-enum {
- // Draw a solid color rectangle
- // The color should be set on the transform member of the hwc_layer_t struct
- // The expected format is a 32 bit ABGR with 8 bits per component
- HWC_COLOR_FILL = 0x8,
- // Swap the RB pixels of gralloc buffer, like RGBA<->BGRA or RGBX<->BGRX
- // The flag will be set inside LayerRenderState
- HWC_FORMAT_RB_SWAP = 0x40
-};
-
-typedef std::vector<hwc_rect_t> RectVector;
-
-/* Utility functions - implemented in HwcUtils.cpp */
-
-/**
- * Calculates the layer's clipping rectangle
- *
- * @param aTransform Input. A transformation matrix
- * It transforms the clip rect to screen space
- * @param aLayerClip Input. The layer's internal clipping rectangle.
- * This may be NULL which means the layer has no internal clipping
- * The origin is the top-left corner of the layer
- * @param aParentClip Input. The parent layer's rendering clipping rectangle
- * The origin is the top-left corner of the screen
- * @param aRenderClip Output. The layer's rendering clipping rectangle
- * The origin is the top-left corner of the screen
- * @return true if the layer should be rendered.
- * false if the layer can be skipped
- */
-static bool CalculateClipRect(const gfx::Matrix& aTransform,
- const nsIntRect* aLayerClip,
- nsIntRect aParentClip, nsIntRect* aRenderClip);
-
-
-/**
- * Prepares hwc layer visible region required for hwc composition
- *
- * @param aVisible Input. Layer's unclipped visible region
- * The origin is the top-left corner of the layer
- * @param aLayerTransform Input. Layer's transformation matrix
- * It transforms from layer space to screen space
- * @param aLayerBufferTransform Input. Layer buffer's transformation matrix
- * It transforms from layer buffer's space to screen space
- * @param aClip Input. A clipping rectangle.
- * The origin is the top-left corner of the screen
- * @param aBufferRect Input. The layer's buffer bounds
- * The origin is the top-left corner of the layer
- * @param aVisibleRegionScreen Output. Visible region in screen space.
- * The origin is the top-left corner of the screen
- * @param aIsVisible Output. true if region is visible
- * false if region is not visible
- * @return true if region can be rendered by HWC.
- * false if region should not be rendered by HWC
- */
-static bool PrepareVisibleRegion(const nsIntRegion& aVisible,
- const gfx::Matrix& aLayerTransform,
- const gfx::Matrix& aLayerBufferTransform,
- nsIntRect aClip, nsIntRect aBufferRect,
- RectVector* aVisibleRegionScreen,
- bool& aIsVisible);
-
-
-/**
- * Sets hwc layer rectangles required for hwc composition
- *
- * @param aVisible Input. Layer's unclipped visible rectangle
- * The origin is the top-left corner of the layer
- * @param aLayerTransform Input. Layer's transformation matrix
- * It transforms from layer space to screen space
- * @param aLayerBufferTransform Input. Layer buffer's transformation matrix
- * It transforms from layer buffer's space to screen space
- * @param aClip Input. A clipping rectangle.
- * The origin is the top-left corner of the screen
- * @param aBufferRect Input. The layer's buffer bounds
- * The origin is the top-left corner of the layer
- * @param aYFlipped Input. true if the buffer is rendered as Y flipped
- * @param aSurceCrop Output. Area of the source to consider,
- * the origin is the top-left corner of the buffer
- * @param aVisibleRegionScreen Output. Visible region in screen space.
- * The origin is the top-left corner of the screen
- * @return true if the layer should be rendered.
- * false if the layer can be skipped
- */
-static bool PrepareLayerRects(nsIntRect aVisible,
- const gfx::Matrix& aLayerTransform,
- const gfx::Matrix& aLayerBufferTransform,
- nsIntRect aClip, nsIntRect aBufferRect,
- bool aYFlipped,
- hwc_rect_t* aSourceCrop,
- hwc_rect_t* aVisibleRegionScreen);
-
-};
-
-} // namespace mozilla
-
-#endif // mozilla_HwcUtils
diff --git a/widget/gonk/OrientationObserver.cpp b/widget/gonk/OrientationObserver.cpp
deleted file mode 100644
index 9096404cf..000000000
--- a/widget/gonk/OrientationObserver.cpp
+++ /dev/null
@@ -1,332 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=8 et ft=cpp : */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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/basictypes.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/Hal.h"
-#include "nsIScreen.h"
-#include "nsIScreenManager.h"
-#include "OrientationObserver.h"
-#include "mozilla/HalSensor.h"
-#include "ProcessOrientation.h"
-#include "nsServiceManagerUtils.h"
-
-using namespace mozilla;
-using namespace dom;
-
-namespace {
-
-struct OrientationMapping {
- uint32_t mScreenRotation;
- ScreenOrientationInternal mDomOrientation;
-};
-
-static OrientationMapping sOrientationMappings[] = {
- {nsIScreen::ROTATION_0_DEG, eScreenOrientation_PortraitPrimary},
- {nsIScreen::ROTATION_180_DEG, eScreenOrientation_PortraitSecondary},
- {nsIScreen::ROTATION_90_DEG, eScreenOrientation_LandscapePrimary},
- {nsIScreen::ROTATION_270_DEG, eScreenOrientation_LandscapeSecondary},
-};
-
-const static uint32_t sDefaultLandscape = 2;
-const static uint32_t sDefaultPortrait = 0;
-
-static uint32_t sOrientationOffset = 0;
-
-static already_AddRefed<nsIScreen>
-GetPrimaryScreen()
-{
- nsCOMPtr<nsIScreenManager> screenMgr =
- do_GetService("@mozilla.org/gfx/screenmanager;1");
- NS_ENSURE_TRUE(screenMgr, nullptr);
-
- nsCOMPtr<nsIScreen> screen;
- screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
- return screen.forget();
-}
-
-static void
-DetectDefaultOrientation()
-{
- nsCOMPtr<nsIScreen> screen = GetPrimaryScreen();
- if (!screen) {
- return;
- }
-
- int32_t left, top, width, height;
- if (NS_FAILED(screen->GetRect(&left, &top, &width, &height))) {
- return;
- }
-
- uint32_t rotation;
- if (NS_FAILED(screen->GetRotation(&rotation))) {
- return;
- }
-
- if (width < height) {
- if (rotation == nsIScreen::ROTATION_0_DEG ||
- rotation == nsIScreen::ROTATION_180_DEG) {
- sOrientationOffset = sDefaultPortrait;
- } else {
- sOrientationOffset = sDefaultLandscape;
- }
- } else {
- if (rotation == nsIScreen::ROTATION_0_DEG ||
- rotation == nsIScreen::ROTATION_180_DEG) {
- sOrientationOffset = sDefaultLandscape;
- } else {
- sOrientationOffset = sDefaultPortrait;
- }
- }
-}
-
-/**
- * Converts DOM orientation to nsIScreen rotation. Portrait and Landscape are
- * treated as PortraitPrimary and LandscapePrimary, respectively, during
- * conversion.
- *
- * @param aOrientation DOM orientation e.g.
- * dom::eScreenOrientation_PortraitPrimary.
- * @param aResult output nsIScreen rotation e.g. nsIScreen::ROTATION_0_DEG.
- * @return NS_OK on success. NS_ILLEGAL_VALUE on failure.
- */
-static nsresult
-ConvertToScreenRotation(ScreenOrientationInternal aOrientation, uint32_t *aResult)
-{
- for (uint32_t i = 0; i < ArrayLength(sOrientationMappings); i++) {
- if (aOrientation & sOrientationMappings[i].mDomOrientation) {
- // Shift the mappings in sOrientationMappings so devices with default
- // landscape orientation map landscape-primary to 0 degree and so forth.
- int adjusted = (i + sOrientationOffset) %
- ArrayLength(sOrientationMappings);
- *aResult = sOrientationMappings[adjusted].mScreenRotation;
- return NS_OK;
- }
- }
-
- *aResult = nsIScreen::ROTATION_0_DEG;
- return NS_ERROR_ILLEGAL_VALUE;
-}
-
-/**
- * Converts nsIScreen rotation to DOM orientation.
- *
- * @param aRotation nsIScreen rotation e.g. nsIScreen::ROTATION_0_DEG.
- * @param aResult output DOM orientation e.g.
- * dom::eScreenOrientation_PortraitPrimary.
- * @return NS_OK on success. NS_ILLEGAL_VALUE on failure.
- */
-nsresult
-ConvertToDomOrientation(uint32_t aRotation, ScreenOrientationInternal *aResult)
-{
- for (uint32_t i = 0; i < ArrayLength(sOrientationMappings); i++) {
- if (aRotation == sOrientationMappings[i].mScreenRotation) {
- // Shift the mappings in sOrientationMappings so devices with default
- // landscape orientation map 0 degree to landscape-primary and so forth.
- int adjusted = (i + sOrientationOffset) %
- ArrayLength(sOrientationMappings);
- *aResult = sOrientationMappings[adjusted].mDomOrientation;
- return NS_OK;
- }
- }
-
- *aResult = eScreenOrientation_None;
- return NS_ERROR_ILLEGAL_VALUE;
-}
-
-// Note that all operations with sOrientationSensorObserver
-// should be on the main thread.
-static StaticAutoPtr<OrientationObserver> sOrientationSensorObserver;
-
-} // namespace
-
-OrientationObserver*
-OrientationObserver::GetInstance()
-{
- if (!sOrientationSensorObserver) {
- sOrientationSensorObserver = new OrientationObserver();
- ClearOnShutdown(&sOrientationSensorObserver);
- }
-
- return sOrientationSensorObserver;
-}
-
-OrientationObserver::OrientationObserver()
- : mAutoOrientationEnabled(false)
- , mAllowedOrientations(sDefaultOrientations)
- , mOrientation(new mozilla::ProcessOrientation())
-{
- DetectDefaultOrientation();
-
- EnableAutoOrientation();
-}
-
-OrientationObserver::~OrientationObserver()
-{
- if (mAutoOrientationEnabled) {
- DisableAutoOrientation();
- }
-}
-
-/* static */ void
-OrientationObserver::ShutDown()
-{
- if (!sOrientationSensorObserver) {
- return;
- }
-
- if (sOrientationSensorObserver->mAutoOrientationEnabled) {
- sOrientationSensorObserver->DisableAutoOrientation();
- }
-}
-
-void
-OrientationObserver::Notify(const hal::SensorData& aSensorData)
-{
- // Sensor will call us on the main thread.
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(aSensorData.sensor() == hal::SensorType::SENSOR_ACCELERATION);
-
- nsCOMPtr<nsIScreen> screen = GetPrimaryScreen();
- if (!screen) {
- return;
- }
-
- uint32_t currRotation;
- if(NS_FAILED(screen->GetRotation(&currRotation))) {
- return;
- }
-
- int rotation = mOrientation->OnSensorChanged(aSensorData, static_cast<int>(currRotation));
- if (rotation < 0 || uint32_t(rotation) == currRotation) {
- return;
- }
-
- ScreenOrientationInternal orientation;
- if (NS_FAILED(ConvertToDomOrientation(rotation, &orientation))) {
- return;
- }
-
- if ((mAllowedOrientations & orientation) == eScreenOrientation_None) {
- // The orientation from sensor is not allowed.
- return;
- }
-
- if (NS_FAILED(screen->SetRotation(static_cast<uint32_t>(rotation)))) {
- // Don't notify dom on rotation failure.
- return;
- }
-}
-
-/**
- * Register the observer. Note that the observer shouldn't be registered.
- */
-void
-OrientationObserver::EnableAutoOrientation()
-{
- MOZ_ASSERT(NS_IsMainThread() && !mAutoOrientationEnabled);
-
- mOrientation->Reset();
- hal::RegisterSensorObserver(hal::SENSOR_ACCELERATION, this);
- mAutoOrientationEnabled = true;
-}
-
-/**
- * Unregister the observer. Note that the observer should already be registered.
- */
-void
-OrientationObserver::DisableAutoOrientation()
-{
- MOZ_ASSERT(NS_IsMainThread() && mAutoOrientationEnabled);
-
- hal::UnregisterSensorObserver(hal::SENSOR_ACCELERATION, this);
- mAutoOrientationEnabled = false;
-}
-
-bool
-OrientationObserver::LockScreenOrientation(ScreenOrientationInternal aOrientation)
-{
- MOZ_ASSERT(aOrientation | (eScreenOrientation_PortraitPrimary |
- eScreenOrientation_PortraitSecondary |
- eScreenOrientation_LandscapePrimary |
- eScreenOrientation_LandscapeSecondary |
- eScreenOrientation_Default));
-
- if (aOrientation == eScreenOrientation_Default) {
- aOrientation = (sOrientationOffset == sDefaultPortrait) ?
- eScreenOrientation_PortraitPrimary :
- eScreenOrientation_LandscapePrimary;
- }
-
- // If there are multiple orientations allowed, we should enable the
- // auto-rotation.
- if (aOrientation != eScreenOrientation_LandscapePrimary &&
- aOrientation != eScreenOrientation_LandscapeSecondary &&
- aOrientation != eScreenOrientation_PortraitPrimary &&
- aOrientation != eScreenOrientation_PortraitSecondary) {
- if (!mAutoOrientationEnabled) {
- EnableAutoOrientation();
- }
- } else if (mAutoOrientationEnabled) {
- DisableAutoOrientation();
- }
-
- mAllowedOrientations = aOrientation;
-
- nsCOMPtr<nsIScreen> screen = GetPrimaryScreen();
- NS_ENSURE_TRUE(screen, false);
-
- uint32_t currRotation;
- nsresult rv = screen->GetRotation(&currRotation);
- NS_ENSURE_SUCCESS(rv, false);
-
- ScreenOrientationInternal currOrientation = eScreenOrientation_None;
- rv = ConvertToDomOrientation(currRotation, &currOrientation);
- NS_ENSURE_SUCCESS(rv, false);
-
- // Don't rotate if the current orientation matches one of the
- // requested orientations.
- if (currOrientation & aOrientation) {
- return true;
- }
-
- // Return false on invalid orientation value.
- uint32_t rotation;
- rv = ConvertToScreenRotation(aOrientation, &rotation);
- NS_ENSURE_SUCCESS(rv, false);
-
- rv = screen->SetRotation(rotation);
- NS_ENSURE_SUCCESS(rv, false);
-
- // This conversion will disambiguate aOrientation.
- ScreenOrientationInternal orientation;
- rv = ConvertToDomOrientation(rotation, &orientation);
- NS_ENSURE_SUCCESS(rv, false);
-
- return true;
-}
-
-void
-OrientationObserver::UnlockScreenOrientation()
-{
- if (!mAutoOrientationEnabled) {
- EnableAutoOrientation();
- }
-
- mAllowedOrientations = sDefaultOrientations;
-}
diff --git a/widget/gonk/OrientationObserver.h b/widget/gonk/OrientationObserver.h
deleted file mode 100644
index c841ea878..000000000
--- a/widget/gonk/OrientationObserver.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=8 et ft=cpp : */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 OrientationObserver_h
-#define OrientationObserver_h
-
-#include "mozilla/Observer.h"
-#include "mozilla/dom/ScreenOrientation.h"
-#include "mozilla/UniquePtr.h"
-
-namespace mozilla {
-class ProcessOrientation;
-namespace hal {
-class SensorData;
-typedef mozilla::Observer<SensorData> ISensorObserver;
-} // namespace hal
-} // namespace mozilla
-
-using mozilla::hal::ISensorObserver;
-using mozilla::hal::SensorData;
-using mozilla::dom::ScreenOrientationInternal;
-
-class OrientationObserver : public ISensorObserver {
-public:
- OrientationObserver();
- ~OrientationObserver();
-
- // Call DisableAutoOrientation on the existing OrientatiOnobserver singleton,
- // if it exists. If no OrientationObserver exists, do nothing.
- static void ShutDown();
-
- // Notification from sensor.
- void Notify(const SensorData& aSensorData);
-
- // Methods to enable/disable automatic orientation.
- void EnableAutoOrientation();
- void DisableAutoOrientation();
-
- // Methods called by methods in hal_impl namespace.
- bool LockScreenOrientation(ScreenOrientationInternal aOrientation);
- void UnlockScreenOrientation();
-
- static OrientationObserver* GetInstance();
-
-private:
- bool mAutoOrientationEnabled;
- uint32_t mAllowedOrientations;
- mozilla::UniquePtr<mozilla::ProcessOrientation> mOrientation;
-
- static const uint32_t sDefaultOrientations =
- mozilla::dom::eScreenOrientation_PortraitPrimary |
- mozilla::dom::eScreenOrientation_PortraitSecondary |
- mozilla::dom::eScreenOrientation_LandscapePrimary |
- mozilla::dom::eScreenOrientation_LandscapeSecondary;
-};
-
-#endif
diff --git a/widget/gonk/ProcessOrientation.cpp b/widget/gonk/ProcessOrientation.cpp
deleted file mode 100644
index bbdcface8..000000000
--- a/widget/gonk/ProcessOrientation.cpp
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Copyright (c) 2013, Linux Foundation. All rights reserved
- *
- * 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.
- */
-
-#include "base/basictypes.h"
-#include "mozilla/Hal.h"
-#include "mozilla/Unused.h"
-#include "nsIScreen.h"
-#include "nsIScreenManager.h"
-#include "OrientationObserver.h"
-#include "ProcessOrientation.h"
-#include "mozilla/HalSensor.h"
-#include "math.h"
-#include "limits.h"
-#include "android/log.h"
-
-#if 0
-#define LOGD(args...) __android_log_print(ANDROID_LOG_DEBUG, "ProcessOrientation" , ## args)
-#else
-#define LOGD(args...)
-#endif
-
-namespace mozilla {
-
-// We work with all angles in degrees in this class.
-#define RADIANS_TO_DEGREES (180/M_PI)
-
-// Number of nanoseconds per millisecond.
-#define NANOS_PER_MS 1000000
-
-// Indices into SensorEvent.values for the accelerometer sensor.
-#define ACCELEROMETER_DATA_X 0
-#define ACCELEROMETER_DATA_Y 1
-#define ACCELEROMETER_DATA_Z 2
-
-// The minimum amount of time that a predicted rotation must be stable before
-// it is accepted as a valid rotation proposal. This value can be quite small
-// because the low-pass filter already suppresses most of the noise so we're
-// really just looking for quick confirmation that the last few samples are in
-// agreement as to the desired orientation.
-#define PROPOSAL_SETTLE_TIME_NANOS (40*NANOS_PER_MS)
-
-// The minimum amount of time that must have elapsed since the device last
-// exited the flat state (time since it was picked up) before the proposed
-// rotation can change.
-#define PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS (500*NANOS_PER_MS)
-
-// The minimum amount of time that must have elapsed since the device stopped
-// swinging (time since device appeared to be in the process of being put down
-// or put away into a pocket) before the proposed rotation can change.
-#define PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS (300*NANOS_PER_MS)
-
-// The minimum amount of time that must have elapsed since the device stopped
-// undergoing external acceleration before the proposed rotation can change.
-#define PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS (500*NANOS_PER_MS)
-
-// If the tilt angle remains greater than the specified angle for a minimum of
-// the specified time, then the device is deemed to be lying flat
-// (just chillin' on a table).
-#define FLAT_ANGLE 75
-#define FLAT_TIME_NANOS (1000*NANOS_PER_MS)
-
-// If the tilt angle has increased by at least delta degrees within the
-// specified amount of time, then the device is deemed to be swinging away
-// from the user down towards flat (tilt = 90).
-#define SWING_AWAY_ANGLE_DELTA 20
-#define SWING_TIME_NANOS (300*NANOS_PER_MS)
-
-// The maximum sample inter-arrival time in milliseconds. If the acceleration
-// samples are further apart than this amount in time, we reset the state of
-// the low-pass filter and orientation properties. This helps to handle
-// boundary conditions when the device is turned on, wakes from suspend or
-// there is a significant gap in samples.
-#define MAX_FILTER_DELTA_TIME_NANOS (1000*NANOS_PER_MS)
-
-// The acceleration filter time constant.
-//
-// This time constant is used to tune the acceleration filter such that
-// impulses and vibrational noise (think car dock) is suppressed before we try
-// to calculate the tilt and orientation angles.
-//
-// The filter time constant is related to the filter cutoff frequency, which
-// is the frequency at which signals are attenuated by 3dB (half the passband
-// power). Each successive octave beyond this frequency is attenuated by an
-// additional 6dB.
-//
-// Given a time constant t in seconds, the filter cutoff frequency Fc in Hertz
-// is given by Fc = 1 / (2pi * t).
-//
-// The higher the time constant, the lower the cutoff frequency, so more noise
-// will be suppressed.
-//
-// Filtering adds latency proportional the time constant (inversely
-// proportional to the cutoff frequency) so we don't want to make the time
-// constant too large or we can lose responsiveness. Likewise we don't want
-// to make it too small or we do a poor job suppressing acceleration spikes.
-// Empirically, 100ms seems to be too small and 500ms is too large. Android
-// default is 200.
-#define FILTER_TIME_CONSTANT_MS 200.0f
-
-// State for orientation detection. Thresholds for minimum and maximum
-// allowable deviation from gravity.
-//
-// If the device is undergoing external acceleration (being bumped, in a car
-// that is turning around a corner or a plane taking off) then the magnitude
-// may be substantially more or less than gravity. This can skew our
-// orientation detection by making us think that up is pointed in a different
-// direction.
-//
-// Conversely, if the device is in freefall, then there will be no gravity to
-// measure at all. This is problematic because we cannot detect the orientation
-// without gravity to tell us which way is up. A magnitude near 0 produces
-// singularities in the tilt and orientation calculations.
-//
-// In both cases, we postpone choosing an orientation.
-//
-// However, we need to tolerate some acceleration because the angular momentum
-// of turning the device can skew the observed acceleration for a short period
-// of time.
-#define NEAR_ZERO_MAGNITUDE 1 // m/s^2
-#define ACCELERATION_TOLERANCE 4 // m/s^2
-#define STANDARD_GRAVITY 9.80665f
-#define MIN_ACCELERATION_MAGNITUDE (STANDARD_GRAVITY-ACCELERATION_TOLERANCE)
-#define MAX_ACCELERATION_MAGNITUDE (STANDARD_GRAVITY+ACCELERATION_TOLERANCE)
-
-// Maximum absolute tilt angle at which to consider orientation data. Beyond
-// this (i.e. when screen is facing the sky or ground), we completely ignore
-// orientation data.
-#define MAX_TILT 75
-
-// The gap angle in degrees between adjacent orientation angles for
-// hysteresis.This creates a "dead zone" between the current orientation and a
-// proposed adjacent orientation. No orientation proposal is made when the
-// orientation angle is within the gap between the current orientation and the
-// adjacent orientation.
-#define ADJACENT_ORIENTATION_ANGLE_GAP 45
-
-const int
-ProcessOrientation::tiltTolerance[][4] = {
- {-25, 70}, // ROTATION_0
- {-25, 65}, // ROTATION_90
- {-25, 60}, // ROTATION_180
- {-25, 65} // ROTATION_270
-};
-
-int
-ProcessOrientation::GetProposedRotation()
-{
- return mProposedRotation;
-}
-
-int
-ProcessOrientation::OnSensorChanged(const SensorData& event,
- int deviceCurrentRotation)
-{
- // The vector given in the SensorEvent points straight up (towards the sky)
- // under ideal conditions (the phone is not accelerating). I'll call this up
- // vector elsewhere.
- const InfallibleTArray<float>& values = event.values();
- float x = values[ACCELEROMETER_DATA_X];
- float y = values[ACCELEROMETER_DATA_Y];
- float z = values[ACCELEROMETER_DATA_Z];
-
- LOGD
- ("ProcessOrientation: Raw acceleration vector: x = %f, y = %f, z = %f,"
- "magnitude = %f\n", x, y, z, sqrt(x * x + y * y + z * z));
- // Apply a low-pass filter to the acceleration up vector in cartesian space.
- // Reset the orientation listener state if the samples are too far apart in
- // time or when we see values of (0, 0, 0) which indicates that we polled the
- // accelerometer too soon after turning it on and we don't have any data yet.
- const int64_t now = (int64_t) event.timestamp();
- const int64_t then = mLastFilteredTimestampNanos;
- const float timeDeltaMS = (now - then) * 0.000001f;
- bool skipSample = false;
- if (now < then
- || now > then + MAX_FILTER_DELTA_TIME_NANOS
- || (x == 0 && y == 0 && z == 0)) {
- LOGD
- ("ProcessOrientation: Resetting orientation listener.");
- Reset();
- skipSample = true;
- } else {
- const float alpha = timeDeltaMS / (FILTER_TIME_CONSTANT_MS + timeDeltaMS);
- x = alpha * (x - mLastFilteredX) + mLastFilteredX;
- y = alpha * (y - mLastFilteredY) + mLastFilteredY;
- z = alpha * (z - mLastFilteredZ) + mLastFilteredZ;
- LOGD
- ("ProcessOrientation: Filtered acceleration vector: x=%f, y=%f, z=%f,"
- "magnitude=%f", z, y, z, sqrt(x * x + y * y + z * z));
- skipSample = false;
- }
- mLastFilteredTimestampNanos = now;
- mLastFilteredX = x;
- mLastFilteredY = y;
- mLastFilteredZ = z;
-
- bool isAccelerating = false;
- bool isFlat = false;
- bool isSwinging = false;
- if (skipSample) {
- return -1;
- }
-
- // Calculate the magnitude of the acceleration vector.
- const float magnitude = sqrt(x * x + y * y + z * z);
- if (magnitude < NEAR_ZERO_MAGNITUDE) {
- LOGD
- ("ProcessOrientation: Ignoring sensor data, magnitude too close to"
- " zero.");
- ClearPredictedRotation();
- } else {
- // Determine whether the device appears to be undergoing external
- // acceleration.
- if (this->IsAccelerating(magnitude)) {
- isAccelerating = true;
- mAccelerationTimestampNanos = now;
- }
- // Calculate the tilt angle. This is the angle between the up vector and
- // the x-y plane (the plane of the screen) in a range of [-90, 90]
- // degrees.
- // -90 degrees: screen horizontal and facing the ground (overhead)
- // 0 degrees: screen vertical
- // 90 degrees: screen horizontal and facing the sky (on table)
- const int tiltAngle =
- static_cast<int>(roundf(asin(z / magnitude) * RADIANS_TO_DEGREES));
- AddTiltHistoryEntry(now, tiltAngle);
-
- // Determine whether the device appears to be flat or swinging.
- if (this->IsFlat(now)) {
- isFlat = true;
- mFlatTimestampNanos = now;
- }
- if (this->IsSwinging(now, tiltAngle)) {
- isSwinging = true;
- mSwingTimestampNanos = now;
- }
- // If the tilt angle is too close to horizontal then we cannot determine
- // the orientation angle of the screen.
- if (abs(tiltAngle) > MAX_TILT) {
- LOGD
- ("ProcessOrientation: Ignoring sensor data, tilt angle too high:"
- " tiltAngle=%d", tiltAngle);
- ClearPredictedRotation();
- } else {
- // Calculate the orientation angle.
- // This is the angle between the x-y projection of the up vector onto
- // the +y-axis, increasing clockwise in a range of [0, 360] degrees.
- int orientationAngle =
- static_cast<int>(roundf(-atan2f(-x, y) * RADIANS_TO_DEGREES));
- if (orientationAngle < 0) {
- // atan2 returns [-180, 180]; normalize to [0, 360]
- orientationAngle += 360;
- }
- // Find the nearest rotation.
- int nearestRotation = (orientationAngle + 45) / 90;
- if (nearestRotation == 4) {
- nearestRotation = 0;
- }
- // Determine the predicted orientation.
- if (IsTiltAngleAcceptable(nearestRotation, tiltAngle)
- &&
- IsOrientationAngleAcceptable
- (nearestRotation, orientationAngle, deviceCurrentRotation)) {
- UpdatePredictedRotation(now, nearestRotation);
- LOGD
- ("ProcessOrientation: Predicted: tiltAngle=%d, orientationAngle=%d,"
- " predictedRotation=%d, predictedRotationAgeMS=%f",
- tiltAngle,
- orientationAngle,
- mPredictedRotation,
- ((now - mPredictedRotationTimestampNanos) * 0.000001f));
- } else {
- LOGD
- ("ProcessOrientation: Ignoring sensor data, no predicted rotation:"
- " tiltAngle=%d, orientationAngle=%d",
- tiltAngle,
- orientationAngle);
- ClearPredictedRotation();
- }
- }
- }
-
- // Determine new proposed rotation.
- const int oldProposedRotation = mProposedRotation;
- if (mPredictedRotation < 0 || IsPredictedRotationAcceptable(now)) {
- mProposedRotation = mPredictedRotation;
- }
- // Write final statistics about where we are in the orientation detection
- // process.
- LOGD
- ("ProcessOrientation: Result: oldProposedRotation=%d,currentRotation=%d, "
- "proposedRotation=%d, predictedRotation=%d, timeDeltaMS=%f, "
- "isAccelerating=%d, isFlat=%d, isSwinging=%d, timeUntilSettledMS=%f, "
- "timeUntilAccelerationDelayExpiredMS=%f, timeUntilFlatDelayExpiredMS=%f, "
- "timeUntilSwingDelayExpiredMS=%f",
- oldProposedRotation,
- deviceCurrentRotation, mProposedRotation,
- mPredictedRotation, timeDeltaMS, isAccelerating, isFlat,
- isSwinging, RemainingMS(now,
- mPredictedRotationTimestampNanos +
- PROPOSAL_SETTLE_TIME_NANOS),
- RemainingMS(now,
- mAccelerationTimestampNanos +
- PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS),
- RemainingMS(now,
- mFlatTimestampNanos +
- PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS),
- RemainingMS(now,
- mSwingTimestampNanos +
- PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS));
-
- // Avoid unused-but-set compile warnings for these variables, when LOGD is
- // a no-op, as it is by default:
- Unused << isAccelerating;
- Unused << isFlat;
- Unused << isSwinging;
-
- // Tell the listener.
- if (mProposedRotation != oldProposedRotation && mProposedRotation >= 0) {
- LOGD
- ("ProcessOrientation: Proposed rotation changed! proposedRotation=%d, "
- "oldProposedRotation=%d",
- mProposedRotation,
- oldProposedRotation);
- return mProposedRotation;
- }
- // Don't rotate screen
- return -1;
-}
-
-bool
-ProcessOrientation::IsTiltAngleAcceptable(int rotation, int tiltAngle)
-{
- return (tiltAngle >= tiltTolerance[rotation][0]
- && tiltAngle <= tiltTolerance[rotation][1]);
-}
-
-bool
-ProcessOrientation::IsOrientationAngleAcceptable(int rotation,
- int orientationAngle,
- int currentRotation)
-{
- // If there is no current rotation, then there is no gap.
- // The gap is used only to introduce hysteresis among advertised orientation
- // changes to avoid flapping.
- if (currentRotation < 0) {
- return true;
- }
- // If the specified rotation is the same or is counter-clockwise adjacent
- // to the current rotation, then we set a lower bound on the orientation
- // angle. For example, if currentRotation is ROTATION_0 and proposed is
- // ROTATION_90, then we want to check orientationAngle > 45 + GAP / 2.
- if (rotation == currentRotation || rotation == (currentRotation + 1) % 4) {
- int lowerBound = rotation * 90 - 45 + ADJACENT_ORIENTATION_ANGLE_GAP / 2;
- if (rotation == 0) {
- if (orientationAngle >= 315 && orientationAngle < lowerBound + 360) {
- return false;
- }
- } else {
- if (orientationAngle < lowerBound) {
- return false;
- }
- }
- }
- // If the specified rotation is the same or is clockwise adjacent, then we
- // set an upper bound on the orientation angle. For example, if
- // currentRotation is ROTATION_0 and rotation is ROTATION_270, then we want
- // to check orientationAngle < 315 - GAP / 2.
- if (rotation == currentRotation || rotation == (currentRotation + 3) % 4) {
- int upperBound = rotation * 90 + 45 - ADJACENT_ORIENTATION_ANGLE_GAP / 2;
- if (rotation == 0) {
- if (orientationAngle <= 45 && orientationAngle > upperBound) {
- return false;
- }
- } else {
- if (orientationAngle > upperBound) {
- return false;
- }
- }
- }
- return true;
-}
-
-bool
-ProcessOrientation::IsPredictedRotationAcceptable(int64_t now)
-{
- // The predicted rotation must have settled long enough.
- if (now < mPredictedRotationTimestampNanos + PROPOSAL_SETTLE_TIME_NANOS) {
- return false;
- }
- // The last flat state (time since picked up) must have been sufficiently long
- // ago.
- if (now < mFlatTimestampNanos + PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS) {
- return false;
- }
- // The last swing state (time since last movement to put down) must have been
- // sufficiently long ago.
- if (now < mSwingTimestampNanos + PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS) {
- return false;
- }
- // The last acceleration state must have been sufficiently long ago.
- if (now < mAccelerationTimestampNanos
- + PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS) {
- return false;
- }
- // Looks good!
- return true;
-}
-
-int
-ProcessOrientation::Reset()
-{
- mLastFilteredTimestampNanos = std::numeric_limits<int64_t>::min();
- mProposedRotation = -1;
- mFlatTimestampNanos = std::numeric_limits<int64_t>::min();
- mSwingTimestampNanos = std::numeric_limits<int64_t>::min();
- mAccelerationTimestampNanos = std::numeric_limits<int64_t>::min();
- ClearPredictedRotation();
- ClearTiltHistory();
- return -1;
-}
-
-void
-ProcessOrientation::ClearPredictedRotation()
-{
- mPredictedRotation = -1;
- mPredictedRotationTimestampNanos = std::numeric_limits<int64_t>::min();
-}
-
-void
-ProcessOrientation::UpdatePredictedRotation(int64_t now, int rotation)
-{
- if (mPredictedRotation != rotation) {
- mPredictedRotation = rotation;
- mPredictedRotationTimestampNanos = now;
- }
-}
-
-bool
-ProcessOrientation::IsAccelerating(float magnitude)
-{
- return magnitude < MIN_ACCELERATION_MAGNITUDE
- || magnitude > MAX_ACCELERATION_MAGNITUDE;
-}
-
-void
-ProcessOrientation::ClearTiltHistory()
-{
- mTiltHistory.history[0].timestampNanos = std::numeric_limits<int64_t>::min();
- mTiltHistory.index = 1;
-}
-
-void
-ProcessOrientation::AddTiltHistoryEntry(int64_t now, float tilt)
-{
- mTiltHistory.history[mTiltHistory.index].tiltAngle = tilt;
- mTiltHistory.history[mTiltHistory.index].timestampNanos = now;
- mTiltHistory.index = (mTiltHistory.index + 1) % TILT_HISTORY_SIZE;
- mTiltHistory.history[mTiltHistory.index].timestampNanos = std::numeric_limits<int64_t>::min();
-}
-
-bool
-ProcessOrientation::IsFlat(int64_t now)
-{
- for (int i = mTiltHistory.index; (i = NextTiltHistoryIndex(i)) >= 0;) {
- if (mTiltHistory.history[i].tiltAngle < FLAT_ANGLE) {
- break;
- }
- if (mTiltHistory.history[i].timestampNanos + FLAT_TIME_NANOS <= now) {
- // Tilt has remained greater than FLAT_TILT_ANGLE for FLAT_TIME_NANOS.
- return true;
- }
- }
- return false;
-}
-
-bool
-ProcessOrientation::IsSwinging(int64_t now, float tilt)
-{
- for (int i = mTiltHistory.index; (i = NextTiltHistoryIndex(i)) >= 0;) {
- if (mTiltHistory.history[i].timestampNanos + SWING_TIME_NANOS < now) {
- break;
- }
- if (mTiltHistory.history[i].tiltAngle + SWING_AWAY_ANGLE_DELTA <= tilt) {
- // Tilted away by SWING_AWAY_ANGLE_DELTA within SWING_TIME_NANOS.
- return true;
- }
- }
- return false;
-}
-
-int
-ProcessOrientation::NextTiltHistoryIndex(int index)
-{
- index = (index == 0 ? TILT_HISTORY_SIZE : index) - 1;
- return mTiltHistory.history[index].timestampNanos != std::numeric_limits<int64_t>::min() ? index : -1;
-}
-
-float
-ProcessOrientation::RemainingMS(int64_t now, int64_t until)
-{
- return now >= until ? 0 : (until - now) * 0.000001f;
-}
-
-} // namespace mozilla
diff --git a/widget/gonk/ProcessOrientation.h b/widget/gonk/ProcessOrientation.h
deleted file mode 100644
index d6d4bc3b6..000000000
--- a/widget/gonk/ProcessOrientation.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2013, Linux Foundation. All rights reserved
- *
- * 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.
- */
-
-#ifndef ProcessOrientation_h
-#define ProcessOrientation_h
-
-#include "mozilla/Hal.h"
-
-namespace mozilla {
-
-// History of observed tilt angles.
-#define TILT_HISTORY_SIZE 40
-
-class ProcessOrientation {
-public:
- ProcessOrientation() {};
- ~ProcessOrientation() {};
-
- int OnSensorChanged(const mozilla::hal::SensorData& event, int deviceCurrentRotation);
- int Reset();
-
-private:
- int GetProposedRotation();
-
- // Returns true if the tilt angle is acceptable for a given predicted
- // rotation.
- bool IsTiltAngleAcceptable(int rotation, int tiltAngle);
-
- // Returns true if the orientation angle is acceptable for a given predicted
- // rotation. This function takes into account the gap between adjacent
- // orientations for hysteresis.
- bool IsOrientationAngleAcceptable(int rotation, int orientationAngle,
- int currentRotation);
-
- // Returns true if the predicted rotation is ready to be advertised as a
- // proposed rotation.
- bool IsPredictedRotationAcceptable(int64_t now);
-
- void ClearPredictedRotation();
- void UpdatePredictedRotation(int64_t now, int rotation);
- bool IsAccelerating(float magnitude);
- void ClearTiltHistory();
- void AddTiltHistoryEntry(int64_t now, float tilt);
- bool IsFlat(int64_t now);
- bool IsSwinging(int64_t now, float tilt);
- int NextTiltHistoryIndex(int index);
- float RemainingMS(int64_t now, int64_t until);
-
- // The tilt angle range in degrees for each orientation. Beyond these tilt
- // angles, we don't even consider transitioning into the specified orientation.
- // We place more stringent requirements on unnatural orientations than natural
- // ones to make it less likely to accidentally transition into those states.
- // The first value of each pair is negative so it applies a limit when the
- // device is facing down (overhead reading in bed). The second value of each
- // pair is positive so it applies a limit when the device is facing up
- // (resting on a table). The ideal tilt angle is 0 (when the device is vertical)
- // so the limits establish how close to vertical the device must be in order
- // to change orientation.
- static const int tiltTolerance[][4];
-
- // Timestamp and value of the last accelerometer sample.
- int64_t mLastFilteredTimestampNanos;
- float mLastFilteredX, mLastFilteredY, mLastFilteredZ;
-
- // The last proposed rotation, -1 if unknown.
- int mProposedRotation;
-
- // Value of the current predicted rotation, -1 if unknown.
- int mPredictedRotation;
-
- // Timestamp of when the predicted rotation most recently changed.
- int64_t mPredictedRotationTimestampNanos;
-
- // Timestamp when the device last appeared to be flat for sure (the flat delay
- // elapsed).
- int64_t mFlatTimestampNanos;
-
- // Timestamp when the device last appeared to be swinging.
- int64_t mSwingTimestampNanos;
-
- // Timestamp when the device last appeared to be undergoing external
- // acceleration.
- int64_t mAccelerationTimestampNanos;
-
- struct {
- struct {
- float tiltAngle;
- int64_t timestampNanos;
- } history[TILT_HISTORY_SIZE];
- int index;
- } mTiltHistory;
-};
-
-} // namespace mozilla
-
-#endif
diff --git a/widget/gonk/WidgetTraceEvent.cpp b/widget/gonk/WidgetTraceEvent.cpp
deleted file mode 100644
index 558d9313e..000000000
--- a/widget/gonk/WidgetTraceEvent.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/WidgetTraceEvent.h"
-#include "mozilla/StaticPtr.h"
-#include "nsThreadUtils.h"
-#include <mozilla/CondVar.h>
-#include <mozilla/Mutex.h>
-
-using mozilla::CondVar;
-using mozilla::Mutex;
-using mozilla::MutexAutoLock;
-
-namespace mozilla {
- class TracerRunnable : public Runnable {
- public:
- TracerRunnable() {
- mTracerLock = new Mutex("TracerRunnable");
- mTracerCondVar = new CondVar(*mTracerLock, "TracerRunnable");
- mMainThread = do_GetMainThread();
- }
-
- ~TracerRunnable() {
- delete mTracerCondVar;
- delete mTracerLock;
- mTracerLock = nullptr;
- mTracerCondVar = nullptr;
- }
-
- virtual nsresult Run() {
- MutexAutoLock lock(*mTracerLock);
- mHasRun = true;
- mTracerCondVar->Notify();
- return NS_OK;
- }
-
- bool Fire() {
- if (!mTracerLock || !mTracerCondVar) {
- return false;
- }
-
- MutexAutoLock lock(*mTracerLock);
- mHasRun = false;
- mMainThread->Dispatch(this, NS_DISPATCH_NORMAL);
- while (!mHasRun) {
- mTracerCondVar->Wait();
- }
- return true;
- }
-
- void Signal() {
- MutexAutoLock lock(*mTracerLock);
- mHasRun = true;
- mTracerCondVar->Notify();
- }
-
- private:
- Mutex* mTracerLock;
- CondVar* mTracerCondVar;
- bool mHasRun;
- nsCOMPtr<nsIThread> mMainThread;
- };
-
- StaticRefPtr<TracerRunnable> sTracerRunnable;
-
- bool InitWidgetTracing()
- {
- if (!sTracerRunnable) {
- sTracerRunnable = new TracerRunnable();
- }
- return true;
- }
-
- void CleanUpWidgetTracing()
- {
- sTracerRunnable = nullptr;
- }
-
- bool FireAndWaitForTracerEvent()
- {
- if (sTracerRunnable) {
- return sTracerRunnable->Fire();
- }
-
- return false;
- }
-
- void SignalTracerThread()
- {
- if (sTracerRunnable) {
- return sTracerRunnable->Signal();
- }
- }
-} // namespace mozilla
-
diff --git a/widget/gonk/hwchal/HwcHAL.cpp b/widget/gonk/hwchal/HwcHAL.cpp
deleted file mode 100644
index 1793b75e6..000000000
--- a/widget/gonk/hwchal/HwcHAL.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim:set ts=4 sw=4 sts=4 et: */
-/*
- * Copyright (c) 2015 The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "HwcHAL.h"
-#include "libdisplay/GonkDisplay.h"
-#include "mozilla/Assertions.h"
-
-namespace mozilla {
-
-HwcHAL::HwcHAL()
- : HwcHALBase()
-{
- // Some HALs don't want to open hwc twice.
- // If GetDisplay already load hwc module, we don't need to load again
- mHwc = (HwcDevice*)GetGonkDisplay()->GetHWCDevice();
- if (!mHwc) {
- printf_stderr("HwcHAL Error: Cannot load hwcomposer");
- return;
- }
-}
-
-HwcHAL::~HwcHAL()
-{
- mHwc = nullptr;
-}
-
-bool
-HwcHAL::Query(QueryType aType)
-{
- if (!mHwc || !mHwc->query) {
- return false;
- }
-
- bool value = false;
- int supported = 0;
- if (mHwc->query(mHwc, static_cast<int>(aType), &supported) == 0/*android::NO_ERROR*/) {
- value = !!supported;
- }
- return value;
-}
-
-int
-HwcHAL::Set(HwcList *aList,
- uint32_t aDisp)
-{
- MOZ_ASSERT(mHwc);
- if (!mHwc) {
- return -1;
- }
-
- HwcList *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
- displays[aDisp] = aList;
- return mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
-}
-
-int
-HwcHAL::ResetHwc()
-{
- return Set(nullptr, HWC_DISPLAY_PRIMARY);
-}
-
-int
-HwcHAL::Prepare(HwcList *aList,
- uint32_t aDisp,
- hwc_rect_t aDispRect,
- buffer_handle_t aHandle,
- int aFenceFd)
-{
- MOZ_ASSERT(mHwc);
- if (!mHwc) {
- printf_stderr("HwcHAL Error: HwcDevice doesn't exist. A fence might be leaked.");
- return -1;
- }
-
- HwcList *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
- displays[aDisp] = aList;
-#if ANDROID_VERSION >= 18
- aList->outbufAcquireFenceFd = -1;
- aList->outbuf = nullptr;
-#endif
- aList->retireFenceFd = -1;
-
- const auto idx = aList->numHwLayers - 1;
- aList->hwLayers[idx].hints = 0;
- aList->hwLayers[idx].flags = 0;
- aList->hwLayers[idx].transform = 0;
- aList->hwLayers[idx].handle = aHandle;
- aList->hwLayers[idx].blending = HWC_BLENDING_PREMULT;
- aList->hwLayers[idx].compositionType = HWC_FRAMEBUFFER_TARGET;
- SetCrop(aList->hwLayers[idx], aDispRect);
- aList->hwLayers[idx].displayFrame = aDispRect;
- aList->hwLayers[idx].visibleRegionScreen.numRects = 1;
- aList->hwLayers[idx].visibleRegionScreen.rects = &aList->hwLayers[idx].displayFrame;
- aList->hwLayers[idx].acquireFenceFd = aFenceFd;
- aList->hwLayers[idx].releaseFenceFd = -1;
-#if ANDROID_VERSION >= 18
- aList->hwLayers[idx].planeAlpha = 0xFF;
-#endif
- return mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
-}
-
-bool
-HwcHAL::SupportTransparency() const
-{
-#if ANDROID_VERSION >= 18
- return true;
-#endif
- return false;
-}
-
-uint32_t
-HwcHAL::GetGeometryChangedFlag(bool aGeometryChanged) const
-{
-#if ANDROID_VERSION >= 19
- return aGeometryChanged ? HWC_GEOMETRY_CHANGED : 0;
-#else
- return HWC_GEOMETRY_CHANGED;
-#endif
-}
-
-void
-HwcHAL::SetCrop(HwcLayer &aLayer,
- const hwc_rect_t &aSrcCrop) const
-{
- if (GetAPIVersion() >= HwcAPIVersion(1, 3)) {
-#if ANDROID_VERSION >= 19
- aLayer.sourceCropf.left = aSrcCrop.left;
- aLayer.sourceCropf.top = aSrcCrop.top;
- aLayer.sourceCropf.right = aSrcCrop.right;
- aLayer.sourceCropf.bottom = aSrcCrop.bottom;
-#endif
- } else {
- aLayer.sourceCrop = aSrcCrop;
- }
-}
-
-bool
-HwcHAL::EnableVsync(bool aEnable)
-{
- // Only support hardware vsync on kitkat, L and up due to inaccurate timings
- // with JellyBean.
-#if (ANDROID_VERSION == 19 || ANDROID_VERSION >= 21)
- if (!mHwc) {
- return false;
- }
- return !mHwc->eventControl(mHwc,
- HWC_DISPLAY_PRIMARY,
- HWC_EVENT_VSYNC,
- aEnable);
-#else
- return false;
-#endif
-}
-
-bool
-HwcHAL::RegisterHwcEventCallback(const HwcHALProcs_t &aProcs)
-{
- if (!mHwc || !mHwc->registerProcs) {
- printf_stderr("Failed to get hwc\n");
- return false;
- }
-
- // Disable Vsync first, and then register callback functions.
- mHwc->eventControl(mHwc,
- HWC_DISPLAY_PRIMARY,
- HWC_EVENT_VSYNC,
- false);
- static const hwc_procs_t sHwcJBProcs = {aProcs.invalidate,
- aProcs.vsync,
- aProcs.hotplug};
- mHwc->registerProcs(mHwc, &sHwcJBProcs);
-
- // Only support hardware vsync on kitkat, L and up due to inaccurate timings
- // with JellyBean.
-#if (ANDROID_VERSION == 19 || ANDROID_VERSION >= 21)
- return true;
-#else
- return false;
-#endif
-}
-
-uint32_t
-HwcHAL::GetAPIVersion() const
-{
- if (!mHwc) {
- // default value: HWC_MODULE_API_VERSION_0_1
- return 1;
- }
- return mHwc->common.version;
-}
-
-// Create HwcHAL
-UniquePtr<HwcHALBase>
-HwcHALBase::CreateHwcHAL()
-{
- return Move(MakeUnique<HwcHAL>());
-}
-
-} // namespace mozilla
diff --git a/widget/gonk/hwchal/HwcHAL.h b/widget/gonk/hwchal/HwcHAL.h
deleted file mode 100644
index 05cb6a45f..000000000
--- a/widget/gonk/hwchal/HwcHAL.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim:set ts=4 sw=4 sts=4 et: */
-/*
- * Copyright (c) 2015 The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef mozilla_HwcHAL
-#define mozilla_HwcHAL
-
-#include "HwcHALBase.h"
-
-namespace mozilla {
-
-class HwcHAL final : public HwcHALBase {
-public:
- explicit HwcHAL();
-
- virtual ~HwcHAL();
-
- virtual bool HasHwc() const override { return static_cast<bool>(mHwc); }
-
- virtual void SetEGLInfo(hwc_display_t aDpy,
- hwc_surface_t aSur) override { }
-
- virtual bool Query(QueryType aType) override;
-
- virtual int Set(HwcList *aList,
- uint32_t aDisp) override;
-
- virtual int ResetHwc() override;
-
- virtual int Prepare(HwcList *aList,
- uint32_t aDisp,
- hwc_rect_t aDispRect,
- buffer_handle_t aHandle,
- int aFenceFd) override;
-
- virtual bool SupportTransparency() const override;
-
- virtual uint32_t GetGeometryChangedFlag(bool aGeometryChanged) const override;
-
- virtual void SetCrop(HwcLayer &aLayer,
- const hwc_rect_t &aSrcCrop) const override;
-
- virtual bool EnableVsync(bool aEnable) override;
-
- virtual bool RegisterHwcEventCallback(const HwcHALProcs_t &aProcs) override;
-
-private:
- uint32_t GetAPIVersion() const;
-
-private:
- HwcDevice *mHwc = nullptr;
-};
-
-} // namespace mozilla
-
-#endif // mozilla_HwcHAL
diff --git a/widget/gonk/hwchal/HwcHALBase.h b/widget/gonk/hwchal/HwcHALBase.h
deleted file mode 100644
index 0ef00a325..000000000
--- a/widget/gonk/hwchal/HwcHALBase.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim:set ts=4 sw=4 sts=4 et: */
-/*
- * Copyright (c) 2015 The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef mozilla_HwcHALBase
-#define mozilla_HwcHALBase
-
-#include "mozilla/UniquePtr.h"
-#include "nsRect.h"
-
-#include <hardware/hwcomposer.h>
-
-#ifndef HWC_BLIT
-#if ANDROID_VERSION >= 21
-#define HWC_BLIT 0xFF
-#elif ANDROID_VERSION >= 17
-#define HWC_BLIT (HWC_FRAMEBUFFER_TARGET + 1)
-#else
-// ICS didn't support this. However, we define this
-// for passing compilation
-#define HWC_BLIT 0xFF
-#endif // #if ANDROID_VERSION
-#endif // #ifndef HWC_BLIT
-
-namespace mozilla {
-
-#if ANDROID_VERSION >= 17
-using HwcDevice = hwc_composer_device_1_t;
-using HwcList = hwc_display_contents_1_t;
-using HwcLayer = hwc_layer_1_t;
-#else
-using HwcDevice = hwc_composer_device_t;
-using HwcList = hwc_layer_list_t;
-using HwcLayer = hwc_layer_t;
-#endif
-
-// HwcHAL definition for HwcEvent callback types
-// Note: hwc_procs is different between ICS and later,
-// and the signature of invalidate is also different.
-// Use this wrap struct to hide the detail. BTW,
-// we don't have to register callback functions on ICS, so
-// there is no callbacks for ICS in HwcHALProcs.
-typedef struct HwcHALProcs {
- void (*invalidate)(const struct hwc_procs* procs);
- void (*vsync)(const struct hwc_procs* procs, int disp, int64_t timestamp);
- void (*hotplug)(const struct hwc_procs* procs, int disp, int connected);
-} HwcHALProcs_t;
-
-// HwcHAL class
-// This class handle all the HAL related work
-// The purpose of HwcHAL is to make HwcComposer2D simpler.
-class HwcHALBase {
-
-public:
- // Query Types. We can add more types easily in the future
- enum class QueryType {
- COLOR_FILL = 0x8,
- RB_SWAP = 0x40
- };
-
-public:
- explicit HwcHALBase() = default;
-
- virtual ~HwcHALBase() {}
-
- // Create HwcHAL module, Only HwcComposer2D calls this.
- // If other modules want to use HwcHAL, please use APIs in
- // HwcComposer2D
- static UniquePtr<HwcHALBase> CreateHwcHAL();
-
- // Check if mHwc exists
- virtual bool HasHwc() const = 0;
-
- // Set EGL info (only ICS need this info)
- virtual void SetEGLInfo(hwc_display_t aEGLDisplay,
- hwc_surface_t aEGLSurface) = 0;
-
- // HwcDevice query properties
- virtual bool Query(QueryType aType) = 0;
-
- // HwcDevice set
- virtual int Set(HwcList *aList,
- uint32_t aDisp) = 0;
-
- // Reset HwcDevice
- virtual int ResetHwc() = 0;
-
- // HwcDevice prepare
- virtual int Prepare(HwcList *aList,
- uint32_t aDisp,
- hwc_rect_t aDispRect,
- buffer_handle_t aHandle,
- int aFenceFd) = 0;
-
- // Check transparency support
- virtual bool SupportTransparency() const = 0;
-
- // Get a geometry change flag
- virtual uint32_t GetGeometryChangedFlag(bool aGeometryChanged) const = 0;
-
- // Set crop help
- virtual void SetCrop(HwcLayer &aLayer,
- const hwc_rect_t &aSrcCrop) const = 0;
-
- // Enable HW Vsync
- virtual bool EnableVsync(bool aEnable) = 0;
-
- // Register HW event callback functions
- virtual bool RegisterHwcEventCallback(const HwcHALProcs_t &aProcs) = 0;
-
-protected:
- constexpr static uint32_t HwcAPIVersion(uint32_t aMaj, uint32_t aMin) {
- // HARDWARE_MAKE_API_VERSION_2, from Android hardware.h
- return (((aMaj & 0xff) << 24) | ((aMin & 0xff) << 16) | (1 & 0xffff));
- }
-};
-
-} // namespace mozilla
-
-#endif // mozilla_HwcHALBase
diff --git a/widget/gonk/libdisplay/BootAnimation.cpp b/widget/gonk/libdisplay/BootAnimation.cpp
deleted file mode 100644
index c275179fc..000000000
--- a/widget/gonk/libdisplay/BootAnimation.cpp
+++ /dev/null
@@ -1,726 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <algorithm>
-#include <endian.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <string>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <vector>
-#include "mozilla/FileUtils.h"
-#include "png.h"
-
-#include "android/log.h"
-#include "GonkDisplay.h"
-#include "hardware/gralloc.h"
-
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
-#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
-#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
-
-using namespace mozilla;
-using namespace std;
-
-static pthread_t sAnimationThread;
-static bool sRunAnimation;
-
-/* See http://www.pkware.com/documents/casestudies/APPNOTE.TXT */
-struct local_file_header {
- uint32_t signature;
- uint16_t min_version;
- uint16_t general_flag;
- uint16_t compression;
- uint16_t lastmod_time;
- uint16_t lastmod_date;
- uint32_t crc32;
- uint32_t compressed_size;
- uint32_t uncompressed_size;
- uint16_t filename_size;
- uint16_t extra_field_size;
- char data[0];
-
- uint32_t GetDataSize() const
- {
- return letoh32(uncompressed_size);
- }
-
- uint32_t GetSize() const
- {
- /* XXX account for data descriptor */
- return sizeof(local_file_header) + letoh16(filename_size) +
- letoh16(extra_field_size) + GetDataSize();
- }
-
- const char * GetData() const
- {
- return data + letoh16(filename_size) + letoh16(extra_field_size);
- }
-} __attribute__((__packed__));
-
-struct data_descriptor {
- uint32_t crc32;
- uint32_t compressed_size;
- uint32_t uncompressed_size;
-} __attribute__((__packed__));
-
-struct cdir_entry {
- uint32_t signature;
- uint16_t creator_version;
- uint16_t min_version;
- uint16_t general_flag;
- uint16_t compression;
- uint16_t lastmod_time;
- uint16_t lastmod_date;
- uint32_t crc32;
- uint32_t compressed_size;
- uint32_t uncompressed_size;
- uint16_t filename_size;
- uint16_t extra_field_size;
- uint16_t file_comment_size;
- uint16_t disk_num;
- uint16_t internal_attr;
- uint32_t external_attr;
- uint32_t offset;
- char data[0];
-
- uint32_t GetDataSize() const
- {
- return letoh32(compressed_size);
- }
-
- uint32_t GetSize() const
- {
- return sizeof(cdir_entry) + letoh16(filename_size) +
- letoh16(extra_field_size) + letoh16(file_comment_size);
- }
-
- bool Valid() const
- {
- return signature == htole32(0x02014b50);
- }
-} __attribute__((__packed__));
-
-struct cdir_end {
- uint32_t signature;
- uint16_t disk_num;
- uint16_t cdir_disk;
- uint16_t disk_entries;
- uint16_t cdir_entries;
- uint32_t cdir_size;
- uint32_t cdir_offset;
- uint16_t comment_size;
- char comment[0];
-
- bool Valid() const
- {
- return signature == htole32(0x06054b50);
- }
-} __attribute__((__packed__));
-
-/* We don't have access to libjar and the zip reader in android
- * doesn't quite fit what we want to do. */
-class ZipReader {
- const char *mBuf;
- const cdir_end *mEnd;
- const char *mCdir_limit;
- uint32_t mBuflen;
-
-public:
- ZipReader() : mBuf(nullptr) {}
- ~ZipReader() {
- if (mBuf)
- munmap((void *)mBuf, mBuflen);
- }
-
- bool OpenArchive(const char *path)
- {
- int fd;
- do {
- fd = open(path, O_RDONLY);
- } while (fd == -1 && errno == EINTR);
- if (fd == -1)
- return false;
-
- struct stat sb;
- if (fstat(fd, &sb) == -1 || sb.st_size < sizeof(cdir_end)) {
- close(fd);
- return false;
- }
-
- mBuflen = sb.st_size;
- mBuf = (char *)mmap(nullptr, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
- close(fd);
-
- if (!mBuf) {
- return false;
- }
-
- madvise(mBuf, sb.st_size, MADV_SEQUENTIAL);
-
- mEnd = (cdir_end *)(mBuf + mBuflen - sizeof(cdir_end));
- while (!mEnd->Valid() &&
- (char *)mEnd > mBuf) {
- mEnd = (cdir_end *)((char *)mEnd - 1);
- }
-
- mCdir_limit = mBuf + letoh32(mEnd->cdir_offset) + letoh32(mEnd->cdir_size);
-
- if (!mEnd->Valid() || mCdir_limit > (char *)mEnd) {
- munmap((void *)mBuf, mBuflen);
- mBuf = nullptr;
- return false;
- }
-
- return true;
- }
-
- /* Pass null to get the first cdir entry */
- const cdir_entry * GetNextEntry(const cdir_entry *prev)
- {
- const cdir_entry *entry;
- if (prev)
- entry = (cdir_entry *)((char *)prev + prev->GetSize());
- else
- entry = (cdir_entry *)(mBuf + letoh32(mEnd->cdir_offset));
-
- if (((char *)entry + entry->GetSize()) > mCdir_limit ||
- !entry->Valid())
- return nullptr;
- return entry;
- }
-
- string GetEntryName(const cdir_entry *entry)
- {
- uint16_t len = letoh16(entry->filename_size);
-
- string name;
- name.append(entry->data, len);
- return name;
- }
-
- const local_file_header * GetLocalEntry(const cdir_entry *entry)
- {
- const local_file_header * data =
- (local_file_header *)(mBuf + letoh32(entry->offset));
- if (((char *)data + data->GetSize()) > (char *)mEnd)
- return nullptr;
- return data;
- }
-};
-
-struct AnimationFrame {
- char path[256];
- png_color_16 bgcolor;
- char *buf;
- const local_file_header *file;
- uint32_t width;
- uint32_t height;
- uint16_t bytepp;
- bool has_bgcolor;
-
- AnimationFrame() : buf(nullptr) {}
- AnimationFrame(const AnimationFrame &frame) : buf(nullptr) {
- strncpy(path, frame.path, sizeof(path));
- file = frame.file;
- }
- ~AnimationFrame()
- {
- if (buf)
- free(buf);
- }
-
- bool operator<(const AnimationFrame &other) const
- {
- return strcmp(path, other.path) < 0;
- }
-
- void ReadPngFrame(int outputFormat);
-};
-
-struct AnimationPart {
- int32_t count;
- int32_t pause;
- // If you alter the size of the path, change ReadFromString() as well.
- char path[256];
- vector<AnimationFrame> frames;
-
- bool
- ReadFromString(const char* aLine)
- {
- MOZ_ASSERT(aLine);
- // this 255 value must be in sync with AnimationPart::path.
- return sscanf(aLine, "p %d %d %255s", &count, &pause, path) == 3;
- }
-};
-
-struct RawReadState {
- const char *start;
- uint32_t offset;
- uint32_t length;
-};
-
-static void
-RawReader(png_structp png_ptr, png_bytep data, png_size_t length)
-{
- RawReadState *state = (RawReadState *)png_get_io_ptr(png_ptr);
- if (length > (state->length - state->offset))
- png_error(png_ptr, "PNG read overrun");
-
- memcpy(data, state->start + state->offset, length);
- state->offset += length;
-}
-
-static void
-TransformTo565(png_structp png_ptr, png_row_infop row_info, png_bytep data)
-{
- uint16_t *outbuf = (uint16_t *)data;
- uint8_t *inbuf = (uint8_t *)data;
- for (uint32_t i = 0; i < row_info->rowbytes; i += 3) {
- *outbuf++ = ((inbuf[i] & 0xF8) << 8) |
- ((inbuf[i + 1] & 0xFC) << 3) |
- ((inbuf[i + 2] ) >> 3);
- }
-}
-
-static uint16_t
-GetFormatBPP(int aFormat)
-{
- uint16_t bpp = 0;
-
- switch (aFormat) {
- case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGBX_8888:
- bpp = 4;
- break;
- case HAL_PIXEL_FORMAT_RGB_888:
- bpp = 3;
- break;
- default:
- LOGW("Unknown pixel format %d. Assuming RGB 565.", aFormat);
- // FALL THROUGH
- case HAL_PIXEL_FORMAT_RGB_565:
- bpp = 2;
- break;
- }
-
- return bpp;
-}
-
-void
-AnimationFrame::ReadPngFrame(int outputFormat)
-{
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- static const png_byte unused_chunks[] =
- { 99, 72, 82, 77, '\0', /* cHRM */
- 104, 73, 83, 84, '\0', /* hIST */
- 105, 67, 67, 80, '\0', /* iCCP */
- 105, 84, 88, 116, '\0', /* iTXt */
- 111, 70, 70, 115, '\0', /* oFFs */
- 112, 67, 65, 76, '\0', /* pCAL */
- 115, 67, 65, 76, '\0', /* sCAL */
- 112, 72, 89, 115, '\0', /* pHYs */
- 115, 66, 73, 84, '\0', /* sBIT */
- 115, 80, 76, 84, '\0', /* sPLT */
- 116, 69, 88, 116, '\0', /* tEXt */
- 116, 73, 77, 69, '\0', /* tIME */
- 122, 84, 88, 116, '\0'}; /* zTXt */
- static const png_byte tRNS_chunk[] =
- {116, 82, 78, 83, '\0'}; /* tRNS */
-#endif
-
- png_structp pngread = png_create_read_struct(PNG_LIBPNG_VER_STRING,
- nullptr, nullptr, nullptr);
-
- if (!pngread)
- return;
-
- png_infop pnginfo = png_create_info_struct(pngread);
-
- if (!pnginfo) {
- png_destroy_read_struct(&pngread, &pnginfo, nullptr);
- return;
- }
-
- if (setjmp(png_jmpbuf(pngread))) {
- // libpng reported an error and longjumped here. Clean up and return.
- png_destroy_read_struct(&pngread, &pnginfo, nullptr);
- return;
- }
-
- RawReadState state;
- state.start = file->GetData();
- state.length = file->GetDataSize();
- state.offset = 0;
-
- png_set_read_fn(pngread, &state, RawReader);
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- /* Ignore unused chunks */
- png_set_keep_unknown_chunks(pngread, 1, unused_chunks,
- (int)sizeof(unused_chunks)/5);
-
- /* Ignore the tRNS chunk if we only want opaque output */
- if (outputFormat == HAL_PIXEL_FORMAT_RGB_888 ||
- outputFormat == HAL_PIXEL_FORMAT_RGB_565) {
- png_set_keep_unknown_chunks(pngread, 1, tRNS_chunk, 1);
- }
-#endif
-
- png_read_info(pngread, pnginfo);
-
- png_color_16p colorp;
- has_bgcolor = (PNG_INFO_bKGD == png_get_bKGD(pngread, pnginfo, &colorp));
- bgcolor = has_bgcolor ? *colorp : png_color_16();
- width = png_get_image_width(pngread, pnginfo);
- height = png_get_image_height(pngread, pnginfo);
-
- LOG("Decoded %s: %d x %d frame with bgcolor? %s (%#x, %#x, %#x; gray:%#x)",
- path, width, height, has_bgcolor ? "yes" : "no",
- bgcolor.red, bgcolor.green, bgcolor.blue, bgcolor.gray);
-
- bytepp = GetFormatBPP(outputFormat);
-
- switch (outputFormat) {
- case HAL_PIXEL_FORMAT_BGRA_8888:
- png_set_bgr(pngread);
- // FALL THROUGH
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGBX_8888:
- png_set_filler(pngread, 0xFF, PNG_FILLER_AFTER);
- break;
- case HAL_PIXEL_FORMAT_RGB_888:
- png_set_strip_alpha(pngread);
- break;
- default:
- LOGW("Unknown pixel format %d. Assuming RGB 565.", outputFormat);
- // FALL THROUGH
- case HAL_PIXEL_FORMAT_RGB_565:
- png_set_strip_alpha(pngread);
- png_set_read_user_transform_fn(pngread, TransformTo565);
- break;
- }
-
- // An extra row is added to give libpng enough space when
- // decoding 3/4 bytepp inputs for 2 bytepp output surfaces
- buf = (char *)malloc(width * (height + 1) * bytepp);
-
- vector<char *> rows(height + 1);
- uint32_t stride = width * bytepp;
- for (uint32_t i = 0; i < height; i++) {
- rows[i] = buf + (stride * i);
- }
- rows[height] = nullptr;
- png_set_strip_16(pngread);
- png_set_palette_to_rgb(pngread);
- png_set_gray_to_rgb(pngread);
- png_read_image(pngread, (png_bytepp)&rows.front());
- png_destroy_read_struct(&pngread, &pnginfo, nullptr);
-}
-
-/**
- * Return a wchar_t that when used to |wmemset()| an image buffer will
- * fill it with the color defined by |color16|. The packed wchar_t
- * may comprise one or two pixels depending on |outputFormat|.
- */
-static wchar_t
-AsBackgroundFill(const png_color_16& color16, int outputFormat)
-{
- static_assert(sizeof(wchar_t) == sizeof(uint32_t),
- "TODO: support 2-byte wchar_t");
- union {
- uint32_t r8g8b8;
- struct {
- uint8_t b8;
- uint8_t g8;
- uint8_t r8;
- uint8_t x8;
- };
- } color;
- color.b8 = color16.blue;
- color.g8 = color16.green;
- color.r8 = color16.red;
- color.x8 = 0xFF;
-
- switch (outputFormat) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGBX_8888:
- return color.r8g8b8;
-
- case HAL_PIXEL_FORMAT_BGRA_8888:
- swap(color.r8, color.b8);
- return color.r8g8b8;
-
- case HAL_PIXEL_FORMAT_RGB_565: {
- // NB: we could do a higher-quality downsample here, but we
- // want the results to be a pixel-perfect match with the fast
- // downsample in TransformTo565().
- uint16_t color565 = ((color.r8 & 0xF8) << 8) |
- ((color.g8 & 0xFC) << 3) |
- ((color.b8 ) >> 3);
- return (color565 << 16) | color565;
- }
- default:
- LOGW("Unhandled pixel format %d; falling back on black", outputFormat);
- return 0;
- }
-}
-
-void
-ShowSolidColorFrame(GonkDisplay *aDisplay,
- const gralloc_module_t *grallocModule,
- int32_t aFormat)
-{
- LOGW("Show solid color frame for bootAnim");
-
- ANativeWindowBuffer *buffer = aDisplay->DequeueBuffer();
- void *mappedAddress = nullptr;
-
- if (!buffer) {
- LOGW("Failed to get an ANativeWindowBuffer");
- return;
- }
-
- if (!grallocModule->lock(grallocModule, buffer->handle,
- GRALLOC_USAGE_SW_READ_NEVER |
- GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_FB,
- 0, 0, buffer->width, buffer->height, &mappedAddress)) {
- // Just show a black solid color frame.
- memset(mappedAddress, 0, buffer->height * buffer->stride * GetFormatBPP(aFormat));
- grallocModule->unlock(grallocModule, buffer->handle);
- }
-
- aDisplay->QueueBuffer(buffer);
-}
-
-static void *
-AnimationThread(void *)
-{
- GonkDisplay *display = GetGonkDisplay();
- int32_t format = display->surfaceformat;
-
- const hw_module_t *module = nullptr;
- if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)) {
- LOGW("Could not get gralloc module");
- return nullptr;
- }
- const gralloc_module_t *grmodule =
- reinterpret_cast<gralloc_module_t const*>(module);
-
- ZipReader reader;
- if (!reader.OpenArchive("/system/media/bootanimation.zip")) {
- LOGW("Could not open boot animation");
- ShowSolidColorFrame(display, grmodule, format);
- return nullptr;
- }
-
- const cdir_entry *entry = nullptr;
- const local_file_header *file = nullptr;
- while ((entry = reader.GetNextEntry(entry))) {
- string name = reader.GetEntryName(entry);
- if (!name.compare("desc.txt")) {
- file = reader.GetLocalEntry(entry);
- break;
- }
- }
-
- if (!file) {
- LOGW("Could not find desc.txt in boot animation");
- ShowSolidColorFrame(display, grmodule, format);
- return nullptr;
- }
-
- string descCopy;
- descCopy.append(file->GetData(), entry->GetDataSize());
- int32_t width, height, fps;
- const char *line = descCopy.c_str();
- const char *end;
- bool headerRead = true;
- vector<AnimationPart> parts;
- bool animPlayed = false;
-
- /*
- * bootanimation.zip
- *
- * This is the boot animation file format that Android uses.
- * It's a zip file with a directories containing png frames
- * and a desc.txt that describes how they should be played.
- *
- * desc.txt contains two types of lines
- * 1. [width] [height] [fps]
- * There is one of these lines per bootanimation.
- * If the width and height are smaller than the screen,
- * the frames are centered on a black background.
- * XXX: Currently we stretch instead of centering the frame.
- * 2. p [count] [pause] [path]
- * This describes one animation part.
- * Each animation part is played in sequence.
- * An animation part contains all the files/frames in the
- * directory specified in [path]
- * [count] indicates the number of times this part repeats.
- * [pause] indicates the number of frames that this part
- * should pause for after playing the full sequence but
- * before repeating.
- */
-
- do {
- end = strstr(line, "\n");
-
- AnimationPart part;
- if (headerRead &&
- sscanf(line, "%d %d %d", &width, &height, &fps) == 3) {
- headerRead = false;
- } else if (part.ReadFromString(line)) {
- parts.push_back(part);
- }
- } while (end && *(line = end + 1));
-
- for (uint32_t i = 0; i < parts.size(); i++) {
- AnimationPart &part = parts[i];
- entry = nullptr;
- char search[256];
- snprintf(search, sizeof(search), "%s/", part.path);
- while ((entry = reader.GetNextEntry(entry))) {
- string name = reader.GetEntryName(entry);
- if (name.find(search) ||
- !entry->GetDataSize() ||
- name.length() >= 256)
- continue;
-
- part.frames.resize(part.frames.size() + 1);
- AnimationFrame &frame = part.frames.back();
- strcpy(frame.path, name.c_str());
- frame.file = reader.GetLocalEntry(entry);
- }
-
- sort(part.frames.begin(), part.frames.end());
- }
-
- long int frameDelayUs = 1000000 / fps;
-
- for (uint32_t i = 0; i < parts.size(); i++) {
- AnimationPart &part = parts[i];
-
- int32_t j = 0;
- while (sRunAnimation && (!part.count || j++ < part.count)) {
- for (uint32_t k = 0; k < part.frames.size(); k++) {
- struct timeval tv1, tv2;
- gettimeofday(&tv1, nullptr);
- AnimationFrame &frame = part.frames[k];
- if (!frame.buf) {
- frame.ReadPngFrame(format);
- }
-
- ANativeWindowBuffer *buf = display->DequeueBuffer();
- if (!buf) {
- LOGW("Failed to get an ANativeWindowBuffer");
- break;
- }
-
- void *vaddr;
- if (grmodule->lock(grmodule, buf->handle,
- GRALLOC_USAGE_SW_READ_NEVER |
- GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_FB,
- 0, 0, width, height, &vaddr)) {
- LOGW("Failed to lock buffer_handle_t");
- display->QueueBuffer(buf);
- break;
- }
-
- if (frame.has_bgcolor) {
- wchar_t bgfill = AsBackgroundFill(frame.bgcolor, format);
- wmemset((wchar_t*)vaddr, bgfill,
- (buf->height * buf->stride * frame.bytepp) / sizeof(wchar_t));
- }
-
- if ((uint32_t)buf->height == frame.height && (uint32_t)buf->stride == frame.width) {
- memcpy(vaddr, frame.buf,
- frame.width * frame.height * frame.bytepp);
- } else if ((uint32_t)buf->height >= frame.height &&
- (uint32_t)buf->width >= frame.width) {
- int startx = (buf->width - frame.width) / 2;
- int starty = (buf->height - frame.height) / 2;
-
- int src_stride = frame.width * frame.bytepp;
- int dst_stride = buf->stride * frame.bytepp;
-
- char *src = frame.buf;
- char *dst = (char *) vaddr + starty * dst_stride + startx * frame.bytepp;
-
- for (uint32_t i = 0; i < frame.height; i++) {
- memcpy(dst, src, src_stride);
- src += src_stride;
- dst += dst_stride;
- }
- }
- grmodule->unlock(grmodule, buf->handle);
-
- gettimeofday(&tv2, nullptr);
-
- timersub(&tv2, &tv1, &tv2);
-
- if (tv2.tv_usec < frameDelayUs) {
- usleep(frameDelayUs - tv2.tv_usec);
- } else {
- LOGW("Frame delay is %ld us but decoding took %ld us",
- frameDelayUs, tv2.tv_usec);
- }
-
- animPlayed = true;
- display->QueueBuffer(buf);
-
- if (part.count && j >= part.count) {
- free(frame.buf);
- frame.buf = nullptr;
- }
- }
- usleep(frameDelayUs * part.pause);
- }
- }
-
- if (!animPlayed) {
- ShowSolidColorFrame(display, grmodule, format);
- }
-
- return nullptr;
-}
-
-namespace mozilla {
-
-__attribute__ ((visibility ("default")))
-void
-StartBootAnimation()
-{
- GetGonkDisplay(); // Ensure GonkDisplay exist
- sRunAnimation = true;
- pthread_create(&sAnimationThread, nullptr, AnimationThread, nullptr);
-}
-
-__attribute__ ((visibility ("default")))
-void
-StopBootAnimation()
-{
- if (sRunAnimation) {
- sRunAnimation = false;
- pthread_join(sAnimationThread, nullptr);
- GetGonkDisplay()->NotifyBootAnimationStopped();
- }
-}
-
-} // namespace mozilla
diff --git a/widget/gonk/libdisplay/BootAnimation.h b/widget/gonk/libdisplay/BootAnimation.h
deleted file mode 100644
index 9fdc20eca..000000000
--- a/widget/gonk/libdisplay/BootAnimation.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 BOOTANIMATION_H
-#define BOOTANIMATION_H
-
-namespace mozilla {
-
-MOZ_EXPORT __attribute__ ((weak))
-void StartBootAnimation();
-
-/* Stop the boot animation if it's still running. */
-MOZ_EXPORT __attribute__ ((weak))
-void StopBootAnimation();
-
-} // namespace mozilla
-
-#endif /* BOOTANIMATION_H */
diff --git a/widget/gonk/libdisplay/DisplaySurface.h b/widget/gonk/libdisplay/DisplaySurface.h
deleted file mode 100644
index 398541c49..000000000
--- a/widget/gonk/libdisplay/DisplaySurface.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SF_DISPLAY_SURFACE_H
-#define ANDROID_SF_DISPLAY_SURFACE_H
-
-#include <gui/ConsumerBase.h>
-#include <system/window.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/StrongPointer.h>
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class IGraphicBufferProducer;
-class String8;
-
-#if ANDROID_VERSION >= 21
-typedef IGraphicBufferConsumer StreamConsumer;
-#else
-typedef BufferQueue StreamConsumer;
-#endif
-
-class DisplaySurface : public ConsumerBase {
-public:
- // beginFrame is called at the beginning of the composition loop, before
- // the configuration is known. The DisplaySurface should do anything it
- // needs to do to enable HWComposer to decide how to compose the frame.
- // We pass in mustRecompose so we can keep VirtualDisplaySurface's state
- // machine happy without actually queueing a buffer if nothing has changed.
- virtual status_t beginFrame(bool mustRecompose) = 0;
-
- // prepareFrame is called after the composition configuration is known but
- // before composition takes place. The DisplaySurface can use the
- // composition type to decide how to manage the flow of buffers between
- // GLES and HWC for this frame.
- enum CompositionType {
- COMPOSITION_UNKNOWN = 0,
- COMPOSITION_GLES = 1,
- COMPOSITION_HWC = 2,
- COMPOSITION_MIXED = COMPOSITION_GLES | COMPOSITION_HWC
- };
- virtual status_t prepareFrame(CompositionType compositionType) = 0;
-
- // Should be called when composition rendering is complete for a frame (but
- // eglSwapBuffers hasn't necessarily been called). Required by certain
- // older drivers for synchronization.
- // TODO: Remove this when we drop support for HWC 1.0.
- virtual status_t compositionComplete() = 0;
-
- // Inform the surface that GLES composition is complete for this frame, and
- // the surface should make sure that HWComposer has the correct buffer for
- // this frame. Some implementations may only push a new buffer to
- // HWComposer if GLES composition took place, others need to push a new
- // buffer on every frame.
- //
- // advanceFrame must be followed by a call to onFrameCommitted before
- // advanceFrame may be called again.
- virtual status_t advanceFrame() = 0;
-
- // onFrameCommitted is called after the frame has been committed to the
- // hardware composer. The surface collects the release fence for this
- // frame's buffer.
- virtual void onFrameCommitted() = 0;
-
- virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
-
- // setReleaseFenceFd stores a fence file descriptor that will signal when the
- // current buffer is no longer being read. This fence will be returned to
- // the producer when the current buffer is released by updateTexImage().
- // Multiple fences can be set for a given buffer; they will be merged into
- // a single union fence. The SurfaceTexture will close the file descriptor
- // when finished with it.
- virtual status_t setReleaseFenceFd(int fenceFd) = 0;
-
- virtual int GetPrevDispAcquireFd() = 0;
-
- buffer_handle_t lastHandle;
-
-protected:
- DisplaySurface(const sp<StreamConsumer>& sc)
-#if ANDROID_VERSION >= 19
- : ConsumerBase(sc, true)
-#else
- : ConsumerBase(sc)
-#endif
- , lastHandle(0)
- { }
- virtual ~DisplaySurface() {}
-};
-
-// ---------------------------------------------------------------------------
-} // namespace android
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_SF_DISPLAY_SURFACE_H
-
diff --git a/widget/gonk/libdisplay/FramebufferSurface.cpp b/widget/gonk/libdisplay/FramebufferSurface.cpp
deleted file mode 100644
index a289acbb8..000000000
--- a/widget/gonk/libdisplay/FramebufferSurface.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- **
- ** Copyright 2012 The Android Open Source Project
- **
- ** Licensed under the Apache License Version 2.0(the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing software
- ** distributed under the License is distributed on an "AS IS" BASIS
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#include <cutils/log.h>
-
-#include <utils/String8.h>
-
-#include <ui/Rect.h>
-
-#include <EGL/egl.h>
-
-#include <hardware/hardware.h>
-#if ANDROID_VERSION == 17
-#include <gui/SurfaceTextureClient.h>
-#endif
-#include <ui/GraphicBuffer.h>
-
-#include "FramebufferSurface.h"
-#include "GraphicBufferAlloc.h"
-
-#ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS
-#define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2)
-#endif
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-/*
- * This implements the (main) framebuffer management. This class
- * was adapted from the version in SurfaceFlinger
- */
-FramebufferSurface::FramebufferSurface(int disp,
- uint32_t width,
- uint32_t height,
- uint32_t format,
- const sp<StreamConsumer>& sc)
- : DisplaySurface(sc)
- , mDisplayType(disp)
- , mCurrentBufferSlot(-1)
- , mCurrentBuffer(0)
-{
- mName = "FramebufferSurface";
-
-#if ANDROID_VERSION >= 19
- sp<IGraphicBufferConsumer> consumer = mConsumer;
-#else
- sp<BufferQueue> consumer = mBufferQueue;
- consumer->setSynchronousMode(true);
-#endif
- consumer->setConsumerName(mName);
- consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_COMPOSER);
- consumer->setDefaultBufferFormat(format);
- consumer->setDefaultBufferSize(width, height);
- consumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
-}
-
-status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
- return NO_ERROR;
-}
-
-status_t FramebufferSurface::prepareFrame(CompositionType /*compositionType*/) {
- return NO_ERROR;
-}
-
-status_t FramebufferSurface::advanceFrame() {
- // Once we remove FB HAL support, we can call nextBuffer() from here
- // instead of using onFrameAvailable(). No real benefit, except it'll be
- // more like VirtualDisplaySurface.
- return NO_ERROR;
-}
-
-status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
- Mutex::Autolock lock(mMutex);
-
- BufferQueue::BufferItem item;
-#if ANDROID_VERSION >= 19
- status_t err = acquireBufferLocked(&item, 0);
-#else
- status_t err = acquireBufferLocked(&item);
-#endif
- if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- outBuffer = mCurrentBuffer;
- return NO_ERROR;
- } else if (err != NO_ERROR) {
- ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
- return err;
- }
-
- // If the BufferQueue has freed and reallocated a buffer in mCurrentSlot
- // then we may have acquired the slot we already own. If we had released
- // our current buffer before we call acquireBuffer then that release call
- // would have returned STALE_BUFFER_SLOT, and we would have called
- // freeBufferLocked on that slot. Because the buffer slot has already
- // been overwritten with the new buffer all we have to do is skip the
- // releaseBuffer call and we should be in the same state we'd be in if we
- // had released the old buffer first.
- if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
- item.mBuf != mCurrentBufferSlot) {
- // Release the previous buffer.
-#if ANDROID_VERSION >= 19
- err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
-#else
- err = releaseBufferLocked(mCurrentBufferSlot, EGL_NO_DISPLAY,
- EGL_NO_SYNC_KHR);
-#endif
- if (err != NO_ERROR && err != StreamConsumer::STALE_BUFFER_SLOT) {
- ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
- return err;
- }
- }
- mCurrentBufferSlot = item.mBuf;
- mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
- outFence = item.mFence;
- outBuffer = mCurrentBuffer;
- return NO_ERROR;
-}
-
-// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
-#if ANDROID_VERSION >= 22
-void FramebufferSurface::onFrameAvailable(const ::android::BufferItem &item) {
-#else
-void FramebufferSurface::onFrameAvailable() {
-#endif
- sp<GraphicBuffer> buf;
- sp<Fence> acquireFence;
- status_t err = nextBuffer(buf, acquireFence);
- if (err != NO_ERROR) {
- ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
- strerror(-err), err);
- return;
- }
- if (acquireFence.get() && acquireFence->isValid())
- mPrevFBAcquireFence = new Fence(acquireFence->dup());
- else
- mPrevFBAcquireFence = Fence::NO_FENCE;
-
- lastHandle = buf->handle;
-}
-
-void FramebufferSurface::freeBufferLocked(int slotIndex) {
- ConsumerBase::freeBufferLocked(slotIndex);
- if (slotIndex == mCurrentBufferSlot) {
- mCurrentBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
- }
-}
-
-status_t FramebufferSurface::setReleaseFenceFd(int fenceFd) {
- status_t err = NO_ERROR;
- if (fenceFd >= 0) {
- sp<Fence> fence(new Fence(fenceFd));
- if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
-#if ANDROID_VERSION >= 19
- status_t err = addReleaseFence(mCurrentBufferSlot, mCurrentBuffer, fence);
-#else
- status_t err = addReleaseFence(mCurrentBufferSlot, fence);
-#endif
- ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
- strerror(-err), err);
- }
- }
- return err;
-}
-
-int FramebufferSurface::GetPrevDispAcquireFd() {
- if (mPrevFBAcquireFence.get() && mPrevFBAcquireFence->isValid()) {
- return mPrevFBAcquireFence->dup();
- }
- return -1;
-}
-
-void FramebufferSurface::onFrameCommitted() {
- // XXX This role is almost same to setReleaseFenceFd().
-}
-
-status_t FramebufferSurface::compositionComplete()
-{
- // Actual implementaiton is in GonkDisplay::SwapBuffers()
- // XXX need to move that to here.
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/widget/gonk/libdisplay/FramebufferSurface.h b/widget/gonk/libdisplay/FramebufferSurface.h
deleted file mode 100644
index c1cc84272..000000000
--- a/widget/gonk/libdisplay/FramebufferSurface.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef ANDROID_SF_FRAMEBUFFER_SURFACE_H
-#define ANDROID_SF_FRAMEBUFFER_SURFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "DisplaySurface.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class Rect;
-class String8;
-
-// ---------------------------------------------------------------------------
-
-class FramebufferSurface : public DisplaySurface {
-public:
- FramebufferSurface(int disp, uint32_t width, uint32_t height, uint32_t format, const sp<StreamConsumer>& sc);
-
- // From DisplaySurface
- virtual status_t beginFrame(bool mustRecompose);
- virtual status_t prepareFrame(CompositionType compositionType);
- virtual status_t compositionComplete();
- virtual status_t advanceFrame();
- virtual void onFrameCommitted();
- // Cannot resize a buffers in a FramebufferSurface. Only works with virtual
- // displays.
- virtual void resizeBuffers(const uint32_t /*w*/, const uint32_t /*h*/) { };
-
- // setReleaseFenceFd stores a fence file descriptor that will signal when the
- // current buffer is no longer being read. This fence will be returned to
- // the producer when the current buffer is released by updateTexImage().
- // Multiple fences can be set for a given buffer; they will be merged into
- // a single union fence. The SurfaceTexture will close the file descriptor
- // when finished with it.
- status_t setReleaseFenceFd(int fenceFd);
-
- virtual int GetPrevDispAcquireFd();
-
-private:
- virtual ~FramebufferSurface() { }; // this class cannot be overloaded
-
-#if ANDROID_VERSION >= 22
- virtual void onFrameAvailable(const ::android::BufferItem &item);
-#else
- virtual void onFrameAvailable();
-#endif
- virtual void freeBufferLocked(int slotIndex);
-
- // nextBuffer waits for and then latches the next buffer from the
- // BufferQueue and releases the previously latched buffer to the
- // BufferQueue. The new buffer is returned in the 'buffer' argument.
- status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence);
-
- // mDisplayType must match one of the HWC display types
- int mDisplayType;
-
- // mCurrentBufferIndex is the slot index of the current buffer or
- // INVALID_BUFFER_SLOT to indicate that either there is no current buffer
- // or the buffer is not associated with a slot.
- int mCurrentBufferSlot;
-
- // mCurrentBuffer is the current buffer or NULL to indicate that there is
- // no current buffer.
- sp<GraphicBuffer> mCurrentBuffer;
-
- android::sp<android::Fence> mPrevFBAcquireFence;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_SF_FRAMEBUFFER_SURFACE_H
-
diff --git a/widget/gonk/libdisplay/GonkDisplay.h b/widget/gonk/libdisplay/GonkDisplay.h
deleted file mode 100644
index 96978a6e9..000000000
--- a/widget/gonk/libdisplay/GonkDisplay.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Copyright 2013 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 GONKDISPLAY_H
-#define GONKDISPLAY_H
-
-#include <system/window.h>
-#include <utils/StrongPointer.h>
-#include "mozilla/Types.h"
-
-namespace android {
-class DisplaySurface;
-class IGraphicBufferProducer;
-}
-
-namespace mozilla {
-
-typedef void * EGLDisplay;
-typedef void * EGLSurface;
-
-class MOZ_EXPORT GonkDisplay {
-public:
- /**
- * This enum is for types of display. DISPLAY_PRIMARY refers to the default
- * built-in display, DISPLAY_EXTERNAL refers to displays connected with
- * HDMI, and DISPLAY_VIRTUAL are displays which makes composited output
- * available within the system. Currently, displays of external are detected
- * via the hotplug detection in HWC, and displays of virtual are connected
- * via Wifi Display.
- */
- enum DisplayType {
- DISPLAY_PRIMARY,
- DISPLAY_EXTERNAL,
- DISPLAY_VIRTUAL,
- NUM_DISPLAY_TYPES
- };
-
- struct NativeData {
- android::sp<ANativeWindow> mNativeWindow;
-#if ANDROID_VERSION >= 17
- android::sp<android::DisplaySurface> mDisplaySurface;
-#endif
- float mXdpi;
- };
-
- virtual void SetEnabled(bool enabled) = 0;
-
- typedef void (*OnEnabledCallbackType)(bool enabled);
-
- virtual void OnEnabled(OnEnabledCallbackType callback) = 0;
-
- virtual void* GetHWCDevice() = 0;
-
- /**
- * Only GonkDisplayICS uses arguments.
- */
- virtual bool SwapBuffers(EGLDisplay dpy, EGLSurface sur) = 0;
-
- virtual ANativeWindowBuffer* DequeueBuffer() = 0;
-
- virtual bool QueueBuffer(ANativeWindowBuffer* buf) = 0;
-
- virtual void UpdateDispSurface(EGLDisplay dpy, EGLSurface sur) = 0;
-
- virtual NativeData GetNativeData(
- GonkDisplay::DisplayType aDisplayType,
- android::IGraphicBufferProducer* aSink = nullptr) = 0;
-
- virtual void NotifyBootAnimationStopped() = 0;
-
- float xdpi;
- int32_t surfaceformat;
-};
-
-MOZ_EXPORT __attribute__ ((weak))
-GonkDisplay* GetGonkDisplay();
-
-}
-#endif /* GONKDISPLAY_H */
diff --git a/widget/gonk/libdisplay/GonkDisplayJB.cpp b/widget/gonk/libdisplay/GonkDisplayJB.cpp
deleted file mode 100644
index 197b85a47..000000000
--- a/widget/gonk/libdisplay/GonkDisplayJB.cpp
+++ /dev/null
@@ -1,461 +0,0 @@
-/* Copyright 2013 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "GonkDisplayJB.h"
-#if ANDROID_VERSION == 17
-#include <gui/SurfaceTextureClient.h>
-#else
-#include <gui/Surface.h>
-#include <gui/GraphicBufferAlloc.h>
-#endif
-
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
-#include <hardware/power.h>
-#include <suspend/autosuspend.h>
-
-#if ANDROID_VERSION >= 19
-#include "VirtualDisplaySurface.h"
-#endif
-#include "FramebufferSurface.h"
-#if ANDROID_VERSION == 17
-#include "GraphicBufferAlloc.h"
-#endif
-#include "mozilla/Assertions.h"
-
-#define DEFAULT_XDPI 75.0
-
-using namespace android;
-
-namespace mozilla {
-
-static GonkDisplayJB* sGonkDisplay = nullptr;
-
-GonkDisplayJB::GonkDisplayJB()
- : mModule(nullptr)
- , mFBModule(nullptr)
- , mHwc(nullptr)
- , mFBDevice(nullptr)
- , mPowerModule(nullptr)
- , mList(nullptr)
- , mWidth(0)
- , mHeight(0)
- , mEnabledCallback(nullptr)
-{
- int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mFBModule);
- ALOGW_IF(err, "%s module not found", GRALLOC_HARDWARE_MODULE_ID);
- if (!err) {
- err = framebuffer_open(mFBModule, &mFBDevice);
- ALOGW_IF(err, "could not open framebuffer");
- }
-
- if (!err && mFBDevice) {
- mWidth = mFBDevice->width;
- mHeight = mFBDevice->height;
- xdpi = mFBDevice->xdpi;
- /* The emulator actually reports RGBA_8888, but EGL doesn't return
- * any matching configuration. We force RGBX here to fix it. */
- surfaceformat = HAL_PIXEL_FORMAT_RGBX_8888;
- }
-
- err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
- ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
- if (!err) {
- err = hwc_open_1(mModule, &mHwc);
- ALOGE_IF(err, "%s device failed to initialize (%s)",
- HWC_HARDWARE_COMPOSER, strerror(-err));
- }
-
- /* Fallback on the FB rendering path instead of trying to support HWC 1.0 */
- if (!err && mHwc->common.version == HWC_DEVICE_API_VERSION_1_0) {
- hwc_close_1(mHwc);
- mHwc = nullptr;
- }
-
- if (!err && mHwc) {
- if (mFBDevice) {
- framebuffer_close(mFBDevice);
- mFBDevice = nullptr;
- }
-
- int32_t values[3];
- const uint32_t attrs[] = {
- HWC_DISPLAY_WIDTH,
- HWC_DISPLAY_HEIGHT,
- HWC_DISPLAY_DPI_X,
- HWC_DISPLAY_NO_ATTRIBUTE
- };
- mHwc->getDisplayAttributes(mHwc, 0, 0, attrs, values);
-
- mWidth = values[0];
- mHeight = values[1];
- xdpi = values[2] / 1000.0f;
- surfaceformat = HAL_PIXEL_FORMAT_RGBA_8888;
- }
-
- err = hw_get_module(POWER_HARDWARE_MODULE_ID,
- (hw_module_t const**)&mPowerModule);
- if (!err)
- mPowerModule->init(mPowerModule);
- ALOGW_IF(err, "Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
-
- mAlloc = new GraphicBufferAlloc();
-
- CreateFramebufferSurface(mSTClient, mDispSurface, mWidth, mHeight);
-
- mList = (hwc_display_contents_1_t *)calloc(1, sizeof(*mList) + (sizeof(hwc_layer_1_t)*2));
-
- uint32_t usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER;
- if (mFBDevice) {
- // If device uses fb, they can not use single buffer for boot animation
- mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_BUFFER_COUNT, 2);
- mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_USAGE, usage);
- } else if (mHwc) {
- PowerOnDisplay(HWC_DISPLAY_PRIMARY);
- // For devices w/ hwc v1.0 or no hwc, this buffer can not be created,
- // only create this buffer for devices w/ hwc version > 1.0.
- CreateFramebufferSurface(mBootAnimSTClient, mBootAnimDispSurface, mWidth, mHeight);
- }
-}
-
-GonkDisplayJB::~GonkDisplayJB()
-{
- if (mHwc)
- hwc_close_1(mHwc);
- if (mFBDevice)
- framebuffer_close(mFBDevice);
- free(mList);
-}
-
-void
-GonkDisplayJB::CreateFramebufferSurface(android::sp<ANativeWindow>& aNativeWindow,
- android::sp<android::DisplaySurface>& aDisplaySurface,
- uint32_t aWidth,
- uint32_t aHeight)
-{
-#if ANDROID_VERSION >= 21
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer, mAlloc);
-#elif ANDROID_VERSION >= 19
- sp<BufferQueue> consumer = new BufferQueue(mAlloc);
- sp<IGraphicBufferProducer> producer = consumer;
-#elif ANDROID_VERSION >= 18
- sp<BufferQueue> consumer = new BufferQueue(true, mAlloc);
- sp<IGraphicBufferProducer> producer = consumer;
-#else
- sp<BufferQueue> consumer = new BufferQueue(true, mAlloc);
-#endif
-
- aDisplaySurface = new FramebufferSurface(0, aWidth, aHeight, surfaceformat, consumer);
-
-#if ANDROID_VERSION == 17
- aNativeWindow = new SurfaceTextureClient(
- static_cast<sp<ISurfaceTexture>>(aDisplaySurface->getBufferQueue()));
-#else
- aNativeWindow = new Surface(producer);
-#endif
-}
-
-void
-GonkDisplayJB::CreateVirtualDisplaySurface(android::IGraphicBufferProducer* aSink,
- android::sp<ANativeWindow>& aNativeWindow,
- android::sp<android::DisplaySurface>& aDisplaySurface)
-{
-#if ANDROID_VERSION >= 21
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer, mAlloc);
-#elif ANDROID_VERSION >= 19
- sp<BufferQueue> consumer = new BufferQueue(mAlloc);
- sp<IGraphicBufferProducer> producer = consumer;
-#endif
-
-#if ANDROID_VERSION >= 19
- sp<VirtualDisplaySurface> virtualDisplay;
- virtualDisplay = new VirtualDisplaySurface(-1, aSink, producer, consumer, String8("VirtualDisplaySurface"));
- aDisplaySurface = virtualDisplay;
- aNativeWindow = new Surface(virtualDisplay);
-#endif
-}
-
-void
-GonkDisplayJB::SetEnabled(bool enabled)
-{
- if (enabled) {
- autosuspend_disable();
- mPowerModule->setInteractive(mPowerModule, true);
- }
-
- if (!enabled && mEnabledCallback) {
- mEnabledCallback(enabled);
- }
-
-#if ANDROID_VERSION >= 21
- if (mHwc) {
- if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_4) {
- mHwc->setPowerMode(mHwc, HWC_DISPLAY_PRIMARY,
- (enabled ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF));
- } else {
- mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, !enabled);
- }
- } else if (mFBDevice && mFBDevice->enableScreen) {
- mFBDevice->enableScreen(mFBDevice, enabled);
- }
-#else
- if (mHwc && mHwc->blank) {
- mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, !enabled);
- } else if (mFBDevice && mFBDevice->enableScreen) {
- mFBDevice->enableScreen(mFBDevice, enabled);
- }
-#endif
-
- if (enabled && mEnabledCallback) {
- mEnabledCallback(enabled);
- }
-
- if (!enabled) {
- autosuspend_enable();
- mPowerModule->setInteractive(mPowerModule, false);
- }
-}
-
-void
-GonkDisplayJB::OnEnabled(OnEnabledCallbackType callback)
-{
- mEnabledCallback = callback;
-}
-
-void*
-GonkDisplayJB::GetHWCDevice()
-{
- return mHwc;
-}
-
-bool
-GonkDisplayJB::SwapBuffers(EGLDisplay dpy, EGLSurface sur)
-{
- // Should be called when composition rendering is complete for a frame.
- // Only HWC v1.0 needs this call.
- // HWC > v1.0 case, do not call compositionComplete().
- // mFBDevice is present only when HWC is v1.0.
- if (mFBDevice && mFBDevice->compositionComplete) {
- mFBDevice->compositionComplete(mFBDevice);
- }
- return Post(mDispSurface->lastHandle, mDispSurface->GetPrevDispAcquireFd());
-}
-
-bool
-GonkDisplayJB::Post(buffer_handle_t buf, int fence)
-{
- if (!mHwc) {
- if (fence >= 0)
- close(fence);
- return !mFBDevice->post(mFBDevice, buf);
- }
-
- hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = {NULL};
- const hwc_rect_t r = { 0, 0, static_cast<int>(mWidth), static_cast<int>(mHeight) };
- displays[HWC_DISPLAY_PRIMARY] = mList;
- mList->retireFenceFd = -1;
- mList->numHwLayers = 2;
- mList->flags = HWC_GEOMETRY_CHANGED;
-#if ANDROID_VERSION >= 18
- mList->outbuf = nullptr;
- mList->outbufAcquireFenceFd = -1;
-#endif
- mList->hwLayers[0].compositionType = HWC_FRAMEBUFFER;
- mList->hwLayers[0].hints = 0;
- /* Skip this layer so the hwc module doesn't complain about null handles */
- mList->hwLayers[0].flags = HWC_SKIP_LAYER;
- mList->hwLayers[0].backgroundColor = {0};
- mList->hwLayers[0].acquireFenceFd = -1;
- mList->hwLayers[0].releaseFenceFd = -1;
- /* hwc module checks displayFrame even though it shouldn't */
- mList->hwLayers[0].displayFrame = r;
- mList->hwLayers[1].compositionType = HWC_FRAMEBUFFER_TARGET;
- mList->hwLayers[1].hints = 0;
- mList->hwLayers[1].flags = 0;
- mList->hwLayers[1].handle = buf;
- mList->hwLayers[1].transform = 0;
- mList->hwLayers[1].blending = HWC_BLENDING_NONE;
-#if ANDROID_VERSION >= 19
- if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_3) {
- mList->hwLayers[1].sourceCropf.left = 0;
- mList->hwLayers[1].sourceCropf.top = 0;
- mList->hwLayers[1].sourceCropf.right = mWidth;
- mList->hwLayers[1].sourceCropf.bottom = mHeight;
- } else {
- mList->hwLayers[1].sourceCrop = r;
- }
-#else
- mList->hwLayers[1].sourceCrop = r;
-#endif
- mList->hwLayers[1].displayFrame = r;
- mList->hwLayers[1].visibleRegionScreen.numRects = 1;
- mList->hwLayers[1].visibleRegionScreen.rects = &mList->hwLayers[1].displayFrame;
- mList->hwLayers[1].acquireFenceFd = fence;
- mList->hwLayers[1].releaseFenceFd = -1;
-#if ANDROID_VERSION >= 18
- mList->hwLayers[1].planeAlpha = 0xFF;
-#endif
- mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
- int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
-
- if (!mBootAnimDispSurface.get()) {
- mDispSurface->setReleaseFenceFd(mList->hwLayers[1].releaseFenceFd);
- } else {
- mBootAnimDispSurface->setReleaseFenceFd(mList->hwLayers[1].releaseFenceFd);
- }
-
- if (mList->retireFenceFd >= 0)
- close(mList->retireFenceFd);
- return !err;
-}
-
-ANativeWindowBuffer*
-GonkDisplayJB::DequeueBuffer()
-{
- // Check for bootAnim or normal display flow.
- sp<ANativeWindow> nativeWindow =
- !mBootAnimSTClient.get() ? mSTClient : mBootAnimSTClient;
-
- ANativeWindowBuffer *buf;
- int fenceFd = -1;
- nativeWindow->dequeueBuffer(nativeWindow.get(), &buf, &fenceFd);
- sp<Fence> fence(new Fence(fenceFd));
-#if ANDROID_VERSION == 17
- fence->waitForever(1000, "GonkDisplayJB_DequeueBuffer");
- // 1000 is what Android uses. It is a warning timeout in ms.
- // This timeout was removed in ANDROID_VERSION 18.
-#else
- fence->waitForever("GonkDisplayJB_DequeueBuffer");
-#endif
- return buf;
-}
-
-bool
-GonkDisplayJB::QueueBuffer(ANativeWindowBuffer* buf)
-{
- bool success = false;
- int error = DoQueueBuffer(buf);
- // Check for bootAnim or normal display flow.
- if (!mBootAnimSTClient.get()) {
- success = Post(mDispSurface->lastHandle, mDispSurface->GetPrevDispAcquireFd());
- } else {
- success = Post(mBootAnimDispSurface->lastHandle, mBootAnimDispSurface->GetPrevDispAcquireFd());
- }
- return error == 0 && success;
-}
-
-int
-GonkDisplayJB::DoQueueBuffer(ANativeWindowBuffer* buf)
-{
- int error = 0;
- // Check for bootAnim or normal display flow.
- if (!mBootAnimSTClient.get()) {
- error = mSTClient->queueBuffer(mSTClient.get(), buf, -1);
- } else {
- error = mBootAnimSTClient->queueBuffer(mBootAnimSTClient.get(), buf, -1);
- }
- return error;
-}
-
-void
-GonkDisplayJB::UpdateDispSurface(EGLDisplay dpy, EGLSurface sur)
-{
- if (sur != EGL_NO_SURFACE) {
- eglSwapBuffers(dpy, sur);
- } else {
- // When BasicCompositor is used as Compositor,
- // EGLSurface does not exit.
- ANativeWindowBuffer* buf = DequeueBuffer();
- DoQueueBuffer(buf);
- }
-}
-
-void
-GonkDisplayJB::NotifyBootAnimationStopped()
-{
- if (mBootAnimSTClient.get()) {
- mBootAnimSTClient = nullptr;
- mBootAnimDispSurface = nullptr;
- }
-}
-
-void
-GonkDisplayJB::PowerOnDisplay(int aDpy)
-{
- MOZ_ASSERT(mHwc);
-#if ANDROID_VERSION >= 21
- if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_4) {
- mHwc->setPowerMode(mHwc, aDpy, HWC_POWER_MODE_NORMAL);
- } else {
- mHwc->blank(mHwc, aDpy, 0);
- }
-#else
- mHwc->blank(mHwc, aDpy, 0);
-#endif
-}
-
-GonkDisplay::NativeData
-GonkDisplayJB::GetNativeData(GonkDisplay::DisplayType aDisplayType,
- android::IGraphicBufferProducer* aSink)
-{
- NativeData data;
-
- if (aDisplayType == DISPLAY_PRIMARY) {
- data.mNativeWindow = mSTClient;
- data.mDisplaySurface = mDispSurface;
- data.mXdpi = xdpi;
- } else if (aDisplayType == DISPLAY_EXTERNAL) {
- int32_t values[3];
- const uint32_t attrs[] = {
- HWC_DISPLAY_WIDTH,
- HWC_DISPLAY_HEIGHT,
- HWC_DISPLAY_DPI_X,
- HWC_DISPLAY_NO_ATTRIBUTE
- };
- mHwc->getDisplayAttributes(mHwc, aDisplayType, 0, attrs, values);
- int width = values[0];
- int height = values[1];
- // FIXME!! values[2] returns 0 for external display, which doesn't
- // sound right, Bug 1169176 is the follow-up bug for this issue.
- data.mXdpi = values[2] ? values[2] / 1000.f : DEFAULT_XDPI;
- PowerOnDisplay(HWC_DISPLAY_EXTERNAL);
- CreateFramebufferSurface(data.mNativeWindow,
- data.mDisplaySurface,
- width,
- height);
- } else if (aDisplayType == DISPLAY_VIRTUAL) {
- data.mXdpi = xdpi;
- CreateVirtualDisplaySurface(aSink,
- data.mNativeWindow,
- data.mDisplaySurface);
- }
-
- return data;
-}
-
-__attribute__ ((visibility ("default")))
-GonkDisplay*
-GetGonkDisplay()
-{
- if (!sGonkDisplay)
- sGonkDisplay = new GonkDisplayJB();
- return sGonkDisplay;
-}
-
-} // namespace mozilla
diff --git a/widget/gonk/libdisplay/GonkDisplayJB.h b/widget/gonk/libdisplay/GonkDisplayJB.h
deleted file mode 100644
index 60bcdffc4..000000000
--- a/widget/gonk/libdisplay/GonkDisplayJB.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright 2013 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 GONKDISPLAYJB_H
-#define GONKDISPLAYJB_H
-
-#include "DisplaySurface.h"
-#include "GonkDisplay.h"
-#include "hardware/hwcomposer.h"
-#include "hardware/power.h"
-#include "ui/Fence.h"
-#include "utils/RefBase.h"
-
-namespace mozilla {
-
-class MOZ_EXPORT GonkDisplayJB : public GonkDisplay {
-public:
- GonkDisplayJB();
- ~GonkDisplayJB();
-
- virtual void SetEnabled(bool enabled);
-
- virtual void OnEnabled(OnEnabledCallbackType callback);
-
- virtual void* GetHWCDevice();
-
- virtual bool SwapBuffers(EGLDisplay dpy, EGLSurface sur);
-
- virtual ANativeWindowBuffer* DequeueBuffer();
-
- virtual bool QueueBuffer(ANativeWindowBuffer* buf);
-
- virtual void UpdateDispSurface(EGLDisplay dpy, EGLSurface sur);
-
- bool Post(buffer_handle_t buf, int fence);
-
- virtual NativeData GetNativeData(
- GonkDisplay::DisplayType aDisplayType,
- android::IGraphicBufferProducer* aSink = nullptr);
-
- virtual void NotifyBootAnimationStopped();
-
-private:
- void CreateFramebufferSurface(android::sp<ANativeWindow>& aNativeWindow,
- android::sp<android::DisplaySurface>& aDisplaySurface,
- uint32_t aWidth, uint32_t aHeight);
- void CreateVirtualDisplaySurface(android::IGraphicBufferProducer* aSink,
- android::sp<ANativeWindow>& aNativeWindow,
- android::sp<android::DisplaySurface>& aDisplaySurface);
-
- void PowerOnDisplay(int aDpy);
-
- int DoQueueBuffer(ANativeWindowBuffer* buf);
-
- hw_module_t const* mModule;
- hw_module_t const* mFBModule;
- hwc_composer_device_1_t* mHwc;
- framebuffer_device_t* mFBDevice;
- power_module_t* mPowerModule;
- android::sp<android::DisplaySurface> mDispSurface;
- android::sp<ANativeWindow> mSTClient;
- android::sp<android::DisplaySurface> mBootAnimDispSurface;
- android::sp<ANativeWindow> mBootAnimSTClient;
- android::sp<android::IGraphicBufferAlloc> mAlloc;
- hwc_display_contents_1_t* mList;
- uint32_t mWidth;
- uint32_t mHeight;
- OnEnabledCallbackType mEnabledCallback;
-};
-
-}
-
-#endif /* GONKDISPLAYJB_H */
diff --git a/widget/gonk/libdisplay/GraphicBufferAlloc.cpp b/widget/gonk/libdisplay/GraphicBufferAlloc.cpp
deleted file mode 100644
index 5722b7fe3..000000000
--- a/widget/gonk/libdisplay/GraphicBufferAlloc.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- **
- ** Copyright 2012 The Android Open Source Project
- **
- ** Licensed under the Apache License Version 2.0(the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing software
- ** distributed under the License is distributed on an "AS IS" BASIS
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#include <cutils/log.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include "GraphicBufferAlloc.h"
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-GraphicBufferAlloc::GraphicBufferAlloc() {
-}
-
-GraphicBufferAlloc::~GraphicBufferAlloc() {
-}
-
-sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error) {
- sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
- status_t err = graphicBuffer->initCheck();
- *error = err;
- if (err != 0 || graphicBuffer->handle == 0) {
- if (err == NO_MEMORY) {
- GraphicBuffer::dumpAllocationsToSystemLog();
- }
- ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
- "failed (%s), handle=%p",
- w, h, strerror(-err), graphicBuffer->handle);
- return 0;
- }
- return graphicBuffer;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/widget/gonk/libdisplay/GraphicBufferAlloc.h b/widget/gonk/libdisplay/GraphicBufferAlloc.h
deleted file mode 100644
index b08750c2f..000000000
--- a/widget/gonk/libdisplay/GraphicBufferAlloc.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
-#define ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <ui/PixelFormat.h>
-#include <utils/Errors.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class GraphicBuffer;
-
-class GraphicBufferAlloc : public BnGraphicBufferAlloc {
-public:
- GraphicBufferAlloc();
- virtual ~GraphicBufferAlloc();
- virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error);
-};
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
diff --git a/widget/gonk/libdisplay/VirtualDisplaySurface.cpp b/widget/gonk/libdisplay/VirtualDisplaySurface.cpp
deleted file mode 100644
index 746707885..000000000
--- a/widget/gonk/libdisplay/VirtualDisplaySurface.cpp
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// #define LOG_NDEBUG 0
-#include "VirtualDisplaySurface.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-#if defined(FORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS)
-static const bool sForceHwcCopy = true;
-#else
-static const bool sForceHwcCopy = false;
-#endif
-
-#define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \
- mDisplayName.string(), ##__VA_ARGS__)
-#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \
- mDisplayName.string(), ##__VA_ARGS__)
-#define VDS_LOGV(msg, ...) ALOGV("[%s] " msg, \
- mDisplayName.string(), ##__VA_ARGS__)
-
-__attribute__((unused))
-static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) {
- switch (type) {
- case DisplaySurface::COMPOSITION_UNKNOWN: return "UNKNOWN";
- case DisplaySurface::COMPOSITION_GLES: return "GLES";
- case DisplaySurface::COMPOSITION_HWC: return "HWC";
- case DisplaySurface::COMPOSITION_MIXED: return "MIXED";
- default: return "<INVALID>";
- }
-}
-
-VirtualDisplaySurface::VirtualDisplaySurface(int32_t dispId,
- const sp<IGraphicBufferProducer>& sink,
- const sp<IGraphicBufferProducer>& bqProducer,
- const sp<StreamConsumer>& bqConsumer,
- const String8& name)
-: DisplaySurface(bqConsumer),
- mDisplayId(dispId),
- mDisplayName(name),
- mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
- mProducerSlotSource(0),
- mDbgState(DBG_STATE_IDLE),
- mDbgLastCompositionType(COMPOSITION_UNKNOWN),
- mMustRecompose(false)
-{
- mSource[SOURCE_SINK] = sink;
- mSource[SOURCE_SCRATCH] = bqProducer;
-
- resetPerFrameState();
-
- int sinkWidth, sinkHeight;
- sink->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
- sink->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
- mSinkBufferWidth = sinkWidth;
- mSinkBufferHeight = sinkHeight;
-
- // Pick the buffer format to request from the sink when not rendering to it
- // with GLES. If the consumer needs CPU access, use the default format
- // set by the consumer. Otherwise allow gralloc to decide the format based
- // on usage bits.
- int sinkUsage;
- sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
- if (sinkUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
- int sinkFormat;
- sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
- mDefaultOutputFormat = sinkFormat;
- } else {
- mDefaultOutputFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- }
- mOutputFormat = mDefaultOutputFormat;
-
- ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.string());
- mConsumer->setConsumerName(ConsumerBase::mName);
- mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
- mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
- mConsumer->setDefaultMaxBufferCount(2);
-}
-
-VirtualDisplaySurface::~VirtualDisplaySurface() {
-}
-
-status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
- if (mDisplayId < 0)
- return NO_ERROR;
-
- mMustRecompose = mustRecompose;
-
- VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE,
- "Unexpected beginFrame() in %s state", dbgStateStr());
- mDbgState = DBG_STATE_BEGUN;
-
- return refreshOutputBuffer();
-}
-
-status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
- if (mDisplayId < 0)
- return NO_ERROR;
-
- VDS_LOGW_IF(mDbgState != DBG_STATE_BEGUN,
- "Unexpected prepareFrame() in %s state", dbgStateStr());
- mDbgState = DBG_STATE_PREPARED;
-
- mCompositionType = compositionType;
- if (sForceHwcCopy && mCompositionType == COMPOSITION_GLES) {
- // Some hardware can do RGB->YUV conversion more efficiently in hardware
- // controlled by HWC than in hardware controlled by the video encoder.
- // Forcing GLES-composed frames to go through an extra copy by the HWC
- // allows the format conversion to happen there, rather than passing RGB
- // directly to the consumer.
- //
- // On the other hand, when the consumer prefers RGB or can consume RGB
- // inexpensively, this forces an unnecessary copy.
- mCompositionType = COMPOSITION_MIXED;
- }
-
- if (mCompositionType != mDbgLastCompositionType) {
- VDS_LOGV("prepareFrame: composition type changed to %s",
- dbgCompositionTypeStr(mCompositionType));
- mDbgLastCompositionType = mCompositionType;
- }
-
- if (mCompositionType != COMPOSITION_GLES &&
- (mOutputFormat != mDefaultOutputFormat ||
- mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) {
- // We must have just switched from GLES-only to MIXED or HWC
- // composition. Stop using the format and usage requested by the GLES
- // driver; they may be suboptimal when HWC is writing to the output
- // buffer. For example, if the output is going to a video encoder, and
- // HWC can write directly to YUV, some hardware can skip a
- // memory-to-memory RGB-to-YUV conversion step.
- //
- // If we just switched *to* GLES-only mode, we'll change the
- // format/usage and get a new buffer when the GLES driver calls
- // dequeueBuffer().
- mOutputFormat = mDefaultOutputFormat;
- mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
- refreshOutputBuffer();
- }
-
- return NO_ERROR;
-}
-
-status_t VirtualDisplaySurface::compositionComplete() {
- return NO_ERROR;
-}
-
-status_t VirtualDisplaySurface::advanceFrame() {
- return NO_ERROR;
-
-// XXX Add HWC support
-
-#if 0
- if (mDisplayId < 0)
- return NO_ERROR;
-
- if (mCompositionType == COMPOSITION_HWC) {
- VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
- "Unexpected advanceFrame() in %s state on HWC frame",
- dbgStateStr());
- } else {
- VDS_LOGW_IF(mDbgState != DBG_STATE_GLES_DONE,
- "Unexpected advanceFrame() in %s state on GLES/MIXED frame",
- dbgStateStr());
- }
- mDbgState = DBG_STATE_HWC;
-
- if (mOutputProducerSlot < 0 ||
- (mCompositionType != COMPOSITION_HWC && mFbProducerSlot < 0)) {
- // Last chance bailout if something bad happened earlier. For example,
- // in a GLES configuration, if the sink disappears then dequeueBuffer
- // will fail, the GLES driver won't queue a buffer, but SurfaceFlinger
- // will soldier on. So we end up here without a buffer. There should
- // be lots of scary messages in the log just before this.
- VDS_LOGE("advanceFrame: no buffer, bailing out");
- return NO_MEMORY;
- }
-
- sp<GraphicBuffer> fbBuffer = mFbProducerSlot >= 0 ?
- mProducerBuffers[mFbProducerSlot] : sp<GraphicBuffer>(NULL);
- sp<GraphicBuffer> outBuffer = mProducerBuffers[mOutputProducerSlot];
- VDS_LOGV("advanceFrame: fb=%d(%p) out=%d(%p)",
- mFbProducerSlot, fbBuffer.get(),
- mOutputProducerSlot, outBuffer.get());
-
- // At this point we know the output buffer acquire fence,
- // so update HWC state with it.
- mHwc.setOutputBuffer(mDisplayId, mOutputFence, outBuffer);
-
- status_t result = NO_ERROR;
- if (fbBuffer != NULL) {
- result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
- }
-
- return result;
-#endif
-}
-
-void VirtualDisplaySurface::onFrameCommitted() {
- return;
-
-// XXX Add HWC support
-
-#if 0
- if (mDisplayId < 0)
- return;
-
- VDS_LOGW_IF(mDbgState != DBG_STATE_HWC,
- "Unexpected onFrameCommitted() in %s state", dbgStateStr());
- mDbgState = DBG_STATE_IDLE;
-
- sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
- if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
- // release the scratch buffer back to the pool
- Mutex::Autolock lock(mMutex);
- int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
- VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot);
- addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence);
- releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot],
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
- }
-
- if (mOutputProducerSlot >= 0) {
- int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
- QueueBufferOutput qbo;
- sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
- VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
- if (mMustRecompose) {
- status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
- QueueBufferInput(
- systemTime(), false /* isAutoTimestamp */,
- Rect(mSinkBufferWidth, mSinkBufferHeight),
- NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
- true /* async*/,
- outFence),
- &qbo);
- if (result == NO_ERROR) {
- updateQueueBufferOutput(qbo);
- }
- } else {
- // If the surface hadn't actually been updated, then we only went
- // through the motions of updating the display to keep our state
- // machine happy. We cancel the buffer to avoid triggering another
- // re-composition and causing an infinite loop.
- mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence);
- }
- }
-
- resetPerFrameState();
-#endif
-}
-
-void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
- uint32_t tmpW, tmpH, transformHint, numPendingBuffers;
- mQueueBufferOutput.deflate(&tmpW, &tmpH, &transformHint, &numPendingBuffers);
- mQueueBufferOutput.inflate(w, h, transformHint, numPendingBuffers);
-
- mSinkBufferWidth = w;
- mSinkBufferHeight = h;
-}
-
-status_t VirtualDisplaySurface::requestBuffer(int pslot,
- sp<GraphicBuffer>* outBuf) {
- if (mDisplayId < 0)
- return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf);
-
- VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
- "Unexpected requestBuffer pslot=%d in %s state",
- pslot, dbgStateStr());
-
- *outBuf = mProducerBuffers[pslot];
- return NO_ERROR;
-}
-
-status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
- return mSource[SOURCE_SINK]->setBufferCount(bufferCount);
-}
-
-status_t VirtualDisplaySurface::dequeueBuffer(Source source,
- uint32_t format, uint32_t usage, int* sslot, sp<Fence>* fence) {
- LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
- // Don't let a slow consumer block us
- bool async = (source == SOURCE_SINK);
-
- status_t result = mSource[source]->dequeueBuffer(sslot, fence, async,
- mSinkBufferWidth, mSinkBufferHeight, format, usage);
- if (result < 0)
- return result;
- int pslot = mapSource2ProducerSlot(source, *sslot);
- VDS_LOGV("dequeueBuffer(%s): sslot=%d pslot=%d result=%d",
- dbgSourceStr(source), *sslot, pslot, result);
- uint64_t sourceBit = static_cast<uint64_t>(source) << pslot;
-
- if ((mProducerSlotSource & (1ULL << pslot)) != sourceBit) {
- // This slot was previously dequeued from the other source; must
- // re-request the buffer.
- result |= BUFFER_NEEDS_REALLOCATION;
- mProducerSlotSource &= ~(1ULL << pslot);
- mProducerSlotSource |= sourceBit;
- }
-
- if (result & RELEASE_ALL_BUFFERS) {
- for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- if ((mProducerSlotSource & (1ULL << i)) == sourceBit)
- mProducerBuffers[i].clear();
- }
- }
- if (result & BUFFER_NEEDS_REALLOCATION) {
- result = mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
- if (result < 0) {
- mProducerBuffers[pslot].clear();
- mSource[source]->cancelBuffer(*sslot, *fence);
- return result;
- }
- VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#x",
- dbgSourceStr(source), pslot, mProducerBuffers[pslot].get(),
- mProducerBuffers[pslot]->getPixelFormat(),
- mProducerBuffers[pslot]->getUsage());
- }
-
- return result;
-}
-
-status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
- if (mDisplayId < 0)
- return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, async, w, h, format, usage);
-
- VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
- "Unexpected dequeueBuffer() in %s state", dbgStateStr());
- mDbgState = DBG_STATE_GLES;
-
- VDS_LOGW_IF(!async, "EGL called dequeueBuffer with !async despite eglSwapInterval(0)");
- VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
-
- status_t result = NO_ERROR;
- Source source = fbSourceForCompositionType(mCompositionType);
-
- if (source == SOURCE_SINK) {
-
- if (mOutputProducerSlot < 0) {
- // Last chance bailout if something bad happened earlier. For example,
- // in a GLES configuration, if the sink disappears then dequeueBuffer
- // will fail, the GLES driver won't queue a buffer, but SurfaceFlinger
- // will soldier on. So we end up here without a buffer. There should
- // be lots of scary messages in the log just before this.
- VDS_LOGE("dequeueBuffer: no buffer, bailing out");
- return NO_MEMORY;
- }
-
- // We already dequeued the output buffer. If the GLES driver wants
- // something incompatible, we have to cancel and get a new one. This
- // will mean that HWC will see a different output buffer between
- // prepare and set, but since we're in GLES-only mode already it
- // shouldn't matter.
-
- usage |= GRALLOC_USAGE_HW_COMPOSER;
- const sp<GraphicBuffer>& buf = mProducerBuffers[mOutputProducerSlot];
- if ((usage & ~buf->getUsage()) != 0 ||
- (format != 0 && format != (uint32_t)buf->getPixelFormat()) ||
- (w != 0 && w != mSinkBufferWidth) ||
- (h != 0 && h != mSinkBufferHeight)) {
- VDS_LOGV("dequeueBuffer: dequeueing new output buffer: "
- "want %dx%d fmt=%d use=%#x, "
- "have %dx%d fmt=%d use=%#x",
- w, h, format, usage,
- mSinkBufferWidth, mSinkBufferHeight,
- buf->getPixelFormat(), buf->getUsage());
- mOutputFormat = format;
- mOutputUsage = usage;
- result = refreshOutputBuffer();
- if (result < 0)
- return result;
- }
- }
-
- if (source == SOURCE_SINK) {
- *pslot = mOutputProducerSlot;
- *fence = mOutputFence;
- } else {
- int sslot;
- result = dequeueBuffer(source, format, usage, &sslot, fence);
- if (result >= 0) {
- *pslot = mapSource2ProducerSlot(source, sslot);
- }
- }
- return result;
-}
-
-status_t VirtualDisplaySurface::detachBuffer(int /* slot */) {
- VDS_LOGE("detachBuffer is not available for VirtualDisplaySurface");
- return INVALID_OPERATION;
-}
-
-status_t VirtualDisplaySurface::detachNextBuffer(
- sp<GraphicBuffer>* /* outBuffer */, sp<Fence>* /* outFence */) {
- VDS_LOGE("detachNextBuffer is not available for VirtualDisplaySurface");
- return INVALID_OPERATION;
-}
-
-status_t VirtualDisplaySurface::attachBuffer(int* /* outSlot */,
- const sp<GraphicBuffer>& /* buffer */) {
- VDS_LOGE("attachBuffer is not available for VirtualDisplaySurface");
- return INVALID_OPERATION;
-}
-
-status_t VirtualDisplaySurface::queueBuffer(int pslot,
- const QueueBufferInput& input, QueueBufferOutput* output) {
- if (mDisplayId < 0)
- return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output);
-
- VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
- "Unexpected queueBuffer(pslot=%d) in %s state", pslot,
- dbgStateStr());
- mDbgState = DBG_STATE_GLES_DONE;
-
- VDS_LOGV("queueBuffer pslot=%d", pslot);
-
- status_t result;
- if (mCompositionType == COMPOSITION_MIXED) {
- // Queue the buffer back into the scratch pool
- QueueBufferOutput scratchQBO;
- int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, pslot);
- result = mSource[SOURCE_SCRATCH]->queueBuffer(sslot, input, &scratchQBO);
- if (result != NO_ERROR)
- return result;
-
- // Now acquire the buffer from the scratch pool -- should be the same
- // slot and fence as we just queued.
- Mutex::Autolock lock(mMutex);
- BufferQueue::BufferItem item;
- result = acquireBufferLocked(&item, 0);
- if (result != NO_ERROR)
- return result;
- VDS_LOGW_IF(item.mBuf != sslot,
- "queueBuffer: acquired sslot %d from SCRATCH after queueing sslot %d",
- item.mBuf, sslot);
- mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mBuf);
- mFbFence = mSlots[item.mBuf].mFence;
-
- } else {
- LOG_FATAL_IF(mCompositionType != COMPOSITION_GLES,
- "Unexpected queueBuffer in state %s for compositionType %s",
- dbgStateStr(), dbgCompositionTypeStr(mCompositionType));
-
- // Extract the GLES release fence for HWC to acquire
- int64_t timestamp;
- bool isAutoTimestamp;
- Rect crop;
- int scalingMode;
- uint32_t transform;
- bool async;
- input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode,
- &transform, &async, &mFbFence);
-
- mFbProducerSlot = pslot;
- mOutputFence = mFbFence;
- }
-
- *output = mQueueBufferOutput;
- return NO_ERROR;
-}
-
-void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
- if (mDisplayId < 0)
- return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence);
-
- VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
- "Unexpected cancelBuffer(pslot=%d) in %s state", pslot,
- dbgStateStr());
- VDS_LOGV("cancelBuffer pslot=%d", pslot);
- Source source = fbSourceForCompositionType(mCompositionType);
- return mSource[source]->cancelBuffer(
- mapProducer2SourceSlot(source, pslot), fence);
-}
-
-int VirtualDisplaySurface::query(int what, int* value) {
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- *value = mSinkBufferWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- *value = mSinkBufferHeight;
- break;
- default:
- return mSource[SOURCE_SINK]->query(what, value);
- }
- return NO_ERROR;
-}
-
-#if ANDROID_VERSION >= 21
-status_t VirtualDisplaySurface::connect(const sp<IProducerListener>& listener,
- int api, bool producerControlledByApp,
- QueueBufferOutput* output) {
- QueueBufferOutput qbo;
- status_t result = mSource[SOURCE_SINK]->connect(listener, api,
- producerControlledByApp, &qbo);
- if (result == NO_ERROR) {
- updateQueueBufferOutput(qbo);
- *output = mQueueBufferOutput;
- }
- return result;
-}
-#else
-status_t VirtualDisplaySurface::connect(const sp<IBinder>& token,
- int api, bool producerControlledByApp,
- QueueBufferOutput* output) {
- QueueBufferOutput qbo;
- status_t result = mSource[SOURCE_SINK]->connect(token, api, producerControlledByApp, &qbo);
- if (result == NO_ERROR) {
- updateQueueBufferOutput(qbo);
- *output = mQueueBufferOutput;
- }
- return result;
-}
-#endif
-
-status_t VirtualDisplaySurface::disconnect(int api) {
- return mSource[SOURCE_SINK]->disconnect(api);
-}
-
-#if ANDROID_VERSION >= 21
-status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stream*/) {
- return INVALID_OPERATION;
-}
-#endif
-
-void VirtualDisplaySurface::allocateBuffers(bool /* async */,
- uint32_t /* width */, uint32_t /* height */, uint32_t /* format */,
- uint32_t /* usage */) {
- // TODO: Should we actually allocate buffers for a virtual display?
-}
-
-void VirtualDisplaySurface::updateQueueBufferOutput(
- const QueueBufferOutput& qbo) {
- uint32_t w, h, transformHint, numPendingBuffers;
- qbo.deflate(&w, &h, &transformHint, &numPendingBuffers);
- mQueueBufferOutput.inflate(w, h, 0, numPendingBuffers);
-}
-
-void VirtualDisplaySurface::resetPerFrameState() {
- mCompositionType = COMPOSITION_UNKNOWN;
- mFbFence = Fence::NO_FENCE;
- mOutputFence = Fence::NO_FENCE;
- mOutputProducerSlot = -1;
- mFbProducerSlot = -1;
-}
-
-status_t VirtualDisplaySurface::refreshOutputBuffer() {
-
- return INVALID_OPERATION;
-
-// XXX Add HWC support
-
-#if 0
- if (mOutputProducerSlot >= 0) {
- mSource[SOURCE_SINK]->cancelBuffer(
- mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot),
- mOutputFence);
- }
-
- int sslot;
- status_t result = dequeueBuffer(SOURCE_SINK, mOutputFormat, mOutputUsage,
- &sslot, &mOutputFence);
- if (result < 0)
- return result;
- mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
-
- // On GLES-only frames, we don't have the right output buffer acquire fence
- // until after GLES calls queueBuffer(). So here we just set the buffer
- // (for use in HWC prepare) but not the fence; we'll call this again with
- // the proper fence once we have it.
- result = mHwc.setOutputBuffer(mDisplayId, Fence::NO_FENCE,
- mProducerBuffers[mOutputProducerSlot]);
-
- return result;
-#endif
-}
-
-// This slot mapping function is its own inverse, so two copies are unnecessary.
-// Both are kept to make the intent clear where the function is called, and for
-// the (unlikely) chance that we switch to a different mapping function.
-int VirtualDisplaySurface::mapSource2ProducerSlot(Source source, int sslot) {
- if (source == SOURCE_SCRATCH) {
- return BufferQueue::NUM_BUFFER_SLOTS - sslot - 1;
- } else {
- return sslot;
- }
-}
-int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) {
- return mapSource2ProducerSlot(source, pslot);
-}
-
-VirtualDisplaySurface::Source
-VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) {
- return type == COMPOSITION_MIXED ? SOURCE_SCRATCH : SOURCE_SINK;
-}
-
-const char* VirtualDisplaySurface::dbgStateStr() const {
- switch (mDbgState) {
- case DBG_STATE_IDLE: return "IDLE";
- case DBG_STATE_PREPARED: return "PREPARED";
- case DBG_STATE_GLES: return "GLES";
- case DBG_STATE_GLES_DONE: return "GLES_DONE";
- case DBG_STATE_HWC: return "HWC";
- default: return "INVALID";
- }
-}
-
-const char* VirtualDisplaySurface::dbgSourceStr(Source s) {
- switch (s) {
- case SOURCE_SINK: return "SINK";
- case SOURCE_SCRATCH: return "SCRATCH";
- default: return "INVALID";
- }
-}
-
-// ---------------------------------------------------------------------------
-} // namespace android
-// ---------------------------------------------------------------------------
diff --git a/widget/gonk/libdisplay/VirtualDisplaySurface.h b/widget/gonk/libdisplay/VirtualDisplaySurface.h
deleted file mode 100644
index 9125d8751..000000000
--- a/widget/gonk/libdisplay/VirtualDisplaySurface.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
-#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
-
-#include <gui/IGraphicBufferProducer.h>
-
-#include "DisplaySurface.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class HWComposer;
-class IProducerListener;
-
-/* This DisplaySurface implementation supports virtual displays, where GLES
- * and/or HWC compose into a buffer that is then passed to an arbitrary
- * consumer (the sink) running in another process.
- *
- * The simplest case is when the virtual display will never use the h/w
- * composer -- either the h/w composer doesn't support writing to buffers, or
- * there are more virtual displays than it supports simultaneously. In this
- * case, the GLES driver works directly with the output buffer queue, and
- * calls to the VirtualDisplay from SurfaceFlinger and DisplayHardware do
- * nothing.
- *
- * If h/w composer might be used, then each frame will fall into one of three
- * configurations: GLES-only, HWC-only, and MIXED composition. In all of these,
- * we must provide a FB target buffer and output buffer for the HWC set() call.
- *
- * In GLES-only composition, the GLES driver is given a buffer from the sink to
- * render into. When the GLES driver queues the buffer to the
- * VirtualDisplaySurface, the VirtualDisplaySurface holds onto it instead of
- * immediately queueing it to the sink. The buffer is used as both the FB
- * target and output buffer for HWC, though on these frames the HWC doesn't
- * do any work for this display and doesn't write to the output buffer. After
- * composition is complete, the buffer is queued to the sink.
- *
- * In HWC-only composition, the VirtualDisplaySurface dequeues a buffer from
- * the sink and passes it to HWC as both the FB target buffer and output
- * buffer. The HWC doesn't need to read from the FB target buffer, but does
- * write to the output buffer. After composition is complete, the buffer is
- * queued to the sink.
- *
- * On MIXED frames, things become more complicated, since some h/w composer
- * implementations can't read from and write to the same buffer. This class has
- * an internal BufferQueue that it uses as a scratch buffer pool. The GLES
- * driver is given a scratch buffer to render into. When it finishes rendering,
- * the buffer is queued and then immediately acquired by the
- * VirtualDisplaySurface. The scratch buffer is then used as the FB target
- * buffer for HWC, and a separate buffer is dequeued from the sink and used as
- * the HWC output buffer. When HWC composition is complete, the scratch buffer
- * is released and the output buffer is queued to the sink.
- */
-class VirtualDisplaySurface : public DisplaySurface,
- public BnGraphicBufferProducer {
-public:
- VirtualDisplaySurface(int32_t dispId,
- const sp<IGraphicBufferProducer>& sink,
- const sp<IGraphicBufferProducer>& bqProducer,
- const sp<StreamConsumer>& bqConsumer,
- const String8& name);
-
- //
- // DisplaySurface interface
- //
- virtual status_t beginFrame(bool mustRecompose);
- virtual status_t prepareFrame(CompositionType compositionType);
- virtual status_t compositionComplete();
- virtual status_t advanceFrame();
- virtual void onFrameCommitted();
- virtual void resizeBuffers(const uint32_t w, const uint32_t h);
-
- virtual status_t setReleaseFenceFd(int fenceFd) { return INVALID_OPERATION; }
- virtual int GetPrevDispAcquireFd() { return -1; };
-
-private:
- enum Source {SOURCE_SINK = 0, SOURCE_SCRATCH = 1};
-
- virtual ~VirtualDisplaySurface();
-
- //
- // IGraphicBufferProducer interface, used by the GLES driver.
- //
- virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
- virtual status_t setBufferCount(int bufferCount);
- virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
- virtual status_t detachBuffer(int slot);
- virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence);
- virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer);
- virtual status_t queueBuffer(int pslot,
- const QueueBufferInput& input, QueueBufferOutput* output);
- virtual void cancelBuffer(int pslot, const sp<Fence>& fence);
- virtual int query(int what, int* value);
-#if ANDROID_VERSION >= 21
- virtual status_t connect(const sp<IProducerListener>& listener,
- int api, bool producerControlledByApp, QueueBufferOutput* output);
-#else
- virtual status_t connect(const sp<IBinder>& token,
- int api, bool producerControlledByApp, QueueBufferOutput* output);
-#endif
- virtual status_t disconnect(int api);
-#if ANDROID_VERSION >= 21
- virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
-#endif
- virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage);
-
- //
- // Utility methods
- //
- static Source fbSourceForCompositionType(CompositionType type);
- status_t dequeueBuffer(Source source, uint32_t format, uint32_t usage,
- int* sslot, sp<Fence>* fence);
- void updateQueueBufferOutput(const QueueBufferOutput& qbo);
- void resetPerFrameState();
- status_t refreshOutputBuffer();
-
- // Both the sink and scratch buffer pools have their own set of slots
- // ("source slots", or "sslot"). We have to merge these into the single
- // set of slots used by the GLES producer ("producer slots" or "pslot") and
- // internally in the VirtualDisplaySurface. To minimize the number of times
- // a producer slot switches which source it comes from, we map source slot
- // numbers to producer slot numbers differently for each source.
- static int mapSource2ProducerSlot(Source source, int sslot);
- static int mapProducer2SourceSlot(Source source, int pslot);
-
- //
- // Immutable after construction
- //
- const int32_t mDisplayId;
- const String8 mDisplayName;
- sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_*
- uint32_t mDefaultOutputFormat;
-
- //
- // Inter-frame state
- //
-
- // To avoid buffer reallocations, we track the buffer usage and format
- // we used on the previous frame and use it again on the new frame. If
- // the composition type changes or the GLES driver starts requesting
- // different usage/format, we'll get a new buffer.
- uint32_t mOutputFormat;
- uint32_t mOutputUsage;
-
- // Since we present a single producer interface to the GLES driver, but
- // are internally muxing between the sink and scratch producers, we have
- // to keep track of which source last returned each producer slot from
- // dequeueBuffer. Each bit in mProducerSlotSource corresponds to a producer
- // slot. Both mProducerSlotSource and mProducerBuffers are indexed by a
- // "producer slot"; see the mapSlot*() functions.
- uint64_t mProducerSlotSource;
- sp<GraphicBuffer> mProducerBuffers[BufferQueue::NUM_BUFFER_SLOTS];
-
- // The QueueBufferOutput with the latest info from the sink, and with the
- // transform hint cleared. Since we defer queueBuffer from the GLES driver
- // to the sink, we have to return the previous version.
- QueueBufferOutput mQueueBufferOutput;
-
- // Details of the current sink buffer. These become valid when a buffer is
- // dequeued from the sink, and are used when queueing the buffer.
- uint32_t mSinkBufferWidth, mSinkBufferHeight;
-
- //
- // Intra-frame state
- //
-
- // Composition type and GLES buffer source for the current frame.
- // Valid after prepareFrame(), cleared in onFrameCommitted.
- CompositionType mCompositionType;
-
- // mFbFence is the fence HWC should wait for before reading the framebuffer
- // target buffer.
- sp<Fence> mFbFence;
-
- // mOutputFence is the fence HWC should wait for before writing to the
- // output buffer.
- sp<Fence> mOutputFence;
-
- // Producer slot numbers for the buffers to use for HWC framebuffer target
- // and output.
- int mFbProducerSlot;
- int mOutputProducerSlot;
-
- // Debug only -- track the sequence of events in each frame so we can make
- // sure they happen in the order we expect. This class implicitly models
- // a state machine; this enum/variable makes it explicit.
- //
- // +-----------+-------------------+-------------+
- // | State | Event || Next State |
- // +-----------+-------------------+-------------+
- // | IDLE | beginFrame || BEGUN |
- // | BEGUN | prepareFrame || PREPARED |
- // | PREPARED | dequeueBuffer [1] || GLES |
- // | PREPARED | advanceFrame [2] || HWC |
- // | GLES | queueBuffer || GLES_DONE |
- // | GLES_DONE | advanceFrame || HWC |
- // | HWC | onFrameCommitted || IDLE |
- // +-----------+-------------------++------------+
- // [1] COMPOSITION_GLES and COMPOSITION_MIXED frames.
- // [2] COMPOSITION_HWC frames.
- //
- enum DbgState {
- // no buffer dequeued, don't know anything about the next frame
- DBG_STATE_IDLE,
- // output buffer dequeued, framebuffer source not yet known
- DBG_STATE_BEGUN,
- // output buffer dequeued, framebuffer source known but not provided
- // to GLES yet.
- DBG_STATE_PREPARED,
- // GLES driver has a buffer dequeued
- DBG_STATE_GLES,
- // GLES driver has queued the buffer, we haven't sent it to HWC yet
- DBG_STATE_GLES_DONE,
- // HWC has the buffer for this frame
- DBG_STATE_HWC,
- };
- DbgState mDbgState;
- CompositionType mDbgLastCompositionType;
-
- const char* dbgStateStr() const;
- static const char* dbgSourceStr(Source s);
-
- bool mMustRecompose;
-};
-
-// ---------------------------------------------------------------------------
-} // namespace android
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
-
diff --git a/widget/gonk/libdisplay/moz.build b/widget/gonk/libdisplay/moz.build
deleted file mode 100644
index 917320592..000000000
--- a/widget/gonk/libdisplay/moz.build
+++ /dev/null
@@ -1,59 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# Copyright 2013 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-SOURCES += [
- 'BootAnimation.cpp',
-]
-
-if CONFIG['ANDROID_VERSION'] >= '19':
- SOURCES += [
- 'FramebufferSurface.cpp',
- 'GonkDisplayJB.cpp',
- 'VirtualDisplaySurface.cpp',
- ]
-elif CONFIG['ANDROID_VERSION'] == '18':
- SOURCES += [
- 'FramebufferSurface.cpp',
- 'GonkDisplayJB.cpp',
- ]
-elif CONFIG['ANDROID_VERSION'] == '17':
- SOURCES += [
- 'FramebufferSurface.cpp',
- 'GonkDisplayJB.cpp',
- 'GraphicBufferAlloc.cpp',
- ]
-elif CONFIG['ANDROID_VERSION'] and CONFIG['COMPILE_ENVIRONMENT']:
- error('Unsupported platform version: %s' % (CONFIG['ANDROID_VERSION']))
-
-Library('display')
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-FORCE_STATIC_LIB = True
-
-DEFINES['XPCOM_GLUE'] = True
-
-DISABLE_STL_WRAPPING = True
-
-LOCAL_INCLUDES += [
- '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/native/include/gui',
- 'frameworks/native/opengl/include',
- 'hardware/libhardware/include',
- 'hardware/libhardware_legacy/include',
- 'system/core/libsuspend/include',
- ]
-]
diff --git a/widget/gonk/libui/EventHub.cpp b/widget/gonk/libui/EventHub.cpp
deleted file mode 100644
index 9da29bbeb..000000000
--- a/widget/gonk/libui/EventHub.cpp
+++ /dev/null
@@ -1,1549 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "EventHub"
-
-// #define LOG_NDEBUG 0
-#include "cutils_log.h"
-
-#include "EventHub.h"
-
-#include <hardware_legacy/power.h>
-
-#include <cutils/properties.h>
-#include "cutils_log.h"
-#include <utils/Timers.h>
-#include <utils/threads.h>
-#include <utils/Errors.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <memory.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "KeyLayoutMap.h"
-#include "KeyCharacterMap.h"
-#include "VirtualKeyMap.h"
-
-#include <string.h>
-#include <stdint.h>
-#include <dirent.h>
-
-#include <sys/inotify.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
-#include <sys/limits.h>
-#include "sha1.h"
-
-/* this macro is used to tell if "bit" is set in "array"
- * it selects a byte from the array, and does a boolean AND
- * 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)))
-
-/* 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 INDENT " "
-#define INDENT2 " "
-#define INDENT3 " "
-
-namespace android {
-
-static const char *WAKE_LOCK_ID = "KeyEvents";
-static const char *DEVICE_PATH = "/dev/input";
-
-/* return the larger integer */
-static inline int max(int v1, int v2)
-{
- return (v1 > v2) ? v1 : v2;
-}
-
-static inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-static String8 sha1(const String8& in) {
- SHA1_CTX ctx;
- SHA1Init(&ctx);
- SHA1Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
- u_char digest[SHA1_DIGEST_LENGTH];
- SHA1Final(digest, &ctx);
-
- String8 out;
- for (size_t i = 0; i < SHA1_DIGEST_LENGTH; i++) {
- out.appendFormat("%02x", digest[i]);
- }
- return out;
-}
-
-static void setDescriptor(InputDeviceIdentifier& identifier) {
- // Compute a device descriptor that uniquely identifies the device.
- // The descriptor is assumed to be a stable identifier. Its value should not
- // change between reboots, reconnections, firmware updates or new releases of Android.
- // Ideally, we also want the descriptor to be short and relatively opaque.
- String8 rawDescriptor;
- rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor, identifier.product);
- if (!identifier.uniqueId.isEmpty()) {
- rawDescriptor.append("uniqueId:");
- rawDescriptor.append(identifier.uniqueId);
- } if (identifier.vendor == 0 && identifier.product == 0) {
- // If we don't know the vendor and product id, then the device is probably
- // built-in so we need to rely on other information to uniquely identify
- // the input device. Usually we try to avoid relying on the device name or
- // location but for built-in input device, they are unlikely to ever change.
- if (!identifier.name.isEmpty()) {
- rawDescriptor.append("name:");
- rawDescriptor.append(identifier.name);
- } else if (!identifier.location.isEmpty()) {
- rawDescriptor.append("location:");
- rawDescriptor.append(identifier.location);
- }
- }
- identifier.descriptor = sha1(rawDescriptor);
- ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.string(),
- identifier.descriptor.string());
-}
-
-// --- Global Functions ---
-
-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;
- }
- }
-
- // Joystick devices get the rest.
- return deviceClasses & INPUT_DEVICE_CLASS_JOYSTICK;
-}
-
-// --- EventHub::Device ---
-
-EventHub::Device::Device(int fd, int32_t id, const String8& path,
- const InputDeviceIdentifier& identifier) :
- next(NULL),
- fd(fd), id(id), path(path), identifier(identifier),
- classes(0), configuration(NULL), virtualKeyMap(NULL),
- ffEffectPlaying(false), ffEffectId(-1),
- timestampOverrideSec(0), timestampOverrideUsec(0) {
- memset(keyBitmask, 0, sizeof(keyBitmask));
- memset(absBitmask, 0, sizeof(absBitmask));
- memset(relBitmask, 0, sizeof(relBitmask));
- memset(swBitmask, 0, sizeof(swBitmask));
- memset(ledBitmask, 0, sizeof(ledBitmask));
- memset(ffBitmask, 0, sizeof(ffBitmask));
- memset(propBitmask, 0, sizeof(propBitmask));
-}
-
-EventHub::Device::~Device() {
- close();
- delete configuration;
- delete virtualKeyMap;
-}
-
-void EventHub::Device::close() {
- if (fd >= 0) {
- ::close(fd);
- fd = -1;
- }
-}
-
-
-// --- EventHub ---
-
-const uint32_t EventHub::EPOLL_ID_INOTIFY;
-const uint32_t EventHub::EPOLL_ID_WAKE;
-const int EventHub::EPOLL_SIZE_HINT;
-const int EventHub::EPOLL_MAX_EVENTS;
-
-EventHub::EventHub(void) :
- mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1),
- mOpeningDevices(0), mClosingDevices(0),
- mNeedToSendFinishedDeviceScan(false),
- mNeedToReopenDevices(false), mNeedToScanDevices(true),
- mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
-
- mEpollFd = epoll_create(EPOLL_SIZE_HINT);
- LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
-
- mINotifyFd = inotify_init();
- int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
- LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s. errno=%d",
- DEVICE_PATH, errno);
-
- struct epoll_event eventItem;
- memset(&eventItem, 0, sizeof(eventItem));
- eventItem.events = EPOLLIN;
- eventItem.data.u32 = EPOLL_ID_INOTIFY;
- result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
-
- int wakeFds[2];
- result = pipe(wakeFds);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
-
- mWakeReadPipeFd = wakeFds[0];
- mWakeWritePipeFd = wakeFds[1];
-
- result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
- 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);
-
- eventItem.data.u32 = EPOLL_ID_WAKE;
- 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);
-}
-
-EventHub::~EventHub(void) {
- closeAllDevicesLocked();
-
- while (mClosingDevices) {
- Device* device = mClosingDevices;
- mClosingDevices = device->next;
- delete device;
- }
-
- ::close(mEpollFd);
- ::close(mINotifyFd);
- ::close(mWakeReadPipeFd);
- ::close(mWakeWritePipeFd);
-
- release_wake_lock(WAKE_LOCK_ID);
-}
-
-InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device == NULL) return InputDeviceIdentifier();
- return device->identifier;
-}
-
-uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device == NULL) return 0;
- return device->classes;
-}
-
-void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && device->configuration) {
- *outConfiguration = *device->configuration;
- } else {
- outConfiguration->clear();
- }
-}
-
-status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const {
- outAxisInfo->clear();
-
- if (axis >= 0 && axis <= ABS_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && 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.string(), device->fd, errno);
- return -errno;
- }
-
- if (info.minimum != info.maximum) {
- outAxisInfo->valid = true;
- outAxisInfo->minValue = info.minimum;
- outAxisInfo->maxValue = info.maximum;
- outAxisInfo->flat = info.flat;
- outAxisInfo->fuzz = info.fuzz;
- outAxisInfo->resolution = info.resolution;
- }
- return OK;
- }
- }
- return -1;
-}
-
-bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const {
- if (axis >= 0 && axis <= REL_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device) {
- return test_bit(axis, device->relBitmask);
- }
- }
- return false;
-}
-
-bool EventHub::hasInputProperty(int32_t deviceId, int property) const {
- if (property >= 0 && property <= INPUT_PROP_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device) {
- return test_bit(property, device->propBitmask);
- }
- }
- return false;
-}
-
-int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
- if (scanCode >= 0 && scanCode <= KEY_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(scanCode, device->keyBitmask)) {
- uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)];
- memset(keyState, 0, sizeof(keyState));
- if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) {
- return test_bit(scanCode, keyState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
- }
- }
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && device->keyMap.haveKeyLayout()) {
- Vector<int32_t> scanCodes;
- device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes);
- if (scanCodes.size() != 0) {
- uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)];
- memset(keyState, 0, sizeof(keyState));
- if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) {
- for (size_t i = 0; i < scanCodes.size(); i++) {
- int32_t sc = scanCodes.itemAt(i);
- if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, keyState)) {
- return AKEY_STATE_DOWN;
- }
- }
- return AKEY_STATE_UP;
- }
- }
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
- if (sw >= 0 && sw <= SW_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(sw, device->swBitmask)) {
- uint8_t swState[sizeof_bit_array(SW_MAX + 1)];
- memset(swState, 0, sizeof(swState));
- if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) {
- return test_bit(sw, swState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
- }
- }
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const {
- *outValue = 0;
-
- if (axis >= 0 && axis <= ABS_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && 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.string(), device->fd, errno);
- return -errno;
- }
-
- *outValue = info.value;
- return OK;
- }
- }
- return -1;
-}
-
-bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) const {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && device->keyMap.haveKeyLayout()) {
- Vector<int32_t> scanCodes;
- for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
- scanCodes.clear();
-
- 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++) {
- if (test_bit(scanCodes[sc], device->keyBitmask)) {
- outFlags[codeIndex] = 1;
- break;
- }
- }
- }
- }
- return true;
- }
- return false;
-}
-
-status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
- int32_t* outKeycode, uint32_t* outFlags) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
-
- if (device) {
- // Check the key character map first.
- sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
- if (kcm != NULL) {
- if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
- *outFlags = 0;
- return NO_ERROR;
- }
- }
-
- // Check the key layout next.
- if (device->keyMap.haveKeyLayout()) {
- if (!device->keyMap.keyLayoutMap->mapKey(
- scanCode, usageCode, outKeycode, outFlags)) {
- return NO_ERROR;
- }
- }
- }
-
- *outKeycode = 0;
- *outFlags = 0;
- return NAME_NOT_FOUND;
-}
-
-status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
-
- if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->mapAxis(scanCode, outAxisInfo);
- if (err == NO_ERROR) {
- return NO_ERROR;
- }
- }
-
- return NAME_NOT_FOUND;
-}
-
-void EventHub::setExcludedDevices(const Vector<String8>& devices) {
- AutoMutex _l(mLock);
-
- mExcludedDevices = devices;
-}
-
-bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && scanCode >= 0 && scanCode <= KEY_MAX) {
- if (test_bit(scanCode, device->keyBitmask)) {
- return true;
- }
- }
- return false;
-}
-
-bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && led >= 0 && led <= LED_MAX) {
- if (test_bit(led, device->ledBitmask)) {
- return true;
- }
- }
- return false;
-}
-
-void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && led >= 0 && led <= LED_MAX) {
- struct input_event ev;
- ev.time.tv_sec = 0;
- ev.time.tv_usec = 0;
- ev.type = EV_LED;
- ev.code = led;
- ev.value = on ? 1 : 0;
-
- ssize_t nWrite;
- do {
- nWrite = write(device->fd, &ev, sizeof(struct input_event));
- } while (nWrite == -1 && errno == EINTR);
- }
-}
-
-void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
- Vector<VirtualKeyDefinition>& outVirtualKeys) const {
- outVirtualKeys.clear();
-
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && device->virtualKeyMap) {
- outVirtualKeys.appendVector(device->virtualKeyMap->getVirtualKeys());
- }
-}
-
-sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device) {
- return device->getKeyCharacterMap();
- }
- return NULL;
-}
-
-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);
- return true;
- }
- }
- return false;
-}
-
-void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual()) {
- ff_effect effect;
- memset(&effect, 0, sizeof(effect));
- effect.type = FF_RUMBLE;
- effect.id = device->ffEffectId;
- effect.u.rumble.strong_magnitude = 0xc000;
- effect.u.rumble.weak_magnitude = 0xc000;
- effect.replay.length = (duration + 999999LL) / 1000000LL;
- 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.string(), errno);
- return;
- }
- device->ffEffectId = effect.id;
-
- struct input_event ev;
- ev.time.tv_sec = 0;
- ev.time.tv_usec = 0;
- ev.type = EV_FF;
- ev.code = device->ffEffectId;
- 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.string(), errno);
- return;
- }
- device->ffEffectPlaying = true;
- }
-}
-
-void EventHub::cancelVibrate(int32_t deviceId) {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual()) {
- if (device->ffEffectPlaying) {
- device->ffEffectPlaying = false;
-
- struct input_event ev;
- ev.time.tv_sec = 0;
- ev.time.tv_usec = 0;
- ev.type = EV_FF;
- ev.code = device->ffEffectId;
- 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.string(), errno);
- return;
- }
- }
- }
-}
-
-EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
- if (deviceId == BUILT_IN_KEYBOARD_ID) {
- deviceId = mBuiltInKeyboardId;
- }
- ssize_t index = mDevices.indexOfKey(deviceId);
- return index >= 0 ? mDevices.valueAt(index) : NULL;
-}
-
-EventHub::Device* EventHub::getDeviceByPathLocked(const char* devicePath) const {
- for (size_t i = 0; i < mDevices.size(); i++) {
- Device* device = mDevices.valueAt(i);
- if (device->path == devicePath) {
- return device;
- }
- }
- return NULL;
-}
-
-size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
- ALOG_ASSERT(bufferSize >= 1);
-
- AutoMutex _l(mLock);
-
- struct input_event readBuffer[bufferSize];
-
- RawEvent* event = buffer;
- size_t capacity = bufferSize;
- bool awoken = false;
- for (;;) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-
- // Reopen input devices if needed.
- if (mNeedToReopenDevices) {
- mNeedToReopenDevices = false;
-
- ALOGI("Reopening all input devices due to a configuration change.");
-
- closeAllDevicesLocked();
- mNeedToScanDevices = true;
- break; // return to the caller before we actually rescan
- }
-
- // 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.string());
- mClosingDevices = device->next;
- event->when = now;
- event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id;
- event->type = DEVICE_REMOVED;
- event += 1;
- delete device;
- mNeedToSendFinishedDeviceScan = true;
- if (--capacity == 0) {
- break;
- }
- }
-
- if (mNeedToScanDevices) {
- mNeedToScanDevices = false;
- scanDevicesLocked();
- mNeedToSendFinishedDeviceScan = true;
- }
-
- while (mOpeningDevices != NULL) {
- Device* device = mOpeningDevices;
- ALOGV("Reporting device opened: id=%d, name=%s\n",
- device->id, device->path.string());
- mOpeningDevices = device->next;
- event->when = now;
- event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
- event->type = DEVICE_ADDED;
- event += 1;
- mNeedToSendFinishedDeviceScan = true;
- if (--capacity == 0) {
- break;
- }
- }
-
- if (mNeedToSendFinishedDeviceScan) {
- mNeedToSendFinishedDeviceScan = false;
- event->when = now;
- event->type = FINISHED_DEVICE_SCAN;
- event += 1;
- if (--capacity == 0) {
- break;
- }
- }
-
- // Grab the next input event.
- bool deviceChanged = false;
- while (mPendingEventIndex < mPendingEventCount) {
- const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
- if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {
- if (eventItem.events & EPOLLIN) {
- mPendingINotify = true;
- } else {
- ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
- }
- continue;
- }
-
- if (eventItem.data.u32 == EPOLL_ID_WAKE) {
- if (eventItem.events & EPOLLIN) {
- ALOGV("awoken after wake()");
- awoken = true;
- char buffer[16];
- ssize_t nRead;
- do {
- nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
- } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
- } else {
- ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
- eventItem.events);
- }
- continue;
- }
-
- ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
- if (deviceIndex < 0) {
- ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",
- eventItem.events, eventItem.data.u32);
- continue;
- }
-
- Device* device = mDevices.valueAt(deviceIndex);
- if (eventItem.events & EPOLLIN) {
- 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: %d bufferSize: %d "
- "capacity: %d errno: %d)\n",
- device->fd, readSize, bufferSize, capacity, errno);
- deviceChanged = true;
- closeDeviceLocked(device);
- } else if (readSize < 0) {
- if (errno != EAGAIN && errno != EINTR) {
- ALOGW("could not get event (errno=%d)", errno);
- }
- } else if ((readSize % sizeof(struct input_event)) != 0) {
- ALOGE("could not get event (wrong size: %d)", readSize);
- } else {
- int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
-
- size_t count = size_t(readSize) / sizeof(struct input_event);
- for (size_t i = 0; i < count; i++) {
- struct input_event& iev = readBuffer[i];
- ALOGV("%s got: time=%d.%06d, type=%d, code=%d, value=%d",
- device->path.string(),
- (int) iev.time.tv_sec, (int) iev.time.tv_usec,
- iev.type, iev.code, iev.value);
-
- // Some input devices may have a better concept of the time
- // when an input event was actually generated than the kernel
- // which simply timestamps all events on entry to evdev.
- // This is a custom Android extension of the input protocol
- // mainly intended for use with uinput based device drivers.
- if (iev.type == EV_MSC) {
- if (iev.code == MSC_ANDROID_TIME_SEC) {
- device->timestampOverrideSec = iev.value;
- continue;
- } else if (iev.code == MSC_ANDROID_TIME_USEC) {
- device->timestampOverrideUsec = iev.value;
- continue;
- }
- }
- if (device->timestampOverrideSec || device->timestampOverrideUsec) {
- iev.time.tv_sec = device->timestampOverrideSec;
- iev.time.tv_usec = device->timestampOverrideUsec;
- if (iev.type == EV_SYN && iev.code == SYN_REPORT) {
- device->timestampOverrideSec = 0;
- device->timestampOverrideUsec = 0;
- }
- ALOGV("applied override time %d.%06d",
- int(iev.time.tv_sec), int(iev.time.tv_usec));
- }
-
-#ifdef HAVE_POSIX_CLOCKS
- // Use the time specified in the event instead of the current time
- // so that downstream code can get more accurate estimates of
- // event dispatch latency from the time the event is enqueued onto
- // the evdev client buffer.
- //
- // The event's timestamp fortuitously uses the same monotonic clock
- // time base as the rest of Android. The kernel event device driver
- // (drivers/input/evdev.c) obtains timestamps using ktime_get_ts().
- // The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere
- // calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a
- // system call that also queries ktime_get_ts().
- event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL
- + nsecs_t(iev.time.tv_usec) * 1000LL;
- ALOGV("event time %lld, now %lld", event->when, now);
-
- // Bug 7291243: Add a guard in case the kernel generates timestamps
- // that appear to be far into the future because they were generated
- // using the wrong clock source.
- //
- // This can happen because when the input device is initially opened
- // it has a default clock source of CLOCK_REALTIME. Any input events
- // enqueued right after the device is opened will have timestamps
- // generated using CLOCK_REALTIME. We later set the clock source
- // to CLOCK_MONOTONIC but it is already too late.
- //
- // Invalid input event timestamps can result in ANRs, crashes and
- // and other issues that are hard to track down. We must not let them
- // propagate through the system.
- //
- // Log a warning so that we notice the problem and recover gracefully.
- if (event->when >= now + 10 * 1000000000LL) {
- // Double-check. Time may have moved on.
- nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC);
- if (event->when > time) {
- ALOGW("An input event from %s has a timestamp that appears to "
- "have been generated using the wrong clock source "
- "(expected CLOCK_MONOTONIC): "
- "event time %lld, current time %lld, call time %lld. "
- "Using current time instead.",
- device->path.string(), event->when, time, now);
- event->when = time;
- } else {
- ALOGV("Event time is ok but failed the fast path and required "
- "an extra call to systemTime: "
- "event time %lld, current time %lld, call time %lld.",
- event->when, time, now);
- }
- }
-#else
- event->when = now;
-#endif
- event->deviceId = deviceId;
- event->type = iev.type;
- event->code = iev.code;
- event->value = iev.value;
- event += 1;
- capacity -= 1;
- }
- if (capacity == 0) {
- // The result buffer is full. Reset the pending event index
- // so we will try to read the device again on the next iteration.
- mPendingEventIndex -= 1;
- break;
- }
- }
- } else if (eventItem.events & EPOLLHUP) {
- ALOGI("Removing device %s due to epoll hang-up event.",
- device->identifier.name.string());
- deviceChanged = true;
- closeDeviceLocked(device);
- } else {
- ALOGW("Received unexpected epoll event 0x%08x for device %s.",
- eventItem.events, device->identifier.name.string());
- }
- }
-
- // readNotify() will modify the list of devices so this must be done after
- // processing all other events to ensure that we read all remaining events
- // before closing the devices.
- if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
- mPendingINotify = false;
- readNotifyLocked();
- deviceChanged = true;
- }
-
- // Report added or removed devices immediately.
- if (deviceChanged) {
- continue;
- }
-
- // Return now if we have collected any events or if we were explicitly awoken.
- if (event != buffer || awoken) {
- break;
- }
-
- // Poll for events. Mind the wake lock dance!
- // We hold a wake lock at all times except during epoll_wait(). This works due to some
- // subtle choreography. When a device driver has pending (unread) events, it acquires
- // a kernel wake lock. However, once the last pending event has been read, the device
- // driver will release the kernel wake lock. To prevent the system from going to sleep
- // when this happens, the EventHub holds onto its own user wake lock while the client
- // is processing events. Thus the system can only sleep if there are no events
- // pending or currently being processed.
- //
- // The timeout is advisory only. If the device is asleep, it will not wake just to
- // service the timeout.
- mPendingEventIndex = 0;
-
- mLock.unlock(); // release lock before poll, must be before release_wake_lock
- release_wake_lock(WAKE_LOCK_ID);
-
- int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
-
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
- mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock
-
- if (pollResult == 0) {
- // Timed out.
- mPendingEventCount = 0;
- break;
- }
-
- if (pollResult < 0) {
- // An error occurred.
- mPendingEventCount = 0;
-
- // Sleep after errors to avoid locking up the system.
- // Hopefully the error is transient.
- if (errno != EINTR) {
- ALOGW("poll failed (errno=%d)\n", errno);
- usleep(100000);
- }
- } else {
- // Some events occurred.
- mPendingEventCount = size_t(pollResult);
- }
- }
-
- // All done, return the number of events we read.
- return event - buffer;
-}
-
-void EventHub::wake() {
- ALOGV("wake() called");
-
- ssize_t nWrite;
- do {
- nWrite = write(mWakeWritePipeFd, "W", 1);
- } while (nWrite == -1 && errno == EINTR);
-
- if (nWrite != 1 && errno != EAGAIN) {
- ALOGW("Could not write wake signal, errno=%d", errno);
- }
-}
-
-void EventHub::scanDevicesLocked() {
- status_t res = scanDirLocked(DEVICE_PATH);
- if(res < 0) {
- ALOGE("scan dir failed for %s\n", DEVICE_PATH);
- }
- if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
- createVirtualKeyboardLocked();
- }
-}
-
-// ----------------------------------------------------------------------------
-
-static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
- const uint8_t* end = array + endIndex;
- array += startIndex;
- while (array != end) {
- if (*(array++) != 0) {
- return true;
- }
- }
- return false;
-}
-
-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_1, AKEYCODE_BUTTON_2, AKEYCODE_BUTTON_3, AKEYCODE_BUTTON_4,
- AKEYCODE_BUTTON_5, AKEYCODE_BUTTON_6, AKEYCODE_BUTTON_7, AKEYCODE_BUTTON_8,
- AKEYCODE_BUTTON_9, AKEYCODE_BUTTON_10, AKEYCODE_BUTTON_11, AKEYCODE_BUTTON_12,
- AKEYCODE_BUTTON_13, AKEYCODE_BUTTON_14, AKEYCODE_BUTTON_15, AKEYCODE_BUTTON_16,
-};
-
-status_t EventHub::openDeviceLocked(const char *devicePath) {
- char buffer[80];
-
- ALOGV("Opening device: %s", devicePath);
-
- int fd = open(devicePath, O_RDWR | O_CLOEXEC);
- if(fd < 0) {
- ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
- return -1;
- }
-
- InputDeviceIdentifier identifier;
-
- // Get device name.
- if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
- //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
- } else {
- buffer[sizeof(buffer) - 1] = '\0';
- identifier.name.setTo(buffer);
- }
-
- // Check to see if the device is on our excluded list
- for (size_t i = 0; i < mExcludedDevices.size(); i++) {
- const String8& item = mExcludedDevices.itemAt(i);
- if (identifier.name == item) {
- ALOGI("ignoring event id %s driver %s\n", devicePath, item.string());
- close(fd);
- return -1;
- }
- }
-
- // Get device driver version.
- int driverVersion;
- if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
- ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
- close(fd);
- return -1;
- }
-
- // Get device identifier.
- struct input_id inputId;
- if(ioctl(fd, EVIOCGID, &inputId)) {
- ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
- close(fd);
- return -1;
- }
- identifier.bus = inputId.bustype;
- identifier.product = inputId.product;
- identifier.vendor = inputId.vendor;
- 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));
- } else {
- buffer[sizeof(buffer) - 1] = '\0';
- identifier.location.setTo(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));
- } else {
- buffer[sizeof(buffer) - 1] = '\0';
- identifier.uniqueId.setTo(buffer);
- }
-
- // Fill in the descriptor.
- setDescriptor(identifier);
-
- // Make file descriptor non-blocking for use with poll().
- if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
- ALOGE("Error %d making device file descriptor non-blocking.", errno);
- close(fd);
- return -1;
- }
-
- // Allocate device. (The device object takes ownership of the fd at this point.)
- int32_t deviceId = mNextDeviceId++;
- Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
-
- 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);
- ALOGV(" name: \"%s\"\n", identifier.name.string());
- ALOGV(" location: \"%s\"\n", identifier.location.string());
- ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string());
- ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.string());
- ALOGV(" driver: v%d.%d.%d\n",
- driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
-
- // Load the configuration file for the device.
- loadConfigurationLocked(device);
-
- // Figure out the kinds of events the device reports.
- ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
- ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
- ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
- ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
- ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
- ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
- ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);
-
- // 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 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));
- 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)) {
- device->classes |= INPUT_DEVICE_CLASS_CURSOR;
- }
-
- // 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)) {
- // 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)) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCH;
- }
-
- // See if this device is a joystick.
- // Assumes that joysticks always have gamepad buttons in order to distinguish them
- // from other devices such as accelerometers that also have absolute axes.
- 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)) {
- device->classes = assumedClasses;
- break;
- }
- }
- }
-
- // Check whether this device has switches.
- for (int i = 0; i <= SW_MAX; i++) {
- if (test_bit(i, device->swBitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_SWITCH;
- break;
- }
- }
-
- // Check whether this device supports the vibrator.
- if (test_bit(FF_RUMBLE, device->ffBitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_VIBRATOR;
- }
-
- // Configure virtual keys.
- if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
- // Load the virtual keys for the touch screen, if any.
- // We do this now so that we can make sure to load the keymap if necessary.
- status_t status = loadVirtualKeyMapLocked(device);
- if (!status) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
- }
- }
-
- // Load the key map.
- // We need to do this for joysticks too because the key layout may specify axes.
- status_t keyMapStatus = NAME_NOT_FOUND;
- if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
- // Load the keymap for the device.
- keyMapStatus = loadKeyMapLocked(device);
- }
-
- // 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)) {
- mBuiltInKeyboardId = device->id;
- }
-
- // 'Q' key support = cheap test of whether this is an alpha-capable kbd
- if (hasKeycodeLocked(device, AKEYCODE_Q)) {
- device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
- }
-
- // 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)) {
- 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++) {
- if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
- device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
- break;
- }
- }
-
- // Disable kernel key repeat since we handle it ourselves
- unsigned int repeatRate[] = {0,0};
- if (ioctl(fd, EVIOCSREP, repeatRate)) {
- ALOGW("Unable to disable kernel key repeat for %s: %s", devicePath, strerror(errno));
- }
- }
-
- // 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.string());
- delete device;
- return -1;
- }
-
- // Determine whether the device is external or internal.
- if (isExternalDeviceLocked(device)) {
- device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
- }
-
- // Register with epoll.
- struct epoll_event eventItem;
- memset(&eventItem, 0, sizeof(eventItem));
- eventItem.events = EPOLLIN;
- eventItem.data.u32 = deviceId;
- if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
- ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
- delete device;
- return -1;
- }
-
- // Enable wake-lock behavior on kernels that support it.
- // TODO: Only need this for devices that can really wake the system.
- bool usingSuspendBlockIoctl = !ioctl(fd, EVIOCSSUSPENDBLOCK, 1);
-
- // Tell the kernel that we want to use the monotonic clock for reporting timestamps
- // associated with input events. This is important because the input system
- // uses the timestamps extensively and assumes they were recorded using the monotonic
- // clock.
- //
- // In older kernel, before Linux 3.4, there was no way to tell the kernel which
- // clock to use to input event timestamps. The standard kernel behavior was to
- // record a real time timestamp, which isn't what we want. Android kernels therefore
- // contained a patch to the evdev_event() function in drivers/input/evdev.c to
- // replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic
- // clock to be used instead of the real time clock.
- //
- // As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock.
- // Therefore, we no longer require the Android-specific kernel patch described above
- // as long as we make sure to set select the monotonic clock. We do that here.
- int clockId = CLOCK_MONOTONIC;
- bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
-
- ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
- "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, "
- "usingSuspendBlockIoctl=%s, usingClockIoctl=%s",
- deviceId, fd, devicePath, device->identifier.name.string(),
- device->classes,
- device->configurationFile.string(),
- device->keyMap.keyLayoutFile.string(),
- device->keyMap.keyCharacterMapFile.string(),
- toString(mBuiltInKeyboardId == deviceId),
- toString(usingSuspendBlockIoctl), toString(usingClockIoctl));
-
- addDeviceLocked(device);
- return 0;
-}
-
-void EventHub::createVirtualKeyboardLocked() {
- InputDeviceIdentifier identifier;
- identifier.name = "Virtual";
- identifier.uniqueId = "<virtual>";
- setDescriptor(identifier);
-
- Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, String8("<virtual>"), identifier);
- device->classes = INPUT_DEVICE_CLASS_KEYBOARD
- | INPUT_DEVICE_CLASS_ALPHAKEY
- | INPUT_DEVICE_CLASS_DPAD
- | INPUT_DEVICE_CLASS_VIRTUAL;
- loadKeyMapLocked(device);
- addDeviceLocked(device);
-}
-
-void EventHub::addDeviceLocked(Device* device) {
- mDevices.add(device->id, device);
- device->next = mOpeningDevices;
- mOpeningDevices = device;
-}
-
-void EventHub::loadConfigurationLocked(Device* device) {
- device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
- device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
- if (device->configurationFile.isEmpty()) {
- ALOGD("No input device configuration file found for device '%s'.",
- device->identifier.name.string());
- } else {
- status_t status = PropertyMap::load(device->configurationFile,
- &device->configuration);
- if (status) {
- ALOGE("Error loading input device configuration file for device '%s'. "
- "Using default configuration.",
- device->identifier.name.string());
- }
- }
-}
-
-status_t EventHub::loadVirtualKeyMapLocked(Device* device) {
- // The virtual key map is supplied by the kernel as a system board property file.
- String8 path;
- path.append("/sys/board_properties/virtualkeys.");
- path.append(device->identifier.name);
- if (access(path.string(), R_OK)) {
- return NAME_NOT_FOUND;
- }
- return VirtualKeyMap::load(path, &device->virtualKeyMap);
-}
-
-status_t EventHub::loadKeyMapLocked(Device* device) {
- return device->keyMap.load(device->identifier, device->configuration);
-}
-
-bool EventHub::isExternalDeviceLocked(Device* device) {
- if (device->configuration) {
- bool value;
- if (device->configuration->tryGetProperty(String8("device.internal"), value)) {
- return !value;
- }
- }
- return device->identifier.bus == BUS_USB || device->identifier.bus == BUS_BLUETOOTH;
-}
-
-bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
- if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
- return false;
- }
-
- 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++) {
- int32_t sc = scanCodes.itemAt(i);
- if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
- return true;
- }
- }
-
- return false;
-}
-
-status_t EventHub::closeDeviceByPathLocked(const char *devicePath) {
- Device* device = getDeviceByPathLocked(devicePath);
- if (device) {
- closeDeviceLocked(device);
- return 0;
- }
- ALOGV("Remove device: %s not found, device may already have been removed.", devicePath);
- return -1;
-}
-
-void EventHub::closeAllDevicesLocked() {
- while (mDevices.size() > 0) {
- closeDeviceLocked(mDevices.valueAt(mDevices.size() - 1));
- }
-}
-
-void EventHub::closeDeviceLocked(Device* device) {
- ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
- device->path.string(), device->identifier.name.string(), 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.string(), mBuiltInKeyboardId);
- mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
- }
-
- if (!device->isVirtual()) {
- if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
- ALOGW("Could not remove device fd from epoll instance. errno=%d", errno);
- }
- }
-
- mDevices.removeItem(device->id);
- device->close();
-
- // Unlink for opening devices list if it is present.
- Device* pred = NULL;
- bool found = false;
- for (Device* entry = mOpeningDevices; entry != NULL; ) {
- if (entry == device) {
- found = true;
- break;
- }
- pred = entry;
- entry = entry->next;
- }
- if (found) {
- // Unlink the device from the opening devices list then delete it.
- // We don't need to tell the client that the device was closed because
- // it does not even know it was opened in the first place.
- ALOGI("Device %s was immediately closed after opening.", device->path.string());
- if (pred) {
- pred->next = device->next;
- } else {
- mOpeningDevices = device->next;
- }
- delete device;
- } else {
- // Link into closing devices list.
- // The device will be deleted later after we have informed the client.
- device->next = mClosingDevices;
- mClosingDevices = device;
- }
-}
-
-status_t EventHub::readNotifyLocked() {
- int res;
- char devname[PATH_MAX];
- char *filename;
- char event_buf[512];
- int event_size;
- int event_pos = 0;
- 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;
- ALOGW("could not get event, %s\n", strerror(errno));
- return -1;
- }
- //printf("got %d bytes of event information\n", res);
-
- strcpy(devname, DEVICE_PATH);
- filename = devname + strlen(devname);
- *filename++ = '/';
-
- while(res >= (int)sizeof(*event)) {
- event = (struct inotify_event *)(event_buf + event_pos);
- //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
- if(event->len) {
- strcpy(filename, event->name);
- if(event->mask & IN_CREATE) {
- openDeviceLocked(devname);
- } else {
- ALOGI("Removing device '%s' due to inotify event\n", devname);
- closeDeviceByPathLocked(devname);
- }
- }
- event_size = sizeof(*event) + event->len;
- res -= event_size;
- event_pos += event_size;
- }
- return 0;
-}
-
-status_t EventHub::scanDirLocked(const char *dirname)
-{
- char devname[PATH_MAX];
- char *filename;
- DIR *dir;
- struct dirent *de;
- dir = opendir(dirname);
- if(dir == NULL)
- 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')))
- continue;
- strcpy(filename, de->d_name);
- openDeviceLocked(devname);
- }
- closedir(dir);
- return 0;
-}
-
-void EventHub::requestReopenDevices() {
- ALOGV("requestReopenDevices() called");
-
- AutoMutex _l(mLock);
- mNeedToReopenDevices = true;
-}
-
-void EventHub::dump(String8& dump) {
- dump.append("Event Hub State:\n");
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- dump.appendFormat(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);
-
- dump.append(INDENT "Devices:\n");
-
- for (size_t i = 0; i < mDevices.size(); i++) {
- const Device* device = mDevices.valueAt(i);
- if (mBuiltInKeyboardId == device->id) {
- dump.appendFormat(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
- device->id, device->identifier.name.string());
- } else {
- dump.appendFormat(INDENT2 "%d: %s\n", device->id,
- device->identifier.name.string());
- }
- dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
- dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
- dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
- dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
- dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
- dump.appendFormat(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);
- dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n",
- device->keyMap.keyLayoutFile.string());
- dump.appendFormat(INDENT3 "KeyCharacterMapFile: %s\n",
- device->keyMap.keyCharacterMapFile.string());
- dump.appendFormat(INDENT3 "ConfigurationFile: %s\n",
- device->configurationFile.string());
- dump.appendFormat(INDENT3 "HaveKeyboardLayoutOverlay: %s\n",
- toString(device->overlayKeyMap != NULL));
- }
- } // release lock
-}
-
-void EventHub::monitor() {
- // Acquire and release the lock to ensure that the event hub has not deadlocked.
- mLock.lock();
- mLock.unlock();
-}
-
-
-}; // namespace android
diff --git a/widget/gonk/libui/EventHub.h b/widget/gonk/libui/EventHub.h
deleted file mode 100644
index e4e658b21..000000000
--- a/widget/gonk/libui/EventHub.h
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 _RUNTIME_EVENT_HUB_H
-#define _RUNTIME_EVENT_HUB_H
-
-#include "Input.h"
-#include "InputDevice.h"
-#include "Keyboard.h"
-#include "KeyLayoutMap.h"
-#include "KeyCharacterMap.h"
-#include "VirtualKeyMap.h"
-#include <utils/String8.h>
-#include <utils/threads.h>
-#include "cutils_log.h"
-#include <utils/threads.h>
-#include <utils/List.h>
-#include <utils/Errors.h>
-#include <utils/PropertyMap.h>
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
-
-#include "linux_input.h"
-#include <sys/epoll.h>
-
-/* Convenience constants. */
-
-#define BTN_FIRST 0x100 // first button code
-#define BTN_LAST 0x15f // last button code
-
-/*
- * These constants are used privately in Android to pass raw timestamps
- * through evdev from uinput device drivers because there is currently no
- * other way to transfer this information. The evdev driver automatically
- * timestamps all input events with the time they were posted and clobbers
- * whatever information was passed in.
- *
- * For the purposes of this hack, the timestamp is specified in the
- * CLOCK_MONOTONIC timebase and is split into two EV_MSC events specifying
- * seconds and microseconds.
- */
-#define MSC_ANDROID_TIME_SEC 0x6
-#define MSC_ANDROID_TIME_USEC 0x7
-
-namespace android {
-
-enum {
- // Device id of a special "virtual" keyboard that is always present.
- VIRTUAL_KEYBOARD_ID = -1,
- // Device id of the "built-in" keyboard if there is one.
- BUILT_IN_KEYBOARD_ID = 0,
-};
-
-/*
- * A raw event as retrieved from the EventHub.
- */
-struct RawEvent {
- nsecs_t when;
- int32_t deviceId;
- int32_t type;
- int32_t code;
- int32_t value;
-};
-
-/* Describes an absolute axis. */
-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 resolution; // resolution in units per mm or radians per mm
-
- inline void clear() {
- valid = false;
- minValue = 0;
- maxValue = 0;
- flat = 0;
- fuzz = 0;
- resolution = 0;
- }
-};
-
-/*
- * Input device classes.
- */
-enum {
- /* The input device is a keyboard or has buttons. */
- INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
-
- /* The input device is an alpha-numeric keyboard (not just a dial pad). */
- 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,
-
- /* The input device is a cursor device such as a trackball or mouse. */
- INPUT_DEVICE_CLASS_CURSOR = 0x00000008,
-
- /* The input device is a multi-touch touchscreen. */
- INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010,
-
- /* The input device is a directional pad (implies keyboard, has DPAD keys). */
- INPUT_DEVICE_CLASS_DPAD = 0x00000020,
-
- /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
- INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
-
- /* The input device has switches. */
- INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
-
- /* The input device is a joystick (implies gamepad, has joystick absolute axes). */
- INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
-
- /* The input device has a vibrator (supports FF_RUMBLE). */
- INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,
-
- /* The input device is virtual (not a real device, not part of UI configuration). */
- INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,
-
- /* The input device is external (not built-in). */
- INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
-};
-
-/*
- * Gets the class that owns an axis, in cases where multiple classes might claim
- * the same axis for different purposes.
- */
-extern uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses);
-
-/*
- * Grand Central Station for events.
- *
- * The event hub aggregates input events received across all known input
- * devices on the system, including devices that may be emulated by the simulator
- * environment. In addition, the event hub generates fake input events to indicate
- * when devices are added or removed.
- *
- * The event hub provides a stream of input events (via the getEvent function).
- * It also supports querying the current actual state of input devices such as identifying
- * which keys are currently down. Finally, the event hub keeps track of the capabilities of
- * individual input devices, such as their class and the set of key codes that they support.
- */
-class EventHubInterface : public virtual RefBase {
-protected:
- EventHubInterface() { }
- virtual ~EventHubInterface() { }
-
-public:
- // Synthetic raw event type codes produced when devices are added or removed.
- enum {
- // Sent when a device is added.
- DEVICE_ADDED = 0x10000000,
- // Sent when a device is removed.
- DEVICE_REMOVED = 0x20000000,
- // Sent when all added/removed devices from the most recent scan have been reported.
- // This event is always sent at least once.
- FINISHED_DEVICE_SCAN = 0x30000000,
-
- FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
- };
-
- virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
-
- virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0;
-
- virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
-
- virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- 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* outKeycode, uint32_t* outFlags) 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.
- virtual void setExcludedDevices(const Vector<String8>& devices) = 0;
-
- /*
- * Wait for events to become available and returns them.
- * After returning, the EventHub holds onto a wake lock until the next call to getEvent.
- * This ensures that the device will not go to sleep while the event is being processed.
- * If the device needs to remain awake longer than that, then the caller is responsible
- * for taking care of it (say, by poking the power manager user activity timer).
- *
- * The timeout is advisory only. If the device is asleep, it will not wake just to
- * service the timeout.
- *
- * Returns the number of events obtained, or 0 if the timeout expired.
- */
- virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0;
-
- /*
- * Query current input state.
- */
- virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
- 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;
-
- /*
- * 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;
-
- virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
- 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,
- 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;
-
- /* Control the vibrator. */
- virtual void vibrate(int32_t deviceId, nsecs_t duration) = 0;
- virtual void cancelVibrate(int32_t deviceId) = 0;
-
- /* Requests the EventHub to reopen all input devices on the next call to getEvents(). */
- virtual void requestReopenDevices() = 0;
-
- /* Wakes up getEvents() if it is blocked on a read. */
- virtual void wake() = 0;
-
- /* Dump EventHub state to a string. */
- virtual void dump(String8& dump) = 0;
-
- /* Called by the heatbeat to ensures that the reader has not deadlocked. */
- virtual void monitor() = 0;
-};
-
-class EventHub : public EventHubInterface
-{
-public:
- EventHub();
-
- virtual uint32_t getDeviceClasses(int32_t deviceId) const;
-
- virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const;
-
- virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
-
- virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- 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* outKeycode, uint32_t* outFlags) const;
-
- virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
- AxisInfo* outAxisInfo) const;
-
- virtual void setExcludedDevices(const Vector<String8>& devices);
-
- virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
- virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
- 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 size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
-
- virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const;
- virtual bool hasLed(int32_t deviceId, int32_t led) const;
- virtual void setLedState(int32_t deviceId, int32_t led, bool on);
-
- virtual void getVirtualKeyDefinitions(int32_t deviceId,
- Vector<VirtualKeyDefinition>& outVirtualKeys) const;
-
- virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const;
- virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map);
-
- virtual void vibrate(int32_t deviceId, nsecs_t duration);
- virtual void cancelVibrate(int32_t deviceId);
-
- virtual void requestReopenDevices();
-
- virtual void wake();
-
- virtual void dump(String8& dump);
- virtual void monitor();
-
-protected:
- virtual ~EventHub();
-
-private:
- struct Device {
- Device* next;
-
- int fd; // may be -1 if device is virtual
- const int32_t id;
- const String8 path;
- const InputDeviceIdentifier identifier;
-
- uint32_t classes;
-
- uint8_t keyBitmask[(KEY_MAX + 1) / 8];
- uint8_t absBitmask[(ABS_MAX + 1) / 8];
- uint8_t relBitmask[(REL_MAX + 1) / 8];
- uint8_t swBitmask[(SW_MAX + 1) / 8];
- uint8_t ledBitmask[(LED_MAX + 1) / 8];
- uint8_t ffBitmask[(FF_MAX + 1) / 8];
- uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8];
-
- String8 configurationFile;
- PropertyMap* configuration;
- VirtualKeyMap* virtualKeyMap;
- KeyMap keyMap;
-
- sp<KeyCharacterMap> overlayKeyMap;
- sp<KeyCharacterMap> combinedKeyMap;
-
- bool ffEffectPlaying;
- int16_t ffEffectId; // initially -1
-
- int32_t timestampOverrideSec;
- int32_t timestampOverrideUsec;
-
- Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);
- ~Device();
-
- void close();
-
- inline bool isVirtual() const { return fd < 0; }
-
- const sp<KeyCharacterMap>& getKeyCharacterMap() const {
- if (combinedKeyMap != NULL) {
- return combinedKeyMap;
- }
- return keyMap.keyCharacterMap;
- }
- };
-
- status_t openDeviceLocked(const char *devicePath);
- void createVirtualKeyboardLocked();
- void addDeviceLocked(Device* device);
-
- status_t closeDeviceByPathLocked(const char *devicePath);
- void closeDeviceLocked(Device* device);
- void closeAllDevicesLocked();
-
- status_t scanDirLocked(const char *dirname);
- void scanDevicesLocked();
- status_t readNotifyLocked();
-
- Device* getDeviceLocked(int32_t deviceId) const;
- Device* getDeviceByPathLocked(const char* devicePath) const;
-
- bool hasKeycodeLocked(Device* device, int keycode) const;
-
- void loadConfigurationLocked(Device* device);
- status_t loadVirtualKeyMapLocked(Device* device);
- status_t loadKeyMapLocked(Device* device);
-
- bool isExternalDeviceLocked(Device* device);
-
- // Protect all internal state.
- mutable Mutex mLock;
-
- // The actual id of the built-in keyboard, or NO_BUILT_IN_KEYBOARD if none.
- // EventHub remaps the built-in keyboard to id 0 externally as required by the API.
- enum {
- // Must not conflict with any other assigned device ids, including
- // the virtual keyboard id (-1).
- NO_BUILT_IN_KEYBOARD = -2,
- };
- int32_t mBuiltInKeyboardId;
-
- int32_t mNextDeviceId;
-
- KeyedVector<int32_t, Device*> mDevices;
-
- Device *mOpeningDevices;
- Device *mClosingDevices;
-
- bool mNeedToSendFinishedDeviceScan;
- bool mNeedToReopenDevices;
- bool mNeedToScanDevices;
- Vector<String8> mExcludedDevices;
-
- int mEpollFd;
- int mINotifyFd;
- int mWakeReadPipeFd;
- int mWakeWritePipeFd;
-
- // Ids used for epoll notifications not associated with devices.
- static const uint32_t EPOLL_ID_INOTIFY = 0x80000001;
- static const uint32_t EPOLL_ID_WAKE = 0x80000002;
-
- // Epoll FD list size hint.
- static const int EPOLL_SIZE_HINT = 8;
-
- // Maximum number of signalled FDs to handle at a time.
- static const int EPOLL_MAX_EVENTS = 16;
-
- // The array of pending epoll events and the index of the next event to be handled.
- struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS];
- size_t mPendingEventCount;
- size_t mPendingEventIndex;
- bool mPendingINotify;
-};
-
-}; // namespace android
-
-#endif // _RUNTIME_EVENT_HUB_H
diff --git a/widget/gonk/libui/Input.cpp b/widget/gonk/libui/Input.cpp
deleted file mode 100644
index 2208191e6..000000000
--- a/widget/gonk/libui/Input.cpp
+++ /dev/null
@@ -1,635 +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.
- */
-
-#define LOG_TAG "Input"
-//#define LOG_NDEBUG 0
-#include "cutils_log.h"
-
-#include <math.h>
-#include <limits.h>
-
-#include "Input.h"
-
-#ifdef HAVE_ANDROID_OS
-#include <binder/Parcel.h>
-
-#include "SkPoint.h"
-#include "SkMatrix.h"
-#include "SkScalar.h"
-#endif
-
-namespace android {
-
-// --- InputEvent ---
-
-void InputEvent::initialize(int32_t deviceId, int32_t source) {
- mDeviceId = deviceId;
- mSource = source;
-}
-
-void InputEvent::initialize(const InputEvent& from) {
- mDeviceId = from.mDeviceId;
- mSource = from.mSource;
-}
-
-// --- KeyEvent ---
-
-bool KeyEvent::hasDefaultAction(int32_t keyCode) {
- switch (keyCode) {
- case AKEYCODE_HOME:
- case AKEYCODE_BACK:
- case AKEYCODE_CALL:
- case AKEYCODE_ENDCALL:
- case AKEYCODE_VOLUME_UP:
- case AKEYCODE_VOLUME_DOWN:
- case AKEYCODE_VOLUME_MUTE:
- case AKEYCODE_POWER:
- case AKEYCODE_CAMERA:
- case AKEYCODE_HEADSETHOOK:
- case AKEYCODE_MENU:
- case AKEYCODE_NOTIFICATION:
- case AKEYCODE_FOCUS:
- case AKEYCODE_SEARCH:
- case AKEYCODE_MEDIA_PLAY:
- case AKEYCODE_MEDIA_PAUSE:
- case AKEYCODE_MEDIA_PLAY_PAUSE:
- 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_MUTE:
- case AKEYCODE_BRIGHTNESS_DOWN:
- case AKEYCODE_BRIGHTNESS_UP:
- return true;
- }
-
- return false;
-}
-
-bool KeyEvent::hasDefaultAction() const {
- return hasDefaultAction(getKeyCode());
-}
-
-bool KeyEvent::isSystemKey(int32_t keyCode) {
- switch (keyCode) {
- case AKEYCODE_MENU:
- case AKEYCODE_SOFT_RIGHT:
- case AKEYCODE_HOME:
- case AKEYCODE_BACK:
- case AKEYCODE_CALL:
- case AKEYCODE_ENDCALL:
- case AKEYCODE_VOLUME_UP:
- case AKEYCODE_VOLUME_DOWN:
- case AKEYCODE_VOLUME_MUTE:
- case AKEYCODE_MUTE:
- case AKEYCODE_POWER:
- case AKEYCODE_HEADSETHOOK:
- case AKEYCODE_MEDIA_PLAY:
- case AKEYCODE_MEDIA_PAUSE:
- case AKEYCODE_MEDIA_PLAY_PAUSE:
- 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_CAMERA:
- case AKEYCODE_FOCUS:
- case AKEYCODE_SEARCH:
- case AKEYCODE_BRIGHTNESS_DOWN:
- case AKEYCODE_BRIGHTNESS_UP:
- return true;
- }
-
- return false;
-}
-
-bool KeyEvent::isSystemKey() const {
- return isSystemKey(getKeyCode());
-}
-
-void KeyEvent::initialize(
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t flags,
- int32_t keyCode,
- int32_t scanCode,
- int32_t metaState,
- int32_t repeatCount,
- nsecs_t downTime,
- nsecs_t eventTime) {
- InputEvent::initialize(deviceId, source);
- mAction = action;
- mFlags = flags;
- mKeyCode = keyCode;
- mScanCode = scanCode;
- mMetaState = metaState;
- mRepeatCount = repeatCount;
- mDownTime = downTime;
- mEventTime = eventTime;
-}
-
-void KeyEvent::initialize(const KeyEvent& from) {
- InputEvent::initialize(from);
- mAction = from.mAction;
- mFlags = from.mFlags;
- mKeyCode = from.mKeyCode;
- mScanCode = from.mScanCode;
- mMetaState = from.mMetaState;
- mRepeatCount = from.mRepeatCount;
- mDownTime = from.mDownTime;
- mEventTime = from.mEventTime;
-}
-
-
-// --- PointerCoords ---
-
-float PointerCoords::getAxisValue(int32_t axis) const {
- if (axis < 0 || axis > 63) {
- return 0;
- }
-
- uint64_t axisBit = 1LL << axis;
- if (!(bits & axisBit)) {
- return 0;
- }
- uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
- return values[index];
-}
-
-status_t PointerCoords::setAxisValue(int32_t axis, float value) {
- if (axis < 0 || axis > 63) {
- return NAME_NOT_FOUND;
- }
-
- uint64_t axisBit = 1LL << axis;
- uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
- if (!(bits & axisBit)) {
- if (value == 0) {
- return OK; // axes with value 0 do not need to be stored
- }
- uint32_t count = __builtin_popcountll(bits);
- if (count >= MAX_AXES) {
- tooManyAxes(axis);
- return NO_MEMORY;
- }
- bits |= axisBit;
- for (uint32_t i = count; i > index; i--) {
- values[i] = values[i - 1];
- }
- }
- values[index] = value;
- return OK;
-}
-
-static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
- float value = c.getAxisValue(axis);
- if (value != 0) {
- c.setAxisValue(axis, value * scaleFactor);
- }
-}
-
-void PointerCoords::scale(float scaleFactor) {
- // No need to scale pressure or size since they are normalized.
- // No need to scale orientation since it is meaningless to do so.
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor);
-}
-
-#ifdef HAVE_ANDROID_OS
-status_t PointerCoords::readFromParcel(Parcel* parcel) {
- bits = parcel->readInt64();
-
- uint32_t count = __builtin_popcountll(bits);
- if (count > MAX_AXES) {
- return BAD_VALUE;
- }
-
- for (uint32_t i = 0; i < count; i++) {
- values[i] = parcel->readFloat();
- }
- return OK;
-}
-
-status_t PointerCoords::writeToParcel(Parcel* parcel) const {
- parcel->writeInt64(bits);
-
- uint32_t count = __builtin_popcountll(bits);
- for (uint32_t i = 0; i < count; i++) {
- parcel->writeFloat(values[i]);
- }
- return OK;
-}
-#endif
-
-void PointerCoords::tooManyAxes(int axis) {
- ALOGW("Could not set value for axis %d because the PointerCoords structure is full and "
- "cannot contain more than %d axis values.", axis, int(MAX_AXES));
-}
-
-bool PointerCoords::operator==(const PointerCoords& other) const {
- if (bits != other.bits) {
- return false;
- }
- uint32_t count = __builtin_popcountll(bits);
- for (uint32_t i = 0; i < count; i++) {
- if (values[i] != other.values[i]) {
- return false;
- }
- }
- return true;
-}
-
-void PointerCoords::copyFrom(const PointerCoords& other) {
- bits = other.bits;
- uint32_t count = __builtin_popcountll(bits);
- for (uint32_t i = 0; i < count; i++) {
- values[i] = other.values[i];
- }
-}
-
-
-// --- PointerProperties ---
-
-bool PointerProperties::operator==(const PointerProperties& other) const {
- return id == other.id
- && toolType == other.toolType;
-}
-
-void PointerProperties::copyFrom(const PointerProperties& other) {
- id = other.id;
- toolType = other.toolType;
-}
-
-
-// --- MotionEvent ---
-
-void MotionEvent::initialize(
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t flags,
- int32_t edgeFlags,
- int32_t metaState,
- int32_t buttonState,
- float xOffset,
- float yOffset,
- float xPrecision,
- float yPrecision,
- nsecs_t downTime,
- nsecs_t eventTime,
- size_t pointerCount,
- const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords) {
- InputEvent::initialize(deviceId, source);
- mAction = action;
- mFlags = flags;
- mEdgeFlags = edgeFlags;
- mMetaState = metaState;
- mButtonState = buttonState;
- mXOffset = xOffset;
- mYOffset = yOffset;
- mXPrecision = xPrecision;
- mYPrecision = yPrecision;
- mDownTime = downTime;
- mPointerProperties.clear();
- mPointerProperties.appendArray(pointerProperties, pointerCount);
- mSampleEventTimes.clear();
- mSamplePointerCoords.clear();
- addSample(eventTime, pointerCoords);
-}
-
-void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
- InputEvent::initialize(other->mDeviceId, other->mSource);
- mAction = other->mAction;
- mFlags = other->mFlags;
- mEdgeFlags = other->mEdgeFlags;
- mMetaState = other->mMetaState;
- mButtonState = other->mButtonState;
- mXOffset = other->mXOffset;
- mYOffset = other->mYOffset;
- mXPrecision = other->mXPrecision;
- mYPrecision = other->mYPrecision;
- mDownTime = other->mDownTime;
- mPointerProperties = other->mPointerProperties;
-
- if (keepHistory) {
- mSampleEventTimes = other->mSampleEventTimes;
- mSamplePointerCoords = other->mSamplePointerCoords;
- } else {
- mSampleEventTimes.clear();
- mSampleEventTimes.push(other->getEventTime());
- mSamplePointerCoords.clear();
- size_t pointerCount = other->getPointerCount();
- size_t historySize = other->getHistorySize();
- mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
- + (historySize * pointerCount), pointerCount);
- }
-}
-
-void MotionEvent::addSample(
- int64_t eventTime,
- const PointerCoords* pointerCoords) {
- mSampleEventTimes.push(eventTime);
- mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
-}
-
-const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
- return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
-}
-
-float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
- return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
-}
-
-float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
- float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
- switch (axis) {
- case AMOTION_EVENT_AXIS_X:
- return value + mXOffset;
- case AMOTION_EVENT_AXIS_Y:
- return value + mYOffset;
- }
- return value;
-}
-
-const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
- size_t pointerIndex, size_t historicalIndex) const {
- return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
-}
-
-float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
- size_t historicalIndex) const {
- return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
-}
-
-float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
- size_t historicalIndex) const {
- float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
- switch (axis) {
- case AMOTION_EVENT_AXIS_X:
- return value + mXOffset;
- case AMOTION_EVENT_AXIS_Y:
- return value + mYOffset;
- }
- return value;
-}
-
-ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
- size_t pointerCount = mPointerProperties.size();
- for (size_t i = 0; i < pointerCount; i++) {
- if (mPointerProperties.itemAt(i).id == pointerId) {
- return i;
- }
- }
- return -1;
-}
-
-void MotionEvent::offsetLocation(float xOffset, float yOffset) {
- mXOffset += xOffset;
- mYOffset += yOffset;
-}
-
-void MotionEvent::scale(float scaleFactor) {
- mXOffset *= scaleFactor;
- mYOffset *= scaleFactor;
- mXPrecision *= scaleFactor;
- mYPrecision *= scaleFactor;
-
- size_t numSamples = mSamplePointerCoords.size();
- for (size_t i = 0; i < numSamples; i++) {
- mSamplePointerCoords.editItemAt(i).scale(scaleFactor);
- }
-}
-
-#ifdef HAVE_ANDROID_OS
-static inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
- // Construct and transform a vector oriented at the specified clockwise angle from vertical.
- // Coordinate system: down is increasing Y, right is increasing X.
- SkPoint vector;
- vector.fX = SkFloatToScalar(sinf(angleRadians));
- vector.fY = SkFloatToScalar(-cosf(angleRadians));
- matrix->mapVectors(& vector, 1);
-
- // Derive the transformed vector's clockwise angle from vertical.
- float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
- if (result < - M_PI_2) {
- result += M_PI;
- } else if (result > M_PI_2) {
- result -= M_PI;
- }
- return result;
-}
-
-void MotionEvent::transform(const SkMatrix* matrix) {
- float oldXOffset = mXOffset;
- float oldYOffset = mYOffset;
-
- // The tricky part of this implementation is to preserve the value of
- // rawX and rawY. So we apply the transformation to the first point
- // then derive an appropriate new X/Y offset that will preserve rawX and rawY.
- SkPoint point;
- float rawX = getRawX(0);
- float rawY = getRawY(0);
- matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
- & point);
- float newX = SkScalarToFloat(point.fX);
- float newY = SkScalarToFloat(point.fY);
- float newXOffset = newX - rawX;
- float newYOffset = newY - rawY;
-
- mXOffset = newXOffset;
- mYOffset = newYOffset;
-
- // Apply the transformation to all samples.
- size_t numSamples = mSamplePointerCoords.size();
- for (size_t i = 0; i < numSamples; i++) {
- PointerCoords& c = mSamplePointerCoords.editItemAt(i);
- float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
- float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
- matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point);
- c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset);
- c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset);
-
- float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
- c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation));
- }
-}
-
-status_t MotionEvent::readFromParcel(Parcel* parcel) {
- size_t pointerCount = parcel->readInt32();
- size_t sampleCount = parcel->readInt32();
- if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
- return BAD_VALUE;
- }
-
- mDeviceId = parcel->readInt32();
- mSource = parcel->readInt32();
- mAction = parcel->readInt32();
- mFlags = parcel->readInt32();
- mEdgeFlags = parcel->readInt32();
- mMetaState = parcel->readInt32();
- mButtonState = parcel->readInt32();
- mXOffset = parcel->readFloat();
- mYOffset = parcel->readFloat();
- mXPrecision = parcel->readFloat();
- mYPrecision = parcel->readFloat();
- mDownTime = parcel->readInt64();
-
- mPointerProperties.clear();
- mPointerProperties.setCapacity(pointerCount);
- mSampleEventTimes.clear();
- mSampleEventTimes.setCapacity(sampleCount);
- mSamplePointerCoords.clear();
- mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
-
- for (size_t i = 0; i < pointerCount; i++) {
- mPointerProperties.push();
- PointerProperties& properties = mPointerProperties.editTop();
- properties.id = parcel->readInt32();
- properties.toolType = parcel->readInt32();
- }
-
- while (sampleCount-- > 0) {
- mSampleEventTimes.push(parcel->readInt64());
- for (size_t i = 0; i < pointerCount; i++) {
- mSamplePointerCoords.push();
- status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
- if (status) {
- return status;
- }
- }
- }
- return OK;
-}
-
-status_t MotionEvent::writeToParcel(Parcel* parcel) const {
- size_t pointerCount = mPointerProperties.size();
- size_t sampleCount = mSampleEventTimes.size();
-
- parcel->writeInt32(pointerCount);
- parcel->writeInt32(sampleCount);
-
- parcel->writeInt32(mDeviceId);
- parcel->writeInt32(mSource);
- parcel->writeInt32(mAction);
- parcel->writeInt32(mFlags);
- parcel->writeInt32(mEdgeFlags);
- parcel->writeInt32(mMetaState);
- parcel->writeInt32(mButtonState);
- parcel->writeFloat(mXOffset);
- parcel->writeFloat(mYOffset);
- parcel->writeFloat(mXPrecision);
- parcel->writeFloat(mYPrecision);
- parcel->writeInt64(mDownTime);
-
- for (size_t i = 0; i < pointerCount; i++) {
- const PointerProperties& properties = mPointerProperties.itemAt(i);
- parcel->writeInt32(properties.id);
- parcel->writeInt32(properties.toolType);
- }
-
- const PointerCoords* pc = mSamplePointerCoords.array();
- for (size_t h = 0; h < sampleCount; h++) {
- parcel->writeInt64(mSampleEventTimes.itemAt(h));
- for (size_t i = 0; i < pointerCount; i++) {
- status_t status = (pc++)->writeToParcel(parcel);
- if (status) {
- return status;
- }
- }
- }
- return OK;
-}
-#endif
-
-bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
- if (source & AINPUT_SOURCE_CLASS_POINTER) {
- // Specifically excludes HOVER_MOVE and SCROLL.
- switch (action & AMOTION_EVENT_ACTION_MASK) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_MOVE:
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- case AMOTION_EVENT_ACTION_POINTER_UP:
- case AMOTION_EVENT_ACTION_CANCEL:
- case AMOTION_EVENT_ACTION_OUTSIDE:
- return true;
- }
- }
- return false;
-}
-
-
-// --- PooledInputEventFactory ---
-
-PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
- mMaxPoolSize(maxPoolSize) {
-}
-
-PooledInputEventFactory::~PooledInputEventFactory() {
- for (size_t i = 0; i < mKeyEventPool.size(); i++) {
- delete mKeyEventPool.itemAt(i);
- }
- for (size_t i = 0; i < mMotionEventPool.size(); i++) {
- delete mMotionEventPool.itemAt(i);
- }
-}
-
-KeyEvent* PooledInputEventFactory::createKeyEvent() {
- if (!mKeyEventPool.isEmpty()) {
- KeyEvent* event = mKeyEventPool.top();
- mKeyEventPool.pop();
- return event;
- }
- return new KeyEvent();
-}
-
-MotionEvent* PooledInputEventFactory::createMotionEvent() {
- if (!mMotionEventPool.isEmpty()) {
- MotionEvent* event = mMotionEventPool.top();
- mMotionEventPool.pop();
- return event;
- }
- return new MotionEvent();
-}
-
-void PooledInputEventFactory::recycle(InputEvent* event) {
- switch (event->getType()) {
- case AINPUT_EVENT_TYPE_KEY:
- if (mKeyEventPool.size() < mMaxPoolSize) {
- mKeyEventPool.push(static_cast<KeyEvent*>(event));
- return;
- }
- break;
- case AINPUT_EVENT_TYPE_MOTION:
- if (mMotionEventPool.size() < mMaxPoolSize) {
- mMotionEventPool.push(static_cast<MotionEvent*>(event));
- return;
- }
- break;
- }
- delete event;
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/Input.h b/widget/gonk/libui/Input.h
deleted file mode 100644
index 3d958bfab..000000000
--- a/widget/gonk/libui/Input.h
+++ /dev/null
@@ -1,622 +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 _ANDROIDFW_INPUT_H
-#define _ANDROIDFW_INPUT_H
-
-/**
- * Native input event structures.
- */
-
-#include "android_input.h"
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-
-#ifdef HAVE_ANDROID_OS
-class SkMatrix;
-#endif
-
-/*
- * Additional private constants not defined in ndk/ui/input.h.
- */
-enum {
- /* Signifies that the key is being predispatched */
- AKEY_EVENT_FLAG_PREDISPATCH = 0x20000000,
-
- /* Private control to determine when an app is tracking a key sequence. */
- AKEY_EVENT_FLAG_START_TRACKING = 0x40000000,
-
- /* Key event is inconsistent with previously sent key events. */
- AKEY_EVENT_FLAG_TAINTED = 0x80000000,
-};
-
-enum {
- /* Motion event is inconsistent with previously sent motion events. */
- AMOTION_EVENT_FLAG_TAINTED = 0x80000000,
-};
-
-enum {
- /* Used when a motion event is not associated with any display.
- * Typically used for non-pointer events. */
- ADISPLAY_ID_NONE = -1,
-
- /* The default display id. */
- ADISPLAY_ID_DEFAULT = 0,
-};
-
-enum {
- /*
- * Indicates that an input device has switches.
- * This input source flag is hidden from the API because switches are only used by the system
- * and applications have no way to interact with them.
- */
- AINPUT_SOURCE_SWITCH = 0x80000000,
-};
-
-/*
- * SystemUiVisibility constants from View.
- */
-enum {
- ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE = 0,
- ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN = 0x00000001,
-};
-
-/*
- * Maximum number of pointers supported per motion event.
- * Smallest number of pointers is 1.
- * (We want at least 10 but some touch controllers obstensibly configured for 10 pointers
- * will occasionally emit 11. There is not much harm making this constant bigger.)
- */
-#define MAX_POINTERS 16
-
-/*
- * Maximum pointer id value supported in a motion event.
- * Smallest pointer id is 0.
- * (This is limited by our use of BitSet32 to track pointer assignments.)
- */
-#define MAX_POINTER_ID 31
-
-/*
- * Declare a concrete type for the NDK's input event forward declaration.
- */
-struct AInputEvent {
- virtual ~AInputEvent() { }
-};
-
-/*
- * Declare a concrete type for the NDK's input device forward declaration.
- */
-struct AInputDevice {
- virtual ~AInputDevice() { }
-};
-
-
-namespace android {
-
-#ifdef HAVE_ANDROID_OS
-class Parcel;
-#endif
-
-/*
- * Flags that flow alongside events in the input dispatch system to help with certain
- * policy decisions such as waking from device sleep.
- *
- * These flags are also defined in frameworks/base/core/java/android/view/WindowManagerPolicy.java.
- */
-enum {
- /* These flags originate in RawEvents and are generally set in the key map.
- * NOTE: If you edit these flags, also edit labels in KeycodeLabels.h. */
-
- POLICY_FLAG_WAKE = 0x00000001,
- POLICY_FLAG_WAKE_DROPPED = 0x00000002,
- POLICY_FLAG_SHIFT = 0x00000004,
- POLICY_FLAG_CAPS_LOCK = 0x00000008,
- POLICY_FLAG_ALT = 0x00000010,
- POLICY_FLAG_ALT_GR = 0x00000020,
- POLICY_FLAG_MENU = 0x00000040,
- POLICY_FLAG_LAUNCHER = 0x00000080,
- POLICY_FLAG_VIRTUAL = 0x00000100,
- POLICY_FLAG_FUNCTION = 0x00000200,
-
- POLICY_FLAG_RAW_MASK = 0x0000ffff,
-
- /* These flags are set by the input dispatcher. */
-
- // Indicates that the input event was injected.
- POLICY_FLAG_INJECTED = 0x01000000,
-
- // Indicates that the input event is from a trusted source such as a directly attached
- // input device or an application with system-wide event injection permission.
- POLICY_FLAG_TRUSTED = 0x02000000,
-
- // Indicates that the input event has passed through an input filter.
- POLICY_FLAG_FILTERED = 0x04000000,
-
- // Disables automatic key repeating behavior.
- POLICY_FLAG_DISABLE_KEY_REPEAT = 0x08000000,
-
- /* These flags are set by the input reader policy as it intercepts each event. */
-
- // Indicates that the screen was off when the event was received and the event
- // should wake the device.
- POLICY_FLAG_WOKE_HERE = 0x10000000,
-
- // Indicates that the screen was dim when the event was received and the event
- // should brighten the device.
- POLICY_FLAG_BRIGHT_HERE = 0x20000000,
-
- // Indicates that the event should be dispatched to applications.
- // The input event should still be sent to the InputDispatcher so that it can see all
- // input events received include those that it will not deliver.
- POLICY_FLAG_PASS_TO_USER = 0x40000000,
-};
-
-/*
- * Pointer coordinate data.
- */
-struct PointerCoords {
- enum { MAX_AXES = 14 }; // 14 so that sizeof(PointerCoords) == 64
-
- // Bitfield of axes that are present in this structure.
- uint64_t bits;
-
- // Values of axes that are stored in this structure packed in order by axis id
- // for each axis that is present in the structure according to 'bits'.
- float values[MAX_AXES];
-
- inline void clear() {
- bits = 0;
- }
-
- float getAxisValue(int32_t axis) const;
- status_t setAxisValue(int32_t axis, float value);
-
- void scale(float scale);
-
- inline float getX() const {
- return getAxisValue(AMOTION_EVENT_AXIS_X);
- }
-
- inline float getY() const {
- return getAxisValue(AMOTION_EVENT_AXIS_Y);
- }
-
-#ifdef HAVE_ANDROID_OS
- status_t readFromParcel(Parcel* parcel);
- status_t writeToParcel(Parcel* parcel) const;
-#endif
-
- bool operator==(const PointerCoords& other) const;
- inline bool operator!=(const PointerCoords& other) const {
- return !(*this == other);
- }
-
- void copyFrom(const PointerCoords& other);
-
-private:
- void tooManyAxes(int axis);
-};
-
-/*
- * Pointer property data.
- */
-struct PointerProperties {
- // The id of the pointer.
- int32_t id;
-
- // The pointer tool type.
- int32_t toolType;
-
- inline void clear() {
- id = -1;
- toolType = 0;
- }
-
- bool operator==(const PointerProperties& other) const;
- inline bool operator!=(const PointerProperties& other) const {
- return !(*this == other);
- }
-
- void copyFrom(const PointerProperties& other);
-};
-
-/*
- * Input events.
- */
-class InputEvent : public AInputEvent {
-public:
- virtual ~InputEvent() { }
-
- virtual int32_t getType() const = 0;
-
- inline int32_t getDeviceId() const { return mDeviceId; }
-
- inline int32_t getSource() const { return mSource; }
-
- inline void setSource(int32_t source) { mSource = source; }
-
-protected:
- void initialize(int32_t deviceId, int32_t source);
- void initialize(const InputEvent& from);
-
- int32_t mDeviceId;
- int32_t mSource;
-};
-
-/*
- * Key events.
- */
-class KeyEvent : public InputEvent {
-public:
- virtual ~KeyEvent() { }
-
- virtual int32_t getType() const { return AINPUT_EVENT_TYPE_KEY; }
-
- inline int32_t getAction() const { return mAction; }
-
- inline int32_t getFlags() const { return mFlags; }
-
- inline void setFlags(int32_t flags) { mFlags = flags; }
-
- inline int32_t getKeyCode() const { return mKeyCode; }
-
- inline int32_t getScanCode() const { return mScanCode; }
-
- inline int32_t getMetaState() const { return mMetaState; }
-
- inline int32_t getRepeatCount() const { return mRepeatCount; }
-
- inline nsecs_t getDownTime() const { return mDownTime; }
-
- inline nsecs_t getEventTime() const { return mEventTime; }
-
- // Return true if this event may have a default action implementation.
- static bool hasDefaultAction(int32_t keyCode);
- bool hasDefaultAction() const;
-
- // Return true if this event represents a system key.
- static bool isSystemKey(int32_t keyCode);
- bool isSystemKey() const;
-
- void initialize(
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t flags,
- int32_t keyCode,
- int32_t scanCode,
- int32_t metaState,
- int32_t repeatCount,
- nsecs_t downTime,
- nsecs_t eventTime);
- void initialize(const KeyEvent& from);
-
-protected:
- int32_t mAction;
- int32_t mFlags;
- int32_t mKeyCode;
- int32_t mScanCode;
- int32_t mMetaState;
- int32_t mRepeatCount;
- nsecs_t mDownTime;
- nsecs_t mEventTime;
-};
-
-/*
- * Motion events.
- */
-class MotionEvent : public InputEvent {
-public:
- virtual ~MotionEvent() { }
-
- virtual int32_t getType() const { return AINPUT_EVENT_TYPE_MOTION; }
-
- inline int32_t getAction() const { return mAction; }
-
- inline int32_t getActionMasked() const { return mAction & AMOTION_EVENT_ACTION_MASK; }
-
- inline int32_t getActionIndex() const {
- return (mAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
- >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
- }
-
- inline void setAction(int32_t action) { mAction = action; }
-
- inline int32_t getFlags() const { return mFlags; }
-
- inline void setFlags(int32_t flags) { mFlags = flags; }
-
- inline int32_t getEdgeFlags() const { return mEdgeFlags; }
-
- inline void setEdgeFlags(int32_t edgeFlags) { mEdgeFlags = edgeFlags; }
-
- inline int32_t getMetaState() const { return mMetaState; }
-
- inline void setMetaState(int32_t metaState) { mMetaState = metaState; }
-
- inline int32_t getButtonState() const { return mButtonState; }
-
- inline float getXOffset() const { return mXOffset; }
-
- inline float getYOffset() const { return mYOffset; }
-
- inline float getXPrecision() const { return mXPrecision; }
-
- inline float getYPrecision() const { return mYPrecision; }
-
- inline nsecs_t getDownTime() const { return mDownTime; }
-
- inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; }
-
- inline size_t getPointerCount() const { return mPointerProperties.size(); }
-
- inline const PointerProperties* getPointerProperties(size_t pointerIndex) const {
- return &mPointerProperties[pointerIndex];
- }
-
- inline int32_t getPointerId(size_t pointerIndex) const {
- return mPointerProperties[pointerIndex].id;
- }
-
- inline int32_t getToolType(size_t pointerIndex) const {
- return mPointerProperties[pointerIndex].toolType;
- }
-
- inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; }
-
- const PointerCoords* getRawPointerCoords(size_t pointerIndex) const;
-
- float getRawAxisValue(int32_t axis, size_t pointerIndex) const;
-
- inline float getRawX(size_t pointerIndex) const {
- return getRawAxisValue(AMOTION_EVENT_AXIS_X, pointerIndex);
- }
-
- inline float getRawY(size_t pointerIndex) const {
- return getRawAxisValue(AMOTION_EVENT_AXIS_Y, pointerIndex);
- }
-
- float getAxisValue(int32_t axis, size_t pointerIndex) const;
-
- inline float getX(size_t pointerIndex) const {
- return getAxisValue(AMOTION_EVENT_AXIS_X, pointerIndex);
- }
-
- inline float getY(size_t pointerIndex) const {
- return getAxisValue(AMOTION_EVENT_AXIS_Y, pointerIndex);
- }
-
- inline float getPressure(size_t pointerIndex) const {
- return getAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pointerIndex);
- }
-
- inline float getSize(size_t pointerIndex) const {
- return getAxisValue(AMOTION_EVENT_AXIS_SIZE, pointerIndex);
- }
-
- inline float getTouchMajor(size_t pointerIndex) const {
- return getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, pointerIndex);
- }
-
- inline float getTouchMinor(size_t pointerIndex) const {
- return getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, pointerIndex);
- }
-
- inline float getToolMajor(size_t pointerIndex) const {
- return getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, pointerIndex);
- }
-
- inline float getToolMinor(size_t pointerIndex) const {
- return getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, pointerIndex);
- }
-
- inline float getOrientation(size_t pointerIndex) const {
- return getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, pointerIndex);
- }
-
- inline size_t getHistorySize() const { return mSampleEventTimes.size() - 1; }
-
- inline nsecs_t getHistoricalEventTime(size_t historicalIndex) const {
- return mSampleEventTimes[historicalIndex];
- }
-
- const PointerCoords* getHistoricalRawPointerCoords(
- size_t pointerIndex, size_t historicalIndex) const;
-
- float getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
- size_t historicalIndex) const;
-
- inline float getHistoricalRawX(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalRawAxisValue(
- AMOTION_EVENT_AXIS_X, pointerIndex, historicalIndex);
- }
-
- inline float getHistoricalRawY(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalRawAxisValue(
- AMOTION_EVENT_AXIS_Y, pointerIndex, historicalIndex);
- }
-
- float getHistoricalAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const;
-
- inline float getHistoricalX(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalAxisValue(
- AMOTION_EVENT_AXIS_X, pointerIndex, historicalIndex);
- }
-
- inline float getHistoricalY(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalAxisValue(
- AMOTION_EVENT_AXIS_Y, pointerIndex, historicalIndex);
- }
-
- inline float getHistoricalPressure(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalAxisValue(
- AMOTION_EVENT_AXIS_PRESSURE, pointerIndex, historicalIndex);
- }
-
- inline float getHistoricalSize(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalAxisValue(
- AMOTION_EVENT_AXIS_SIZE, pointerIndex, historicalIndex);
- }
-
- inline float getHistoricalTouchMajor(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalAxisValue(
- AMOTION_EVENT_AXIS_TOUCH_MAJOR, pointerIndex, historicalIndex);
- }
-
- inline float getHistoricalTouchMinor(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalAxisValue(
- AMOTION_EVENT_AXIS_TOUCH_MINOR, pointerIndex, historicalIndex);
- }
-
- inline float getHistoricalToolMajor(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalAxisValue(
- AMOTION_EVENT_AXIS_TOOL_MAJOR, pointerIndex, historicalIndex);
- }
-
- inline float getHistoricalToolMinor(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalAxisValue(
- AMOTION_EVENT_AXIS_TOOL_MINOR, pointerIndex, historicalIndex);
- }
-
- inline float getHistoricalOrientation(size_t pointerIndex, size_t historicalIndex) const {
- return getHistoricalAxisValue(
- AMOTION_EVENT_AXIS_ORIENTATION, pointerIndex, historicalIndex);
- }
-
- ssize_t findPointerIndex(int32_t pointerId) const;
-
- void initialize(
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t flags,
- int32_t edgeFlags,
- int32_t metaState,
- int32_t buttonState,
- float xOffset,
- float yOffset,
- float xPrecision,
- float yPrecision,
- nsecs_t downTime,
- nsecs_t eventTime,
- size_t pointerCount,
- const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords);
-
- void copyFrom(const MotionEvent* other, bool keepHistory);
-
- void addSample(
- nsecs_t eventTime,
- const PointerCoords* pointerCoords);
-
- void offsetLocation(float xOffset, float yOffset);
-
- void scale(float scaleFactor);
-
-#ifdef HAVE_ANDROID_OS
- void transform(const SkMatrix* matrix);
-
- status_t readFromParcel(Parcel* parcel);
- status_t writeToParcel(Parcel* parcel) const;
-#endif
-
- static bool isTouchEvent(int32_t source, int32_t action);
- inline bool isTouchEvent() const {
- return isTouchEvent(mSource, mAction);
- }
-
- // Low-level accessors.
- inline const PointerProperties* getPointerProperties() const {
- return mPointerProperties.array();
- }
- inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); }
- inline const PointerCoords* getSamplePointerCoords() const {
- return mSamplePointerCoords.array();
- }
-
-protected:
- int32_t mAction;
- int32_t mFlags;
- int32_t mEdgeFlags;
- int32_t mMetaState;
- int32_t mButtonState;
- float mXOffset;
- float mYOffset;
- float mXPrecision;
- float mYPrecision;
- nsecs_t mDownTime;
- Vector<PointerProperties> mPointerProperties;
- Vector<nsecs_t> mSampleEventTimes;
- Vector<PointerCoords> mSamplePointerCoords;
-};
-
-/*
- * Input event factory.
- */
-class InputEventFactoryInterface {
-protected:
- virtual ~InputEventFactoryInterface() { }
-
-public:
- InputEventFactoryInterface() { }
-
- virtual KeyEvent* createKeyEvent() = 0;
- virtual MotionEvent* createMotionEvent() = 0;
-};
-
-/*
- * A simple input event factory implementation that uses a single preallocated instance
- * of each type of input event that are reused for each request.
- */
-class PreallocatedInputEventFactory : public InputEventFactoryInterface {
-public:
- PreallocatedInputEventFactory() { }
- virtual ~PreallocatedInputEventFactory() { }
-
- virtual KeyEvent* createKeyEvent() { return & mKeyEvent; }
- virtual MotionEvent* createMotionEvent() { return & mMotionEvent; }
-
-private:
- KeyEvent mKeyEvent;
- MotionEvent mMotionEvent;
-};
-
-/*
- * An input event factory implementation that maintains a pool of input events.
- */
-class PooledInputEventFactory : public InputEventFactoryInterface {
-public:
- PooledInputEventFactory(size_t maxPoolSize = 20);
- virtual ~PooledInputEventFactory();
-
- virtual KeyEvent* createKeyEvent();
- virtual MotionEvent* createMotionEvent();
-
- void recycle(InputEvent* event);
-
-private:
- const size_t mMaxPoolSize;
-
- Vector<KeyEvent*> mKeyEventPool;
- Vector<MotionEvent*> mMotionEventPool;
-};
-
-} // namespace android
-
-#endif // _ANDROIDFW_INPUT_H
diff --git a/widget/gonk/libui/InputApplication.cpp b/widget/gonk/libui/InputApplication.cpp
deleted file mode 100644
index ce432356b..000000000
--- a/widget/gonk/libui/InputApplication.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputApplication"
-
-#include "InputApplication.h"
-
-#include "cutils_log.h"
-
-namespace android {
-
-// --- InputApplicationHandle ---
-
-InputApplicationHandle::InputApplicationHandle() :
- mInfo(NULL) {
-}
-
-InputApplicationHandle::~InputApplicationHandle() {
- delete mInfo;
-}
-
-void InputApplicationHandle::releaseInfo() {
- if (mInfo) {
- delete mInfo;
- mInfo = NULL;
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/InputApplication.h b/widget/gonk/libui/InputApplication.h
deleted file mode 100644
index ba789559c..000000000
--- a/widget/gonk/libui/InputApplication.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_APPLICATION_H
-#define _UI_INPUT_APPLICATION_H
-
-#include "Input.h"
-
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-#include <utils/String8.h>
-
-namespace android {
-
-/*
- * Describes the properties of an application that can receive input.
- */
-struct InputApplicationInfo {
- String8 name;
- nsecs_t dispatchingTimeout;
-};
-
-
-/*
- * Handle for an application that can receive input.
- *
- * Used by the native input dispatcher as a handle for the window manager objects
- * that describe an application.
- */
-class InputApplicationHandle : public RefBase {
-public:
- inline const InputApplicationInfo* getInfo() const {
- return mInfo;
- }
-
- inline String8 getName() const {
- return mInfo ? mInfo->name : String8("<invalid>");
- }
-
- inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
- return mInfo ? mInfo->dispatchingTimeout : defaultValue;
- }
-
- /**
- * Requests that the state of this object be updated to reflect
- * the most current available information about the application.
- *
- * This method should only be called from within the input dispatcher's
- * critical section.
- *
- * Returns true on success, or false if the handle is no longer valid.
- */
- virtual bool updateInfo() = 0;
-
- /**
- * Releases the storage used by the associated information when it is
- * no longer needed.
- */
- void releaseInfo();
-
-protected:
- InputApplicationHandle();
- virtual ~InputApplicationHandle();
-
- InputApplicationInfo* mInfo;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_APPLICATION_H
diff --git a/widget/gonk/libui/InputDevice.cpp b/widget/gonk/libui/InputDevice.cpp
deleted file mode 100644
index 01a437dd4..000000000
--- a/widget/gonk/libui/InputDevice.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputDevice"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <ctype.h>
-
-#include "InputDevice.h"
-
-namespace android {
-
-static const char* CONFIGURATION_FILE_DIR[] = {
- "idc/",
- "keylayout/",
- "keychars/",
-};
-
-static const char* CONFIGURATION_FILE_EXTENSION[] = {
- ".idc",
- ".kl",
- ".kcm",
-};
-
-static bool isValidNameChar(char ch) {
- return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
-}
-
-static void appendInputDeviceConfigurationFileRelativePath(String8& path,
- const String8& name, InputDeviceConfigurationFileType type) {
- path.append(CONFIGURATION_FILE_DIR[type]);
- for (size_t i = 0; i < name.length(); i++) {
- char ch = name[i];
- if (!isValidNameChar(ch)) {
- ch = '_';
- }
- path.append(&ch, 1);
- }
- path.append(CONFIGURATION_FILE_EXTENSION[type]);
-}
-
-String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
- const InputDeviceIdentifier& deviceIdentifier,
- InputDeviceConfigurationFileType type) {
- if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
- if (deviceIdentifier.version != 0) {
- // Try vendor product version.
- String8 versionPath(getInputDeviceConfigurationFilePathByName(
- String8::format("Vendor_%04x_Product_%04x_Version_%04x",
- deviceIdentifier.vendor, deviceIdentifier.product,
- deviceIdentifier.version),
- type));
- if (!versionPath.isEmpty()) {
- return versionPath;
- }
- }
-
- // Try vendor product.
- String8 productPath(getInputDeviceConfigurationFilePathByName(
- String8::format("Vendor_%04x_Product_%04x",
- deviceIdentifier.vendor, deviceIdentifier.product),
- type));
- if (!productPath.isEmpty()) {
- return productPath;
- }
- }
-
- // Try device name.
- return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
-}
-
-String8 getInputDeviceConfigurationFilePathByName(
- const String8& name, InputDeviceConfigurationFileType type) {
- // Search system repository.
- String8 path;
- path.setTo(getenv("ANDROID_ROOT"));
- path.append("/usr/");
- appendInputDeviceConfigurationFileRelativePath(path, name, type);
-#if DEBUG_PROBE
- ALOGD("Probing for system provided input device configuration file: path='%s'", path.string());
-#endif
- if (!access(path.string(), R_OK)) {
-#if DEBUG_PROBE
- ALOGD("Found");
-#endif
- return path;
- }
-
- // Search user repository.
- // TODO Should only look here if not in safe mode.
- path.setTo(getenv("ANDROID_DATA"));
- path.append("/system/devices/");
- appendInputDeviceConfigurationFileRelativePath(path, name, type);
-#if DEBUG_PROBE
- ALOGD("Probing for system user input device configuration file: path='%s'", path.string());
-#endif
- if (!access(path.string(), R_OK)) {
-#if DEBUG_PROBE
- ALOGD("Found");
-#endif
- return path;
- }
-
- // Not found.
-#if DEBUG_PROBE
- ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
- name.string(), type);
-#endif
- return String8();
-}
-
-
-// --- InputDeviceInfo ---
-
-InputDeviceInfo::InputDeviceInfo() {
- initialize(-1, -1, InputDeviceIdentifier(), String8(), false);
-}
-
-InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
- mId(other.mId), mGeneration(other.mGeneration), mIdentifier(other.mIdentifier),
- mAlias(other.mAlias), mIsExternal(other.mIsExternal), mSources(other.mSources),
- mKeyboardType(other.mKeyboardType),
- mKeyCharacterMap(other.mKeyCharacterMap),
- mHasVibrator(other.mHasVibrator),
- mMotionRanges(other.mMotionRanges) {
-}
-
-InputDeviceInfo::~InputDeviceInfo() {
-}
-
-void InputDeviceInfo::initialize(int32_t id, int32_t generation,
- const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal) {
- mId = id;
- mGeneration = generation;
- mIdentifier = identifier;
- mAlias = alias;
- mIsExternal = isExternal;
- mSources = 0;
- mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
- mHasVibrator = false;
- mMotionRanges.clear();
-}
-
-const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
- int32_t axis, uint32_t source) const {
- size_t numRanges = mMotionRanges.size();
- for (size_t i = 0; i < numRanges; i++) {
- const MotionRange& range = mMotionRanges.itemAt(i);
- if (range.axis == axis && range.source == source) {
- return &range;
- }
- }
- return NULL;
-}
-
-void InputDeviceInfo::addSource(uint32_t source) {
- mSources |= source;
-}
-
-void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
- float flat, float fuzz, float resolution) {
- MotionRange range = { axis, source, min, max, flat, fuzz, resolution };
- mMotionRanges.add(range);
-}
-
-void InputDeviceInfo::addMotionRange(const MotionRange& range) {
- mMotionRanges.add(range);
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/InputDevice.h b/widget/gonk/libui/InputDevice.h
deleted file mode 100644
index 0ab5863c9..000000000
--- a/widget/gonk/libui/InputDevice.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _ANDROIDFW_INPUT_DEVICE_H
-#define _ANDROIDFW_INPUT_DEVICE_H
-
-#include "Input.h"
-#include "KeyCharacterMap.h"
-
-namespace android {
-
-/*
- * Identifies a device.
- */
-struct InputDeviceIdentifier {
- inline InputDeviceIdentifier() :
- bus(0), vendor(0), product(0), version(0) {
- }
-
- // Information provided by the kernel.
- String8 name;
- String8 location;
- String8 uniqueId;
- uint16_t bus;
- uint16_t vendor;
- uint16_t product;
- uint16_t version;
-
- // A composite input device descriptor string that uniquely identifies the device
- // even across reboots or reconnections. The value of this field is used by
- // upper layers of the input system to associate settings with individual devices.
- // It is hashed from whatever kernel provided information is available.
- // Ideally, the way this value is computed should not change between Android releases
- // because that would invalidate persistent settings that rely on it.
- String8 descriptor;
-};
-
-/*
- * Describes the characteristics and capabilities of an input device.
- */
-class InputDeviceInfo {
-public:
- InputDeviceInfo();
- InputDeviceInfo(const InputDeviceInfo& other);
- ~InputDeviceInfo();
-
- struct MotionRange {
- int32_t axis;
- uint32_t source;
- float min;
- float max;
- float flat;
- float fuzz;
- float resolution;
- };
-
- void initialize(int32_t id, int32_t generation, const InputDeviceIdentifier& identifier,
- const String8& alias, bool isExternal);
-
- inline int32_t getId() const { return mId; }
- inline int32_t getGeneration() const { return mGeneration; }
- inline const InputDeviceIdentifier& getIdentifier() const { return mIdentifier; }
- inline const String8& getAlias() const { return mAlias; }
- inline const String8& getDisplayName() const {
- return mAlias.isEmpty() ? mIdentifier.name : mAlias;
- }
- inline bool isExternal() const { return mIsExternal; }
- inline uint32_t getSources() const { return mSources; }
-
- const MotionRange* getMotionRange(int32_t axis, uint32_t source) const;
-
- void addSource(uint32_t source);
- void addMotionRange(int32_t axis, uint32_t source,
- float min, float max, float flat, float fuzz, float resolution);
- void addMotionRange(const MotionRange& range);
-
- inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
- inline int32_t getKeyboardType() const { return mKeyboardType; }
-
- inline void setKeyCharacterMap(const sp<KeyCharacterMap>& value) {
- mKeyCharacterMap = value;
- }
-
- inline sp<KeyCharacterMap> getKeyCharacterMap() const {
- return mKeyCharacterMap;
- }
-
- inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; }
- inline bool hasVibrator() const { return mHasVibrator; }
-
- inline const Vector<MotionRange>& getMotionRanges() const {
- return mMotionRanges;
- }
-
-private:
- int32_t mId;
- int32_t mGeneration;
- InputDeviceIdentifier mIdentifier;
- String8 mAlias;
- bool mIsExternal;
- uint32_t mSources;
- int32_t mKeyboardType;
- sp<KeyCharacterMap> mKeyCharacterMap;
- bool mHasVibrator;
-
- Vector<MotionRange> mMotionRanges;
-};
-
-/* Types of input device configuration files. */
-enum InputDeviceConfigurationFileType {
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0, /* .idc file */
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT = 1, /* .kl file */
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP = 2, /* .kcm file */
-};
-
-/*
- * Gets the path of an input device configuration file, if one is available.
- * Considers both system provided and user installed configuration files.
- *
- * The device identifier is used to construct several default configuration file
- * names to try based on the device name, vendor, product, and version.
- *
- * Returns an empty string if not found.
- */
-extern String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
- const InputDeviceIdentifier& deviceIdentifier,
- InputDeviceConfigurationFileType type);
-
-/*
- * Gets the path of an input device configuration file, if one is available.
- * Considers both system provided and user installed configuration files.
- *
- * The name is case-sensitive and is used to construct the filename to resolve.
- * All characters except 'a'-'z', 'A'-'Z', '0'-'9', '-', and '_' are replaced by underscores.
- *
- * Returns an empty string if not found.
- */
-extern String8 getInputDeviceConfigurationFilePathByName(
- const String8& name, InputDeviceConfigurationFileType type);
-
-} // namespace android
-
-#endif // _ANDROIDFW_INPUT_DEVICE_H
diff --git a/widget/gonk/libui/InputDispatcher.cpp b/widget/gonk/libui/InputDispatcher.cpp
deleted file mode 100644
index 7adaa1998..000000000
--- a/widget/gonk/libui/InputDispatcher.cpp
+++ /dev/null
@@ -1,4430 +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.
- */
-
-#define LOG_TAG "InputDispatcher"
-#define ATRACE_TAG ATRACE_TAG_INPUT
-
-//#define LOG_NDEBUG 0
-#include "cutils_log.h"
-
-// Log detailed debug messages about each inbound event notification to the dispatcher.
-#define DEBUG_INBOUND_EVENT_DETAILS 0
-
-// Log detailed debug messages about each outbound event processed by the dispatcher.
-#define DEBUG_OUTBOUND_EVENT_DETAILS 0
-
-// Log debug messages about the dispatch cycle.
-#define DEBUG_DISPATCH_CYCLE 0
-
-// Log debug messages about registrations.
-#define DEBUG_REGISTRATION 0
-
-// Log debug messages about input event injection.
-#define DEBUG_INJECTION 0
-
-// Log debug messages about input focus tracking.
-#define DEBUG_FOCUS 0
-
-// Log debug messages about the app switch latency optimization.
-#define DEBUG_APP_SWITCH 0
-
-// Log debug messages about hover events.
-#define DEBUG_HOVER 0
-
-#include "InputDispatcher.h"
-
-#include "Trace.h"
-#include "PowerManager.h"
-
-#include <stddef.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <time.h>
-
-#define INDENT " "
-#define INDENT2 " "
-#define INDENT3 " "
-#define INDENT4 " "
-
-namespace android {
-
-// Default input dispatching timeout if there is no focused application or paused window
-// from which to determine an appropriate dispatching timeout.
-const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
-
-// Amount of time to allow for all pending events to be processed when an app switch
-// key is on the way. This is used to preempt input dispatch and drop input events
-// when an application takes too long to respond and the user has pressed an app switch key.
-const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
-
-// Amount of time to allow for an event to be dispatched (measured since its eventTime)
-// before considering it stale and dropping it.
-const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
-
-// Amount of time to allow touch events to be streamed out to a connection before requiring
-// that the first event be finished. This value extends the ANR timeout by the specified
-// amount. For example, if streaming is allowed to get ahead by one second relative to the
-// queue of waiting unfinished events, then ANRs will similarly be delayed by one second.
-const nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec
-
-// Log a warning when an event takes longer than this to process, even if an ANR does not occur.
-const nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
-
-
-static inline nsecs_t now() {
- return systemTime(SYSTEM_TIME_MONOTONIC);
-}
-
-static inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
- 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;
- }
-}
-
-static bool validateKeyEvent(int32_t action) {
- if (! isValidKeyAction(action)) {
- ALOGE("Key event has invalid action code 0x%x", action);
- return false;
- }
- return true;
-}
-
-static bool isValidMotionAction(int32_t action, size_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 && size_t(index) < pointerCount;
- }
- default:
- return false;
- }
-}
-
-static bool validateMotionEvent(int32_t action, size_t pointerCount,
- const PointerProperties* pointerProperties) {
- if (! isValidMotionAction(action, 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 %d; value must be between 1 and %d.",
- 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);
- return false;
- }
- if (pointerIdBits.hasBit(id)) {
- ALOGE("Motion event has duplicate pointer id %d", id);
- return false;
- }
- pointerIdBits.markBit(id);
- }
- return true;
-}
-
-static bool isMainDisplay(int32_t displayId) {
- return displayId == ADISPLAY_ID_DEFAULT || displayId == ADISPLAY_ID_NONE;
-}
-
-static void dumpRegion(String8& dump, const SkRegion& region) {
- if (region.isEmpty()) {
- dump.append("<empty>");
- return;
- }
-
- bool first = true;
- for (SkRegion::Iterator it(region); !it.done(); it.next()) {
- if (first) {
- first = false;
- } else {
- dump.append("|");
- }
- const SkIRect& rect = it.rect();
- dump.appendFormat("[%d,%d][%d,%d]", rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
- }
-}
-
-
-// --- InputDispatcher ---
-
-InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
- mPolicy(policy),
- mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
- mNextUnblockedEvent(NULL),
- mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
- mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
- mLooper = new Looper(false);
-
- mKeyRepeatState.lastKeyEntry = NULL;
-
- policy->getDispatcherConfiguration(&mConfig);
-}
-
-InputDispatcher::~InputDispatcher() {
- { // acquire lock
- AutoMutex _l(mLock);
-
- resetKeyRepeatLocked();
- releasePendingEventLocked();
- drainInboundQueueLocked();
- }
-
- while (mConnectionsByFd.size() != 0) {
- unregisterInputChannel(mConnectionsByFd.valueAt(0)->inputChannel);
- }
-}
-
-void InputDispatcher::dispatchOnce() {
- nsecs_t nextWakeupTime = LONG_LONG_MAX;
- { // acquire lock
- AutoMutex _l(mLock);
- mDispatcherIsAliveCondition.broadcast();
-
- // Run a dispatch loop if there are no pending commands.
- // The dispatch loop might enqueue commands to run afterwards.
- if (!haveCommandsLocked()) {
- dispatchOnceInnerLocked(&nextWakeupTime);
- }
-
- // Run all pending commands if there are any.
- // If any commands were run then force the next poll to wake up immediately.
- if (runCommandsLockedInterruptible()) {
- nextWakeupTime = LONG_LONG_MIN;
- }
- } // release lock
-
- // Wait for callback or timeout or wake. (make sure we round up, not down)
- nsecs_t currentTime = now();
- int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
- mLooper->pollOnce(timeoutMillis);
-}
-
-void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
- nsecs_t currentTime = now();
-
- // Reset the key repeat timer whenever we disallow key events, even if the next event
- // is not a key. This is to ensure that we abort a key repeat if the device is just coming
- // out of sleep.
- if (!mPolicy->isKeyRepeatEnabled()) {
- resetKeyRepeatLocked();
- }
-
- // If dispatching is frozen, do not process timeouts or try to deliver any new events.
- if (mDispatchFrozen) {
-#if DEBUG_FOCUS
- ALOGD("Dispatch frozen. Waiting some more.");
-#endif
- return;
- }
-
- // Optimize latency of app switches.
- // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
- // been pressed. When it expires, we preempt dispatch and drop all other pending events.
- bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
- if (mAppSwitchDueTime < *nextWakeupTime) {
- *nextWakeupTime = mAppSwitchDueTime;
- }
-
- // Ready to start a new event.
- // If we don't already have a pending event, go grab one.
- if (! mPendingEvent) {
- if (mInboundQueue.isEmpty()) {
- if (isAppSwitchDue) {
- // The inbound queue is empty so the app switch key we were waiting
- // for will never arrive. Stop waiting for it.
- resetPendingAppSwitchLocked(false);
- isAppSwitchDue = false;
- }
-
- // Synthesize a key repeat if appropriate.
- if (mKeyRepeatState.lastKeyEntry) {
- if (currentTime >= mKeyRepeatState.nextRepeatTime) {
- mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
- } else {
- if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
- *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
- }
- }
- }
-
- // Nothing to do if there is no pending event.
- if (!mPendingEvent) {
- return;
- }
- } else {
- // Inbound queue has at least one entry.
- mPendingEvent = mInboundQueue.dequeueAtHead();
- traceInboundQueueLengthLocked();
- }
-
- // Poke user activity for this event.
- if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
- pokeUserActivityLocked(mPendingEvent);
- }
-
- // Get ready to dispatch the event.
- resetANRTimeoutsLocked();
- }
-
- // Now we have an event to dispatch.
- // All events are eventually dequeued and processed this way, even if we intend to drop them.
- ALOG_ASSERT(mPendingEvent != NULL);
- bool done = false;
- DropReason dropReason = DROP_REASON_NOT_DROPPED;
- if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
- dropReason = DROP_REASON_POLICY;
- } else if (!mDispatchEnabled) {
- dropReason = DROP_REASON_DISABLED;
- }
-
- if (mNextUnblockedEvent == mPendingEvent) {
- mNextUnblockedEvent = NULL;
- }
-
- 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_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 (isAppSwitchKeyEventLocked(typedEntry)) {
- resetPendingAppSwitchLocked(true);
- isAppSwitchDue = false;
- } else if (dropReason == DROP_REASON_NOT_DROPPED) {
- dropReason = DROP_REASON_APP_SWITCH;
- }
- }
- if (dropReason == DROP_REASON_NOT_DROPPED
- && isStaleEventLocked(currentTime, typedEntry)) {
- dropReason = DROP_REASON_STALE;
- }
- 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
- && isStaleEventLocked(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;
- }
-
- if (done) {
- if (dropReason != DROP_REASON_NOT_DROPPED) {
- dropInboundEventLocked(mPendingEvent, dropReason);
- }
-
- releasePendingEventLocked();
- *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
- }
-}
-
-bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
- bool needWake = mInboundQueue.isEmpty();
- mInboundQueue.enqueueAtTail(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 (isAppSwitchKeyEventLocked(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!");
-#endif
- 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
- && mInputTargetWaitApplicationHandle != NULL) {
- 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 != NULL
- && touchedWindowHandle->inputApplicationHandle
- != mInputTargetWaitApplicationHandle) {
- // 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;
- }
- }
-
- return needWake;
-}
-
-sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
- int32_t x, int32_t y) {
- // Traverse windows from front to back to find touched window.
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
- if (windowInfo->displayId == displayId) {
- int32_t flags = windowInfo->layoutParamsFlags;
-
- if (windowInfo->visible) {
- if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
- bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
- | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
- // Found window.
- return windowHandle;
- }
- }
- }
-
- if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
- // Error window is on top but not visible, so touch is dropped.
- return NULL;
- }
- }
- }
- return NULL;
-}
-
-void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
- const char* reason;
- switch (dropReason) {
- case DROP_REASON_POLICY:
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("Dropped event because policy consumed it.");
-#endif
- reason = "inbound event was dropped because the policy consumed it";
- break;
- case 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: {
- 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;
- }
- }
-}
-
-bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
- return keyCode == AKEYCODE_HOME
- || keyCode == AKEYCODE_ENDCALL
- || keyCode == AKEYCODE_APP_SWITCH;
-}
-
-bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
- 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() {
- return mAppSwitchDueTime != LONG_LONG_MAX;
-}
-
-void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
- mAppSwitchDueTime = LONG_LONG_MAX;
-
-#if DEBUG_APP_SWITCH
- if (handled) {
- ALOGD("App switch has arrived.");
- } else {
- ALOGD("App switch was abandoned.");
- }
-#endif
-}
-
-bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) {
- return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
-}
-
-bool InputDispatcher::haveCommandsLocked() const {
- return !mCommandQueue.isEmpty();
-}
-
-bool InputDispatcher::runCommandsLockedInterruptible() {
- if (mCommandQueue.isEmpty()) {
- return false;
- }
-
- do {
- CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
-
- Command command = commandEntry->command;
- (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
-
- commandEntry->connection.clear();
- delete commandEntry;
- } while (! mCommandQueue.isEmpty());
- return true;
-}
-
-InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
- CommandEntry* commandEntry = new CommandEntry(command);
- mCommandQueue.enqueueAtTail(commandEntry);
- return commandEntry;
-}
-
-void InputDispatcher::drainInboundQueueLocked() {
- while (! mInboundQueue.isEmpty()) {
- EventEntry* entry = mInboundQueue.dequeueAtHead();
- releaseInboundEventLocked(entry);
- }
- traceInboundQueueLengthLocked();
-}
-
-void InputDispatcher::releasePendingEventLocked() {
- if (mPendingEvent) {
- resetANRTimeoutsLocked();
- releaseInboundEventLocked(mPendingEvent);
- mPendingEvent = NULL;
- }
-}
-
-void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("Injected inbound event was dropped.");
-#endif
- setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
- }
- if (entry == mNextUnblockedEvent) {
- mNextUnblockedEvent = NULL;
- }
- entry->release();
-}
-
-void InputDispatcher::resetKeyRepeatLocked() {
- if (mKeyRepeatState.lastKeyEntry) {
- mKeyRepeatState.lastKeyEntry->release();
- mKeyRepeatState.lastKeyEntry = NULL;
- }
-}
-
-InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
- KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
-
- // Reuse the repeated key entry if it is otherwise unreferenced.
- uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
- | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
- if (entry->refCount == 1) {
- entry->recycle();
- entry->eventTime = currentTime;
- entry->policyFlags = policyFlags;
- entry->repeatCount += 1;
- } else {
- KeyEntry* newEntry = new KeyEntry(currentTime,
- entry->deviceId, entry->source, policyFlags,
- entry->action, entry->flags, entry->keyCode, entry->scanCode,
- entry->metaState, entry->repeatCount + 1, entry->downTime);
-
- mKeyRepeatState.lastKeyEntry = newEntry;
- entry->release();
-
- entry = newEntry;
- }
- entry->syntheticRepeat = true;
-
- // Increment reference count since we keep a reference to the event in
- // mKeyRepeatState.lastKeyEntry in addition to the one we return.
- entry->refCount += 1;
-
- mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay;
- return entry;
-}
-
-bool InputDispatcher::dispatchConfigurationChangedLocked(
- nsecs_t currentTime, ConfigurationChangedEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
-#endif
-
- // Reset key repeating in case a keyboard device was added or removed or something.
- resetKeyRepeatLocked();
-
- // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doNotifyConfigurationChangedInterruptible);
- commandEntry->eventTime = entry->eventTime;
- return true;
-}
-
-bool InputDispatcher::dispatchDeviceResetLocked(
- nsecs_t currentTime, DeviceResetEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("dispatchDeviceReset - eventTime=%lld, deviceId=%d", entry->eventTime, entry->deviceId);
-#endif
-
- 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) {
- // 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) {
- // 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
- // we will not need to synthesize key repeats ourselves.
- entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
- resetKeyRepeatLocked();
- mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
- } else {
- // Not a repeat. Save key down state in case we do see a repeat later.
- resetKeyRepeatLocked();
- mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
- }
- mKeyRepeatState.lastKeyEntry = entry;
- entry->refCount += 1;
- } else if (! entry->syntheticRepeat) {
- resetKeyRepeatLocked();
- }
-
- if (entry->repeatCount == 1) {
- entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
- } else {
- entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
- }
-
- entry->dispatchInProgress = true;
-
- logOutboundKeyDetailsLocked("dispatchKey - ", entry);
- }
-
- // Handle case where the policy asked us to try again later last time.
- if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
- if (currentTime < entry->interceptKeyWakeupTime) {
- if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
- *nextWakeupTime = entry->interceptKeyWakeupTime;
- }
- return false; // wait until next wakeup
- }
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
- entry->interceptKeyWakeupTime = 0;
- }
-
- // Give the policy a chance to intercept the key.
- if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
- if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
- if (mFocusedWindowHandle != NULL) {
- commandEntry->inputWindowHandle = mFocusedWindowHandle;
- }
- commandEntry->keyEntry = entry;
- entry->refCount += 1;
- return false; // wait for the command to run
- } else {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
- }
- } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
- if (*dropReason == DROP_REASON_NOT_DROPPED) {
- *dropReason = DROP_REASON_POLICY;
- }
- }
-
- // Clean up if dropping the event.
- if (*dropReason != DROP_REASON_NOT_DROPPED) {
- setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
- ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
- return true;
- }
-
- // Identify targets.
- Vector<InputTarget> inputTargets;
- int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
- entry, inputTargets, nextWakeupTime);
- if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
- return false;
- }
-
- setInjectionResultLocked(entry, injectionResult);
- if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
- return true;
- }
-
- addMonitoringTargetsLocked(inputTargets);
-
- // Dispatch the key.
- dispatchEventLocked(currentTime, entry, inputTargets);
- return true;
-}
-
-void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
- "repeatCount=%d, downTime=%lld",
- prefix,
- entry->eventTime, entry->deviceId, entry->source, 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) {
- // Preprocessing.
- if (! entry->dispatchInProgress) {
- entry->dispatchInProgress = true;
-
- logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
- }
-
- // Clean up if dropping the event.
- if (*dropReason != DROP_REASON_NOT_DROPPED) {
- setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
- ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
- return true;
- }
-
- bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
-
- // Identify targets.
- Vector<InputTarget> inputTargets;
-
- bool conflictingPointerActions = false;
- int32_t injectionResult;
- if (isPointerEvent) {
- // Pointer event. (eg. touchscreen)
- injectionResult = findTouchedWindowTargetsLocked(currentTime,
- entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
- } else {
- // Non touch event. (eg. trackball)
- injectionResult = findFocusedWindowTargetsLocked(currentTime,
- entry, inputTargets, nextWakeupTime);
- }
- if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
- return false;
- }
-
- setInjectionResultLocked(entry, injectionResult);
- if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
- return true;
- }
-
- // TODO: support sending secondary display events to input monitors
- if (isMainDisplay(entry->displayId)) {
- addMonitoringTargetsLocked(inputTargets);
- }
-
- // Dispatch the motion.
- if (conflictingPointerActions) {
- CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "conflicting pointer actions");
- synthesizeCancelationEventsForAllConnectionsLocked(options);
- }
- dispatchEventLocked(currentTime, entry, inputTargets);
- return true;
-}
-
-
-void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, "
- "metaState=0x%x, buttonState=0x%x, "
- "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
- prefix,
- entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
- entry->action, 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));
- }
-#endif
-}
-
-void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
- EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("dispatchEventToCurrentInputTargets");
-#endif
-
- ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
-
- pokeUserActivityLocked(eventEntry);
-
- for (size_t i = 0; i < inputTargets.size(); i++) {
- const InputTarget& inputTarget = inputTargets.itemAt(i);
-
- ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
- } 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().string());
-#endif
- }
- }
-}
-
-int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
- const EventEntry* entry,
- const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle,
- nsecs_t* nextWakeupTime, const char* reason) {
- if (applicationHandle == NULL && windowHandle == NULL) {
- if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
-#if DEBUG_FOCUS
- ALOGD("Waiting for system to become ready for input. Reason: %s", reason);
-#endif
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
- mInputTargetWaitStartTime = currentTime;
- mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
- mInputTargetWaitTimeoutExpired = false;
- mInputTargetWaitApplicationHandle.clear();
- }
- } else {
- if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-#if DEBUG_FOCUS
- ALOGD("Waiting for application to become ready for input: %s. Reason: %s",
- getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
- reason);
-#endif
- nsecs_t timeout;
- if (windowHandle != NULL) {
- timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
- } else if (applicationHandle != NULL) {
- timeout = applicationHandle->getDispatchingTimeout(
- DEFAULT_INPUT_DISPATCHING_TIMEOUT);
- } else {
- timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
- }
-
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
- mInputTargetWaitStartTime = currentTime;
- mInputTargetWaitTimeoutTime = currentTime + timeout;
- mInputTargetWaitTimeoutExpired = false;
- mInputTargetWaitApplicationHandle.clear();
-
- if (windowHandle != NULL) {
- mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;
- }
- if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
- mInputTargetWaitApplicationHandle = applicationHandle;
- }
- }
- }
-
- if (mInputTargetWaitTimeoutExpired) {
- return INPUT_EVENT_INJECTION_TIMED_OUT;
- }
-
- if (currentTime >= mInputTargetWaitTimeoutTime) {
- 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.
- *nextWakeupTime = LONG_LONG_MIN;
- return INPUT_EVENT_INJECTION_PENDING;
- } else {
- // Force poll loop to wake up when timeout is due.
- if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
- *nextWakeupTime = mInputTargetWaitTimeoutTime;
- }
- return INPUT_EVENT_INJECTION_PENDING;
- }
-}
-
-void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
- const sp<InputChannel>& inputChannel) {
- if (newTimeout > 0) {
- // Extend the timeout.
- mInputTargetWaitTimeoutTime = now() + newTimeout;
- } else {
- // Give up.
- mInputTargetWaitTimeoutExpired = true;
-
- // Input state will not be realistic. Mark it out of sync.
- if (inputChannel.get()) {
- ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- sp<InputWindowHandle> windowHandle = connection->inputWindowHandle;
-
- if (windowHandle != NULL) {
- mTouchState.removeWindow(windowHandle);
- }
-
- if (connection->status == Connection::STATUS_NORMAL) {
- CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
- "application not responding");
- synthesizeCancelationEventsForConnectionLocked(connection, options);
- }
- }
- }
- }
-}
-
-nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
- nsecs_t currentTime) {
- if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
- return currentTime - mInputTargetWaitStartTime;
- }
- return 0;
-}
-
-void InputDispatcher::resetANRTimeoutsLocked() {
-#if DEBUG_FOCUS
- ALOGD("Resetting ANR timeouts.");
-#endif
-
- // Reset input target wait timeout.
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
- mInputTargetWaitApplicationHandle.clear();
-}
-
-int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
- const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
- int32_t injectionResult;
-
- // If there is no currently focused window and no focused application
- // then drop the event.
- if (mFocusedWindowHandle == NULL) {
- if (mFocusedApplicationHandle != NULL) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, NULL, 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.");
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
-
- // Check permissions.
- if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
- injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- goto Failed;
- }
-
- // If the currently focused window is paused then keep waiting.
- if (mFocusedWindowHandle->getInfo()->paused) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
- "Waiting because the focused window is paused.");
- goto Unresponsive;
- }
-
- // If the currently focused window is still working on previous events then keep waiting.
- if (!isWindowReadyForMoreInputLocked(currentTime, mFocusedWindowHandle, entry)) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
- "Waiting because the focused window has not finished "
- "processing the input events that were previously delivered to it.");
- goto Unresponsive;
- }
-
- // Success! Output targets.
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
- addWindowTargetLocked(mFocusedWindowHandle,
- InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
- inputTargets);
-
- // Done.
-Failed:
-Unresponsive:
- nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatisticsLocked(currentTime, entry,
- injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
- ALOGD("findFocusedWindow finished: injectionResult=%d, "
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult, timeSpentWaitingForApplication / 1000000.0);
-#endif
- return injectionResult;
-}
-
-int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
- const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
- bool* outConflictingPointerActions) {
- enum InjectionPermission {
- INJECTION_PERMISSION_UNKNOWN,
- INJECTION_PERMISSION_GRANTED,
- INJECTION_PERMISSION_DENIED
- };
-
- // For security reasons, we defer updating the touch state until we are sure that
- // event injection will be allowed.
- //
- // FIXME In the original code, screenWasOff could never be set to true.
- // The reason is that the POLICY_FLAG_WOKE_HERE
- // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
- // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
- // actually enqueued using the policyFlags that appeared in the final EV_SYN
- // events upon which no preprocessing took place. So policyFlags was always 0.
- // In the new native input dispatcher we're a bit more careful about event
- // preprocessing so the touches we receive can actually have non-zero policyFlags.
- // Unfortunately we obtain undesirable behavior.
- //
- // Here's what happens:
- //
- // When the device dims in anticipation of going to sleep, touches
- // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
- // the device to brighten and reset the user activity timer.
- // Touches on other windows (such as the launcher window)
- // are dropped. Then after a moment, the device goes to sleep. Oops.
- //
- // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
- // instead of POLICY_FLAG_WOKE_HERE...
- //
- bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
-
- int32_t displayId = entry->displayId;
- int32_t action = entry->action;
- int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-
- // Update the touch state as needed based on the properties of the touch event.
- int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
- InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
- sp<InputWindowHandle> newHoverWindowHandle;
-
- bool isSplit = mTouchState.split;
- bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0
- && (mTouchState.deviceId != entry->deviceId
- || mTouchState.source != entry->source
- || mTouchState.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 && mTouchState.down && !down) {
-#if DEBUG_FOCUS
- ALOGD("Dropping event because a pointer for a different device is already down.");
-#endif
- mTempTouchState.copyFrom(mTouchState);
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- switchedDevice = false;
- wrongDevice = true;
- goto Failed;
- }
- mTempTouchState.reset();
- mTempTouchState.down = down;
- mTempTouchState.deviceId = entry->deviceId;
- mTempTouchState.source = entry->source;
- mTempTouchState.displayId = displayId;
- isSplit = false;
- } else {
- mTempTouchState.copyFrom(mTouchState);
- }
-
- if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
- /* 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));
- sp<InputWindowHandle> newTouchedWindowHandle;
- sp<InputWindowHandle> topErrorWindowHandle;
- bool isTouchModal = false;
-
- // Traverse windows from front to back to find touched window and outside targets.
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
- if (windowInfo->displayId != displayId) {
- continue; // wrong display
- }
-
- int32_t flags = windowInfo->layoutParamsFlags;
- if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
- if (topErrorWindowHandle == NULL) {
- topErrorWindowHandle = windowHandle;
- }
- }
-
- if (windowInfo->visible) {
- if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
- isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
- | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
- if (! screenWasOff
- || (flags & InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING)) {
- newTouchedWindowHandle = windowHandle;
- }
- break; // found touched window, exit window loop
- }
- }
-
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN
- && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
- int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
- if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
- outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
-
- mTempTouchState.addOrUpdateWindow(
- windowHandle, outsideTargetFlags, BitSet32(0));
- }
- }
- }
-
- // If there is an error window but it is not taking focus (typically because
- // it is invisible) then wait for it. Any other focused window may in
- // fact be in ANR state.
- if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, NULL, nextWakeupTime,
- "Waiting because a system error window is about to be displayed.");
- injectionPermission = INJECTION_PERMISSION_UNKNOWN;
- goto Unresponsive;
- }
-
- // Figure out whether splitting will be allowed for this window.
- if (newTouchedWindowHandle != NULL
- && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
- // New window supports splitting.
- isSplit = true;
- } else if (isSplit) {
- // New window does not support splitting but we have already split events.
- // Ignore the new window.
- newTouchedWindowHandle = NULL;
- }
-
- // Handle the case where we did not find a window.
- if (newTouchedWindowHandle == NULL) {
- // Try to assign the pointer to the first foreground window we find, if there is one.
- newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
- if (newTouchedWindowHandle == NULL) {
- // There is no touched window. If this is an initial down event
- // then wait for a window to appear that will handle the touch. This is
- // to ensure that we report an ANR in the case where an application has started
- // but not yet put up a window and the user is starting to get impatient.
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN
- && mFocusedApplicationHandle != NULL) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, NULL, nextWakeupTime,
- "Waiting because there is no touchable window that can "
- "handle the event but there is focused application that may "
- "eventually add a new window when it finishes starting up.");
- goto Unresponsive;
- }
-
- ALOGI("Dropping event because there is no touched window.");
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
- }
-
- // Set target flags.
- int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS;
- if (isSplit) {
- targetFlags |= InputTarget::FLAG_SPLIT;
- }
- if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
- targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
-
- // Update hover state.
- if (isHoverAction) {
- newHoverWindowHandle = newTouchedWindowHandle;
- } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
- newHoverWindowHandle = mLastHoverWindowHandle;
- }
-
- // Update the temporary touch state.
- BitSet32 pointerIds;
- if (isSplit) {
- uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
- pointerIds.markBit(pointerId);
- }
- mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
- } else {
- /* 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 DEBUG_FOCUS
- ALOGD("Dropping event because the pointer is not down or we previously "
- "dropped the pointer down event.");
-#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()) {
- 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));
-
- sp<InputWindowHandle> oldTouchedWindowHandle =
- mTempTouchState.getFirstForegroundWindowHandle();
- sp<InputWindowHandle> newTouchedWindowHandle =
- findTouchedWindowAtLocked(displayId, x, y);
- if (oldTouchedWindowHandle != newTouchedWindowHandle
- && newTouchedWindowHandle != NULL) {
-#if DEBUG_FOCUS
- ALOGD("Touch is slipping out of window %s into window %s.",
- oldTouchedWindowHandle->getName().string(),
- newTouchedWindowHandle->getName().string());
-#endif
- // Make a slippery exit from the old window.
- mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
- 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;
- if (isSplit) {
- targetFlags |= InputTarget::FLAG_SPLIT;
- }
- if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
- targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
-
- BitSet32 pointerIds;
- if (isSplit) {
- pointerIds.markBit(entry->pointerProperties[0].id);
- }
- mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
- }
- }
- }
-
- if (newHoverWindowHandle != mLastHoverWindowHandle) {
- // Let the previous window know that the hover sequence is over.
- if (mLastHoverWindowHandle != NULL) {
-#if DEBUG_HOVER
- ALOGD("Sending hover exit event to window %s.",
- mLastHoverWindowHandle->getName().string());
-#endif
- mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
- InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
- }
-
- // Let the new window know that the hover sequence is starting.
- if (newHoverWindowHandle != NULL) {
-#if DEBUG_HOVER
- ALOGD("Sending hover enter event to window %s.",
- newHoverWindowHandle->getName().string());
-#endif
- mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
- InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0));
- }
- }
-
- // Check permission to inject into all touched foreground windows and ensure there
- // is at least one touched foreground window.
- {
- bool haveForegroundWindow = false;
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
- if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
- haveForegroundWindow = true;
- if (! checkInjectionPermission(touchedWindow.windowHandle,
- entry->injectionState)) {
- injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- injectionPermission = INJECTION_PERMISSION_DENIED;
- goto Failed;
- }
- }
- }
- if (! haveForegroundWindow) {
-#if DEBUG_FOCUS
- ALOGD("Dropping event because there is no touched foreground window to receive it.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
-
- // Permission granted to injection into all touched foreground windows.
- injectionPermission = INJECTION_PERMISSION_GRANTED;
- }
-
- // Check whether windows listening for outside touches are owned by the same UID. If it is
- // set the policy flag that we will not reveal coordinate information to this window.
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- sp<InputWindowHandle> foregroundWindowHandle =
- mTempTouchState.getFirstForegroundWindowHandle();
- const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
- if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
- sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
- if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
- mTempTouchState.addOrUpdateWindow(inputWindowHandle,
- InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
- }
- }
- }
- }
-
- // Ensure all touched foreground windows are ready for new input.
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
- if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
- // If the touched window is paused then keep waiting.
- if (touchedWindow.windowHandle->getInfo()->paused) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, touchedWindow.windowHandle, nextWakeupTime,
- "Waiting because the touched window is paused.");
- goto Unresponsive;
- }
-
- // If the touched window is still working on previous events then keep waiting.
- if (!isWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle, entry)) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, touchedWindow.windowHandle, nextWakeupTime,
- "Waiting because the touched window has not finished "
- "processing the input events that were previously delivered to it.");
- goto Unresponsive;
- }
- }
- }
-
- // If this is the first pointer going down and the touched window has a wallpaper
- // then also add the touched wallpaper windows so they are locked in for the duration
- // of the touch gesture.
- // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
- // engine only supports touch events. We would need to add a mechanism similar
- // to View.onGenericMotionEvent to enable wallpapers to handle these events.
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- sp<InputWindowHandle> foregroundWindowHandle =
- mTempTouchState.getFirstForegroundWindowHandle();
- if (foregroundWindowHandle->getInfo()->hasWallpaper) {
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
- 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_DISPATCH_AS_IS,
- BitSet32(0));
- }
- }
- }
- }
-
- // Success! Output targets.
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
- addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
- touchedWindow.pointerIds, inputTargets);
- }
-
- // Drop the outside or hover touch windows since we will not care about them
- // in the next iteration.
- mTempTouchState.filterNonAsIsTouchWindows();
-
-Failed:
- // Check injection permission once and for all.
- if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
- if (checkInjectionPermission(NULL, entry->injectionState)) {
- injectionPermission = INJECTION_PERMISSION_GRANTED;
- } else {
- injectionPermission = INJECTION_PERMISSION_DENIED;
- }
- }
-
- // Update final pieces of touch state if the injector had permission.
- if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
- if (!wrongDevice) {
- if (switchedDevice) {
-#if DEBUG_FOCUS
- ALOGD("Conflicting pointer actions: Switched to a different device.");
-#endif
- *outConflictingPointerActions = true;
- }
-
- if (isHoverAction) {
- // Started hovering, therefore no longer down.
- if (mTouchState.down) {
-#if DEBUG_FOCUS
- ALOGD("Conflicting pointer actions: Hover received while pointer was down.");
-#endif
- *outConflictingPointerActions = true;
- }
- mTouchState.reset();
- if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
- || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
- mTouchState.deviceId = entry->deviceId;
- mTouchState.source = entry->source;
- mTouchState.displayId = displayId;
- }
- } else if (maskedAction == AMOTION_EVENT_ACTION_UP
- || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
- // All pointers up or canceled.
- mTouchState.reset();
- } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- // First pointer went down.
- if (mTouchState.down) {
-#if DEBUG_FOCUS
- ALOGD("Conflicting pointer actions: Down received while already down.");
-#endif
- *outConflictingPointerActions = true;
- }
- mTouchState.copyFrom(mTempTouchState);
- } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
- // One pointer went up.
- if (isSplit) {
- int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
-
- for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
- TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
- if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
- touchedWindow.pointerIds.clearBit(pointerId);
- if (touchedWindow.pointerIds.isEmpty()) {
- mTempTouchState.windows.removeAt(i);
- continue;
- }
- }
- i += 1;
- }
- }
- mTouchState.copyFrom(mTempTouchState);
- } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
- // Discard temporary touch state since it was only valid for this action.
- } else {
- // Save changes to touch state as-is for all other actions.
- mTouchState.copyFrom(mTempTouchState);
- }
-
- // Update hover state.
- mLastHoverWindowHandle = newHoverWindowHandle;
- }
- } else {
-#if DEBUG_FOCUS
- ALOGD("Not updating touch focus because injection was denied.");
-#endif
- }
-
-Unresponsive:
- // Reset temporary touch state to ensure we release unnecessary references to input channels.
- mTempTouchState.reset();
-
- nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatisticsLocked(currentTime, entry,
- injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
- ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
-#endif
- return injectionResult;
-}
-
-void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
- int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {
- inputTargets.push();
-
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
- InputTarget& target = inputTargets.editTop();
- target.inputChannel = windowInfo->inputChannel;
- target.flags = targetFlags;
- target.xOffset = - windowInfo->frameLeft;
- target.yOffset = - windowInfo->frameTop;
- target.scaleFactor = windowInfo->scaleFactor;
- target.pointerIds = pointerIds;
-}
-
-void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets) {
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- inputTargets.push();
-
- InputTarget& target = inputTargets.editTop();
- target.inputChannel = mMonitoringChannels[i];
- target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
- target.xOffset = 0;
- target.yOffset = 0;
- target.pointerIds.clear();
- target.scaleFactor = 1.0f;
- }
-}
-
-bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
- const InjectionState* injectionState) {
- if (injectionState
- && (windowHandle == NULL
- || windowHandle->getInfo()->ownerUid != injectionState->injectorUid)
- && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
- if (windowHandle != NULL) {
- ALOGW("Permission denied: injecting event from pid %d uid %d to window %s "
- "owned by uid %d",
- injectionState->injectorPid, injectionState->injectorUid,
- windowHandle->getName().string(),
- windowHandle->getInfo()->ownerUid);
- } else {
- ALOGW("Permission denied: injecting event from pid %d uid %d",
- injectionState->injectorPid, injectionState->injectorUid);
- }
- return false;
- }
- return true;
-}
-
-bool InputDispatcher::isWindowObscuredAtPointLocked(
- const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
- int32_t displayId = windowHandle->getInfo()->displayId;
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
- if (otherHandle == windowHandle) {
- break;
- }
-
- const InputWindowInfo* otherInfo = otherHandle->getInfo();
- if (otherInfo->displayId == displayId
- && otherInfo->visible && !otherInfo->isTrustedOverlay()
- && otherInfo->frameContainsPoint(x, y)) {
- return true;
- }
- }
- return false;
-}
-
-bool InputDispatcher::isWindowReadyForMoreInputLocked(nsecs_t currentTime,
- const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry) {
- ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->getInputChannel());
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- if (connection->inputPublisherBlocked) {
- return false;
- }
- if (eventEntry->type == EventEntry::TYPE_KEY) {
- // If the event is a key event, then we must wait for all previous events to
- // complete before delivering it because previous events may have the
- // side-effect of transferring focus to a different window and we want to
- // ensure that the following keys are sent to the new window.
- //
- // Suppose the user touches a button in a window then immediately presses "A".
- // If the button causes a pop-up window to appear then we want to ensure that
- // the "A" key is delivered to the new pop-up window. This is because users
- // often anticipate pending UI changes when typing on a keyboard.
- // To obtain this behavior, we must serialize key events with respect to all
- // prior input events.
- return connection->outboundQueue.isEmpty()
- && connection->waitQueue.isEmpty();
- }
- // Touch events can always be sent to a window immediately because the user intended
- // to touch whatever was visible at the time. Even if focus changes or a new
- // window appears moments later, the touch event was meant to be delivered to
- // whatever window happened to be on screen at the time.
- //
- // Generic motion events, such as trackball or joystick events are a little trickier.
- // Like key events, generic motion events are delivered to the focused window.
- // Unlike key events, generic motion events don't tend to transfer focus to other
- // windows and it is not important for them to be serialized. So we prefer to deliver
- // generic motion events as soon as possible to improve efficiency and reduce lag
- // through batching.
- //
- // 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->eventEntry->eventTime
- + STREAM_AHEAD_EVENT_TIMEOUT) {
- return false;
- }
- }
- return true;
-}
-
-String8 InputDispatcher::getApplicationWindowLabelLocked(
- const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle) {
- if (applicationHandle != NULL) {
- if (windowHandle != NULL) {
- String8 label(applicationHandle->getName());
- label.append(" - ");
- label.append(windowHandle->getName());
- return label;
- } else {
- return applicationHandle->getName();
- }
- } else if (windowHandle != NULL) {
- return windowHandle->getName();
- } else {
- return String8("<unknown application or window>");
- }
-}
-
-void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
- if (mFocusedWindowHandle != NULL) {
- const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
- if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("Not poking user activity: disabled by window '%s'.", info->name.string());
-#endif
- return;
- }
- }
-
- 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;
- }
-
- if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
- eventType = USER_ACTIVITY_EVENT_TOUCH;
- }
- 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->eventTime = eventEntry->eventTime;
- commandEntry->userActivityEventType = eventType;
-}
-
-void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
- "xOffset=%f, yOffset=%f, scaleFactor=%f, "
- "pointerIds=0x%x",
- connection->getInputChannelName(), inputTarget->flags,
- inputTarget->xOffset, inputTarget->yOffset,
- inputTarget->scaleFactor, inputTarget->pointerIds.value);
-#endif
-
- // Skip this event if the connection status is not normal.
- // We don't want to enqueue additional outbound events if the connection is broken.
- if (connection->status != Connection::STATUS_NORMAL) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
- connection->getInputChannelName(), connection->getStatusLabel());
-#endif
- return;
- }
-
- // Split a motion event if needed.
- if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
- ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION);
-
- MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
- if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
- MotionEntry* splitMotionEntry = splitMotionEvent(
- originalMotionEntry, inputTarget->pointerIds);
- if (!splitMotionEntry) {
- return; // split event was dropped
- }
-#if DEBUG_FOCUS
- ALOGD("channel '%s' ~ Split motion event.",
- connection->getInputChannelName());
- logOutboundMotionDetailsLocked(" ", splitMotionEntry);
-#endif
- enqueueDispatchEntriesLocked(currentTime, connection,
- splitMotionEntry, inputTarget);
- splitMotionEntry->release();
- return;
- }
- }
-
- // Not splitting. Enqueue dispatch entries for the event as is.
- enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
-}
-
-void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
- const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
- bool wasEmpty = connection->outboundQueue.isEmpty();
-
- // Enqueue dispatch entries for the requested modes.
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_IS);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
-
- // If the outbound queue was previously empty, start the dispatch cycle going.
- if (wasEmpty && !connection->outboundQueue.isEmpty()) {
- startDispatchCycleLocked(currentTime, connection);
- }
-}
-
-void InputDispatcher::enqueueDispatchEntryLocked(
- const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
- int32_t dispatchMode) {
- int32_t inputTargetFlags = inputTarget->flags;
- if (!(inputTargetFlags & dispatchMode)) {
- return;
- }
- inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
-
- // 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->scaleFactor);
-
- // 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;
-
- if (!connection->inputState.trackKey(keyEntry,
- dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
- connection->getInputChannelName());
-#endif
- 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;
- }
- 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());
-#endif
- 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 (!connection->inputState.trackMotion(motionEntry,
- dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
- connection->getInputChannelName());
-#endif
- delete dispatchEntry;
- return; // skip the inconsistent event
- }
- break;
- }
- }
-
- // Remember that we are waiting for this dispatch to complete.
- if (dispatchEntry->hasForegroundTarget()) {
- incrementPendingForegroundDispatchesLocked(eventEntry);
- }
-
- // Enqueue the dispatch entry.
- connection->outboundQueue.enqueueAtTail(dispatchEntry);
- traceOutboundQueueLengthLocked(connection);
-}
-
-void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ startDispatchCycle",
- connection->getInputChannelName());
-#endif
-
- while (connection->status == Connection::STATUS_NORMAL
- && !connection->outboundQueue.isEmpty()) {
- DispatchEntry* dispatchEntry = connection->outboundQueue.head;
- dispatchEntry->deliveryTime = currentTime;
-
- // Publish the event.
- 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,
- dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
- keyEntry->keyCode, keyEntry->scanCode,
- keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
- keyEntry->eventTime);
- break;
- }
-
- 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, scaleFactor;
- if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
- && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
- scaleFactor = dispatchEntry->scaleFactor;
- xOffset = dispatchEntry->xOffset * scaleFactor;
- yOffset = dispatchEntry->yOffset * scaleFactor;
- if (scaleFactor != 1.0f) {
- for (size_t i = 0; i < motionEntry->pointerCount; i++) {
- scaledCoords[i] = motionEntry->pointerCoords[i];
- scaledCoords[i].scale(scaleFactor);
- }
- usingCoords = scaledCoords;
- }
- } else {
- xOffset = 0.0f;
- yOffset = 0.0f;
- scaleFactor = 1.0f;
-
- // We don't want the dispatch target to know.
- if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
- for (size_t i = 0; i < motionEntry->pointerCount; i++) {
- scaledCoords[i].clear();
- }
- usingCoords = scaledCoords;
- }
- }
-
- // Publish the motion event.
- status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
- motionEntry->deviceId, motionEntry->source,
- dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
- motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
- xOffset, yOffset,
- motionEntry->xPrecision, motionEntry->yPrecision,
- motionEntry->downTime, motionEntry->eventTime,
- motionEntry->pointerCount, motionEntry->pointerProperties,
- usingCoords);
- break;
- }
-
- default:
- ALOG_ASSERT(false);
- return;
- }
-
- // Check the result.
- if (status) {
- 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(), 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());
-#endif
- connection->inputPublisherBlocked = true;
- }
- } else {
- ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
- "status=%d", connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
- }
- return;
- }
-
- // Re-enqueue the event on the wait queue.
- connection->outboundQueue.dequeue(dispatchEntry);
- traceOutboundQueueLengthLocked(connection);
- connection->waitQueue.enqueueAtTail(dispatchEntry);
- traceWaitQueueLengthLocked(connection);
- }
-}
-
-void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, uint32_t seq, bool handled) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
- connection->getInputChannelName(), seq, toString(handled));
-#endif
-
- connection->inputPublisherBlocked = false;
-
- if (connection->status == Connection::STATUS_BROKEN
- || connection->status == Connection::STATUS_ZOMBIE) {
- return;
- }
-
- // Notify other system components and prepare to start the next dispatch cycle.
- onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
-}
-
-void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, bool notify) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s",
- connection->getInputChannelName(), toString(notify));
-#endif
-
- // Clear the dispatch queues.
- drainDispatchQueueLocked(&connection->outboundQueue);
- traceOutboundQueueLengthLocked(connection);
- drainDispatchQueueLocked(&connection->waitQueue);
- traceWaitQueueLengthLocked(connection);
-
- // The connection appears to be unrecoverably broken.
- // Ignore already broken or zombie connections.
- if (connection->status == Connection::STATUS_NORMAL) {
- connection->status = Connection::STATUS_BROKEN;
-
- if (notify) {
- // Notify other system components.
- onDispatchCycleBrokenLocked(currentTime, connection);
- }
- }
-}
-
-void InputDispatcher::drainDispatchQueueLocked(Queue<DispatchEntry>* queue) {
- while (!queue->isEmpty()) {
- DispatchEntry* dispatchEntry = queue->dequeueAtHead();
- releaseDispatchEntryLocked(dispatchEntry);
- }
-}
-
-void InputDispatcher::releaseDispatchEntryLocked(DispatchEntry* dispatchEntry) {
- if (dispatchEntry->hasForegroundTarget()) {
- decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
- }
- delete dispatchEntry;
-}
-
-int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
- InputDispatcher* d = static_cast<InputDispatcher*>(data);
-
- { // acquire lock
- AutoMutex _l(d->mLock);
-
- 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);
- return 0; // remove the callback
- }
-
- bool notify;
- sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
- 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(), events);
- return 1;
- }
-
- nsecs_t currentTime = now();
- bool gotOne = false;
- status_t status;
- for (;;) {
- uint32_t seq;
- bool handled;
- status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
- if (status) {
- break;
- }
- d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
- gotOne = true;
- }
- if (gotOne) {
- d->runCommandsLockedInterruptible();
- if (status == WOULD_BLOCK) {
- return 1;
- }
- }
-
- notify = status != DEAD_OBJECT || !connection->monitor;
- if (notify) {
- ALOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
- connection->getInputChannelName(), status);
- }
- } else {
- // Monitor channels are never explicitly unregistered.
- // We do it automatically when the remote endpoint is closed so don't warn
- // about them.
- notify = !connection->monitor;
- if (notify) {
- ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. "
- "events=0x%x", connection->getInputChannelName(), events);
- }
- }
-
- // Unregister the channel.
- d->unregisterInputChannelLocked(connection->inputChannel, notify);
- return 0; // remove the callback
- } // release lock
-}
-
-void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
- const CancelationOptions& options) {
- for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
- synthesizeCancelationEventsForConnectionLocked(
- mConnectionsByFd.valueAt(i), options);
- }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
- const sp<InputChannel>& channel, const CancelationOptions& options) {
- ssize_t index = getConnectionIndexLocked(channel);
- if (index >= 0) {
- synthesizeCancelationEventsForConnectionLocked(
- mConnectionsByFd.valueAt(index), options);
- }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
- const sp<Connection>& connection, const CancelationOptions& options) {
- if (connection->status == Connection::STATUS_BROKEN) {
- return;
- }
-
- nsecs_t currentTime = now();
-
- Vector<EventEntry*> cancelationEvents;
- connection->inputState.synthesizeCancelationEvents(currentTime,
- cancelationEvents, options);
-
- if (!cancelationEvents.isEmpty()) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
- "with reality: %s, mode=%d.",
- connection->getInputChannelName(), cancelationEvents.size(),
- options.reason, options.mode);
-#endif
- for (size_t i = 0; i < cancelationEvents.size(); i++) {
- EventEntry* cancelationEventEntry = cancelationEvents.itemAt(i);
- switch (cancelationEventEntry->type) {
- case EventEntry::TYPE_KEY:
- logOutboundKeyDetailsLocked("cancel - ",
- static_cast<KeyEntry*>(cancelationEventEntry));
- break;
- case EventEntry::TYPE_MOTION:
- logOutboundMotionDetailsLocked("cancel - ",
- static_cast<MotionEntry*>(cancelationEventEntry));
- break;
- }
-
- InputTarget target;
- sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
- if (windowHandle != NULL) {
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
- target.xOffset = -windowInfo->frameLeft;
- target.yOffset = -windowInfo->frameTop;
- target.scaleFactor = windowInfo->scaleFactor;
- } else {
- target.xOffset = 0;
- target.yOffset = 0;
- target.scaleFactor = 1.0f;
- }
- target.inputChannel = connection->inputChannel;
- target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
-
- enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
- &target, InputTarget::FLAG_DISPATCH_AS_IS);
-
- cancelationEventEntry->release();
- }
-
- startDispatchCycleLocked(currentTime, connection);
- }
-}
-
-InputDispatcher::MotionEntry*
-InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
- ALOG_ASSERT(pointerIds.value != 0);
-
- PointerProperties splitPointerProperties[MAX_POINTERS];
- PointerCoords splitPointerCoords[MAX_POINTERS];
-
- uint32_t originalPointerCount = originalMotionEntry->pointerCount;
- uint32_t splitPointerCount = 0;
-
- for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
- originalPointerIndex++) {
- const PointerProperties& pointerProperties =
- originalMotionEntry->pointerProperties[originalPointerIndex];
- uint32_t pointerId = uint32_t(pointerProperties.id);
- if (pointerIds.hasBit(pointerId)) {
- splitPointerProperties[splitPointerCount].copyFrom(pointerProperties);
- splitPointerCoords[splitPointerCount].copyFrom(
- originalMotionEntry->pointerCoords[originalPointerIndex]);
- splitPointerCount += 1;
- }
- }
-
- if (splitPointerCount != pointerIds.count()) {
- // This is bad. We are missing some of the pointers that we expected to deliver.
- // Most likely this indicates that we received an ACTION_MOVE events that has
- // different pointer ids than we expected based on the previous ACTION_DOWN
- // 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());
- return NULL;
- }
-
- 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) {
- int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
- const PointerProperties& pointerProperties =
- originalMotionEntry->pointerProperties[originalPointerIndex];
- uint32_t pointerId = uint32_t(pointerProperties.id);
- if (pointerIds.hasBit(pointerId)) {
- 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;
- } 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);
- }
- } else {
- // An unrelated pointer changed.
- action = AMOTION_EVENT_ACTION_MOVE;
- }
- }
-
- MotionEntry* splitMotionEntry = new MotionEntry(
- originalMotionEntry->eventTime,
- originalMotionEntry->deviceId,
- originalMotionEntry->source,
- originalMotionEntry->policyFlags,
- action,
- originalMotionEntry->flags,
- originalMotionEntry->metaState,
- originalMotionEntry->buttonState,
- originalMotionEntry->edgeFlags,
- originalMotionEntry->xPrecision,
- originalMotionEntry->yPrecision,
- originalMotionEntry->downTime,
- originalMotionEntry->displayId,
- splitPointerCount, splitPointerProperties, splitPointerCoords);
-
- if (originalMotionEntry->injectionState) {
- splitMotionEntry->injectionState = originalMotionEntry->injectionState;
- splitMotionEntry->injectionState->refCount += 1;
- }
-
- return splitMotionEntry;
-}
-
-void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyConfigurationChanged - eventTime=%lld", args->eventTime);
-#endif
-
- bool needWake;
- { // acquire lock
- AutoMutex _l(mLock);
-
- ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime);
- needWake = enqueueInboundEventLocked(newEntry);
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
- "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
- args->eventTime, args->deviceId, args->source, args->policyFlags,
- args->action, args->flags, args->keyCode, args->scanCode,
- args->metaState, args->downTime);
-#endif
- if (!validateKeyEvent(args->action)) {
- return;
- }
-
- uint32_t policyFlags = args->policyFlags;
- int32_t flags = args->flags;
- int32_t metaState = args->metaState;
- if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
- policyFlags |= POLICY_FLAG_VIRTUAL;
- flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
- }
- if (policyFlags & POLICY_FLAG_ALT) {
- metaState |= AMETA_ALT_ON | AMETA_ALT_LEFT_ON;
- }
- if (policyFlags & POLICY_FLAG_ALT_GR) {
- metaState |= AMETA_ALT_ON | AMETA_ALT_RIGHT_ON;
- }
- if (policyFlags & POLICY_FLAG_SHIFT) {
- metaState |= AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON;
- }
- if (policyFlags & POLICY_FLAG_CAPS_LOCK) {
- metaState |= AMETA_CAPS_LOCK_ON;
- }
- if (policyFlags & POLICY_FLAG_FUNCTION) {
- metaState |= AMETA_FUNCTION_ON;
- }
-
- policyFlags |= POLICY_FLAG_TRUSTED;
-
- KeyEvent event;
- event.initialize(args->deviceId, args->source, args->action,
- flags, args->keyCode, args->scanCode, metaState, 0,
- args->downTime, args->eventTime);
-
- mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
-
- if (policyFlags & POLICY_FLAG_WOKE_HERE) {
- flags |= AKEY_EVENT_FLAG_WOKE_HERE;
- }
-
- bool needWake;
- { // acquire lock
- mLock.lock();
-
- if (shouldSendKeyToInputFilterLocked(args)) {
- mLock.unlock();
-
- policyFlags |= POLICY_FLAG_FILTERED;
- if (!mPolicy->filterInputEvent(&event, policyFlags)) {
- return; // event was consumed by the filter
- }
-
- mLock.lock();
- }
-
- int32_t repeatCount = 0;
- KeyEntry* newEntry = new KeyEntry(args->eventTime,
- args->deviceId, args->source, policyFlags,
- args->action, flags, args->keyCode, args->scanCode,
- metaState, repeatCount, args->downTime);
-
- needWake = enqueueInboundEventLocked(newEntry);
- mLock.unlock();
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) {
- return mInputFilterEnabled;
-}
-
-void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, edgeFlags=0x%x, "
- "xPrecision=%f, yPrecision=%f, downTime=%lld",
- args->eventTime, args->deviceId, args->source, args->policyFlags,
- args->action, 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));
- }
-#endif
- if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) {
- return;
- }
-
- uint32_t policyFlags = args->policyFlags;
- policyFlags |= POLICY_FLAG_TRUSTED;
- mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
-
- bool needWake;
- { // acquire lock
- mLock.lock();
-
- if (shouldSendMotionToInputFilterLocked(args)) {
- mLock.unlock();
-
- MotionEvent event;
- event.initialize(args->deviceId, args->source, args->action, args->flags,
- args->edgeFlags, args->metaState, args->buttonState, 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)) {
- return; // event was consumed by the filter
- }
-
- mLock.lock();
- }
-
- // Just enqueue a new motion event.
- MotionEntry* newEntry = new MotionEntry(args->eventTime,
- args->deviceId, args->source, policyFlags,
- args->action, args->flags, args->metaState, args->buttonState,
- args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
- args->displayId,
- args->pointerCount, args->pointerProperties, args->pointerCoords);
-
- needWake = enqueueInboundEventLocked(newEntry);
- mLock.unlock();
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) {
- // TODO: support sending secondary display events to input filter
- return mInputFilterEnabled && isMainDisplay(args->displayId);
-}
-
-void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchValues=0x%08x, 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);
-}
-
-void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyDeviceReset - eventTime=%lld, deviceId=%d",
- args->eventTime, args->deviceId);
-#endif
-
- bool needWake;
- { // acquire lock
- AutoMutex _l(mLock);
-
- DeviceResetEntry* newEntry = new DeviceResetEntry(args->eventTime, args->deviceId);
- needWake = enqueueInboundEventLocked(newEntry);
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-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);
-#endif
-
- nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
-
- policyFlags |= POLICY_FLAG_INJECTED;
- if (hasInjectionPermission(injectorPid, injectorUid)) {
- policyFlags |= POLICY_FLAG_TRUSTED;
- }
-
- EventEntry* firstInjectedEntry;
- EventEntry* lastInjectedEntry;
- switch (event->getType()) {
- case AINPUT_EVENT_TYPE_KEY: {
- const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
- int32_t action = keyEvent->getAction();
- if (! validateKeyEvent(action)) {
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- int32_t flags = keyEvent->getFlags();
- if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
- policyFlags |= POLICY_FLAG_VIRTUAL;
- }
-
- if (!(policyFlags & POLICY_FLAG_FILTERED)) {
- mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
- }
-
- if (policyFlags & POLICY_FLAG_WOKE_HERE) {
- flags |= AKEY_EVENT_FLAG_WOKE_HERE;
- }
-
- mLock.lock();
- firstInjectedEntry = new KeyEntry(keyEvent->getEventTime(),
- keyEvent->getDeviceId(), keyEvent->getSource(),
- 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 displayId = ADISPLAY_ID_DEFAULT;
- int32_t action = motionEvent->getAction();
- size_t pointerCount = motionEvent->getPointerCount();
- const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
- if (! validateMotionEvent(action, pointerCount, pointerProperties)) {
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- if (!(policyFlags & POLICY_FLAG_FILTERED)) {
- nsecs_t eventTime = motionEvent->getEventTime();
- mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
- }
-
- mLock.lock();
- const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
- const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
- firstInjectedEntry = new MotionEntry(*sampleEventTimes,
- motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
- action, motionEvent->getFlags(),
- motionEvent->getMetaState(), motionEvent->getButtonState(),
- motionEvent->getEdgeFlags(),
- motionEvent->getXPrecision(), motionEvent->getYPrecision(),
- motionEvent->getDownTime(), displayId,
- uint32_t(pointerCount), pointerProperties, samplePointerCoords);
- lastInjectedEntry = firstInjectedEntry;
- for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
- sampleEventTimes += 1;
- samplePointerCoords += pointerCount;
- MotionEntry* nextInjectedEntry = new MotionEntry(*sampleEventTimes,
- motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
- action, motionEvent->getFlags(),
- motionEvent->getMetaState(), motionEvent->getButtonState(),
- motionEvent->getEdgeFlags(),
- motionEvent->getXPrecision(), motionEvent->getYPrecision(),
- motionEvent->getDownTime(), displayId,
- uint32_t(pointerCount), pointerProperties, samplePointerCoords);
- 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);
- if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
- injectionState->injectionIsAsync = true;
- }
-
- injectionState->refCount += 1;
- lastInjectedEntry->injectionState = injectionState;
-
- bool needWake = false;
- for (EventEntry* entry = firstInjectedEntry; entry != NULL; ) {
- EventEntry* nextEntry = entry->next;
- needWake |= enqueueInboundEventLocked(entry);
- entry = nextEntry;
- }
-
- mLock.unlock();
-
- if (needWake) {
- mLooper->wake();
- }
-
- int32_t injectionResult;
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
- } else {
- for (;;) {
- injectionResult = injectionState->injectionResult;
- if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
- break;
- }
-
- nsecs_t remainingTimeout = endTime - now();
- if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
- ALOGD("injectInputEvent - Timed out waiting for injection result "
- "to become available.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
- break;
- }
-
- mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
- }
-
- 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);
-#endif
- nsecs_t remainingTimeout = endTime - now();
- if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
- ALOGD("injectInputEvent - Timed out waiting for pending foreground "
- "dispatches to finish.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
- break;
- }
-
- mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
- }
- }
- }
-
- injectionState->release();
- } // release lock
-
-#if DEBUG_INJECTION
- ALOGD("injectInputEvent - Finished with result %d. "
- "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);
-}
-
-void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState) {
-#if DEBUG_INJECTION
- ALOGD("Setting input event injection result to %d. "
- "injectorPid=%d, injectorUid=%d",
- injectionResult, injectionState->injectorPid, injectionState->injectorUid);
-#endif
-
- 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;
- }
- }
-
- injectionState->injectionResult = injectionResult;
- mInjectionResultAvailableCondition.broadcast();
- }
-}
-
-void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState) {
- injectionState->pendingForegroundDispatches += 1;
- }
-}
-
-void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState) {
- injectionState->pendingForegroundDispatches -= 1;
-
- if (injectionState->pendingForegroundDispatches == 0) {
- mInjectionSyncFinishedCondition.broadcast();
- }
- }
-}
-
-sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
- const sp<InputChannel>& inputChannel) const {
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- if (windowHandle->getInputChannel() == inputChannel) {
- return windowHandle;
- }
- }
- return NULL;
-}
-
-bool InputDispatcher::hasWindowHandleLocked(
- const sp<InputWindowHandle>& windowHandle) const {
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- if (mWindowHandles.itemAt(i) == windowHandle) {
- return true;
- }
- }
- return false;
-}
-
-void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
-#if DEBUG_FOCUS
- ALOGD("setInputWindows");
-#endif
- { // acquire lock
- AutoMutex _l(mLock);
-
- Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
- mWindowHandles = inputWindowHandles;
-
- sp<InputWindowHandle> newFocusedWindowHandle;
- bool foundHoveredWindow = false;
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) {
- mWindowHandles.removeAt(i--);
- continue;
- }
- if (windowHandle->getInfo()->hasFocus) {
- newFocusedWindowHandle = windowHandle;
- }
- if (windowHandle == mLastHoverWindowHandle) {
- foundHoveredWindow = true;
- }
- }
-
- if (!foundHoveredWindow) {
- mLastHoverWindowHandle = NULL;
- }
-
- if (mFocusedWindowHandle != newFocusedWindowHandle) {
- if (mFocusedWindowHandle != NULL) {
-#if DEBUG_FOCUS
- ALOGD("Focus left window: %s",
- mFocusedWindowHandle->getName().string());
-#endif
- sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
- if (focusedInputChannel != NULL) {
- CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
- "focus left window");
- synthesizeCancelationEventsForInputChannelLocked(
- focusedInputChannel, options);
- }
- }
- if (newFocusedWindowHandle != NULL) {
-#if DEBUG_FOCUS
- ALOGD("Focus entered window: %s",
- newFocusedWindowHandle->getName().string());
-#endif
- }
- mFocusedWindowHandle = newFocusedWindowHandle;
- }
-
- for (size_t i = 0; i < mTouchState.windows.size(); i++) {
- TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
- if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
-#if DEBUG_FOCUS
- ALOGD("Touched window was removed: %s",
- touchedWindow.windowHandle->getName().string());
-#endif
- sp<InputChannel> touchedInputChannel =
- touchedWindow.windowHandle->getInputChannel();
- if (touchedInputChannel != NULL) {
- CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "touched window was removed");
- synthesizeCancelationEventsForInputChannelLocked(
- touchedInputChannel, options);
- }
- mTouchState.windows.removeAt(i--);
- }
- }
-
- // Release information for windows that are no longer present.
- // This ensures that unused input channels are released promptly.
- // Otherwise, they might stick around until the window handle is destroyed
- // which might not happen until the next GC.
- for (size_t i = 0; i < oldWindowHandles.size(); i++) {
- const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i);
- if (!hasWindowHandleLocked(oldWindowHandle)) {
-#if DEBUG_FOCUS
- ALOGD("Window went away: %s", oldWindowHandle->getName().string());
-#endif
- oldWindowHandle->releaseInfo();
- }
- }
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
-}
-
-void InputDispatcher::setFocusedApplication(
- const sp<InputApplicationHandle>& inputApplicationHandle) {
-#if DEBUG_FOCUS
- ALOGD("setFocusedApplication");
-#endif
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (inputApplicationHandle != NULL && inputApplicationHandle->updateInfo()) {
- if (mFocusedApplicationHandle != inputApplicationHandle) {
- if (mFocusedApplicationHandle != NULL) {
- resetANRTimeoutsLocked();
- mFocusedApplicationHandle->releaseInfo();
- }
- mFocusedApplicationHandle = inputApplicationHandle;
- }
- } else if (mFocusedApplicationHandle != NULL) {
- resetANRTimeoutsLocked();
- mFocusedApplicationHandle->releaseInfo();
- mFocusedApplicationHandle.clear();
- }
-
-#if DEBUG_FOCUS
- //logDispatchStateLocked();
-#endif
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
-}
-
-void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
-#if DEBUG_FOCUS
- ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
-#endif
-
- bool changed;
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
- if (mDispatchFrozen && !frozen) {
- resetANRTimeoutsLocked();
- }
-
- if (mDispatchEnabled && !enabled) {
- resetAndDropEverythingLocked("dispatcher is being disabled");
- }
-
- mDispatchEnabled = enabled;
- mDispatchFrozen = frozen;
- changed = true;
- } else {
- changed = false;
- }
-
-#if DEBUG_FOCUS
- //logDispatchStateLocked();
-#endif
- } // release lock
-
- if (changed) {
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
- }
-}
-
-void InputDispatcher::setInputFilterEnabled(bool enabled) {
-#if DEBUG_FOCUS
- ALOGD("setInputFilterEnabled: enabled=%d", enabled);
-#endif
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (mInputFilterEnabled == enabled) {
- return;
- }
-
- mInputFilterEnabled = enabled;
- resetAndDropEverythingLocked("input filter is being enabled or disabled");
- } // release lock
-
- // Wake up poll loop since there might be work to do to drop everything.
- mLooper->wake();
-}
-
-bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel) {
-#if DEBUG_FOCUS
- ALOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
- fromChannel->getName().string(), toChannel->getName().string());
-#endif
- { // acquire lock
- AutoMutex _l(mLock);
-
- sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel);
- sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel);
- if (fromWindowHandle == NULL || toWindowHandle == NULL) {
-#if DEBUG_FOCUS
- ALOGD("Cannot transfer focus because from or to window not found.");
-#endif
- return false;
- }
- if (fromWindowHandle == toWindowHandle) {
-#if DEBUG_FOCUS
- ALOGD("Trivial transfer to same window.");
-#endif
- return true;
- }
- if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) {
-#if DEBUG_FOCUS
- ALOGD("Cannot transfer focus because windows are on different displays.");
-#endif
- return false;
- }
-
- bool found = false;
- for (size_t i = 0; i < mTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTouchState.windows[i];
- if (touchedWindow.windowHandle == fromWindowHandle) {
- int32_t oldTargetFlags = touchedWindow.targetFlags;
- BitSet32 pointerIds = touchedWindow.pointerIds;
-
- mTouchState.windows.removeAt(i);
-
- int32_t newTargetFlags = oldTargetFlags
- & (InputTarget::FLAG_FOREGROUND
- | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
- mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
-
- found = true;
- break;
- }
- }
-
- if (! found) {
-#if DEBUG_FOCUS
- ALOGD("Focus transfer failed because from window did not have focus.");
-#endif
- return false;
- }
-
- ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
- ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
- if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
- sp<Connection> fromConnection = mConnectionsByFd.valueAt(fromConnectionIndex);
- 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");
- synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
- }
-
-#if DEBUG_FOCUS
- logDispatchStateLocked();
-#endif
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
- return true;
-}
-
-void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
-#if DEBUG_FOCUS
- ALOGD("Resetting and dropping all events (%s).", reason);
-#endif
-
- CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, reason);
- synthesizeCancelationEventsForAllConnectionsLocked(options);
-
- resetKeyRepeatLocked();
- releasePendingEventLocked();
- drainInboundQueueLocked();
- resetANRTimeoutsLocked();
-
- mTouchState.reset();
- mLastHoverWindowHandle.clear();
-}
-
-void InputDispatcher::logDispatchStateLocked() {
- String8 dump;
- dumpDispatchStateLocked(dump);
-
- char* text = dump.lockBuffer(dump.size());
- char* start = text;
- while (*start != '\0') {
- char* end = strchr(start, '\n');
- if (*end == '\n') {
- *(end++) = '\0';
- }
- ALOGD("%s", start);
- start = end;
- }
-}
-
-void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
- dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
- dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
-
- if (mFocusedApplicationHandle != NULL) {
- dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
- mFocusedApplicationHandle->getName().string(),
- mFocusedApplicationHandle->getDispatchingTimeout(
- DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
- } else {
- dump.append(INDENT "FocusedApplication: <null>\n");
- }
- dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
- mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>");
-
- dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
- dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
- dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
- dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source);
- dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId);
- if (!mTouchState.windows.isEmpty()) {
- dump.append(INDENT "TouchedWindows:\n");
- for (size_t i = 0; i < mTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTouchState.windows[i];
- dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
- i, touchedWindow.windowHandle->getName().string(),
- touchedWindow.pointerIds.value,
- touchedWindow.targetFlags);
- }
- } else {
- dump.append(INDENT "TouchedWindows: <none>\n");
- }
-
- if (!mWindowHandles.isEmpty()) {
- dump.append(INDENT "Windows:\n");
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
-
- dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, "
- "paused=%s, hasFocus=%s, hasWallpaper=%s, "
- "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
- "frame=[%d,%d][%d,%d], scale=%f, "
- "touchableRegion=",
- i, windowInfo->name.string(), windowInfo->displayId,
- 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->scaleFactor);
- dumpRegion(dump, windowInfo->touchableRegion);
- dump.appendFormat(", inputFeatures=0x%08x", windowInfo->inputFeatures);
- dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
- windowInfo->ownerPid, windowInfo->ownerUid,
- windowInfo->dispatchingTimeout / 1000000.0);
- }
- } else {
- dump.append(INDENT "Windows: <none>\n");
- }
-
- if (!mMonitoringChannels.isEmpty()) {
- dump.append(INDENT "MonitoringChannels:\n");
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- const sp<InputChannel>& channel = mMonitoringChannels[i];
- dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
- }
- } else {
- dump.append(INDENT "MonitoringChannels: <none>\n");
- }
-
- nsecs_t currentTime = now();
-
- if (!mInboundQueue.isEmpty()) {
- dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
- for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) {
- dump.append(INDENT2);
- entry->appendDescription(dump);
- dump.appendFormat(", age=%0.1fms\n",
- (currentTime - entry->eventTime) * 0.000001f);
- }
- } else {
- dump.append(INDENT "InboundQueue: <empty>\n");
- }
-
- if (!mConnectionsByFd.isEmpty()) {
- dump.append(INDENT "Connections:\n");
- for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
- const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
- dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', "
- "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
- i, connection->getInputChannelName(), connection->getWindowName(),
- connection->getStatusLabel(), toString(connection->monitor),
- toString(connection->inputPublisherBlocked));
-
- if (!connection->outboundQueue.isEmpty()) {
- dump.appendFormat(INDENT3 "OutboundQueue: length=%u\n",
- connection->outboundQueue.count());
- for (DispatchEntry* entry = connection->outboundQueue.head; entry;
- entry = entry->next) {
- dump.append(INDENT4);
- entry->eventEntry->appendDescription(dump);
- dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, age=%0.1fms\n",
- entry->targetFlags, entry->resolvedAction,
- (currentTime - entry->eventEntry->eventTime) * 0.000001f);
- }
- } else {
- dump.append(INDENT3 "OutboundQueue: <empty>\n");
- }
-
- if (!connection->waitQueue.isEmpty()) {
- dump.appendFormat(INDENT3 "WaitQueue: length=%u\n",
- connection->waitQueue.count());
- for (DispatchEntry* entry = connection->waitQueue.head; entry;
- entry = entry->next) {
- dump.append(INDENT4);
- entry->eventEntry->appendDescription(dump);
- dump.appendFormat(", 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);
- }
- } else {
- dump.append(INDENT3 "WaitQueue: <empty>\n");
- }
- }
- } else {
- dump.append(INDENT "Connections: <none>\n");
- }
-
- if (isAppSwitchPendingLocked()) {
- dump.appendFormat(INDENT "AppSwitch: pending, due in %0.1fms\n",
- (mAppSwitchDueTime - now()) / 1000000.0);
- } else {
- dump.append(INDENT "AppSwitch: not pending\n");
- }
-
- dump.append(INDENT "Configuration:\n");
- dump.appendFormat(INDENT2 "KeyRepeatDelay: %0.1fms\n",
- mConfig.keyRepeatDelay * 0.000001f);
- dump.appendFormat(INDENT2 "KeyRepeatTimeout: %0.1fms\n",
- mConfig.keyRepeatTimeout * 0.000001f);
-}
-
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
-#if DEBUG_REGISTRATION
- ALOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
- toString(monitor));
-#endif
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (getConnectionIndexLocked(inputChannel) >= 0) {
- ALOGW("Attempted to register already registered input channel '%s'",
- inputChannel->getName().string());
- return BAD_VALUE;
- }
-
- sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
-
- int fd = inputChannel->getFd();
- mConnectionsByFd.add(fd, connection);
-
- if (monitor) {
- mMonitoringChannels.push(inputChannel);
- }
-
- mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
- } // release lock
-
- // Wake the looper because some connections have changed.
- mLooper->wake();
- return OK;
-}
-
-status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
-#if DEBUG_REGISTRATION
- ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
-#endif
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- status_t status = unregisterInputChannelLocked(inputChannel, false /*notify*/);
- if (status) {
- return status;
- }
- } // release lock
-
- // Wake the poll loop because removing the connection may have changed the current
- // synchronization state.
- mLooper->wake();
- return OK;
-}
-
-status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,
- bool notify) {
- ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
- if (connectionIndex < 0) {
- ALOGW("Attempted to unregister already unregistered input channel '%s'",
- inputChannel->getName().string());
- return BAD_VALUE;
- }
-
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- mConnectionsByFd.removeItemsAt(connectionIndex);
-
- if (connection->monitor) {
- removeMonitorChannelLocked(inputChannel);
- }
-
- mLooper->removeFd(inputChannel->getFd());
-
- nsecs_t currentTime = now();
- abortBrokenDispatchCycleLocked(currentTime, connection, notify);
-
- connection->status = Connection::STATUS_ZOMBIE;
- return OK;
-}
-
-void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) {
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- if (mMonitoringChannels[i] == inputChannel) {
- mMonitoringChannels.removeAt(i);
- break;
- }
- }
-}
-
-ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
- ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd());
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- if (connection->inputChannel.get() == inputChannel.get()) {
- return connectionIndex;
- }
- }
-
- return -1;
-}
-
-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) {
- ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
- connection->getInputChannelName());
-
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
- commandEntry->connection = connection;
-}
-
-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",
- getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
- dispatchLatency, waitDuration, reason);
-
- // Capture a record of the InputDispatcher state at the time of the ANR.
- time_t t = time(NULL);
- struct tm tm;
- localtime_r(&t, &tm);
- char timestr[64];
- strftime(timestr, sizeof(timestr), "%F %T", &tm);
- mLastANRState.clear();
- mLastANRState.append(INDENT "ANR:\n");
- mLastANRState.appendFormat(INDENT2 "Time: %s\n", timestr);
- mLastANRState.appendFormat(INDENT2 "Window: %s\n",
- getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
- mLastANRState.appendFormat(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
- mLastANRState.appendFormat(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
- mLastANRState.appendFormat(INDENT2 "Reason: %s\n", reason);
- dumpDispatchStateLocked(mLastANRState);
-
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doNotifyANRLockedInterruptible);
- commandEntry->inputApplicationHandle = applicationHandle;
- commandEntry->inputWindowHandle = windowHandle;
-}
-
-void InputDispatcher::doNotifyConfigurationChangedInterruptible(
- CommandEntry* commandEntry) {
- mLock.unlock();
-
- mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
-
- mLock.lock();
-}
-
-void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
- CommandEntry* commandEntry) {
- sp<Connection> connection = commandEntry->connection;
-
- if (connection->status != Connection::STATUS_ZOMBIE) {
- mLock.unlock();
-
- mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
-
- mLock.lock();
- }
-}
-
-void InputDispatcher::doNotifyANRLockedInterruptible(
- CommandEntry* commandEntry) {
- mLock.unlock();
-
- nsecs_t newTimeout = mPolicy->notifyANR(
- commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle);
-
- mLock.lock();
-
- resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
- commandEntry->inputWindowHandle != NULL
- ? commandEntry->inputWindowHandle->getInputChannel() : NULL);
-}
-
-void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
- CommandEntry* commandEntry) {
- KeyEntry* entry = commandEntry->keyEntry;
-
- KeyEvent event;
- initializeKeyEvent(&event, entry);
-
- mLock.unlock();
-
- nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
- &event, entry->policyFlags);
-
- mLock.lock();
-
- if (delay < 0) {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
- } else if (!delay) {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
- } else {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
- entry->interceptKeyWakeupTime = now() + delay;
- }
- entry->release();
-}
-
-void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
- CommandEntry* commandEntry) {
- sp<Connection> connection = commandEntry->connection;
- nsecs_t finishTime = commandEntry->eventTime;
- uint32_t seq = commandEntry->seq;
- bool handled = commandEntry->handled;
-
- // Handle post-event policy actions.
- DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
- if (dispatchEntry) {
- nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
- if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
- String8 msg;
- msg.appendFormat("Window '%s' spent %0.1fms processing the last input event: ",
- connection->getWindowName(), eventDuration * 0.000001f);
- dispatchEntry->eventEntry->appendDescription(msg);
- ALOGI("%s", msg.string());
- }
-
- bool restartEvent;
- if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
- 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);
- } else {
- restartEvent = false;
- }
-
- // Dequeue the event and start the next cycle.
- // Note that because the lock might have been released, it is possible that the
- // contents of the wait queue to have been drained, so we need to double-check
- // a few things.
- if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
- connection->waitQueue.dequeue(dispatchEntry);
- traceWaitQueueLengthLocked(connection);
- if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
- connection->outboundQueue.enqueueAtHead(dispatchEntry);
- traceOutboundQueueLengthLocked(connection);
- } else {
- releaseDispatchEntryLocked(dispatchEntry);
- }
- }
-
- // Start the next dispatch cycle for this connection.
- startDispatchCycleLocked(now(), connection);
- }
-}
-
-bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
- if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
- // Get the fallback key state.
- // Clear it out after dispatching the UP.
- int32_t originalKeyCode = keyEntry->keyCode;
- int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
- if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
- connection->inputState.removeFallbackKey(originalKeyCode);
- }
-
- if (handled || !dispatchEntry->hasForegroundTarget()) {
- // If the application handles the original key for which we previously
- // generated a fallback or if the window is not a foreground window,
- // then cancel the associated fallback key, if any.
- if (fallbackKeyCode != -1) {
- // 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);
-#endif
- KeyEvent event;
- initializeKeyEvent(&event, keyEntry);
- event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
-
- mLock.unlock();
-
- mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
- &event, keyEntry->policyFlags, &event);
-
- mLock.lock();
-
- // Cancel the fallback key.
- if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
- CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
- "application handled the original non-fallback key "
- "or is no longer a foreground target, "
- "canceling previously dispatched fallback key");
- options.keyCode = fallbackKeyCode;
- synthesizeCancelationEventsForConnectionLocked(connection, options);
- }
- connection->inputState.removeFallbackKey(originalKeyCode);
- }
- } else {
- // 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;
- 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);
-#endif
- return false;
- }
-
- // 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);
-#endif
- KeyEvent event;
- initializeKeyEvent(&event, keyEntry);
-
- mLock.unlock();
-
- bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
- &event, keyEntry->policyFlags, &event);
-
- mLock.lock();
-
- if (connection->status != Connection::STATUS_NORMAL) {
- connection->inputState.removeFallbackKey(originalKeyCode);
- return false;
- }
-
- // Latch the fallback keycode for this key on an initial down.
- // The fallback keycode cannot change at any other point in the lifecycle.
- if (initialDown) {
- if (fallback) {
- fallbackKeyCode = event.getKeyCode();
- } else {
- fallbackKeyCode = AKEYCODE_UNKNOWN;
- }
- connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
- }
-
- ALOG_ASSERT(fallbackKeyCode != -1);
-
- // 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 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);
- } 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);
- }
-#endif
-
- CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
- "canceling fallback, policy no longer desires it");
- options.keyCode = fallbackKeyCode;
- synthesizeCancelationEventsForConnectionLocked(connection, options);
-
- fallback = false;
- fallbackKeyCode = AKEYCODE_UNKNOWN;
- if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
- connection->inputState.setFallbackKey(originalKeyCode,
- fallbackKeyCode);
- }
- }
-
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- {
- String8 msg;
- const KeyedVector<int32_t, int32_t>& fallbackKeys =
- connection->inputState.getFallbackKeys();
- for (size_t i = 0; i < fallbackKeys.size(); i++) {
- msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i),
- fallbackKeys.valueAt(i));
- }
- ALOGD("Unhandled key event: %d currently tracked fallback keys%s.",
- fallbackKeys.size(), msg.string());
- }
-#endif
-
- if (fallback) {
- // Restart the dispatch cycle using the fallback key.
- keyEntry->eventTime = event.getEventTime();
- keyEntry->deviceId = event.getDeviceId();
- keyEntry->source = event.getSource();
- keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
- keyEntry->keyCode = fallbackKeyCode;
- keyEntry->scanCode = event.getScanCode();
- keyEntry->metaState = event.getMetaState();
- keyEntry->repeatCount = event.getRepeatCount();
- keyEntry->downTime = event.getDownTime();
- keyEntry->syntheticRepeat = false;
-
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Unhandled key event: Dispatching fallback key. "
- "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
- originalKeyCode, fallbackKeyCode, keyEntry->metaState);
-#endif
- return true; // restart the event
- } else {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Unhandled key event: No fallback key.");
-#endif
- }
- }
- }
- return false;
-}
-
-bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) {
- return false;
-}
-
-void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
- mLock.unlock();
-
- mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
-
- mLock.lock();
-}
-
-void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
- event->initialize(entry->deviceId, entry->source, entry->action, entry->flags,
- entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
- entry->downTime, entry->eventTime);
-}
-
-void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
- int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
- // TODO Write some statistics about how long we spend waiting.
-}
-
-void InputDispatcher::traceInboundQueueLengthLocked() {
-#ifdef HAVE_ANDROID_OS
- if (ATRACE_ENABLED()) {
- ATRACE_INT("iq", mInboundQueue.count());
- }
-#endif
-}
-
-void InputDispatcher::traceOutboundQueueLengthLocked(const sp<Connection>& connection) {
-#ifdef HAVE_ANDROID_OS
- if (ATRACE_ENABLED()) {
- char counterName[40];
- snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName());
- ATRACE_INT(counterName, connection->outboundQueue.count());
- }
-#endif
-}
-
-void InputDispatcher::traceWaitQueueLengthLocked(const sp<Connection>& connection) {
-#ifdef HAVE_ANDROID_OS
- if (ATRACE_ENABLED()) {
- char counterName[40];
- snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName());
- ATRACE_INT(counterName, connection->waitQueue.count());
- }
-#endif
-}
-
-void InputDispatcher::dump(String8& dump) {
- AutoMutex _l(mLock);
-
- dump.append("Input Dispatcher State:\n");
- dumpDispatchStateLocked(dump);
-
- if (!mLastANRState.isEmpty()) {
- dump.append("\nInput Dispatcher State at time of last ANR:\n");
- dump.append(mLastANRState);
- }
-}
-
-void InputDispatcher::monitor() {
- // Acquire and release the lock to ensure that the dispatcher has not deadlocked.
- mLock.lock();
- mLooper->wake();
- mDispatcherIsAliveCondition.wait(mLock);
- mLock.unlock();
-}
-
-
-// --- InputDispatcher::Queue ---
-
-template <typename T>
-uint32_t InputDispatcher::Queue<T>::count() const {
- uint32_t result = 0;
- for (const T* entry = head; entry; entry = entry->next) {
- result += 1;
- }
- return result;
-}
-
-
-// --- 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(int32_t type, nsecs_t eventTime, uint32_t policyFlags) :
- refCount(1), type(type), eventTime(eventTime), policyFlags(policyFlags),
- injectionState(NULL), 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 = NULL;
- }
-}
-
-
-// --- InputDispatcher::ConfigurationChangedEntry ---
-
-InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(nsecs_t eventTime) :
- EventEntry(TYPE_CONFIGURATION_CHANGED, eventTime, 0) {
-}
-
-InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
-}
-
-void InputDispatcher::ConfigurationChangedEntry::appendDescription(String8& msg) const {
- msg.append("ConfigurationChangedEvent()");
-}
-
-
-// --- InputDispatcher::DeviceResetEntry ---
-
-InputDispatcher::DeviceResetEntry::DeviceResetEntry(nsecs_t eventTime, int32_t deviceId) :
- EventEntry(TYPE_DEVICE_RESET, eventTime, 0),
- deviceId(deviceId) {
-}
-
-InputDispatcher::DeviceResetEntry::~DeviceResetEntry() {
-}
-
-void InputDispatcher::DeviceResetEntry::appendDescription(String8& msg) const {
- msg.appendFormat("DeviceResetEvent(deviceId=%d)", deviceId);
-}
-
-
-// --- InputDispatcher::KeyEntry ---
-
-InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, 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(TYPE_KEY, eventTime, policyFlags),
- deviceId(deviceId), source(source), 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(String8& msg) const {
- msg.appendFormat("KeyEvent(action=%d, deviceId=%d, source=0x%08x)",
- action, deviceId, source);
-}
-
-void InputDispatcher::KeyEntry::recycle() {
- releaseInjectionState();
-
- dispatchInProgress = false;
- syntheticRepeat = false;
- interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
- interceptKeyWakeupTime = 0;
-}
-
-
-// --- InputDispatcher::MotionEntry ---
-
-InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, float xPrecision, float yPrecision,
- nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) :
- EventEntry(TYPE_MOTION, eventTime, policyFlags),
- eventTime(eventTime),
- deviceId(deviceId), source(source), action(action), flags(flags),
- metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags),
- xPrecision(xPrecision), yPrecision(yPrecision),
- downTime(downTime), displayId(displayId), pointerCount(pointerCount) {
- for (uint32_t i = 0; i < pointerCount; i++) {
- this->pointerProperties[i].copyFrom(pointerProperties[i]);
- this->pointerCoords[i].copyFrom(pointerCoords[i]);
- }
-}
-
-InputDispatcher::MotionEntry::~MotionEntry() {
-}
-
-void InputDispatcher::MotionEntry::appendDescription(String8& msg) const {
- msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x, displayId=%d)",
- action, deviceId, source, displayId);
-}
-
-
-// --- InputDispatcher::DispatchEntry ---
-
-volatile int32_t InputDispatcher::DispatchEntry::sNextSeqAtomic;
-
-InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry,
- int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) :
- seq(nextSeq()),
- eventEntry(eventEntry), targetFlags(targetFlags),
- xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor),
- 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.isEmpty() && mMotionMementos.isEmpty();
-}
-
-bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source,
- int32_t displayId) const {
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos.itemAt(i);
- 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.removeAt(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.removeAt(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.removeAt(index);
- return true;
- }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
- "actionMasked=%d",
- entry->deviceId, entry->source, actionMasked);
-#endif
- return false;
- }
-
- case AMOTION_EVENT_ACTION_DOWN: {
- ssize_t index = findMotionMemento(entry, false /*hovering*/);
- if (index >= 0) {
- mMotionMementos.removeAt(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: {
- ssize_t index = findMotionMemento(entry, false /*hovering*/);
- if (index >= 0) {
- MotionMemento& memento = mMotionMementos.editItemAt(index);
- memento.setPointers(entry);
- return true;
- }
- if (actionMasked == AMOTION_EVENT_ACTION_MOVE
- && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK
- | AINPUT_SOURCE_CLASS_NAVIGATION))) {
- // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
- return true;
- }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion pointer up/down or move event: "
- "deviceId=%d, source=%08x, actionMasked=%d",
- entry->deviceId, entry->source, actionMasked);
-#endif
- return false;
- }
-
- case AMOTION_EVENT_ACTION_HOVER_EXIT: {
- ssize_t index = findMotionMemento(entry, true /*hovering*/);
- if (index >= 0) {
- mMotionMementos.removeAt(index);
- return true;
- }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x",
- entry->deviceId, entry->source);
-#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.removeAt(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.itemAt(i);
- if (memento.deviceId == entry->deviceId
- && memento.source == entry->source
- && 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.itemAt(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) {
- mKeyMementos.push();
- KeyMemento& memento = mKeyMementos.editTop();
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.keyCode = entry->keyCode;
- memento.scanCode = entry->scanCode;
- memento.metaState = entry->metaState;
- memento.flags = flags;
- memento.downTime = entry->downTime;
- memento.policyFlags = entry->policyFlags;
-}
-
-void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry,
- int32_t flags, bool hovering) {
- mMotionMementos.push();
- MotionMemento& memento = mMotionMementos.editTop();
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.flags = flags;
- memento.xPrecision = entry->xPrecision;
- memento.yPrecision = entry->yPrecision;
- memento.downTime = entry->downTime;
- memento.displayId = entry->displayId;
- memento.setPointers(entry);
- memento.hovering = hovering;
- memento.policyFlags = entry->policyFlags;
-}
-
-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,
- Vector<EventEntry*>& outEvents, const CancelationOptions& options) {
- for (size_t i = 0; i < mKeyMementos.size(); i++) {
- const KeyMemento& memento = mKeyMementos.itemAt(i);
- if (shouldCancelKey(memento, options)) {
- outEvents.push(new KeyEntry(currentTime,
- memento.deviceId, memento.source, memento.policyFlags,
- AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
- memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime));
- }
- }
-
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos.itemAt(i);
- if (shouldCancelMotion(memento, options)) {
- outEvents.push(new MotionEntry(currentTime,
- memento.deviceId, memento.source, memento.policyFlags,
- memento.hovering
- ? AMOTION_EVENT_ACTION_HOVER_EXIT
- : AMOTION_EVENT_ACTION_CANCEL,
- memento.flags, 0, 0, 0,
- memento.xPrecision, memento.yPrecision, memento.downTime,
- memento.displayId,
- memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
- }
- }
-}
-
-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.itemAt(i);
- if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
- for (size_t j = 0; j < other.mMotionMementos.size(); ) {
- const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j);
- if (memento.deviceId == otherMemento.deviceId
- && memento.source == otherMemento.source
- && memento.displayId == otherMemento.displayId) {
- other.mMotionMementos.removeAt(j);
- } else {
- j += 1;
- }
- }
- other.mMotionMementos.push(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 != -1 && memento.keyCode != options.keyCode) {
- return false;
- }
-
- if (options.deviceId != -1 && memento.deviceId != options.deviceId) {
- 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 != -1 && memento.deviceId != options.deviceId) {
- 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,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
- status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
- monitor(monitor),
- inputPublisher(inputChannel), inputPublisherBlocked(false) {
-}
-
-InputDispatcher::Connection::~Connection() {
-}
-
-const char* InputDispatcher::Connection::getWindowName() const {
- if (inputWindowHandle != NULL) {
- return inputWindowHandle->getName().string();
- }
- 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 != NULL; entry = entry->next) {
- if (entry->seq == seq) {
- return entry;
- }
- }
- return NULL;
-}
-
-
-// --- InputDispatcher::CommandEntry ---
-
-InputDispatcher::CommandEntry::CommandEntry(Command command) :
- command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0),
- seq(0), handled(false) {
-}
-
-InputDispatcher::CommandEntry::~CommandEntry() {
-}
-
-
-// --- InputDispatcher::TouchState ---
-
-InputDispatcher::TouchState::TouchState() :
- down(false), split(false), deviceId(-1), source(0), displayId(-1) {
-}
-
-InputDispatcher::TouchState::~TouchState() {
-}
-
-void InputDispatcher::TouchState::reset() {
- down = false;
- split = false;
- deviceId = -1;
- source = 0;
- displayId = -1;
- windows.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;
-}
-
-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.editItemAt(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;
- }
- }
-
- windows.push();
-
- TouchedWindow& touchedWindow = windows.editTop();
- touchedWindow.windowHandle = windowHandle;
- touchedWindow.targetFlags = targetFlags;
- touchedWindow.pointerIds = pointerIds;
-}
-
-void InputDispatcher::TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
- for (size_t i = 0; i < windows.size(); i++) {
- if (windows.itemAt(i).windowHandle == windowHandle) {
- windows.removeAt(i);
- return;
- }
- }
-}
-
-void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
- for (size_t i = 0 ; i < windows.size(); ) {
- TouchedWindow& window = windows.editItemAt(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.removeAt(i);
- }
- }
-}
-
-sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const {
- for (size_t i = 0; i < windows.size(); i++) {
- const TouchedWindow& window = windows.itemAt(i);
- if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
- return window.windowHandle;
- }
- }
- return NULL;
-}
-
-bool InputDispatcher::TouchState::isSlippery() const {
- // Must have exactly one foreground window.
- bool haveSlipperyForegroundWindow = false;
- for (size_t i = 0; i < windows.size(); i++) {
- const TouchedWindow& window = windows.itemAt(i);
- 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/widget/gonk/libui/InputDispatcher.h b/widget/gonk/libui/InputDispatcher.h
deleted file mode 100644
index 5453421f6..000000000
--- a/widget/gonk/libui/InputDispatcher.h
+++ /dev/null
@@ -1,1117 +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 "Input.h"
-#include "InputTransport.h"
-#include <utils/KeyedVector.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Looper.h>
-#include <utils/BitSet.h>
-#include <cutils/atomic.h>
-
-#include <stddef.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include "InputWindow.h"
-#include "InputApplication.h"
-#include "InputListener.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 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_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,
- };
-
- // 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 scaleFactor;
-
- // 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<InputWindowHandle>& inputWindowHandle) = 0;
-
- /* Notifies the system that an input channel is unrecoverably broken. */
- virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
-
- /* Gets the input dispatcher configuration. */
- virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
-
- /* Returns true if automatic key repeating is enabled. */
- virtual bool isKeyRepeatEnabled() = 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(nsecs_t when, uint32_t& policyFlags) = 0;
-
- /* Allows the policy a chance to intercept a key before dispatching. */
- virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
- 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<InputWindowHandle>& inputWindowHandle,
- 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 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(String8& 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 Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
-
- /* Sets the focused application.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void setFocusedApplication(
- const sp<InputApplicationHandle>& inputApplicationHandle) = 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 the window associated with one channel to the
- * window associated with the other channel.
- *
- * Returns true on success. False if the window did not actually have touch focus.
- */
- virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel) = 0;
-
- /* Registers or unregister input channels that may be used as targets for input events.
- * If monitor is true, the channel will receive a copy of all input events.
- *
- * These methods may be called on any thread (usually by the input manager).
- */
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor) = 0;
- virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 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(String8& dump);
- virtual void monitor();
-
- virtual void dispatchOnce();
-
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
- virtual void notifyKey(const NotifyKeyArgs* args);
- virtual void notifyMotion(const NotifyMotionArgs* args);
- virtual void notifySwitch(const NotifySwitchArgs* args);
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
-
- virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
- uint32_t policyFlags);
-
- virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
- virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
- virtual void setInputDispatchMode(bool enabled, bool frozen);
- virtual void setInputFilterEnabled(bool enabled);
-
- virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel);
-
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
- virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
-
-private:
- template <typename T>
- struct Link {
- T* next;
- T* prev;
-
- protected:
- inline Link() : next(NULL), prev(NULL) { }
- };
-
- 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
- };
-
- 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 != NULL; }
-
- void release();
-
- virtual void appendDescription(String8& msg) const = 0;
-
- protected:
- EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags);
- virtual ~EventEntry();
- void releaseInjectionState();
- };
-
- struct ConfigurationChangedEntry : EventEntry {
- ConfigurationChangedEntry(nsecs_t eventTime);
- virtual void appendDescription(String8& msg) const;
-
- protected:
- virtual ~ConfigurationChangedEntry();
- };
-
- struct DeviceResetEntry : EventEntry {
- int32_t deviceId;
-
- DeviceResetEntry(nsecs_t eventTime, int32_t deviceId);
- virtual void appendDescription(String8& msg) const;
-
- protected:
- virtual ~DeviceResetEntry();
- };
-
- struct KeyEntry : EventEntry {
- int32_t deviceId;
- uint32_t source;
- 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(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, 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(String8& msg) const;
- void recycle();
-
- protected:
- virtual ~KeyEntry();
- };
-
- struct MotionEntry : EventEntry {
- nsecs_t eventTime;
- int32_t deviceId;
- uint32_t source;
- int32_t action;
- int32_t flags;
- int32_t metaState;
- int32_t buttonState;
- int32_t edgeFlags;
- float xPrecision;
- float yPrecision;
- nsecs_t downTime;
- int32_t displayId;
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
-
- MotionEntry(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, uint32_t policyFlags,
- int32_t action, int32_t flags,
- int32_t metaState, int32_t buttonState, int32_t edgeFlags,
- float xPrecision, float yPrecision,
- nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
- virtual void appendDescription(String8& 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 scaleFactor;
- 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 scaleFactor);
- ~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> {
- 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;
- sp<InputWindowHandle> inputWindowHandle;
- int32_t userActivityEventType;
- uint32_t seq;
- bool handled;
- };
-
- // Generic queue implementation.
- template <typename T>
- struct Queue {
- T* head;
- T* tail;
-
- inline Queue() : head(NULL), tail(NULL) {
- }
-
- inline bool isEmpty() const {
- return !head;
- }
-
- inline void enqueueAtTail(T* entry) {
- entry->prev = tail;
- if (tail) {
- tail->next = entry;
- } else {
- head = entry;
- }
- entry->next = NULL;
- tail = entry;
- }
-
- inline void enqueueAtHead(T* entry) {
- entry->next = head;
- if (head) {
- head->prev = entry;
- } else {
- tail = entry;
- }
- entry->prev = NULL;
- head = entry;
- }
-
- inline void dequeue(T* entry) {
- 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() {
- T* entry = head;
- head = entry->next;
- if (head) {
- head->prev = NULL;
- } else {
- tail = NULL;
- }
- return entry;
- }
-
- uint32_t count() const;
- };
-
- /* 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 -1 to cancel any key event.
- int32_t keyCode;
-
- // The specific device id of events to cancel, or -1 to cancel events from any device.
- int32_t deviceId;
-
- CancelationOptions(Mode mode, const char* reason) :
- mode(mode), reason(reason), keyCode(-1), deviceId(-1) { }
- };
-
- /* 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,
- 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 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 flags;
- float xPrecision;
- float yPrecision;
- nsecs_t downTime;
- int32_t displayId;
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
- bool hovering;
- uint32_t policyFlags;
-
- void setPointers(const MotionEntry* entry);
- };
-
- Vector<KeyMemento> mKeyMementos;
- 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
- sp<InputWindowHandle> inputWindowHandle; // may be 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,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
-
- inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
-
- const char* getWindowName() const;
- const char* getStatusLabel() const;
-
- DispatchEntry* findWaitQueueEntry(uint32_t seq);
- };
-
- 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;
-
- Mutex mLock;
-
- Condition mDispatcherIsAliveCondition;
-
- sp<Looper> mLooper;
-
- EventEntry* mPendingEvent;
- Queue<EventEntry> mInboundQueue;
- Queue<CommandEntry> mCommandQueue;
-
- void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime);
-
- // Enqueues an inbound event. Returns true if mLooper->wake() should be called.
- bool enqueueInboundEventLocked(EventEntry* entry);
-
- // Cleans up input state when dropping an inbound event.
- void dropInboundEventLocked(EventEntry* entry, DropReason dropReason);
-
- // App switch latency optimization.
- bool mAppSwitchSawKeyDown;
- nsecs_t mAppSwitchDueTime;
-
- static bool isAppSwitchKeyCode(int32_t keyCode);
- bool isAppSwitchKeyEventLocked(KeyEntry* keyEntry);
- bool isAppSwitchPendingLocked();
- void resetPendingAppSwitchLocked(bool handled);
-
- // Stale event latency optimization.
- static bool isStaleEventLocked(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;
-
- sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y);
-
- // All registered connections mapped by channel file descriptor.
- KeyedVector<int, sp<Connection> > mConnectionsByFd;
-
- ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel);
-
- // Input channels that will receive a copy of all input events.
- Vector<sp<InputChannel> > mMonitoringChannels;
-
- // Event injection and synchronization.
- Condition mInjectionResultAvailableCondition;
- bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
- void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult);
-
- Condition mInjectionSyncFinishedCondition;
- void incrementPendingForegroundDispatchesLocked(EventEntry* entry);
- void decrementPendingForegroundDispatchesLocked(EventEntry* entry);
-
- // Key repeat tracking.
- struct KeyRepeatState {
- KeyEntry* lastKeyEntry; // or null if no repeat
- nsecs_t nextRepeatTime;
- } mKeyRepeatState;
-
- void resetKeyRepeatLocked();
- KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime);
-
- // Deferred command processing.
- bool haveCommandsLocked() const;
- bool runCommandsLockedInterruptible();
- CommandEntry* postCommandLocked(Command command);
-
- // Input filter processing.
- bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args);
- bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args);
-
- // Inbound event processing.
- void drainInboundQueueLocked();
- void releasePendingEventLocked();
- void releaseInboundEventLocked(EventEntry* entry);
-
- // Dispatch state.
- bool mDispatchEnabled;
- bool mDispatchFrozen;
- bool mInputFilterEnabled;
-
- Vector<sp<InputWindowHandle> > mWindowHandles;
-
- sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
- bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
-
- // Focus tracking for keys, trackball, etc.
- sp<InputWindowHandle> mFocusedWindowHandle;
-
- // Focus tracking for touch.
- struct TouchedWindow {
- sp<InputWindowHandle> windowHandle;
- int32_t targetFlags;
- BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set
- };
- 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
- Vector<TouchedWindow> windows;
-
- TouchState();
- ~TouchState();
- void reset();
- void copyFrom(const TouchState& other);
- void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
- int32_t targetFlags, BitSet32 pointerIds);
- void removeWindow(const sp<InputWindowHandle>& windowHandle);
- void filterNonAsIsTouchWindows();
- sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
- bool isSlippery() const;
- };
-
- TouchState mTouchState;
- TouchState mTempTouchState;
-
- // Focused application.
- sp<InputApplicationHandle> mFocusedApplicationHandle;
-
- // Dispatcher state at time of last ANR.
- String8 mLastANRState;
-
- // Dispatch inbound events.
- bool dispatchConfigurationChangedLocked(
- nsecs_t currentTime, ConfigurationChangedEntry* entry);
- bool dispatchDeviceResetLocked(
- nsecs_t currentTime, DeviceResetEntry* entry);
- bool dispatchKeyLocked(
- nsecs_t currentTime, KeyEntry* entry,
- DropReason* dropReason, nsecs_t* nextWakeupTime);
- bool dispatchMotionLocked(
- nsecs_t currentTime, MotionEntry* entry,
- DropReason* dropReason, nsecs_t* nextWakeupTime);
- void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry,
- const Vector<InputTarget>& inputTargets);
-
- void logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry);
- void logOutboundMotionDetailsLocked(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;
- nsecs_t mInputTargetWaitStartTime;
- nsecs_t mInputTargetWaitTimeoutTime;
- bool mInputTargetWaitTimeoutExpired;
- sp<InputApplicationHandle> mInputTargetWaitApplicationHandle;
-
- // Contains the last window which received a hover event.
- sp<InputWindowHandle> mLastHoverWindowHandle;
-
- // 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);
- void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
- const sp<InputChannel>& inputChannel);
- nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
- void resetANRTimeoutsLocked();
-
- int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
- Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime);
- int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
- Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
- bool* outConflictingPointerActions);
-
- void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
- int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets);
- void addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets);
-
- void pokeUserActivityLocked(const EventEntry* eventEntry);
- bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
- const InjectionState* injectionState);
- bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
- int32_t x, int32_t y) const;
- bool isWindowReadyForMoreInputLocked(nsecs_t currentTime,
- const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry);
- String8 getApplicationWindowLabelLocked(const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle);
-
- // 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);
- void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection,
- EventEntry* eventEntry, const InputTarget* inputTarget);
- void enqueueDispatchEntryLocked(const sp<Connection>& connection,
- EventEntry* eventEntry, const InputTarget* inputTarget, int32_t dispatchMode);
- void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
- void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- uint32_t seq, bool handled);
- void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- bool notify);
- void drainDispatchQueueLocked(Queue<DispatchEntry>* queue);
- void releaseDispatchEntryLocked(DispatchEntry* dispatchEntry);
- static int handleReceiveCallback(int fd, int events, void* data);
-
- void synthesizeCancelationEventsForAllConnectionsLocked(
- const CancelationOptions& options);
- void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
- const CancelationOptions& options);
- void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
- const CancelationOptions& options);
-
- // 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);
-
- // Dump state.
- void dumpDispatchStateLocked(String8& dump);
- void logDispatchStateLocked();
-
- // Registration.
- void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel);
- status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify);
-
- // Add or remove a connection to the mActiveConnections vector.
- void activateConnectionLocked(Connection* connection);
- void deactivateConnectionLocked(Connection* connection);
-
- // 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);
- void onDispatchCycleBrokenLocked(
- nsecs_t currentTime, const sp<Connection>& connection);
- void onANRLocked(
- nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle,
- nsecs_t eventTime, nsecs_t waitStartTime, const char* reason);
-
- // Outbound policy interactions.
- void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry);
- void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
- void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
- void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
- void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);
- bool afterKeyEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled);
- bool afterMotionEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled);
- void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
- void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
-
- // Statistics gathering.
- void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
- int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
- void traceInboundQueueLengthLocked();
- void traceOutboundQueueLengthLocked(const sp<Connection>& connection);
- void traceWaitQueueLengthLocked(const sp<Connection>& connection);
-};
-
-/* 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/widget/gonk/libui/InputListener.cpp b/widget/gonk/libui/InputListener.cpp
deleted file mode 100644
index 3b673f0ad..000000000
--- a/widget/gonk/libui/InputListener.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputListener"
-
-//#define LOG_NDEBUG 0
-
-#include "InputListener.h"
-
-#include "cutils_log.h"
-
-namespace android {
-
-// --- NotifyConfigurationChangedArgs ---
-
-NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(nsecs_t eventTime) :
- eventTime(eventTime) {
-}
-
-NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(
- const NotifyConfigurationChangedArgs& other) :
- eventTime(other.eventTime) {
-}
-
-void NotifyConfigurationChangedArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifyConfigurationChanged(this);
-}
-
-
-// --- NotifyKeyArgs ---
-
-NotifyKeyArgs::NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
- uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
- int32_t metaState, nsecs_t downTime) :
- eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags),
- action(action), flags(flags), keyCode(keyCode), scanCode(scanCode),
- metaState(metaState), downTime(downTime) {
-}
-
-NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other) :
- eventTime(other.eventTime), deviceId(other.deviceId), source(other.source),
- policyFlags(other.policyFlags),
- action(other.action), flags(other.flags),
- keyCode(other.keyCode), scanCode(other.scanCode),
- metaState(other.metaState), downTime(other.downTime) {
-}
-
-void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifyKey(this);
-}
-
-
-// --- NotifyMotionArgs ---
-
-NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
- uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, int32_t displayId, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
- float xPrecision, float yPrecision, nsecs_t downTime) :
- eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags),
- action(action), flags(flags), metaState(metaState), buttonState(buttonState),
- edgeFlags(edgeFlags), displayId(displayId), pointerCount(pointerCount),
- xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) {
- for (uint32_t i = 0; i < pointerCount; i++) {
- this->pointerProperties[i].copyFrom(pointerProperties[i]);
- this->pointerCoords[i].copyFrom(pointerCoords[i]);
- }
-}
-
-NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) :
- eventTime(other.eventTime), deviceId(other.deviceId), source(other.source),
- policyFlags(other.policyFlags),
- action(other.action), flags(other.flags),
- metaState(other.metaState), buttonState(other.buttonState),
- edgeFlags(other.edgeFlags), displayId(other.displayId),
- pointerCount(other.pointerCount),
- xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) {
- for (uint32_t i = 0; i < pointerCount; i++) {
- pointerProperties[i].copyFrom(other.pointerProperties[i]);
- pointerCoords[i].copyFrom(other.pointerCoords[i]);
- }
-}
-
-void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifyMotion(this);
-}
-
-
-// --- NotifySwitchArgs ---
-
-NotifySwitchArgs::NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
- uint32_t switchValues, uint32_t switchMask) :
- eventTime(eventTime), policyFlags(policyFlags),
- switchValues(switchValues), switchMask(switchMask) {
-}
-
-NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other) :
- eventTime(other.eventTime), policyFlags(other.policyFlags),
- switchValues(other.switchValues), switchMask(other.switchMask) {
-}
-
-void NotifySwitchArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifySwitch(this);
-}
-
-
-// --- NotifyDeviceResetArgs ---
-
-NotifyDeviceResetArgs::NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId) :
- eventTime(eventTime), deviceId(deviceId) {
-}
-
-NotifyDeviceResetArgs::NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) :
- eventTime(other.eventTime), deviceId(other.deviceId) {
-}
-
-void NotifyDeviceResetArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifyDeviceReset(this);
-}
-
-
-// --- QueuedInputListener ---
-
-QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
- mInnerListener(innerListener) {
-}
-
-QueuedInputListener::~QueuedInputListener() {
- size_t count = mArgsQueue.size();
- for (size_t i = 0; i < count; i++) {
- delete mArgsQueue[i];
- }
-}
-
-void QueuedInputListener::notifyConfigurationChanged(
- const NotifyConfigurationChangedArgs* args) {
- mArgsQueue.push(new NotifyConfigurationChangedArgs(*args));
-}
-
-void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
- mArgsQueue.push(new NotifyKeyArgs(*args));
-}
-
-void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
- mArgsQueue.push(new NotifyMotionArgs(*args));
-}
-
-void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) {
- mArgsQueue.push(new NotifySwitchArgs(*args));
-}
-
-void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
- mArgsQueue.push(new NotifyDeviceResetArgs(*args));
-}
-
-void QueuedInputListener::flush() {
- size_t count = mArgsQueue.size();
- for (size_t i = 0; i < count; i++) {
- NotifyArgs* args = mArgsQueue[i];
- args->notify(mInnerListener);
- delete args;
- }
- mArgsQueue.clear();
-}
-
-
-} // namespace android
diff --git a/widget/gonk/libui/InputListener.h b/widget/gonk/libui/InputListener.h
deleted file mode 100644
index de799322f..000000000
--- a/widget/gonk/libui/InputListener.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_LISTENER_H
-#define _UI_INPUT_LISTENER_H
-
-#include "Input.h"
-#include <utils/RefBase.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-class InputListenerInterface;
-
-
-/* Superclass of all input event argument objects */
-struct NotifyArgs {
- virtual ~NotifyArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const = 0;
-};
-
-
-/* Describes a configuration change event. */
-struct NotifyConfigurationChangedArgs : public NotifyArgs {
- nsecs_t eventTime;
-
- inline NotifyConfigurationChangedArgs() { }
-
- NotifyConfigurationChangedArgs(nsecs_t eventTime);
-
- NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other);
-
- virtual ~NotifyConfigurationChangedArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/* Describes a key event. */
-struct NotifyKeyArgs : public NotifyArgs {
- nsecs_t eventTime;
- int32_t deviceId;
- uint32_t source;
- uint32_t policyFlags;
- int32_t action;
- int32_t flags;
- int32_t keyCode;
- int32_t scanCode;
- int32_t metaState;
- nsecs_t downTime;
-
- inline NotifyKeyArgs() { }
-
- NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
- int32_t metaState, nsecs_t downTime);
-
- NotifyKeyArgs(const NotifyKeyArgs& other);
-
- virtual ~NotifyKeyArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/* Describes a motion event. */
-struct NotifyMotionArgs : public NotifyArgs {
- nsecs_t eventTime;
- int32_t deviceId;
- uint32_t source;
- uint32_t policyFlags;
- int32_t action;
- int32_t flags;
- int32_t metaState;
- int32_t buttonState;
- int32_t edgeFlags;
- int32_t displayId;
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
- float xPrecision;
- float yPrecision;
- nsecs_t downTime;
-
- inline NotifyMotionArgs() { }
-
- NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, int32_t displayId, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
- float xPrecision, float yPrecision, nsecs_t downTime);
-
- NotifyMotionArgs(const NotifyMotionArgs& other);
-
- virtual ~NotifyMotionArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/* Describes a switch event. */
-struct NotifySwitchArgs : public NotifyArgs {
- nsecs_t eventTime;
- uint32_t policyFlags;
- uint32_t switchValues;
- uint32_t switchMask;
-
- inline NotifySwitchArgs() { }
-
- NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
- uint32_t switchValues, uint32_t switchMask);
-
- NotifySwitchArgs(const NotifySwitchArgs& other);
-
- virtual ~NotifySwitchArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/* Describes a device reset event, such as when a device is added,
- * reconfigured, or removed. */
-struct NotifyDeviceResetArgs : public NotifyArgs {
- nsecs_t eventTime;
- int32_t deviceId;
-
- inline NotifyDeviceResetArgs() { }
-
- NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId);
-
- NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other);
-
- virtual ~NotifyDeviceResetArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/*
- * The interface used by the InputReader to notify the InputListener about input events.
- */
-class InputListenerInterface : public virtual RefBase {
-protected:
- InputListenerInterface() { }
- virtual ~InputListenerInterface() { }
-
-public:
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0;
- virtual void notifyKey(const NotifyKeyArgs* args) = 0;
- virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
- virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
-};
-
-
-/*
- * An implementation of the listener interface that queues up and defers dispatch
- * of decoded events until flushed.
- */
-class QueuedInputListener : public InputListenerInterface {
-protected:
- virtual ~QueuedInputListener();
-
-public:
- QueuedInputListener(const sp<InputListenerInterface>& innerListener);
-
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
- virtual void notifyKey(const NotifyKeyArgs* args);
- virtual void notifyMotion(const NotifyMotionArgs* args);
- virtual void notifySwitch(const NotifySwitchArgs* args);
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
-
- void flush();
-
-private:
- sp<InputListenerInterface> mInnerListener;
- Vector<NotifyArgs*> mArgsQueue;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_LISTENER_H
diff --git a/widget/gonk/libui/InputManager.cpp b/widget/gonk/libui/InputManager.cpp
deleted file mode 100644
index 91af056bf..000000000
--- a/widget/gonk/libui/InputManager.cpp
+++ /dev/null
@@ -1,93 +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.
- */
-
-#define LOG_TAG "InputManager"
-
-//#define LOG_NDEBUG 0
-
-#include "InputManager.h"
-
-#include "cutils_log.h"
-
-namespace android {
-
-InputManager::InputManager(
- const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& readerPolicy,
- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
- mDispatcher = new InputDispatcher(dispatcherPolicy);
- mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
- initialize();
-}
-
-InputManager::InputManager(
- const sp<InputReaderInterface>& reader,
- const sp<InputDispatcherInterface>& dispatcher) :
- mReader(reader),
- mDispatcher(dispatcher) {
- initialize();
-}
-
-InputManager::~InputManager() {
- stop();
-}
-
-void InputManager::initialize() {
- mReaderThread = new InputReaderThread(mReader);
- mDispatcherThread = new InputDispatcherThread(mDispatcher);
-}
-
-status_t InputManager::start() {
- status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
- if (result) {
- ALOGE("Could not start InputDispatcher thread due to error %d.", result);
- return result;
- }
-
- result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
- if (result) {
- ALOGE("Could not start InputReader thread due to error %d.", result);
-
- mDispatcherThread->requestExit();
- return result;
- }
-
- return OK;
-}
-
-status_t InputManager::stop() {
- status_t result = mReaderThread->requestExitAndWait();
- if (result) {
- ALOGW("Could not stop InputReader thread due to error %d.", result);
- }
-
- result = mDispatcherThread->requestExitAndWait();
- if (result) {
- ALOGW("Could not stop InputDispatcher thread due to error %d.", result);
- }
-
- return OK;
-}
-
-sp<InputReaderInterface> InputManager::getReader() {
- return mReader;
-}
-
-sp<InputDispatcherInterface> InputManager::getDispatcher() {
- return mDispatcher;
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/InputManager.h b/widget/gonk/libui/InputManager.h
deleted file mode 100644
index 15a5176ec..000000000
--- a/widget/gonk/libui/InputManager.h
+++ /dev/null
@@ -1,109 +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_MANAGER_H
-#define _UI_INPUT_MANAGER_H
-
-/**
- * Native input manager.
- */
-
-#include "EventHub.h"
-#include "InputReader.h"
-#include "InputDispatcher.h"
-
-#include "Input.h"
-#include "InputTransport.h"
-#include <utils/Errors.h>
-#include <utils/Vector.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-
-namespace android {
-
-/*
- * The input manager is the core of the system event processing.
- *
- * The input manager uses two threads.
- *
- * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events,
- * applies policy, and posts messages to a queue managed by the DispatcherThread.
- * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
- * queue and asynchronously dispatches them to applications.
- *
- * By design, the InputReaderThread class and InputDispatcherThread class do not share any
- * internal state. Moreover, all communication is done one way from the InputReaderThread
- * into the InputDispatcherThread and never the reverse. Both classes may interact with the
- * InputDispatchPolicy, however.
- *
- * The InputManager class never makes any calls into Java itself. Instead, the
- * InputDispatchPolicy is responsible for performing all external interactions with the
- * system, including calling DVM services.
- */
-class InputManagerInterface : public virtual RefBase {
-protected:
- InputManagerInterface() { }
- virtual ~InputManagerInterface() { }
-
-public:
- /* Starts the input manager threads. */
- virtual status_t start() = 0;
-
- /* Stops the input manager threads and waits for them to exit. */
- virtual status_t stop() = 0;
-
- /* Gets the input reader. */
- virtual sp<InputReaderInterface> getReader() = 0;
-
- /* Gets the input dispatcher. */
- virtual sp<InputDispatcherInterface> getDispatcher() = 0;
-};
-
-class InputManager : public InputManagerInterface {
-protected:
- virtual ~InputManager();
-
-public:
- InputManager(
- const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& readerPolicy,
- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
-
- // (used for testing purposes)
- InputManager(
- const sp<InputReaderInterface>& reader,
- const sp<InputDispatcherInterface>& dispatcher);
-
- virtual status_t start();
- virtual status_t stop();
-
- virtual sp<InputReaderInterface> getReader();
- virtual sp<InputDispatcherInterface> getDispatcher();
-
-private:
- sp<InputReaderInterface> mReader;
- sp<InputReaderThread> mReaderThread;
-
- sp<InputDispatcherInterface> mDispatcher;
- sp<InputDispatcherThread> mDispatcherThread;
-
- void initialize();
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_MANAGER_H
diff --git a/widget/gonk/libui/InputReader.cpp b/widget/gonk/libui/InputReader.cpp
deleted file mode 100644
index 3699569aa..000000000
--- a/widget/gonk/libui/InputReader.cpp
+++ /dev/null
@@ -1,6510 +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.
- */
-
-#define LOG_TAG "InputReader"
-
-//#define LOG_NDEBUG 0
-#include "cutils_log.h"
-
-// 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
-
-#include "InputReader.h"
-
-#include "Keyboard.h"
-#include "VirtualKeyMap.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-
-#define INDENT " "
-#define INDENT2 " "
-#define INDENT3 " "
-#define INDENT4 " "
-#define INDENT5 " "
-
-namespace android {
-
-// --- Constants ---
-
-// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
-static const size_t MAX_SLOTS = 32;
-
-// --- 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 },
-};
-static const size_t keyCodeRotationMapSize =
- sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
-
-static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
- 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,
- 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(when, deviceId, source, 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,
- uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
- synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
- lastButtonState, currentButtonState,
- AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
- synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
- lastButtonState, currentButtonState,
- AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
-}
-
-
-// --- InputReaderConfiguration ---
-
-bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const {
- const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay;
- if (viewport.displayId >= 0) {
- *outViewport = viewport;
- return true;
- }
- return false;
-}
-
-void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) {
- DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay;
- v = viewport;
-}
-
-
-// --- InputReader ---
-
-InputReader::InputReader(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener) :
- mContext(this), mEventHub(eventHub), mPolicy(policy),
- 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;
- 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: %d Count: %d", 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);
-
- InputDevice* device = createDeviceLocked(deviceId, 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.string());
- } else {
- ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
- identifier.name.string(), device->getSources());
- }
-
- mDevices.add(deviceId, device);
- bumpGenerationLocked();
-}
-
-void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
- InputDevice* device = NULL;
- 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().string());
- } else {
- ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
- device->getId(), device->getName().string(), device->getSources());
- }
-
- device->reset(when);
- delete device;
-}
-
-InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
- const InputDeviceIdentifier& identifier, uint32_t classes) {
- InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
- identifier, classes);
-
- // External devices.
- if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
- device->setExternal(true);
- }
-
- // Switch-like devices.
- if (classes & INPUT_DEVICE_CLASS_SWITCH) {
- device->addMapper(new SwitchInputMapper(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));
- }
-
- 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(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::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().string(),
- (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(Vector<InputDeviceInfo>& outInputDevices) {
- AutoMutex _l(mLock);
- getInputDevicesLocked(outInputDevices);
-}
-
-void InputReader::getInputDevicesLocked(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()) {
- outInputDevices.push();
- device->getDeviceInfo(&outInputDevices.editTop());
- }
- }
-}
-
-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;
-}
-
-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);
- }
-}
-
-void InputReader::dump(String8& dump) {
- AutoMutex _l(mLock);
-
- mEventHub->dump(dump);
- dump.append("\n");
-
- dump.append("Input Reader State:\n");
-
- for (size_t i = 0; i < mDevices.size(); i++) {
- mDevices.valueAt(i)->dump(dump);
- }
-
- dump.append(INDENT "Configuration:\n");
- dump.append(INDENT2 "ExcludedDeviceNames: [");
- for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
- if (i != 0) {
- dump.append(", ");
- }
- dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
- }
- dump.append("]\n");
- dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
- mConfig.virtualKeyQuietTime * 0.000001f);
-
- dump.appendFormat(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.appendFormat(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.appendFormat(INDENT2 "PointerGesture:\n");
- dump.appendFormat(INDENT3 "Enabled: %s\n",
- toString(mConfig.pointerGesturesEnabled));
- dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
- mConfig.pointerGestureQuietInterval * 0.000001f);
- dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
- mConfig.pointerGestureDragMinSwitchSpeed);
- dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
- mConfig.pointerGestureTapInterval * 0.000001f);
- dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
- mConfig.pointerGestureTapDragInterval * 0.000001f);
- dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
- mConfig.pointerGestureTapSlop);
- dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
- mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
- dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
- mConfig.pointerGestureMultitouchMinDistance);
- dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
- mConfig.pointerGestureSwipeTransitionAngleCosine);
- dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
- mConfig.pointerGestureSwipeMaxWidthRatio);
- dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
- mConfig.pointerGestureMovementSpeedRatio);
- dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
- mConfig.pointerGestureZoomSpeedRatio);
-}
-
-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();
-}
-
-InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
- return mReader->mPolicy.get();
-}
-
-InputListenerInterface* InputReader::ContextImpl::getListener() {
- return mReader->mQueuedListener.get();
-}
-
-EventHubInterface* InputReader::ContextImpl::getEventHub() {
- return mReader->mEventHub.get();
-}
-
-
-// --- InputReaderThread ---
-
-InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
- Thread(/*canCallJava*/ true), mReader(reader) {
-}
-
-InputReaderThread::~InputReaderThread() {
-}
-
-bool InputReaderThread::threadLoop() {
- mReader->loopOnce();
- return true;
-}
-
-
-// --- InputDevice ---
-
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
- const InputDeviceIdentifier& identifier, uint32_t classes) :
- mContext(context), mId(id), mGeneration(generation),
- mIdentifier(identifier), mClasses(classes),
- mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
-}
-
-InputDevice::~InputDevice() {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- delete mMappers[i];
- }
- mMappers.clear();
-}
-
-void InputDevice::dump(String8& dump) {
- InputDeviceInfo deviceInfo;
- getDeviceInfo(& deviceInfo);
-
- dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
- deviceInfo.getDisplayName().string());
- dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration);
- dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
- dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
- dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
-
- const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
- if (!ranges.isEmpty()) {
- dump.append(INDENT2 "Motion Ranges:\n");
- for (size_t i = 0; i < ranges.size(); i++) {
- const InputDeviceInfo::MotionRange& range = ranges.itemAt(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.appendFormat(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.add(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.descriptor);
- if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
- bumpGeneration();
- }
- }
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
- if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
- String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
- if (mAlias != alias) {
- mAlias = alias;
- bumpGeneration();
- }
- }
- }
-
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->configure(when, config, changes);
- mSources |= mapper->getSources();
- }
- }
-}
-
-void InputDevice::reset(nsecs_t when) {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- 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.
- size_t numMappers = mMappers.size();
- for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
-#if DEBUG_RAW_EVENTS
- ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",
- 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().string());
- mDropUntilNextSync = true;
- reset(rawEvent->when);
- } else {
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->process(rawEvent);
- }
- }
- }
-}
-
-void InputDevice::timeoutExpired(nsecs_t when) {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->timeoutExpired(when);
- }
-}
-
-void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
- outDeviceInfo->initialize(mId, mGeneration, mIdentifier, mAlias, mIsExternal);
-
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- 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;
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- 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;
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- 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) {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->vibrate(pattern, patternSize, repeat, token);
- }
-}
-
-void InputDevice::cancelVibrate(int32_t token) {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->cancelVibrate(token);
- }
-}
-
-int32_t InputDevice::getMetaState() {
- int32_t result = 0;
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- result |= mapper->getMetaState();
- }
- return result;
-}
-
-void InputDevice::fadePointer() {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->fadePointer();
- }
-}
-
-void InputDevice::bumpGeneration() {
- mGeneration = mContext->bumpGeneration();
-}
-
-void InputDevice::notifyReset(nsecs_t when) {
- NotifyDeviceResetArgs args(when, mId);
- mContext->getListener()->notifyDeviceReset(&args);
-}
-
-
-// --- 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);
- mBtnStylus2 = device->isKeyPressed(BTN_STYLUS);
- 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:
- 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_SECONDARY;
- }
- if (mBtnStylus2) {
- result |= AMOTION_EVENT_BUTTON_TERTIARY;
- }
- 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(NULL), 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);
- }
-}
-
-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) {
-#if DEBUG_POINTERS
- bool newSlot = false;
-#endif
- if (mUsingSlotsProtocol) {
- if (rawEvent->code == ABS_MT_SLOT) {
- mCurrentSlot = rawEvent->value;
-#if DEBUG_POINTERS
- newSlot = true;
-#endif
- }
- } 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 %d; 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;
- }
-}
-
-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(String8& 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) {
-}
-
-int32_t InputMapper::getMetaState() {
- return 0;
-}
-
-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(String8& dump,
- const RawAbsoluteAxisInfo& axis, const char* name) {
- if (axis.valid) {
- dump.appendFormat(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.appendFormat(INDENT4 "%s: unknown range\n", name);
- }
-}
-
-
-// --- SwitchInputMapper ---
-
-SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
- InputMapper(device), mUpdatedSwitchValues(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) {
- mUpdatedSwitchValues |= 1 << switchCode;
- }
- mUpdatedSwitchMask |= 1 << switchCode;
- }
-}
-
-void SwitchInputMapper::sync(nsecs_t when) {
- if (mUpdatedSwitchMask) {
- NotifySwitchArgs args(when, 0, mUpdatedSwitchValues, mUpdatedSwitchMask);
- getListener()->notifySwitch(&args);
-
- mUpdatedSwitchValues = 0;
- mUpdatedSwitchMask = 0;
- }
-}
-
-int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return getEventHub()->getSwitchState(getDeviceId(), switchCode);
-}
-
-
-// --- 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
- String8 patternStr;
- for (size_t i = 0; i < patternSize; i++) {
- if (i != 0) {
- patternStr.append(", ");
- }
- patternStr.appendFormat("%lld", pattern[i]);
- }
- ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%ld, token=%d",
- getDeviceId(), patternStr.string(), 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=%lld",
- 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(String8& dump) {
- dump.append(INDENT2 "Vibrator Input Mapper:\n");
- dump.appendFormat(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;
-}
-
-void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- info->setKeyboardType(mKeyboardType);
- info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
-}
-
-void KeyboardInputMapper::dump(String8& dump) {
- dump.append(INDENT2 "Keyboard Input Mapper:\n");
- dumpParameters(dump);
- dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
- dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
- dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
- dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
- dump.appendFormat(INDENT3 "DownTime: %lld\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 && mParameters.hasAssociatedDisplay) {
- DisplayViewport v;
- if (config->getDisplayInfo(false /*external*/, &v)) {
- mOrientation = v.orientation;
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
- }
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
- }
- }
-}
-
-void KeyboardInputMapper::configureParameters() {
- mParameters.orientationAware = false;
- getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
- mParameters.orientationAware);
-
- mParameters.hasAssociatedDisplay = false;
- if (mParameters.orientationAware) {
- mParameters.hasAssociatedDisplay = true;
- }
-}
-
-void KeyboardInputMapper::dumpParameters(String8& dump) {
- dump.append(INDENT3 "Parameters:\n");
- dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
- toString(mParameters.hasAssociatedDisplay));
- dump.appendFormat(INDENT4 "OrientationAware: %s\n",
- toString(mParameters.orientationAware));
-}
-
-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)) {
- int32_t keyCode;
- uint32_t flags;
- if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
- keyCode = AKEYCODE_UNKNOWN;
- flags = 0;
- }
- processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
- }
- 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);
-}
-
-void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
- int32_t scanCode, uint32_t policyFlags) {
-
- if (down) {
- // Rotate key codes according to orientation if needed.
- if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
- keyCode = rotateKeyCode(keyCode, mOrientation);
- }
-
- // 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.itemAt(keyDownIndex).keyCode;
- } else {
- // key down
- if ((policyFlags & POLICY_FLAG_VIRTUAL)
- && mContext->shouldDropVirtualKey(when,
- getDevice(), keyCode, scanCode)) {
- return;
- }
-
- mKeyDowns.push();
- KeyDown& keyDown = mKeyDowns.editTop();
- keyDown.keyCode = keyCode;
- keyDown.scanCode = scanCode;
- }
-
- 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.itemAt(keyDownIndex).keyCode;
- mKeyDowns.removeAt(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().string(), keyCode, scanCode);
- return;
- }
- }
-
- bool metaStateChanged = false;
- int32_t oldMetaState = mMetaState;
- int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
- if (oldMetaState != newMetaState) {
- mMetaState = newMetaState;
- metaStateChanged = true;
- updateLedState(false);
- }
-
- 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()
- && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
- policyFlags |= POLICY_FLAG_WAKE_DROPPED;
- }
-
- if (metaStateChanged) {
- getContext()->updateGlobalMetaState();
- }
-
- if (down && !isMetaKey(keyCode)) {
- getContext()->fadePointer();
- }
-
- NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
- down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, 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::resetLedState() {
- initializeLedState(mCapsLockLedState, LED_CAPSL);
- initializeLedState(mNumLockLedState, LED_NUML);
- initializeLedState(mScrollLockLedState, LED_SCROLLL);
-
- 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, LED_CAPSL,
- AMETA_CAPS_LOCK_ON, reset);
- updateLedStateForModifier(mNumLockLedState, LED_NUML,
- AMETA_NUM_LOCK_ON, reset);
- updateLedStateForModifier(mScrollLockLedState, LED_SCROLLL,
- 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(String8& dump) {
- dump.append(INDENT2 "Cursor Input Mapper:\n");
- dumpParameters(dump);
- dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
- dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
- dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
- dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
- dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
- toString(mCursorScrollAccumulator.haveRelativeVWheel()));
- dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
- toString(mCursorScrollAccumulator.haveRelativeHWheel()));
- dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
- dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
- dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
- dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
- dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
- dump.appendFormat(INDENT3 "DownTime: %lld\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:
- 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 || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
- mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
- mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
- mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
- DisplayViewport v;
- if (config->getDisplayInfo(false /*external*/, &v)) {
- mOrientation = v.orientation;
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
- }
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
- }
- 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(String8& dump) {
- dump.append(INDENT3 "Parameters:\n");
- dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
- toString(mParameters.hasAssociatedDisplay));
-
- switch (mParameters.mode) {
- case Parameters::MODE_POINTER:
- dump.append(INDENT4 "Mode: pointer\n");
- break;
- case Parameters::MODE_NAVIGATION:
- dump.append(INDENT4 "Mode: navigation\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- dump.appendFormat(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;
- bool buttonsPressed = currentButtonState & ~lastButtonState;
-
- 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, NULL, &vscroll);
- mWheelXVelocityControl.move(when, &hscroll, NULL);
-
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- int32_t displayId;
- if (mPointerController != NULL) {
- 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);
- displayId = ADISPLAY_ID_DEFAULT;
- } 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_DROPPED;
- }
-
- // Synthesize key down from buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
- policyFlags, lastButtonState, currentButtonState);
-
- // Send motion event.
- if (downChanged || moved || scrolled || buttonsChanged) {
- int32_t metaState = mContext->getGlobalMetaState();
- int32_t motionEventAction;
- if (downChanged) {
- motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
- } else if (down || mPointerController == NULL) {
- motionEventAction = AMOTION_EVENT_ACTION_MOVE;
- } else {
- motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
- }
-
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- motionEventAction, 0, metaState, currentButtonState, 0,
- displayId, 1, &pointerProperties, &pointerCoords,
- mXPrecision, mYPrecision, downTime);
- getListener()->notifyMotion(&args);
-
- // Send hover move after UP to tell the application that the mouse is hovering now.
- if (motionEventAction == AMOTION_EVENT_ACTION_UP
- && mPointerController != NULL) {
- NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
- metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, 1, &pointerProperties, &pointerCoords,
- mXPrecision, mYPrecision, downTime);
- getListener()->notifyMotion(&hoverArgs);
- }
-
- // Send scroll events.
- if (scrolled) {
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
-
- NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, 1, &pointerProperties, &pointerCoords,
- mXPrecision, mYPrecision, downTime);
- getListener()->notifyMotion(&scrollArgs);
- }
- }
-
- // Synthesize key up from buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
- 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 != NULL) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
-}
-
-
-// --- TouchInputMapper ---
-
-TouchInputMapper::TouchInputMapper(InputDevice* device) :
- InputMapper(device),
- mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
- mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(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);
- }
- }
-}
-
-void TouchInputMapper::dump(String8& dump) {
- dump.append(INDENT2 "Touch Input Mapper:\n");
- dumpParameters(dump);
- dumpVirtualKeys(dump);
- dumpRawPointerAxes(dump);
- dumpCalibration(dump);
- dumpSurface(dump);
-
- dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
- dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
- dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
- dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale);
- dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale);
- dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
- dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
- dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
- dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
- dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
- dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
- dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
- dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
- dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
- dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
- dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
- dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
-
- dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState);
-
- dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n",
- mLastRawPointerData.pointerCount);
- for (uint32_t i = 0; i < mLastRawPointerData.pointerCount; i++) {
- const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i];
- dump.appendFormat(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.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
- mLastCookedPointerData.pointerCount);
- for (uint32_t i = 0; i < mLastCookedPointerData.pointerCount; i++) {
- const PointerProperties& pointerProperties = mLastCookedPointerData.pointerProperties[i];
- const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i];
- dump.appendFormat(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(mLastCookedPointerData.isHovering(i)));
- }
-
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
- dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
- mPointerXMovementScale);
- dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
- mPointerYMovementScale);
- dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
- mPointerXZoomScale);
- dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
- mPointerYZoomScale);
- dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
- mPointerGestureMaxSwipeWidth);
- }
-}
-
-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_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))) {
- // 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::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_POINTER : Parameters::GESTURE_MODE_SPOTS;
-
- String8 gestureModeString;
- if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
- gestureModeString)) {
- if (gestureModeString == "pointer") {
- mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
- } else if (gestureModeString == "spots") {
- mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
- } 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;
- }
-
- 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;
- mParameters.associatedDisplayIsExternal =
- mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
- && getDevice()->isExternal();
- }
-}
-
-void TouchInputMapper::dumpParameters(String8& dump) {
- dump.append(INDENT3 "Parameters:\n");
-
- switch (mParameters.gestureMode) {
- case Parameters::GESTURE_MODE_POINTER:
- dump.append(INDENT4 "GestureMode: pointer\n");
- break;
- case Parameters::GESTURE_MODE_SPOTS:
- dump.append(INDENT4 "GestureMode: spots\n");
- break;
- default:
- assert(false);
- }
-
- switch (mParameters.deviceType) {
- case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
- dump.append(INDENT4 "DeviceType: touchScreen\n");
- break;
- case Parameters::DEVICE_TYPE_TOUCH_PAD:
- dump.append(INDENT4 "DeviceType: touchPad\n");
- break;
- case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
- dump.append(INDENT4 "DeviceType: touchNavigation\n");
- break;
- case Parameters::DEVICE_TYPE_POINTER:
- dump.append(INDENT4 "DeviceType: pointer\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n",
- toString(mParameters.hasAssociatedDisplay),
- toString(mParameters.associatedDisplayIsExternal));
- dump.appendFormat(INDENT4 "OrientationAware: %s\n",
- toString(mParameters.orientationAware));
-}
-
-void TouchInputMapper::configureRawPointerAxes() {
- mRawPointerAxes.clear();
-}
-
-void TouchInputMapper::dumpRawPointerAxes(String8& dump) {
- dump.append(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");
-}
-
-void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
- int32_t oldDeviceMode = mDeviceMode;
-
- // 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;
- }
- } 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(INDENT "Touch device '%s' did not report support for X or Y axis! "
- "The device will be inoperable.", getDeviceName().string());
- mDeviceMode = DEVICE_MODE_DISABLED;
- return;
- }
-
- // Raw width and height in the natural orientation.
- int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
- int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
-
- // Get associated display dimensions.
- bool viewportChanged = false;
- DisplayViewport newViewport;
- if (mParameters.hasAssociatedDisplay) {
- if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) {
- ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
- "display. The device will be inoperable until the display size "
- "becomes available.",
- getDeviceName().string());
- mDeviceMode = DEVICE_MODE_DISABLED;
- return;
- }
- } else {
- newViewport.setNonDisplayViewport(rawWidth, rawHeight);
- }
- if (mViewport != newViewport) {
- mViewport = newViewport;
- viewportChanged = true;
-
- 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;
- }
-
- 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 {
- 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 pointer controller if needed.
- if (mDeviceMode == DEVICE_MODE_POINTER ||
- (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
- if (mPointerController == NULL) {
- 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().string(), 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;
- if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
- || mCalibration.pressureCalibration
- == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
- if (mCalibration.havePressureScale) {
- mPressureScale = mCalibration.pressureScale;
- } 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 = 1.0;
- 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;
- }
-
- 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(String8& dump) {
- dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, "
- "logicalFrame=[%d, %d, %d, %d], "
- "physicalFrame=[%d, %d, %d, %d], "
- "deviceSize=[%d, %d]\n",
- mViewport.displayId, mViewport.orientation,
- mViewport.logicalLeft, mViewport.logicalTop,
- mViewport.logicalRight, mViewport.logicalBottom,
- mViewport.physicalLeft, mViewport.physicalTop,
- mViewport.physicalRight, mViewport.physicalBottom,
- mViewport.deviceWidth, mViewport.deviceHeight);
-
- dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
- dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
- dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
- dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
- dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
-}
-
-void TouchInputMapper::configureVirtualKeys() {
- Vector<VirtualKeyDefinition> virtualKeyDefinitions;
- getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
-
- mVirtualKeys.clear();
-
- if (virtualKeyDefinitions.size() == 0) {
- return;
- }
-
- mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
-
- int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
- int32_t touchScreenTop = mRawPointerAxes.y.minValue;
- int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
- int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
-
- for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
- const VirtualKeyDefinition& virtualKeyDefinition =
- virtualKeyDefinitions[i];
-
- mVirtualKeys.add();
- VirtualKey& virtualKey = mVirtualKeys.editTop();
-
- virtualKey.scanCode = virtualKeyDefinition.scanCode;
- int32_t keyCode;
- uint32_t flags;
- if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) {
- ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
- virtualKey.scanCode);
- mVirtualKeys.pop(); // drop the key
- continue;
- }
-
- 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;
- }
-}
-
-void TouchInputMapper::dumpVirtualKeys(String8& dump) {
- if (!mVirtualKeys.isEmpty()) {
- dump.append(INDENT3 "Virtual Keys:\n");
-
- for (size_t i = 0; i < mVirtualKeys.size(); i++) {
- const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
- dump.appendFormat(INDENT4 "%d: 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(String8& dump) {
- dump.append(INDENT3 "Calibration:\n");
-
- // Size
- switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.size.calibration: none\n");
- break;
- case Calibration::SIZE_CALIBRATION_GEOMETRIC:
- dump.append(INDENT4 "touch.size.calibration: geometric\n");
- break;
- case Calibration::SIZE_CALIBRATION_DIAMETER:
- dump.append(INDENT4 "touch.size.calibration: diameter\n");
- break;
- case Calibration::SIZE_CALIBRATION_BOX:
- dump.append(INDENT4 "touch.size.calibration: box\n");
- break;
- case Calibration::SIZE_CALIBRATION_AREA:
- dump.append(INDENT4 "touch.size.calibration: area\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- if (mCalibration.haveSizeScale) {
- dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n",
- mCalibration.sizeScale);
- }
-
- if (mCalibration.haveSizeBias) {
- dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n",
- mCalibration.sizeBias);
- }
-
- if (mCalibration.haveSizeIsSummed) {
- dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n",
- toString(mCalibration.sizeIsSummed));
- }
-
- // Pressure
- switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.pressure.calibration: none\n");
- break;
- case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
- dump.append(INDENT4 "touch.pressure.calibration: physical\n");
- break;
- case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
- dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- if (mCalibration.havePressureScale) {
- dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
- mCalibration.pressureScale);
- }
-
- // Orientation
- switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.orientation.calibration: none\n");
- break;
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
- dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
- break;
- case Calibration::ORIENTATION_CALIBRATION_VECTOR:
- dump.append(INDENT4 "touch.orientation.calibration: vector\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- // Distance
- switch (mCalibration.distanceCalibration) {
- case Calibration::DISTANCE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.distance.calibration: none\n");
- break;
- case Calibration::DISTANCE_CALIBRATION_SCALED:
- dump.append(INDENT4 "touch.distance.calibration: scaled\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- if (mCalibration.haveDistanceScale) {
- dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
- mCalibration.distanceScale);
- }
-
- switch (mCalibration.coverageCalibration) {
- case Calibration::COVERAGE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.coverage.calibration: none\n");
- break;
- case Calibration::COVERAGE_CALIBRATION_BOX:
- dump.append(INDENT4 "touch.coverage.calibration: box\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-}
-
-void TouchInputMapper::reset(nsecs_t when) {
- mCursorButtonAccumulator.reset(getDevice());
- mCursorScrollAccumulator.reset(getDevice());
- mTouchButtonAccumulator.reset(getDevice());
-
- mPointerVelocityControl.reset();
- mWheelXVelocityControl.reset();
- mWheelYVelocityControl.reset();
-
- mCurrentRawPointerData.clear();
- mLastRawPointerData.clear();
- mCurrentCookedPointerData.clear();
- mLastCookedPointerData.clear();
- mCurrentButtonState = 0;
- mLastButtonState = 0;
- mCurrentRawVScroll = 0;
- mCurrentRawHScroll = 0;
- mCurrentFingerIdBits.clear();
- mLastFingerIdBits.clear();
- mCurrentStylusIdBits.clear();
- mLastStylusIdBits.clear();
- mCurrentMouseIdBits.clear();
- mLastMouseIdBits.clear();
- mPointerUsage = POINTER_USAGE_NONE;
- mSentHoverEnter = false;
- mDownTime = 0;
-
- mCurrentVirtualKey.down = false;
-
- mPointerGesture.reset();
- mPointerSimple.reset();
-
- if (mPointerController != NULL) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- mPointerController->clearSpots();
- }
-
- InputMapper::reset(when);
-}
-
-void TouchInputMapper::process(const RawEvent* rawEvent) {
- mCursorButtonAccumulator.process(rawEvent);
- mCursorScrollAccumulator.process(rawEvent);
- mTouchButtonAccumulator.process(rawEvent);
-
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- sync(rawEvent->when);
- }
-}
-
-void TouchInputMapper::sync(nsecs_t when) {
- // Sync button state.
- mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
- | mCursorButtonAccumulator.getButtonState();
-
- // Sync scroll state.
- mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
- mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
- mCursorScrollAccumulator.finishSync();
-
- // Sync touch state.
- bool havePointerIds = true;
- mCurrentRawPointerData.clear();
- syncTouch(when, &havePointerIds);
-
-#if DEBUG_RAW_EVENTS
- if (!havePointerIds) {
- ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
- mLastRawPointerData.pointerCount,
- mCurrentRawPointerData.pointerCount);
- } else {
- ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
- "hovering ids 0x%08x -> 0x%08x",
- mLastRawPointerData.pointerCount,
- mCurrentRawPointerData.pointerCount,
- mLastRawPointerData.touchingIdBits.value,
- mCurrentRawPointerData.touchingIdBits.value,
- mLastRawPointerData.hoveringIdBits.value,
- mCurrentRawPointerData.hoveringIdBits.value);
- }
-#endif
-
- // Reset state that we will compute below.
- mCurrentFingerIdBits.clear();
- mCurrentStylusIdBits.clear();
- mCurrentMouseIdBits.clear();
- mCurrentCookedPointerData.clear();
-
- if (mDeviceMode == DEVICE_MODE_DISABLED) {
- // Drop all input if the device is disabled.
- mCurrentRawPointerData.clear();
- mCurrentButtonState = 0;
- } else {
- // Preprocess pointer data.
- if (!havePointerIds) {
- assignPointerIds();
- }
-
- // Handle policy on initial down or hover events.
- uint32_t policyFlags = 0;
- bool initialDown = mLastRawPointerData.pointerCount == 0
- && mCurrentRawPointerData.pointerCount != 0;
- bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;
- if (initialDown || buttonsPressed) {
- // If this is a touch screen, hide the pointer on an initial down.
- if (mDeviceMode == DEVICE_MODE_DIRECT) {
- getContext()->fadePointer();
- }
-
- // Initial downs on external touch devices should wake the device.
- // We don't do this for internal touch screens to prevent them from waking
- // up in your pocket.
- // TODO: Use the input device configuration to control this behavior more finely.
- if (getDevice()->isExternal()) {
- policyFlags |= POLICY_FLAG_WAKE_DROPPED;
- }
- }
-
- // Synthesize key down from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
- policyFlags, mLastButtonState, mCurrentButtonState);
-
- // 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)) {
- mCurrentRawPointerData.clear();
- }
-
- // Cook pointer data. This call populates the mCurrentCookedPointerData 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();
-
- // Dispatch the touches either directly or by translation through a pointer on screen.
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
- || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
- mCurrentStylusIdBits.markBit(id);
- } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
- || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- mCurrentFingerIdBits.markBit(id);
- } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
- mCurrentMouseIdBits.markBit(id);
- }
- }
- for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
- || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
- mCurrentStylusIdBits.markBit(id);
- }
- }
-
- // Stylus takes precedence over all tools, then mouse, then finger.
- PointerUsage pointerUsage = mPointerUsage;
- if (!mCurrentStylusIdBits.isEmpty()) {
- mCurrentMouseIdBits.clear();
- mCurrentFingerIdBits.clear();
- pointerUsage = POINTER_USAGE_STYLUS;
- } else if (!mCurrentMouseIdBits.isEmpty()) {
- mCurrentFingerIdBits.clear();
- pointerUsage = POINTER_USAGE_MOUSE;
- } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {
- pointerUsage = POINTER_USAGE_GESTURES;
- }
-
- dispatchPointerUsage(when, policyFlags, pointerUsage);
- } else {
- if (mDeviceMode == DEVICE_MODE_DIRECT
- && mConfig.showTouches && mPointerController != NULL) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-
- mPointerController->setButtonState(mCurrentButtonState);
- mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mCurrentCookedPointerData.touchingIdBits);
- }
-
- dispatchHoverExit(when, policyFlags);
- dispatchTouches(when, policyFlags);
- dispatchHoverEnterAndMove(when, policyFlags);
- }
-
- // Synthesize key up from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
- policyFlags, mLastButtonState, mCurrentButtonState);
- }
-
- // Copy current touch to last touch in preparation for the next cycle.
- mLastRawPointerData.copyFrom(mCurrentRawPointerData);
- mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);
- mLastButtonState = mCurrentButtonState;
- mLastFingerIdBits = mCurrentFingerIdBits;
- mLastStylusIdBits = mCurrentStylusIdBits;
- mLastMouseIdBits = mCurrentMouseIdBits;
-
- // Clear some transient state.
- mCurrentRawVScroll = 0;
- mCurrentRawHScroll = 0;
-}
-
-void TouchInputMapper::timeoutExpired(nsecs_t when) {
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- if (mPointerUsage == POINTER_USAGE_GESTURES) {
- dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
- }
- }
-}
-
-bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
- // Check for release of a virtual key.
- if (mCurrentVirtualKey.down) {
- if (mCurrentRawPointerData.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 (mCurrentRawPointerData.touchingIdBits.count() == 1) {
- uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.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 (mLastRawPointerData.touchingIdBits.isEmpty()
- && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
- // Pointer just went down. Check for virtual key press or off-screen touches.
- uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.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 (mCurrentRawPointerData.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 && !mCurrentRawPointerData.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(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
- keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
- getListener()->notifyKey(&args);
-}
-
-void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
- BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
- BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentButtonState;
-
- 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, metaState, buttonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.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(
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mLastCookedPointerData.pointerProperties,
- mLastCookedPointerData.pointerCoords,
- mLastCookedPointerData.idToIndex,
- moveIdBits);
- if (buttonState != mLastButtonState) {
- moveNeeded = true;
- }
-
- // Dispatch pointer up events.
- while (!upIdBits.isEmpty()) {
- uint32_t upId = upIdBits.clearFirstMarkedBit();
-
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
- mLastCookedPointerData.pointerProperties,
- mLastCookedPointerData.pointerCoords,
- mLastCookedPointerData.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) {
- ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.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, metaState, buttonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- dispatchedIdBits, downId,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
- }
-}
-
-void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
- if (mSentHoverEnter &&
- (mCurrentCookedPointerData.hoveringIdBits.isEmpty()
- || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {
- int32_t metaState = getContext()->getGlobalMetaState();
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
- mLastCookedPointerData.pointerProperties,
- mLastCookedPointerData.pointerCoords,
- mLastCookedPointerData.idToIndex,
- mLastCookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- mSentHoverEnter = false;
- }
-}
-
-void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
- if (mCurrentCookedPointerData.touchingIdBits.isEmpty()
- && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) {
- int32_t metaState = getContext()->getGlobalMetaState();
- if (!mSentHoverEnter) {
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mCurrentCookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- mSentHoverEnter = true;
- }
-
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mCurrentCookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
-}
-
-void TouchInputMapper::cookPointerData() {
- uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
-
- mCurrentCookedPointerData.clear();
- mCurrentCookedPointerData.pointerCount = currentPointerCount;
- mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;
- mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;
-
- // 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 = mCurrentRawPointerData.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 = mCurrentRawPointerData.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;
- }
-
- // X, Y, and the bounding box for coverage information
- // Adjust coords for surface orientation.
- float x, y, left, top, right, bottom;
- switch (mSurfaceOrientation) {
- case DISPLAY_ORIENTATION_90:
- x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- y = float(mRawPointerAxes.x.maxValue - in.x) * 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 (orientation < - M_PI_2) {
- orientation += M_PI;
- }
- break;
- case DISPLAY_ORIENTATION_180:
- x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
- y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
- left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
- right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
- bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
- top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
- break;
- case DISPLAY_ORIENTATION_270:
- x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
- y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
- right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
- bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- orientation += M_PI_2;
- if (orientation > M_PI_2) {
- orientation -= M_PI;
- }
- break;
- default:
- x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- y = float(in.y - 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 = mCurrentCookedPointerData.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 = mCurrentCookedPointerData.pointerProperties[i];
- uint32_t id = in.id;
- properties.clear();
- properties.id = id;
- properties.toolType = in.toolType;
-
- // Write id index.
- mCurrentCookedPointerData.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_SPOTS) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
- if (finishPreviousGesture || cancelPreviousGesture) {
- mPointerController->clearSpots();
- }
- mPointerController->setSpots(mPointerGesture.currentGestureCoords,
- mPointerGesture.currentGestureIdToIndex,
- mPointerGesture.currentGestureIdBits);
- } 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_SPOTS
- && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
- || 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:
- // Unfade the pointer when the current gesture manipulates the
- // area directly under the pointer.
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- break;
- case PointerGesture::SWIPE:
- 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_SPOTS) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- } else {
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- }
- break;
- }
-
- // Send events!
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentButtonState;
-
- // 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 != mLastButtonState) {
- 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, metaState, buttonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- 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,
- metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- 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, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- 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, metaState, buttonState, 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,
- metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- 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);
-
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
- metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mViewport.displayId, 1, &pointerProperties, &pointerCoords,
- 0, 0, mPointerGesture.downTime);
- 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 = mCurrentButtonState;
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- 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 != NULL) {
- 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 = mCurrentFingerIdBits.count();
- const uint32_t lastFingerCount = mLastFingerIdBits.count();
-
- // Update the velocity tracker.
- {
- VelocityTracker::Position positions[MAX_POINTERS];
- uint32_t count = 0;
- for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- positions[count].x = pointer.x * mPointerXMovementScale;
- positions[count].y = pointer.y * mPointerYMovementScale;
- }
- mPointerGesture.velocityTracker.addMovement(when,
- mCurrentFingerIdBits, positions);
- }
-
- // 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 (!mCurrentFingerIdBits.isEmpty()) {
- activeTouchId = mPointerGesture.activeTouchId =
- mCurrentFingerIdBits.firstMarkedBit();
- mPointerGesture.firstTouchTime = when;
- }
- } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) {
- if (!mCurrentFingerIdBits.isEmpty()) {
- activeTouchId = mPointerGesture.activeTouchId =
- mCurrentFingerIdBits.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(mCurrentButtonState)) {
- // 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(mCurrentButtonState)) {
- // 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(mCurrentFingerIdBits); !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
- }
- }
-
- if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) {
- const RawPointerData::Pointer& currentPointer =
- mCurrentRawPointerData.pointerForId(activeTouchId);
- const RawPointerData::Pointer& lastPointer =
- mLastRawPointerData.pointerForId(activeTouchId);
- float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
- float 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
- ALOGD("Gestures: Not a TAP, %0.3fms since down",
- (when - mPointerGesture.tapDownTime) * 0.000001f);
-#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;
- }
-
- if (mLastFingerIdBits.hasBit(activeTouchId)) {
- const RawPointerData::Pointer& currentPointer =
- mCurrentRawPointerData.pointerForId(activeTouchId);
- const RawPointerData::Pointer& lastPointer =
- mLastRawPointerData.pointerForId(activeTouchId);
- float deltaX = (currentPointer.x - lastPointer.x)
- * mPointerXMovementScale;
- float 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
- mCurrentRawPointerData.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(mCurrentFingerIdBits.value
- & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- mPointerGesture.referenceDeltas[id].dx = 0;
- mPointerGesture.referenceDeltas[id].dy = 0;
- }
- mPointerGesture.referenceIdBits = mCurrentFingerIdBits;
-
- // Add delta for all fingers and calculate a common movement delta.
- float commonDeltaX = 0, commonDeltaY = 0;
- BitSet32 commonIdBits(mLastFingerIdBits.value
- & mCurrentFingerIdBits.value);
- for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
- bool first = (idBits == commonIdBits);
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id);
- const RawPointerData::Pointer& lpd = mLastRawPointerData.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(mCurrentFingerIdBits);
- uint32_t id1 = idBits.clearFirstMarkedBit();
- uint32_t id2 = idBits.firstMarkedBit();
- const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1);
- const RawPointerData::Pointer& p2 = mCurrentRawPointerData.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 = mLastFingerIdBits.value
- & mCurrentFingerIdBits.value;
- usedGestureIdBits = mPointerGesture.lastGestureIdBits;
-
- // Check whether we need to choose a new active gesture id because the
- // current went went up.
- for (BitSet32 upTouchIdBits(mLastFingerIdBits.value
- & ~mCurrentFingerIdBits.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(mCurrentFingerIdBits);
- 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 =
- mCurrentRawPointerData.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(mCurrentButtonState);
-
-#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 (!mCurrentStylusIdBits.isEmpty()) {
- uint32_t id = mCurrentStylusIdBits.firstMarkedBit();
- uint32_t index = mCurrentCookedPointerData.idToIndex[id];
- float x = mCurrentCookedPointerData.pointerCoords[index].getX();
- float y = mCurrentCookedPointerData.pointerCoords[index].getY();
- mPointerController->setPosition(x, y);
-
- hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id);
- down = !hovering;
-
- mPointerController->getPosition(&x, &y);
- mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.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 =
- mCurrentCookedPointerData.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 (!mCurrentMouseIdBits.isEmpty()) {
- uint32_t id = mCurrentMouseIdBits.firstMarkedBit();
- uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id];
- if (mLastMouseIdBits.hasBit(id)) {
- uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id];
- float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x
- - mLastRawPointerData.pointers[lastIndex].x)
- * mPointerXMovementScale;
- float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y
- - mLastRawPointerData.pointers[lastIndex].y)
- * mPointerYMovementScale;
-
- rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- mPointerController->move(deltaX, deltaY);
- } else {
- mPointerVelocityControl.reset();
- }
-
- down = isPointerDown(mCurrentButtonState);
- hovering = !down;
-
- float x, y;
- mPointerController->getPosition(&x, &y);
- mPointerSimple.currentCoords.copyFrom(
- mCurrentCookedPointerData.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 =
- mCurrentCookedPointerData.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();
-
- if (mPointerController != NULL) {
- if (down || hovering) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
- mPointerController->clearSpots();
- mPointerController->setButtonState(mCurrentButtonState);
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
- }
-
- if (mPointerSimple.down && !down) {
- mPointerSimple.down = false;
-
- // Send up.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- if (mPointerSimple.hovering && !hovering) {
- mPointerSimple.hovering = false;
-
- // Send hover exit.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- if (down) {
- if (!mPointerSimple.down) {
- mPointerSimple.down = true;
- mPointerSimple.downTime = when;
-
- // Send down.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- // Send move.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- if (hovering) {
- if (!mPointerSimple.hovering) {
- mPointerSimple.hovering = true;
-
- // Send hover enter.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- // Send hover move.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- if (mCurrentRawVScroll || mCurrentRawHScroll) {
- float vscroll = mCurrentRawVScroll;
- float hscroll = mCurrentRawHScroll;
- mWheelYVelocityControl.move(when, NULL, &vscroll);
- mWheelXVelocityControl.move(when, &hscroll, NULL);
-
- // Send scroll.
- PointerCoords pointerCoords;
- pointerCoords.copyFrom(mPointerSimple.currentCoords);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
-
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &pointerCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- 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 flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
- 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);
- }
- }
-
- NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
- action, flags, metaState, buttonState, edgeFlags,
- mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
- xPrecision, yPrecision, downTime);
- 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 != NULL) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
-}
-
-bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
- return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
- && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
-}
-
-const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
- int32_t x, int32_t y) {
- size_t numVirtualKeys = mVirtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mVirtualKeys[i];
-
-#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 NULL;
-}
-
-void TouchInputMapper::assignPointerIds() {
- uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
- uint32_t lastPointerCount = mLastRawPointerData.pointerCount;
-
- mCurrentRawPointerData.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;
- mCurrentRawPointerData.pointers[i].id = id;
- mCurrentRawPointerData.idToIndex[id] = i;
- mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i));
- }
- return;
- }
-
- if (currentPointerCount == 1 && lastPointerCount == 1
- && mCurrentRawPointerData.pointers[0].toolType
- == mLastRawPointerData.pointers[0].toolType) {
- // Only one pointer and no change in count so it must have the same id as before.
- uint32_t id = mLastRawPointerData.pointers[0].id;
- mCurrentRawPointerData.pointers[0].id = id;
- mCurrentRawPointerData.idToIndex[id] = 0;
- mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.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 =
- mCurrentRawPointerData.pointers[currentPointerIndex];
- const RawPointerData::Pointer& lastPointer =
- mLastRawPointerData.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[%d]: cur=%d, last=%d, distance=%lld",
- 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[%d]: cur=%d, last=%d, distance=%lld",
- 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 = mLastRawPointerData.pointers[lastPointerIndex].id;
- mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
- mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
- mCurrentRawPointerData.markIdBit(id,
- mCurrentRawPointerData.isHovering(currentPointerIndex));
- usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
- 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();
-
- mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
- mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
- mCurrentRawPointerData.markIdBit(id,
- mCurrentRawPointerData.isHovering(currentPointerIndex));
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
- currentPointerIndex, id);
-#endif
- }
-}
-
-int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
- return AKEY_STATE_VIRTUAL;
- }
-
- size_t numVirtualKeys = mVirtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mVirtualKeys[i];
- 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;
- }
-
- size_t numVirtualKeys = mVirtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mVirtualKeys[i];
- 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) {
- size_t numVirtualKeys = mVirtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mVirtualKeys[i];
-
- for (size_t i = 0; i < numCodes; i++) {
- if (virtualKey.keyCode == keyCodes[i]) {
- outFlags[i] = 1;
- }
- }
- }
-
- return true;
-}
-
-
-// --- 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, bool* outHavePointerIds) {
- if (mTouchButtonAccumulator.isToolActive()) {
- mCurrentRawPointerData.pointerCount = 1;
- mCurrentRawPointerData.idToIndex[0] = 0;
-
- bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
- && (mTouchButtonAccumulator.isHovering()
- || (mRawPointerAxes.pressure.valid
- && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
- mCurrentRawPointerData.markIdBit(0, isHovering);
-
- RawPointerData::Pointer& outPointer = mCurrentRawPointerData.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, bool* outHavePointerIds) {
- size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
- size_t outCount = 0;
- BitSet32 newPointerIdBits;
-
- 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().string(), MAX_POINTERS);
-#endif
- break; // too many fingers!
- }
-
- RawPointerData::Pointer& outPointer = mCurrentRawPointerData.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 (*outHavePointerIds) {
- 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) {
- *outHavePointerIds = false;
- mCurrentRawPointerData.clearIdBits();
- newPointerIdBits.clear();
- } else {
- outPointer.id = id;
- mCurrentRawPointerData.idToIndex[id] = outCount;
- mCurrentRawPointerData.markIdBit(id, isHovering);
- newPointerIdBits.markBit(id);
- }
- }
-
- outCount += 1;
- }
-
- mCurrentRawPointerData.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 %d slots but the framework "
- "only supports a maximum of %d slots at this time.",
- getDeviceName().string(), 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();
-}
-
-
-// --- 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(String8& dump) {
- dump.append(INDENT2 "Joystick Input Mapper:\n");
-
- dump.append(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.appendFormat(INDENT4 "%s", label);
- } else {
- dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
- }
- if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
- label = getAxisLabel(axis.axisInfo.highAxis);
- if (label) {
- dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
- } else {
- dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
- axis.axisInfo.splitValue);
- }
- } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
- dump.append(" (invert)");
- }
-
- dump.appendFormat(": 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.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
- "highScale=%0.5f, highOffset=%0.5f\n",
- axis.scale, axis.offset, axis.highScale, axis.highOffset);
- dump.appendFormat(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.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 %d axes but the framework only supports a maximum of %d.",
- getDeviceName().string(), 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().string(), 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().string(), 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(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0);
- 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/widget/gonk/libui/InputReader.h b/widget/gonk/libui/InputReader.h
deleted file mode 100644
index 5c790fdb8..000000000
--- a/widget/gonk/libui/InputReader.h
+++ /dev/null
@@ -1,1811 +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_READER_H
-#define _UI_INPUT_READER_H
-
-#include "EventHub.h"
-#include "PointerController.h"
-#include "InputListener.h"
-
-#include "Input.h"
-#include "VelocityControl.h"
-#include "VelocityTracker.h"
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/BitSet.h>
-
-#include <stddef.h>
-#include <unistd.h>
-
-// Maximum supported size of a vibration pattern.
-// Must be at least 2.
-#define MAX_VIBRATE_PATTERN_SIZE 100
-
-// Maximum allowable delay value in a vibration pattern before
-// which the delay will be truncated.
-#define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL)
-
-namespace android {
-
-class InputDevice;
-class InputMapper;
-
-/*
- * Describes how coordinates are mapped on a physical display.
- * See com.android.server.display.DisplayViewport.
- */
-struct DisplayViewport {
- int32_t displayId; // -1 if invalid
- int32_t orientation;
- int32_t logicalLeft;
- int32_t logicalTop;
- int32_t logicalRight;
- int32_t logicalBottom;
- int32_t physicalLeft;
- int32_t physicalTop;
- int32_t physicalRight;
- int32_t physicalBottom;
- int32_t deviceWidth;
- int32_t deviceHeight;
-
- DisplayViewport() :
- displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
- logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
- physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
- deviceWidth(0), deviceHeight(0) {
- }
-
- bool operator==(const DisplayViewport& other) const {
- return displayId == other.displayId
- && orientation == other.orientation
- && logicalLeft == other.logicalLeft
- && logicalTop == other.logicalTop
- && logicalRight == other.logicalRight
- && logicalBottom == other.logicalBottom
- && physicalLeft == other.physicalLeft
- && physicalTop == other.physicalTop
- && physicalRight == other.physicalRight
- && physicalBottom == other.physicalBottom
- && deviceWidth == other.deviceWidth
- && deviceHeight == other.deviceHeight;
- }
-
- bool operator!=(const DisplayViewport& other) const {
- return !(*this == other);
- }
-
- inline bool isValid() const {
- return displayId >= 0;
- }
-
- void setNonDisplayViewport(int32_t width, int32_t height) {
- displayId = ADISPLAY_ID_NONE;
- orientation = DISPLAY_ORIENTATION_0;
- logicalLeft = 0;
- logicalTop = 0;
- logicalRight = width;
- logicalBottom = height;
- physicalLeft = 0;
- physicalTop = 0;
- physicalRight = width;
- physicalBottom = height;
- deviceWidth = width;
- deviceHeight = height;
- }
-};
-
-/*
- * Input reader configuration.
- *
- * Specifies various options that modify the behavior of the input reader.
- */
-struct InputReaderConfiguration {
- // Describes changes that have occurred.
- enum {
- // The pointer speed changed.
- CHANGE_POINTER_SPEED = 1 << 0,
-
- // The pointer gesture control changed.
- CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1,
-
- // The display size or orientation changed.
- CHANGE_DISPLAY_INFO = 1 << 2,
-
- // The visible touches option changed.
- CHANGE_SHOW_TOUCHES = 1 << 3,
-
- // The keyboard layouts must be reloaded.
- CHANGE_KEYBOARD_LAYOUTS = 1 << 4,
-
- // The device name alias supplied by the may have changed for some devices.
- CHANGE_DEVICE_ALIAS = 1 << 5,
-
- // All devices must be reopened.
- CHANGE_MUST_REOPEN = 1 << 31,
- };
-
- // Gets the amount of time to disable virtual keys after the screen is touched
- // in order to filter out accidental virtual key presses due to swiping gestures
- // or taps near the edge of the display. May be 0 to disable the feature.
- nsecs_t virtualKeyQuietTime;
-
- // The excluded device names for the platform.
- // Devices with these names will be ignored.
- Vector<String8> excludedDeviceNames;
-
- // Velocity control parameters for mouse pointer movements.
- VelocityControlParameters pointerVelocityControlParameters;
-
- // Velocity control parameters for mouse wheel movements.
- VelocityControlParameters wheelVelocityControlParameters;
-
- // True if pointer gestures are enabled.
- bool pointerGesturesEnabled;
-
- // Quiet time between certain pointer gesture transitions.
- // Time to allow for all fingers or buttons to settle into a stable state before
- // starting a new gesture.
- nsecs_t pointerGestureQuietInterval;
-
- // The minimum speed that a pointer must travel for us to consider switching the active
- // touch pointer to it during a drag. This threshold is set to avoid switching due
- // to noise from a finger resting on the touch pad (perhaps just pressing it down).
- float pointerGestureDragMinSwitchSpeed; // in pixels per second
-
- // Tap gesture delay time.
- // The time between down and up must be less than this to be considered a tap.
- nsecs_t pointerGestureTapInterval;
-
- // Tap drag gesture delay time.
- // The time between the previous tap's up and the next down must be less than
- // this to be considered a drag. Otherwise, the previous tap is finished and a
- // new tap begins.
- //
- // Note that the previous tap will be held down for this entire duration so this
- // interval must be shorter than the long press timeout.
- nsecs_t pointerGestureTapDragInterval;
-
- // The distance in pixels that the pointer is allowed to move from initial down
- // to up and still be called a tap.
- float pointerGestureTapSlop; // in pixels
-
- // Time after the first touch points go down to settle on an initial centroid.
- // This is intended to be enough time to handle cases where the user puts down two
- // fingers at almost but not quite exactly the same time.
- nsecs_t pointerGestureMultitouchSettleInterval;
-
- // The transition from PRESS to SWIPE or FREEFORM gesture mode is made when
- // at least two pointers have moved at least this far from their starting place.
- float pointerGestureMultitouchMinDistance; // in pixels
-
- // The transition from PRESS to SWIPE gesture mode can only occur when the
- // cosine of the angle between the two vectors is greater than or equal to than this value
- // which indicates that the vectors are oriented in the same direction.
- // When the vectors are oriented in the exactly same direction, the cosine is 1.0.
- // (In exactly opposite directions, the cosine is -1.0.)
- float pointerGestureSwipeTransitionAngleCosine;
-
- // The transition from PRESS to SWIPE gesture mode can only occur when the
- // fingers are no more than this far apart relative to the diagonal size of
- // the touch pad. For example, a ratio of 0.5 means that the fingers must be
- // no more than half the diagonal size of the touch pad apart.
- float pointerGestureSwipeMaxWidthRatio;
-
- // The gesture movement speed factor relative to the size of the display.
- // Movement speed applies when the fingers are moving in the same direction.
- // Without acceleration, a full swipe of the touch pad diagonal in movement mode
- // will cover this portion of the display diagonal.
- float pointerGestureMovementSpeedRatio;
-
- // The gesture zoom speed factor relative to the size of the display.
- // Zoom speed applies when the fingers are mostly moving relative to each other
- // to execute a scale gesture or similar.
- // Without acceleration, a full swipe of the touch pad diagonal in zoom mode
- // will cover this portion of the display diagonal.
- float pointerGestureZoomSpeedRatio;
-
- // True to show the location of touches on the touch screen as spots.
- bool showTouches;
-
- InputReaderConfiguration() :
- virtualKeyQuietTime(0),
- pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
- wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f),
- pointerGesturesEnabled(true),
- pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
- pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
- pointerGestureTapInterval(150 * 1000000LL), // 150 ms
- pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms
- pointerGestureTapSlop(10.0f), // 10 pixels
- pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms
- pointerGestureMultitouchMinDistance(15), // 15 pixels
- pointerGestureSwipeTransitionAngleCosine(0.2588f), // cosine of 75 degrees
- pointerGestureSwipeMaxWidthRatio(0.25f),
- pointerGestureMovementSpeedRatio(0.8f),
- pointerGestureZoomSpeedRatio(0.3f),
- showTouches(false) { }
-
- bool getDisplayInfo(bool external, DisplayViewport* outViewport) const;
- void setDisplayInfo(bool external, const DisplayViewport& viewport);
-
-private:
- DisplayViewport mInternalDisplay;
- DisplayViewport mExternalDisplay;
-};
-
-
-/*
- * Input reader 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.
- *
- * These methods must NOT re-enter the input reader since they may be called while
- * holding the input reader lock.
- */
-class InputReaderPolicyInterface : public virtual RefBase {
-protected:
- InputReaderPolicyInterface() { }
- virtual ~InputReaderPolicyInterface() { }
-
-public:
- /* Gets the input reader configuration. */
- virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
-
- /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
- virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
-
- /* Notifies the input reader policy that some input devices have changed
- * and provides information about all current input devices.
- */
- virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) = 0;
-
- /* Gets the keyboard layout for a particular input device. */
- virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor) = 0;
-
- /* Gets a user-supplied alias for a particular input device, or an empty string if none. */
- virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;
-};
-
-
-/* Processes raw input events and sends cooked event data to an input listener. */
-class InputReaderInterface : public virtual RefBase {
-protected:
- InputReaderInterface() { }
- virtual ~InputReaderInterface() { }
-
-public:
- /* Dumps the state of the input reader.
- *
- * This method may be called on any thread (usually by the input manager). */
- virtual void dump(String8& dump) = 0;
-
- /* Called by the heatbeat to ensures that the reader has not deadlocked. */
- virtual void monitor() = 0;
-
- /* Runs a single iteration of the processing loop.
- * Nominally reads and processes one incoming message from the EventHub.
- *
- * This method should be called on the input reader thread.
- */
- virtual void loopOnce() = 0;
-
- /* Gets information about all input devices.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices) = 0;
-
- /* Query current input state. */
- virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t scanCode) = 0;
- virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t keyCode) = 0;
- virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
- int32_t sw) = 0;
-
- /* Determine whether physical keys exist for the given framework-domain key codes. */
- virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
- size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
-
- /* Requests that a reconfiguration of all input devices.
- * The changes flag is a bitfield that indicates what has changed and whether
- * the input devices must all be reopened. */
- virtual void requestRefreshConfiguration(uint32_t changes) = 0;
-
- /* Controls the vibrator of a particular input device. */
- virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
- ssize_t repeat, int32_t token) = 0;
- virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0;
-};
-
-
-/* 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 InputReaderPolicyInterface* getPolicy() = 0;
- virtual InputListenerInterface* getListener() = 0;
- virtual EventHubInterface* getEventHub() = 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(String8& dump);
- virtual void monitor();
-
- virtual void loopOnce();
-
- virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices);
-
- 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 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);
-
-protected:
- // These members are protected so they can be instrumented by test cases.
- virtual InputDevice* createDeviceLocked(int32_t deviceId,
- const InputDeviceIdentifier& identifier, uint32_t classes);
-
- class ContextImpl : public InputReaderContext {
- InputReader* mReader;
-
- public:
- 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 InputReaderPolicyInterface* getPolicy();
- virtual InputListenerInterface* getListener();
- virtual EventHubInterface* getEventHub();
- } mContext;
-
- friend class ContextImpl;
-
-private:
- Mutex mLock;
-
- Condition mReaderIsAliveCondition;
-
- sp<EventHubInterface> mEventHub;
- sp<InputReaderPolicyInterface> mPolicy;
- sp<QueuedInputListener> mQueuedListener;
-
- InputReaderConfiguration mConfig;
-
- // 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 fadePointerLocked();
-
- int32_t mGeneration;
- int32_t bumpGenerationLocked();
-
- void getInputDevicesLocked(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);
-};
-
-
-/* Reads raw events from the event hub and processes them, endlessly. */
-class InputReaderThread : public Thread {
-public:
- InputReaderThread(const sp<InputReaderInterface>& reader);
- virtual ~InputReaderThread();
-
-private:
- uint32_t mFoo;
- sp<InputReaderInterface> mReader;
-
- virtual bool threadLoop();
-};
-
-
-/* Represents the state of a single input device. */
-class InputDevice {
-public:
- InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
- const InputDeviceIdentifier& identifier, uint32_t classes);
- ~InputDevice();
-
- inline InputReaderContext* getContext() { return mContext; }
- inline int32_t getId() { return mId; }
- inline int32_t getGeneration() { return mGeneration; }
- inline const String8& getName() { return mIdentifier.name; }
- inline uint32_t getClasses() { return mClasses; }
- inline uint32_t getSources() { return mSources; }
-
- inline bool isExternal() { return mIsExternal; }
- inline void setExternal(bool external) { mIsExternal = external; }
-
- inline bool isIgnored() { return mMappers.isEmpty(); }
-
- void dump(String8& 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 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);
-
- int32_t getMetaState();
-
- 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;
- }
-
-private:
- InputReaderContext* mContext;
- int32_t mId;
- int32_t mGeneration;
- InputDeviceIdentifier mIdentifier;
- String8 mAlias;
- uint32_t mClasses;
-
- Vector<InputMapper*> mMappers;
-
- uint32_t mSources;
- bool mIsExternal;
- 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();
- 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 bool isHovering(uint32_t pointerIndex) {
- return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id);
- }
-};
-
-
-/* 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]; }
-
-private:
- int32_t mCurrentSlot;
- Slot* mSlots;
- size_t mSlotCount;
- bool mUsingSlotsProtocol;
- bool mHaveStylus;
-
- 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:
- InputMapper(InputDevice* device);
- virtual ~InputMapper();
-
- inline InputDevice* getDevice() { return mDevice; }
- inline int32_t getDeviceId() { return mDevice->getId(); }
- inline const String8 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(String8& 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 int32_t getMetaState();
-
- virtual void fadePointer();
-
-protected:
- InputDevice* mDevice;
- InputReaderContext* mContext;
-
- status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
- void bumpGeneration();
-
- static void dumpRawAbsoluteAxisInfo(String8& dump,
- const RawAbsoluteAxisInfo& axis, const char* name);
-};
-
-
-class SwitchInputMapper : public InputMapper {
-public:
- 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);
-
-private:
- uint32_t mUpdatedSwitchValues;
- uint32_t mUpdatedSwitchMask;
-
- void processSwitch(int32_t switchCode, int32_t switchValue);
- void sync(nsecs_t when);
-};
-
-
-class VibratorInputMapper : public InputMapper {
-public:
- 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(String8& 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(String8& 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();
-
-private:
- struct KeyDown {
- int32_t keyCode;
- int32_t scanCode;
- };
-
- uint32_t mSource;
- int32_t mKeyboardType;
-
- int32_t mOrientation; // orientation for dpad keys
-
- 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 hasAssociatedDisplay;
- bool orientationAware;
- } mParameters;
-
- void configureParameters();
- void dumpParameters(String8& dump);
-
- bool isKeyboardOrGamepadKey(int32_t scanCode);
-
- void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
- uint32_t policyFlags);
-
- 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:
- CursorInputMapper(InputDevice* device);
- virtual ~CursorInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(String8& 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();
-
-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_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(String8& dump);
-
- void sync(nsecs_t when);
-};
-
-
-class TouchInputMapper : public InputMapper {
-public:
- TouchInputMapper(InputDevice* device);
- virtual ~TouchInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(String8& 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 timeoutExpired(nsecs_t when);
-
-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;
-
- enum GestureMode {
- GESTURE_MODE_POINTER,
- GESTURE_MODE_SPOTS,
- };
- GestureMode gestureMode;
- } 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;
- }
- }
- } mCalibration;
-
- // Raw pointer axis information from the driver.
- RawPointerAxes mRawPointerAxes;
-
- // Raw pointer sample data.
- RawPointerData mCurrentRawPointerData;
- RawPointerData mLastRawPointerData;
-
- // Cooked pointer sample data.
- CookedPointerData mCurrentCookedPointerData;
- CookedPointerData mLastCookedPointerData;
-
- // Button state.
- int32_t mCurrentButtonState;
- int32_t mLastButtonState;
-
- // Scroll state.
- int32_t mCurrentRawVScroll;
- int32_t mCurrentRawHScroll;
-
- // Id bits used to differentiate fingers, stylus and mouse tools.
- BitSet32 mCurrentFingerIdBits; // finger or unknown
- BitSet32 mLastFingerIdBits;
- BitSet32 mCurrentStylusIdBits; // stylus or eraser
- BitSet32 mLastStylusIdBits;
- BitSet32 mCurrentMouseIdBits; // mouse or lens
- BitSet32 mLastMouseIdBits;
-
- // True if we sent a HOVER_ENTER event.
- bool mSentHoverEnter;
-
- // 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;
-
- Vector<VirtualKey> mVirtualKeys;
-
- virtual void configureParameters();
- virtual void dumpParameters(String8& dump);
- virtual void configureRawPointerAxes();
- virtual void dumpRawPointerAxes(String8& dump);
- virtual void configureSurface(nsecs_t when, bool* outResetNeeded);
- virtual void dumpSurface(String8& dump);
- virtual void configureVirtualKeys();
- virtual void dumpVirtualKeys(String8& dump);
- virtual void parseCalibration();
- virtual void resolveCalibration();
- virtual void dumpCalibration(String8& dump);
- virtual bool hasStylus() const = 0;
-
- virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 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.
- // 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 mSurfaceWidth;
- int32_t mSurfaceHeight;
- int32_t mSurfaceLeft;
- int32_t mSurfaceTop;
- 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;
-
- // 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;
-
- void sync(nsecs_t when);
-
- bool consumeRawTouches(nsecs_t when, uint32_t policyFlags);
- 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 cookPointerData();
-
- 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);
-
- // 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 flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags,
- 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);
-
- void assignPointerIds();
-};
-
-
-class SingleTouchInputMapper : public TouchInputMapper {
-public:
- SingleTouchInputMapper(InputDevice* device);
- virtual ~SingleTouchInputMapper();
-
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
-protected:
- virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
- virtual void configureRawPointerAxes();
- virtual bool hasStylus() const;
-
-private:
- SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
-};
-
-
-class MultiTouchInputMapper : public TouchInputMapper {
-public:
- MultiTouchInputMapper(InputDevice* device);
- virtual ~MultiTouchInputMapper();
-
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
-protected:
- virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
- 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 JoystickInputMapper : public InputMapper {
-public:
- JoystickInputMapper(InputDevice* device);
- virtual ~JoystickInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(String8& 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/widget/gonk/libui/InputTransport.cpp b/widget/gonk/libui/InputTransport.cpp
deleted file mode 100644
index 3f0fcb047..000000000
--- a/widget/gonk/libui/InputTransport.cpp
+++ /dev/null
@@ -1,957 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// Provides a shared memory transport for input events.
-//
-#define LOG_TAG "InputTransport"
-
-//#define LOG_NDEBUG 0
-
-// Log debug messages about channel messages (send message, receive message)
-#define DEBUG_CHANNEL_MESSAGES 0
-
-// Log debug messages whenever InputChannel objects are created/destroyed
-#define DEBUG_CHANNEL_LIFECYCLE 0
-
-// Log debug messages about transport actions
-#define DEBUG_TRANSPORT_ACTIONS 0
-
-// Log debug messages about touch event resampling
-#define DEBUG_RESAMPLING 0
-
-
-#include "cutils_log.h"
-#include <cutils/properties.h>
-#include <errno.h>
-#include <fcntl.h>
-#include "InputTransport.h"
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <math.h>
-
-
-namespace android {
-
-// Socket buffer size. The default is typically about 128KB, which is much larger than
-// we really need. So we make it smaller. It just needs to be big enough to hold
-// a few dozen large multi-finger motion events in the case where an application gets
-// behind processing touches.
-static const size_t SOCKET_BUFFER_SIZE = 32 * 1024;
-
-// Nanoseconds per milliseconds.
-static const nsecs_t NANOS_PER_MS = 1000000;
-
-// Latency added during resampling. A few milliseconds doesn't hurt much but
-// reduces the impact of mispredicted touch positions.
-static const nsecs_t RESAMPLE_LATENCY = 5 * NANOS_PER_MS;
-
-// Minimum time difference between consecutive samples before attempting to resample.
-static const nsecs_t RESAMPLE_MIN_DELTA = 2 * NANOS_PER_MS;
-
-// Maximum time to predict forward from the last known state, to avoid predicting too
-// far into the future. This time is further bounded by 50% of the last time delta.
-static const nsecs_t RESAMPLE_MAX_PREDICTION = 8 * NANOS_PER_MS;
-
-template<typename T>
-inline static T min(const T& a, const T& b) {
- return a < b ? a : b;
-}
-
-inline static float lerp(float a, float b, float alpha) {
- return a + alpha * (b - a);
-}
-
-// --- InputMessage ---
-
-bool InputMessage::isValid(size_t actualSize) const {
- if (size() == actualSize) {
- switch (header.type) {
- case TYPE_KEY:
- return true;
- case TYPE_MOTION:
- return body.motion.pointerCount > 0
- && body.motion.pointerCount <= MAX_POINTERS;
- case TYPE_FINISHED:
- return true;
- }
- }
- return false;
-}
-
-size_t InputMessage::size() const {
- switch (header.type) {
- case TYPE_KEY:
- return sizeof(Header) + body.key.size();
- case TYPE_MOTION:
- return sizeof(Header) + body.motion.size();
- case TYPE_FINISHED:
- return sizeof(Header) + body.finished.size();
- }
- return sizeof(Header);
-}
-
-
-// --- InputChannel ---
-
-InputChannel::InputChannel(const String8& name, int fd) :
- mName(name), mFd(fd) {
-#if DEBUG_CHANNEL_LIFECYCLE
- ALOGD("Input channel constructed: name='%s', fd=%d",
- mName.string(), fd);
-#endif
-
- int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket "
- "non-blocking. errno=%d", mName.string(), errno);
-}
-
-InputChannel::~InputChannel() {
-#if DEBUG_CHANNEL_LIFECYCLE
- ALOGD("Input channel destroyed: name='%s', fd=%d",
- mName.string(), mFd);
-#endif
-
- ::close(mFd);
-}
-
-status_t InputChannel::openInputChannelPair(const String8& name,
- sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
- int sockets[2];
- if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
- status_t result = -errno;
- ALOGE("channel '%s' ~ Could not create socket pair. errno=%d",
- name.string(), errno);
- outServerChannel.clear();
- outClientChannel.clear();
- return result;
- }
-
- int bufferSize = SOCKET_BUFFER_SIZE;
- setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
- setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
- setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
- setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
-
- String8 serverChannelName = name;
- serverChannelName.append(" (server)");
- outServerChannel = new InputChannel(serverChannelName, sockets[0]);
-
- String8 clientChannelName = name;
- clientChannelName.append(" (client)");
- outClientChannel = new InputChannel(clientChannelName, sockets[1]);
- return OK;
-}
-
-status_t InputChannel::sendMessage(const InputMessage* msg) {
- size_t msgLength = msg->size();
- ssize_t nWrite;
- do {
- nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
- } while (nWrite == -1 && errno == EINTR);
-
- if (nWrite < 0) {
- int error = errno;
-#if DEBUG_CHANNEL_MESSAGES
- ALOGD("channel '%s' ~ error sending message of type %d, errno=%d", mName.string(),
- msg->header.type, error);
-#endif
- if (error == EAGAIN || error == EWOULDBLOCK) {
- return WOULD_BLOCK;
- }
- if (error == EPIPE || error == ENOTCONN) {
- return DEAD_OBJECT;
- }
- return -error;
- }
-
- if (size_t(nWrite) != msgLength) {
-#if DEBUG_CHANNEL_MESSAGES
- ALOGD("channel '%s' ~ error sending message type %d, send was incomplete",
- mName.string(), msg->header.type);
-#endif
- return DEAD_OBJECT;
- }
-
-#if DEBUG_CHANNEL_MESSAGES
- ALOGD("channel '%s' ~ sent message of type %d", mName.string(), msg->header.type);
-#endif
- return OK;
-}
-
-status_t InputChannel::receiveMessage(InputMessage* msg) {
- ssize_t nRead;
- do {
- nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
- } while (nRead == -1 && errno == EINTR);
-
- if (nRead < 0) {
- int error = errno;
-#if DEBUG_CHANNEL_MESSAGES
- ALOGD("channel '%s' ~ receive message failed, errno=%d", mName.string(), errno);
-#endif
- if (error == EAGAIN || error == EWOULDBLOCK) {
- return WOULD_BLOCK;
- }
- if (error == EPIPE || error == ENOTCONN) {
- return DEAD_OBJECT;
- }
- return -error;
- }
-
- if (nRead == 0) { // check for EOF
-#if DEBUG_CHANNEL_MESSAGES
- ALOGD("channel '%s' ~ receive message failed because peer was closed", mName.string());
-#endif
- return DEAD_OBJECT;
- }
-
- if (!msg->isValid(nRead)) {
-#if DEBUG_CHANNEL_MESSAGES
- ALOGD("channel '%s' ~ received invalid message", mName.string());
-#endif
- return BAD_VALUE;
- }
-
-#if DEBUG_CHANNEL_MESSAGES
- ALOGD("channel '%s' ~ received message of type %d", mName.string(), msg->header.type);
-#endif
- return OK;
-}
-
-sp<InputChannel> InputChannel::dup() const {
- int fd = ::dup(getFd());
- return fd >= 0 ? new InputChannel(getName(), fd) : NULL;
-}
-
-
-// --- InputPublisher ---
-
-InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
- mChannel(channel) {
-}
-
-InputPublisher::~InputPublisher() {
-}
-
-status_t InputPublisher::publishKeyEvent(
- uint32_t seq,
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t flags,
- int32_t keyCode,
- int32_t scanCode,
- int32_t metaState,
- int32_t repeatCount,
- nsecs_t downTime,
- nsecs_t eventTime) {
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, "
- "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
- "downTime=%lld, eventTime=%lld",
- mChannel->getName().string(), seq,
- deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
- downTime, eventTime);
-#endif
-
- if (!seq) {
- ALOGE("Attempted to publish a key event with sequence number 0.");
- return BAD_VALUE;
- }
-
- InputMessage msg;
- msg.header.type = InputMessage::TYPE_KEY;
- msg.body.key.seq = seq;
- msg.body.key.deviceId = deviceId;
- msg.body.key.source = source;
- msg.body.key.action = action;
- msg.body.key.flags = flags;
- msg.body.key.keyCode = keyCode;
- msg.body.key.scanCode = scanCode;
- msg.body.key.metaState = metaState;
- msg.body.key.repeatCount = repeatCount;
- msg.body.key.downTime = downTime;
- msg.body.key.eventTime = eventTime;
- return mChannel->sendMessage(&msg);
-}
-
-status_t InputPublisher::publishMotionEvent(
- uint32_t seq,
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t flags,
- int32_t edgeFlags,
- int32_t metaState,
- int32_t buttonState,
- float xOffset,
- float yOffset,
- float xPrecision,
- float yPrecision,
- nsecs_t downTime,
- nsecs_t eventTime,
- size_t pointerCount,
- const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords) {
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
- "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
- "xOffset=%f, yOffset=%f, "
- "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
- "pointerCount=%d",
- mChannel->getName().string(), seq,
- deviceId, source, action, flags, edgeFlags, metaState, buttonState,
- xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
-#endif
-
- if (!seq) {
- ALOGE("Attempted to publish a motion event with sequence number 0.");
- return BAD_VALUE;
- }
-
- if (pointerCount > MAX_POINTERS || pointerCount < 1) {
- ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.",
- mChannel->getName().string(), pointerCount);
- return BAD_VALUE;
- }
-
- InputMessage msg;
- msg.header.type = InputMessage::TYPE_MOTION;
- msg.body.motion.seq = seq;
- msg.body.motion.deviceId = deviceId;
- msg.body.motion.source = source;
- msg.body.motion.action = action;
- msg.body.motion.flags = flags;
- msg.body.motion.edgeFlags = edgeFlags;
- msg.body.motion.metaState = metaState;
- msg.body.motion.buttonState = buttonState;
- msg.body.motion.xOffset = xOffset;
- msg.body.motion.yOffset = yOffset;
- msg.body.motion.xPrecision = xPrecision;
- msg.body.motion.yPrecision = yPrecision;
- msg.body.motion.downTime = downTime;
- msg.body.motion.eventTime = eventTime;
- msg.body.motion.pointerCount = pointerCount;
- for (size_t i = 0; i < pointerCount; i++) {
- msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]);
- msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
- }
- return mChannel->sendMessage(&msg);
-}
-
-status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' publisher ~ receiveFinishedSignal",
- mChannel->getName().string());
-#endif
-
- InputMessage msg;
- status_t result = mChannel->receiveMessage(&msg);
- if (result) {
- *outSeq = 0;
- *outHandled = false;
- return result;
- }
- if (msg.header.type != InputMessage::TYPE_FINISHED) {
- ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer",
- mChannel->getName().string(), msg.header.type);
- return UNKNOWN_ERROR;
- }
- *outSeq = msg.body.finished.seq;
- *outHandled = msg.body.finished.handled;
- return OK;
-}
-
-// --- InputConsumer ---
-
-InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
- mResampleTouch(isTouchResamplingEnabled()),
- mChannel(channel), mMsgDeferred(false) {
-}
-
-InputConsumer::~InputConsumer() {
-}
-
-bool InputConsumer::isTouchResamplingEnabled() {
- char value[PROPERTY_VALUE_MAX];
- int length = property_get("debug.inputconsumer.resample", value, NULL);
- if (length > 0) {
- if (!strcmp("0", value)) {
- return false;
- }
- if (strcmp("1", value)) {
- ALOGD("Unrecognized property value for 'debug.inputconsumer.resample'. "
- "Use '1' or '0'.");
- }
- }
- return true;
-}
-
-status_t InputConsumer::consume(InputEventFactoryInterface* factory,
- bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%lld",
- mChannel->getName().string(), consumeBatches ? "true" : "false", frameTime);
-#endif
-
- *outSeq = 0;
- *outEvent = NULL;
-
- // Fetch the next input message.
- // Loop until an event can be returned or no additional events are received.
- while (!*outEvent) {
- if (mMsgDeferred) {
- // mMsg contains a valid input message from the previous call to consume
- // that has not yet been processed.
- mMsgDeferred = false;
- } else {
- // Receive a fresh message.
- status_t result = mChannel->receiveMessage(&mMsg);
- if (result) {
- // Consume the next batched event unless batches are being held for later.
- if (consumeBatches || result != WOULD_BLOCK) {
- result = consumeBatch(factory, frameTime, outSeq, outEvent);
- if (*outEvent) {
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
- mChannel->getName().string(), *outSeq);
-#endif
- break;
- }
- }
- return result;
- }
- }
-
- switch (mMsg.header.type) {
- case InputMessage::TYPE_KEY: {
- KeyEvent* keyEvent = factory->createKeyEvent();
- if (!keyEvent) return NO_MEMORY;
-
- initializeKeyEvent(keyEvent, &mMsg);
- *outSeq = mMsg.body.key.seq;
- *outEvent = keyEvent;
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ consumed key event, seq=%u",
- mChannel->getName().string(), *outSeq);
-#endif
- break;
- }
-
- case AINPUT_EVENT_TYPE_MOTION: {
- ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);
- if (batchIndex >= 0) {
- Batch& batch = mBatches.editItemAt(batchIndex);
- if (canAddSample(batch, &mMsg)) {
- batch.samples.push(mMsg);
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ appended to batch event",
- mChannel->getName().string());
-#endif
- break;
- } else {
- // We cannot append to the batch in progress, so we need to consume
- // the previous batch right now and defer the new message until later.
- mMsgDeferred = true;
- status_t result = consumeSamples(factory,
- batch, batch.samples.size(), outSeq, outEvent);
- mBatches.removeAt(batchIndex);
- if (result) {
- return result;
- }
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ consumed batch event and "
- "deferred current event, seq=%u",
- mChannel->getName().string(), *outSeq);
-#endif
- break;
- }
- }
-
- // Start a new batch if needed.
- if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE
- || mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
- mBatches.push();
- Batch& batch = mBatches.editTop();
- batch.samples.push(mMsg);
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ started batch event",
- mChannel->getName().string());
-#endif
- break;
- }
-
- MotionEvent* motionEvent = factory->createMotionEvent();
- if (! motionEvent) return NO_MEMORY;
-
- updateTouchState(&mMsg);
- initializeMotionEvent(motionEvent, &mMsg);
- *outSeq = mMsg.body.motion.seq;
- *outEvent = motionEvent;
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u",
- mChannel->getName().string(), *outSeq);
-#endif
- break;
- }
-
- default:
- ALOGE("channel '%s' consumer ~ Received unexpected message of type %d",
- mChannel->getName().string(), mMsg.header.type);
- return UNKNOWN_ERROR;
- }
- }
- return OK;
-}
-
-status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
- nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
- status_t result;
- for (size_t i = mBatches.size(); i-- > 0; ) {
- Batch& batch = mBatches.editItemAt(i);
- if (frameTime < 0) {
- result = consumeSamples(factory, batch, batch.samples.size(),
- outSeq, outEvent);
- mBatches.removeAt(i);
- return result;
- }
-
- nsecs_t sampleTime = frameTime - RESAMPLE_LATENCY;
- ssize_t split = findSampleNoLaterThan(batch, sampleTime);
- if (split < 0) {
- continue;
- }
-
- result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
- const InputMessage* next;
- if (batch.samples.isEmpty()) {
- mBatches.removeAt(i);
- next = NULL;
- } else {
- next = &batch.samples.itemAt(0);
- }
- if (!result) {
- resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
- }
- return result;
- }
-
- return WOULD_BLOCK;
-}
-
-status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory,
- Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent) {
- MotionEvent* motionEvent = factory->createMotionEvent();
- if (! motionEvent) return NO_MEMORY;
-
- uint32_t chain = 0;
- for (size_t i = 0; i < count; i++) {
- InputMessage& msg = batch.samples.editItemAt(i);
- updateTouchState(&msg);
- if (i) {
- SeqChain seqChain;
- seqChain.seq = msg.body.motion.seq;
- seqChain.chain = chain;
- mSeqChains.push(seqChain);
- addSample(motionEvent, &msg);
- } else {
- initializeMotionEvent(motionEvent, &msg);
- }
- chain = msg.body.motion.seq;
- }
- batch.samples.removeItemsAt(0, count);
-
- *outSeq = chain;
- *outEvent = motionEvent;
- return OK;
-}
-
-void InputConsumer::updateTouchState(InputMessage* msg) {
- if (!mResampleTouch ||
- !(msg->body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
- return;
- }
-
- int32_t deviceId = msg->body.motion.deviceId;
- int32_t source = msg->body.motion.source;
- nsecs_t eventTime = msg->body.motion.eventTime;
-
- // Update the touch state history to incorporate the new input message.
- // If the message is in the past relative to the most recently produced resampled
- // touch, then use the resampled time and coordinates instead.
- switch (msg->body.motion.action & AMOTION_EVENT_ACTION_MASK) {
- case AMOTION_EVENT_ACTION_DOWN: {
- ssize_t index = findTouchState(deviceId, source);
- if (index < 0) {
- mTouchStates.push();
- index = mTouchStates.size() - 1;
- }
- TouchState& touchState = mTouchStates.editItemAt(index);
- touchState.initialize(deviceId, source);
- touchState.addHistory(msg);
- break;
- }
-
- case AMOTION_EVENT_ACTION_MOVE: {
- ssize_t index = findTouchState(deviceId, source);
- if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
- touchState.addHistory(msg);
- if (eventTime < touchState.lastResample.eventTime) {
- rewriteMessage(touchState, msg);
- } else {
- touchState.lastResample.idBits.clear();
- }
- }
- break;
- }
-
- case AMOTION_EVENT_ACTION_POINTER_DOWN: {
- ssize_t index = findTouchState(deviceId, source);
- if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
- touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
- rewriteMessage(touchState, msg);
- }
- break;
- }
-
- case AMOTION_EVENT_ACTION_POINTER_UP: {
- ssize_t index = findTouchState(deviceId, source);
- if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
- rewriteMessage(touchState, msg);
- touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
- }
- break;
- }
-
- case AMOTION_EVENT_ACTION_SCROLL: {
- ssize_t index = findTouchState(deviceId, source);
- if (index >= 0) {
- const TouchState& touchState = mTouchStates.itemAt(index);
- rewriteMessage(touchState, msg);
- }
- break;
- }
-
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL: {
- ssize_t index = findTouchState(deviceId, source);
- if (index >= 0) {
- const TouchState& touchState = mTouchStates.itemAt(index);
- rewriteMessage(touchState, msg);
- mTouchStates.removeAt(index);
- }
- break;
- }
- }
-}
-
-void InputConsumer::rewriteMessage(const TouchState& state, InputMessage* msg) {
- for (size_t i = 0; i < msg->body.motion.pointerCount; i++) {
- uint32_t id = msg->body.motion.pointers[i].properties.id;
- if (state.lastResample.idBits.hasBit(id)) {
- PointerCoords& msgCoords = msg->body.motion.pointers[i].coords;
- const PointerCoords& resampleCoords = state.lastResample.getPointerById(id);
-#if DEBUG_RESAMPLING
- ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
- resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
- resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_Y),
- msgCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
- msgCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
-#endif
- msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
- msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
- }
- }
-}
-
-void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
- const InputMessage* next) {
- if (!mResampleTouch
- || !(event->getSource() & AINPUT_SOURCE_CLASS_POINTER)
- || event->getAction() != AMOTION_EVENT_ACTION_MOVE) {
- return;
- }
-
- ssize_t index = findTouchState(event->getDeviceId(), event->getSource());
- if (index < 0) {
-#if DEBUG_RESAMPLING
- ALOGD("Not resampled, no touch state for device.");
-#endif
- return;
- }
-
- TouchState& touchState = mTouchStates.editItemAt(index);
- if (touchState.historySize < 1) {
-#if DEBUG_RESAMPLING
- ALOGD("Not resampled, no history for device.");
-#endif
- return;
- }
-
- // Ensure that the current sample has all of the pointers that need to be reported.
- const History* current = touchState.getHistory(0);
- size_t pointerCount = event->getPointerCount();
- for (size_t i = 0; i < pointerCount; i++) {
- uint32_t id = event->getPointerId(i);
- if (!current->idBits.hasBit(id)) {
-#if DEBUG_RESAMPLING
- ALOGD("Not resampled, missing id %d", id);
-#endif
- return;
- }
- }
-
- // Find the data to use for resampling.
- const History* other;
- History future;
- float alpha;
- if (next) {
- // Interpolate between current sample and future sample.
- // So current->eventTime <= sampleTime <= future.eventTime.
- future.initializeFrom(next);
- other = &future;
- nsecs_t delta = future.eventTime - current->eventTime;
- if (delta < RESAMPLE_MIN_DELTA) {
-#if DEBUG_RESAMPLING
- ALOGD("Not resampled, delta time is %lld ns.", delta);
-#endif
- return;
- }
- alpha = float(sampleTime - current->eventTime) / delta;
- } else if (touchState.historySize >= 2) {
- // Extrapolate future sample using current sample and past sample.
- // So other->eventTime <= current->eventTime <= sampleTime.
- other = touchState.getHistory(1);
- nsecs_t delta = current->eventTime - other->eventTime;
- if (delta < RESAMPLE_MIN_DELTA) {
-#if DEBUG_RESAMPLING
- ALOGD("Not resampled, delta time is %lld ns.", delta);
-#endif
- return;
- }
- nsecs_t maxPredict = current->eventTime + min(delta / 2, RESAMPLE_MAX_PREDICTION);
- if (sampleTime > maxPredict) {
-#if DEBUG_RESAMPLING
- ALOGD("Sample time is too far in the future, adjusting prediction "
- "from %lld to %lld ns.",
- sampleTime - current->eventTime, maxPredict - current->eventTime);
-#endif
- sampleTime = maxPredict;
- }
- alpha = float(current->eventTime - sampleTime) / delta;
- } else {
-#if DEBUG_RESAMPLING
- ALOGD("Not resampled, insufficient data.");
-#endif
- return;
- }
-
- // Resample touch coordinates.
- touchState.lastResample.eventTime = sampleTime;
- touchState.lastResample.idBits.clear();
- for (size_t i = 0; i < pointerCount; i++) {
- uint32_t id = event->getPointerId(i);
- touchState.lastResample.idToIndex[id] = i;
- touchState.lastResample.idBits.markBit(id);
- PointerCoords& resampledCoords = touchState.lastResample.pointers[i];
- const PointerCoords& currentCoords = current->getPointerById(id);
- if (other->idBits.hasBit(id)
- && shouldResampleTool(event->getToolType(i))) {
- const PointerCoords& otherCoords = other->getPointerById(id);
- resampledCoords.copyFrom(currentCoords);
- resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
- lerp(currentCoords.getX(), otherCoords.getX(), alpha));
- resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
- lerp(currentCoords.getY(), otherCoords.getY(), alpha));
-#if DEBUG_RESAMPLING
- ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
- "other (%0.3f, %0.3f), alpha %0.3f",
- id, resampledCoords.getX(), resampledCoords.getY(),
- currentCoords.getX(), currentCoords.getY(),
- otherCoords.getX(), otherCoords.getY(),
- alpha);
-#endif
- } else {
- resampledCoords.copyFrom(currentCoords);
-#if DEBUG_RESAMPLING
- ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)",
- id, resampledCoords.getX(), resampledCoords.getY(),
- currentCoords.getX(), currentCoords.getY());
-#endif
- }
- }
-
- event->addSample(sampleTime, touchState.lastResample.pointers);
-}
-
-bool InputConsumer::shouldResampleTool(int32_t toolType) {
- return toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
- || toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-}
-
-status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
-#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s",
- mChannel->getName().string(), seq, handled ? "true" : "false");
-#endif
-
- if (!seq) {
- ALOGE("Attempted to send a finished signal with sequence number 0.");
- return BAD_VALUE;
- }
-
- // Send finished signals for the batch sequence chain first.
- size_t seqChainCount = mSeqChains.size();
- if (seqChainCount) {
- uint32_t currentSeq = seq;
- uint32_t chainSeqs[seqChainCount];
- size_t chainIndex = 0;
- for (size_t i = seqChainCount; i-- > 0; ) {
- const SeqChain& seqChain = mSeqChains.itemAt(i);
- if (seqChain.seq == currentSeq) {
- currentSeq = seqChain.chain;
- chainSeqs[chainIndex++] = currentSeq;
- mSeqChains.removeAt(i);
- }
- }
- status_t status = OK;
- while (!status && chainIndex-- > 0) {
- status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
- }
- if (status) {
- // An error occurred so at least one signal was not sent, reconstruct the chain.
- do {
- SeqChain seqChain;
- seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
- seqChain.chain = chainSeqs[chainIndex];
- mSeqChains.push(seqChain);
- } while (chainIndex-- > 0);
- return status;
- }
- }
-
- // Send finished signal for the last message in the batch.
- return sendUnchainedFinishedSignal(seq, handled);
-}
-
-status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
- InputMessage msg;
- msg.header.type = InputMessage::TYPE_FINISHED;
- msg.body.finished.seq = seq;
- msg.body.finished.handled = handled;
- return mChannel->sendMessage(&msg);
-}
-
-bool InputConsumer::hasDeferredEvent() const {
- return mMsgDeferred;
-}
-
-bool InputConsumer::hasPendingBatch() const {
- return !mBatches.isEmpty();
-}
-
-ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const {
- for (size_t i = 0; i < mBatches.size(); i++) {
- const Batch& batch = mBatches.itemAt(i);
- const InputMessage& head = batch.samples.itemAt(0);
- if (head.body.motion.deviceId == deviceId && head.body.motion.source == source) {
- return i;
- }
- }
- return -1;
-}
-
-ssize_t InputConsumer::findTouchState(int32_t deviceId, int32_t source) const {
- for (size_t i = 0; i < mTouchStates.size(); i++) {
- const TouchState& touchState = mTouchStates.itemAt(i);
- if (touchState.deviceId == deviceId && touchState.source == source) {
- return i;
- }
- }
- return -1;
-}
-
-void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) {
- event->initialize(
- msg->body.key.deviceId,
- msg->body.key.source,
- msg->body.key.action,
- msg->body.key.flags,
- msg->body.key.keyCode,
- msg->body.key.scanCode,
- msg->body.key.metaState,
- msg->body.key.repeatCount,
- msg->body.key.downTime,
- msg->body.key.eventTime);
-}
-
-void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage* msg) {
- size_t pointerCount = msg->body.motion.pointerCount;
- PointerProperties pointerProperties[pointerCount];
- PointerCoords pointerCoords[pointerCount];
- for (size_t i = 0; i < pointerCount; i++) {
- pointerProperties[i].copyFrom(msg->body.motion.pointers[i].properties);
- pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
- }
-
- event->initialize(
- msg->body.motion.deviceId,
- msg->body.motion.source,
- msg->body.motion.action,
- msg->body.motion.flags,
- msg->body.motion.edgeFlags,
- msg->body.motion.metaState,
- msg->body.motion.buttonState,
- msg->body.motion.xOffset,
- msg->body.motion.yOffset,
- msg->body.motion.xPrecision,
- msg->body.motion.yPrecision,
- msg->body.motion.downTime,
- msg->body.motion.eventTime,
- pointerCount,
- pointerProperties,
- pointerCoords);
-}
-
-void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) {
- size_t pointerCount = msg->body.motion.pointerCount;
- PointerCoords pointerCoords[pointerCount];
- for (size_t i = 0; i < pointerCount; i++) {
- pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
- }
-
- event->setMetaState(event->getMetaState() | msg->body.motion.metaState);
- event->addSample(msg->body.motion.eventTime, pointerCoords);
-}
-
-bool InputConsumer::canAddSample(const Batch& batch, const InputMessage *msg) {
- const InputMessage& head = batch.samples.itemAt(0);
- size_t pointerCount = msg->body.motion.pointerCount;
- if (head.body.motion.pointerCount != pointerCount
- || head.body.motion.action != msg->body.motion.action) {
- return false;
- }
- for (size_t i = 0; i < pointerCount; i++) {
- if (head.body.motion.pointers[i].properties
- != msg->body.motion.pointers[i].properties) {
- return false;
- }
- }
- return true;
-}
-
-ssize_t InputConsumer::findSampleNoLaterThan(const Batch& batch, nsecs_t time) {
- size_t numSamples = batch.samples.size();
- size_t index = 0;
- while (index < numSamples
- && batch.samples.itemAt(index).body.motion.eventTime <= time) {
- index += 1;
- }
- return ssize_t(index) - 1;
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/InputTransport.h b/widget/gonk/libui/InputTransport.h
deleted file mode 100644
index 66ef2850a..000000000
--- a/widget/gonk/libui/InputTransport.h
+++ /dev/null
@@ -1,443 +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 _ANDROIDFW_INPUT_TRANSPORT_H
-#define _ANDROIDFW_INPUT_TRANSPORT_H
-
-/**
- * Native input transport.
- *
- * The InputChannel provides a mechanism for exchanging InputMessage structures across processes.
- *
- * The InputPublisher and InputConsumer each handle one end-point of an input channel.
- * The InputPublisher is used by the input dispatcher to send events to the application.
- * The InputConsumer is used by the application to receive events from the input dispatcher.
- */
-
-#include "Input.h"
-#include <utils/Errors.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/BitSet.h>
-
-namespace android {
-
-/*
- * Intermediate representation used to send input events and related signals.
- */
-struct InputMessage {
- enum {
- TYPE_KEY = 1,
- TYPE_MOTION = 2,
- TYPE_FINISHED = 3,
- };
-
- struct Header {
- uint32_t type;
- uint32_t padding; // 8 byte alignment for the body that follows
- } header;
-
- union Body {
- struct Key {
- uint32_t seq;
- nsecs_t eventTime;
- int32_t deviceId;
- int32_t source;
- int32_t action;
- int32_t flags;
- int32_t keyCode;
- int32_t scanCode;
- int32_t metaState;
- int32_t repeatCount;
- nsecs_t downTime;
-
- inline size_t size() const {
- return sizeof(Key);
- }
- } key;
-
- struct Motion {
- uint32_t seq;
- nsecs_t eventTime;
- int32_t deviceId;
- int32_t source;
- int32_t action;
- int32_t flags;
- int32_t metaState;
- int32_t buttonState;
- int32_t edgeFlags;
- nsecs_t downTime;
- float xOffset;
- float yOffset;
- float xPrecision;
- float yPrecision;
- size_t pointerCount;
- struct Pointer {
- PointerProperties properties;
- PointerCoords coords;
- } pointers[MAX_POINTERS];
-
- int32_t getActionId() const {
- uint32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
- >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
- return pointers[index].properties.id;
- }
-
- inline size_t size() const {
- return sizeof(Motion) - sizeof(Pointer) * MAX_POINTERS
- + sizeof(Pointer) * pointerCount;
- }
- } motion;
-
- struct Finished {
- uint32_t seq;
- bool handled;
-
- inline size_t size() const {
- return sizeof(Finished);
- }
- } finished;
- } body;
-
- bool isValid(size_t actualSize) const;
- size_t size() const;
-};
-
-/*
- * An input channel consists of a local unix domain socket used to send and receive
- * input messages across processes. Each channel has a descriptive name for debugging purposes.
- *
- * Each endpoint has its own InputChannel object that specifies its file descriptor.
- *
- * The input channel is closed when all references to it are released.
- */
-class InputChannel : public RefBase {
-protected:
- virtual ~InputChannel();
-
-public:
- InputChannel(const String8& name, int fd);
-
- /* Creates a pair of input channels.
- *
- * Returns OK on success.
- */
- static status_t openInputChannelPair(const String8& name,
- sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);
-
- inline String8 getName() const { return mName; }
- inline int getFd() const { return mFd; }
-
- /* Sends a message to the other endpoint.
- *
- * If the channel is full then the message is guaranteed not to have been sent at all.
- * Try again after the consumer has sent a finished signal indicating that it has
- * consumed some of the pending messages from the channel.
- *
- * Returns OK on success.
- * Returns WOULD_BLOCK if the channel is full.
- * Returns DEAD_OBJECT if the channel's peer has been closed.
- * Other errors probably indicate that the channel is broken.
- */
- status_t sendMessage(const InputMessage* msg);
-
- /* Receives a message sent by the other endpoint.
- *
- * If there is no message present, try again after poll() indicates that the fd
- * is readable.
- *
- * Returns OK on success.
- * Returns WOULD_BLOCK if there is no message present.
- * Returns DEAD_OBJECT if the channel's peer has been closed.
- * Other errors probably indicate that the channel is broken.
- */
- status_t receiveMessage(InputMessage* msg);
-
- /* Returns a new object that has a duplicate of this channel's fd. */
- sp<InputChannel> dup() const;
-
-private:
- String8 mName;
- int mFd;
-};
-
-/*
- * Publishes input events to an input channel.
- */
-class InputPublisher {
-public:
- /* Creates a publisher associated with an input channel. */
- explicit InputPublisher(const sp<InputChannel>& channel);
-
- /* Destroys the publisher and releases its input channel. */
- ~InputPublisher();
-
- /* Gets the underlying input channel. */
- inline sp<InputChannel> getChannel() { return mChannel; }
-
- /* Publishes a key event to the input channel.
- *
- * Returns OK on success.
- * Returns WOULD_BLOCK if the channel is full.
- * Returns DEAD_OBJECT if the channel's peer has been closed.
- * Returns BAD_VALUE if seq is 0.
- * Other errors probably indicate that the channel is broken.
- */
- status_t publishKeyEvent(
- uint32_t seq,
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t flags,
- int32_t keyCode,
- int32_t scanCode,
- int32_t metaState,
- int32_t repeatCount,
- nsecs_t downTime,
- nsecs_t eventTime);
-
- /* Publishes a motion event to the input channel.
- *
- * Returns OK on success.
- * Returns WOULD_BLOCK if the channel is full.
- * Returns DEAD_OBJECT if the channel's peer has been closed.
- * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS.
- * Other errors probably indicate that the channel is broken.
- */
- status_t publishMotionEvent(
- uint32_t seq,
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t flags,
- int32_t edgeFlags,
- int32_t metaState,
- int32_t buttonState,
- float xOffset,
- float yOffset,
- float xPrecision,
- float yPrecision,
- nsecs_t downTime,
- nsecs_t eventTime,
- size_t pointerCount,
- const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords);
-
- /* Receives the finished signal from the consumer in reply to the original dispatch signal.
- * If a signal was received, returns the message sequence number,
- * and whether the consumer handled the message.
- *
- * The returned sequence number is never 0 unless the operation failed.
- *
- * Returns OK on success.
- * Returns WOULD_BLOCK if there is no signal present.
- * Returns DEAD_OBJECT if the channel's peer has been closed.
- * Other errors probably indicate that the channel is broken.
- */
- status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled);
-
-private:
- sp<InputChannel> mChannel;
-};
-
-/*
- * Consumes input events from an input channel.
- */
-class InputConsumer {
-public:
- /* Creates a consumer associated with an input channel. */
- explicit InputConsumer(const sp<InputChannel>& channel);
-
- /* Destroys the consumer and releases its input channel. */
- ~InputConsumer();
-
- /* Gets the underlying input channel. */
- inline sp<InputChannel> getChannel() { return mChannel; }
-
- /* Consumes an input event from the input channel and copies its contents into
- * an InputEvent object created using the specified factory.
- *
- * Tries to combine a series of move events into larger batches whenever possible.
- *
- * If consumeBatches is false, then defers consuming pending batched events if it
- * is possible for additional samples to be added to them later. Call hasPendingBatch()
- * to determine whether a pending batch is available to be consumed.
- *
- * If consumeBatches is true, then events are still batched but they are consumed
- * immediately as soon as the input channel is exhausted.
- *
- * The frameTime parameter specifies the time when the current display frame started
- * rendering in the CLOCK_MONOTONIC time base, or -1 if unknown.
- *
- * The returned sequence number is never 0 unless the operation failed.
- *
- * Returns OK on success.
- * Returns WOULD_BLOCK if there is no event present.
- * Returns DEAD_OBJECT if the channel's peer has been closed.
- * Returns NO_MEMORY if the event could not be created.
- * Other errors probably indicate that the channel is broken.
- */
- status_t consume(InputEventFactoryInterface* factory, bool consumeBatches,
- nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
-
- /* Sends a finished signal to the publisher to inform it that the message
- * with the specified sequence number has finished being process and whether
- * the message was handled by the consumer.
- *
- * Returns OK on success.
- * Returns BAD_VALUE if seq is 0.
- * Other errors probably indicate that the channel is broken.
- */
- status_t sendFinishedSignal(uint32_t seq, bool handled);
-
- /* Returns true if there is a deferred event waiting.
- *
- * Should be called after calling consume() to determine whether the consumer
- * has a deferred event to be processed. Deferred events are somewhat special in
- * that they have already been removed from the input channel. If the input channel
- * becomes empty, the client may need to do extra work to ensure that it processes
- * the deferred event despite the fact that the input channel's file descriptor
- * is not readable.
- *
- * One option is simply to call consume() in a loop until it returns WOULD_BLOCK.
- * This guarantees that all deferred events will be processed.
- *
- * Alternately, the caller can call hasDeferredEvent() to determine whether there is
- * a deferred event waiting and then ensure that its event loop wakes up at least
- * one more time to consume the deferred event.
- */
- bool hasDeferredEvent() const;
-
- /* Returns true if there is a pending batch.
- *
- * Should be called after calling consume() with consumeBatches == false to determine
- * whether consume() should be called again later on with consumeBatches == true.
- */
- bool hasPendingBatch() const;
-
-private:
- // True if touch resampling is enabled.
- const bool mResampleTouch;
-
- // The input channel.
- sp<InputChannel> mChannel;
-
- // The current input message.
- InputMessage mMsg;
-
- // True if mMsg contains a valid input message that was deferred from the previous
- // call to consume and that still needs to be handled.
- bool mMsgDeferred;
-
- // Batched motion events per device and source.
- struct Batch {
- Vector<InputMessage> samples;
- };
- Vector<Batch> mBatches;
-
- // Touch state per device and source, only for sources of class pointer.
- struct History {
- nsecs_t eventTime;
- BitSet32 idBits;
- int32_t idToIndex[MAX_POINTER_ID + 1];
- PointerCoords pointers[MAX_POINTERS];
-
- void initializeFrom(const InputMessage* msg) {
- eventTime = msg->body.motion.eventTime;
- idBits.clear();
- for (size_t i = 0; i < msg->body.motion.pointerCount; i++) {
- uint32_t id = msg->body.motion.pointers[i].properties.id;
- idBits.markBit(id);
- idToIndex[id] = i;
- pointers[i].copyFrom(msg->body.motion.pointers[i].coords);
- }
- }
-
- const PointerCoords& getPointerById(uint32_t id) const {
- return pointers[idToIndex[id]];
- }
- };
- struct TouchState {
- int32_t deviceId;
- int32_t source;
- size_t historyCurrent;
- size_t historySize;
- History history[2];
- History lastResample;
-
- void initialize(int32_t deviceId, int32_t source) {
- this->deviceId = deviceId;
- this->source = source;
- historyCurrent = 0;
- historySize = 0;
- lastResample.eventTime = 0;
- lastResample.idBits.clear();
- }
-
- void addHistory(const InputMessage* msg) {
- historyCurrent ^= 1;
- if (historySize < 2) {
- historySize += 1;
- }
- history[historyCurrent].initializeFrom(msg);
- }
-
- const History* getHistory(size_t index) const {
- return &history[(historyCurrent + index) & 1];
- }
- };
- Vector<TouchState> mTouchStates;
-
- // Chain of batched sequence numbers. When multiple input messages are combined into
- // a batch, we append a record here that associates the last sequence number in the
- // batch with the previous one. When the finished signal is sent, we traverse the
- // chain to individually finish all input messages that were part of the batch.
- struct SeqChain {
- uint32_t seq; // sequence number of batched input message
- uint32_t chain; // sequence number of previous batched input message
- };
- Vector<SeqChain> mSeqChains;
-
- status_t consumeBatch(InputEventFactoryInterface* factory,
- nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
- status_t consumeSamples(InputEventFactoryInterface* factory,
- Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent);
-
- void updateTouchState(InputMessage* msg);
- void rewriteMessage(const TouchState& state, InputMessage* msg);
- void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
- const InputMessage *next);
-
- ssize_t findBatch(int32_t deviceId, int32_t source) const;
- ssize_t findTouchState(int32_t deviceId, int32_t source) const;
-
- status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled);
-
- static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg);
- static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg);
- static void addSample(MotionEvent* event, const InputMessage* msg);
- static bool canAddSample(const Batch& batch, const InputMessage* msg);
- static ssize_t findSampleNoLaterThan(const Batch& batch, nsecs_t time);
- static bool shouldResampleTool(int32_t toolType);
-
- static bool isTouchResamplingEnabled();
-};
-
-} // namespace android
-
-#endif // _ANDROIDFW_INPUT_TRANSPORT_H
diff --git a/widget/gonk/libui/InputWindow.cpp b/widget/gonk/libui/InputWindow.cpp
deleted file mode 100644
index 3aea445a0..000000000
--- a/widget/gonk/libui/InputWindow.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputWindow"
-
-#include "InputWindow.h"
-
-#include "cutils_log.h"
-
-namespace android {
-
-// --- InputWindowInfo ---
-
-bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
- return touchableRegion.contains(x, y);
-}
-
-bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
- return x >= frameLeft && x <= frameRight
- && y >= frameTop && y <= frameBottom;
-}
-
-bool InputWindowInfo::isTrustedOverlay() const {
- return layoutParamsType == TYPE_INPUT_METHOD
- || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
- || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
-}
-
-bool InputWindowInfo::supportsSplitTouch() const {
- return layoutParamsFlags & FLAG_SPLIT_TOUCH;
-}
-
-
-// --- InputWindowHandle ---
-
-InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
- inputApplicationHandle(inputApplicationHandle), mInfo(NULL) {
-}
-
-InputWindowHandle::~InputWindowHandle() {
- delete mInfo;
-}
-
-void InputWindowHandle::releaseInfo() {
- if (mInfo) {
- delete mInfo;
- mInfo = NULL;
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/InputWindow.h b/widget/gonk/libui/InputWindow.h
deleted file mode 100644
index cce5fd4fe..000000000
--- a/widget/gonk/libui/InputWindow.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_WINDOW_H
-#define _UI_INPUT_WINDOW_H
-
-#include "Input.h"
-#include "InputTransport.h"
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-#include <utils/String8.h>
-
-#include <SkRegion.h>
-
-#include "InputApplication.h"
-
-namespace android {
-
-/*
- * Describes the properties of a window that can receive input.
- */
-struct InputWindowInfo {
- // Window flags from WindowManager.LayoutParams
- enum {
- FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
- FLAG_DIM_BEHIND = 0x00000002,
- FLAG_BLUR_BEHIND = 0x00000004,
- FLAG_NOT_FOCUSABLE = 0x00000008,
- FLAG_NOT_TOUCHABLE = 0x00000010,
- FLAG_NOT_TOUCH_MODAL = 0x00000020,
- FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
- FLAG_KEEP_SCREEN_ON = 0x00000080,
- FLAG_LAYOUT_IN_SCREEN = 0x00000100,
- FLAG_LAYOUT_NO_LIMITS = 0x00000200,
- FLAG_FULLSCREEN = 0x00000400,
- FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
- FLAG_DITHER = 0x00001000,
- FLAG_SECURE = 0x00002000,
- FLAG_SCALED = 0x00004000,
- FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
- FLAG_LAYOUT_INSET_DECOR = 0x00010000,
- FLAG_ALT_FOCUSABLE_IM = 0x00020000,
- FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
- FLAG_SHOW_WHEN_LOCKED = 0x00080000,
- FLAG_SHOW_WALLPAPER = 0x00100000,
- FLAG_TURN_SCREEN_ON = 0x00200000,
- FLAG_DISMISS_KEYGUARD = 0x00400000,
- FLAG_SPLIT_TOUCH = 0x00800000,
- FLAG_HARDWARE_ACCELERATED = 0x01000000,
- FLAG_HARDWARE_ACCELERATED_SYSTEM = 0x02000000,
- FLAG_SLIPPERY = 0x04000000,
- FLAG_NEEDS_MENU_KEY = 0x08000000,
- FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
- FLAG_COMPATIBLE_WINDOW = 0x20000000,
- FLAG_SYSTEM_ERROR = 0x40000000,
- };
-
- // Window types from WindowManager.LayoutParams
- enum {
- FIRST_APPLICATION_WINDOW = 1,
- TYPE_BASE_APPLICATION = 1,
- TYPE_APPLICATION = 2,
- TYPE_APPLICATION_STARTING = 3,
- LAST_APPLICATION_WINDOW = 99,
- FIRST_SUB_WINDOW = 1000,
- TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
- TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
- TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
- TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
- TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
- LAST_SUB_WINDOW = 1999,
- FIRST_SYSTEM_WINDOW = 2000,
- TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
- TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
- TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
- TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
- TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
- TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
- TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
- TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
- TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
- TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
- TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
- TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
- TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
- TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
- TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
- TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
- TYPE_DRAG = FIRST_SYSTEM_WINDOW+16,
- TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17,
- TYPE_POINTER = FIRST_SYSTEM_WINDOW+18,
- TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19,
- TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20,
- TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21,
- LAST_SYSTEM_WINDOW = 2999,
- };
-
- enum {
- INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001,
- INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002,
- INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004,
- };
-
- sp<InputChannel> inputChannel;
- String8 name;
- int32_t layoutParamsFlags;
- int32_t layoutParamsType;
- nsecs_t dispatchingTimeout;
- int32_t frameLeft;
- int32_t frameTop;
- int32_t frameRight;
- int32_t frameBottom;
- float scaleFactor;
- SkRegion touchableRegion;
- bool visible;
- bool canReceiveKeys;
- bool hasFocus;
- bool hasWallpaper;
- bool paused;
- int32_t layer;
- int32_t ownerPid;
- int32_t ownerUid;
- int32_t inputFeatures;
- int32_t displayId;
-
- bool touchableRegionContainsPoint(int32_t x, int32_t y) const;
- bool frameContainsPoint(int32_t x, int32_t y) const;
-
- /* Returns true if the window is of a trusted type that is allowed to silently
- * overlay other windows for the purpose of implementing the secure views feature.
- * Trusted overlays, such as IME windows, can partly obscure other windows without causing
- * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
- */
- bool isTrustedOverlay() const;
-
- bool supportsSplitTouch() const;
-};
-
-
-/*
- * Handle for a window that can receive input.
- *
- * Used by the native input dispatcher to indirectly refer to the window manager objects
- * that describe a window.
- */
-class InputWindowHandle : public RefBase {
-public:
- const sp<InputApplicationHandle> inputApplicationHandle;
-
- inline const InputWindowInfo* getInfo() const {
- return mInfo;
- }
-
- inline sp<InputChannel> getInputChannel() const {
- return mInfo ? mInfo->inputChannel : NULL;
- }
-
- inline String8 getName() const {
- return mInfo ? mInfo->name : String8("<invalid>");
- }
-
- inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
- return mInfo ? mInfo->dispatchingTimeout : defaultValue;
- }
-
- /**
- * Requests that the state of this object be updated to reflect
- * the most current available information about the application.
- *
- * This method should only be called from within the input dispatcher's
- * critical section.
- *
- * Returns true on success, or false if the handle is no longer valid.
- */
- virtual bool updateInfo() = 0;
-
- /**
- * Releases the storage used by the associated information when it is
- * no longer needed.
- */
- void releaseInfo();
-
-protected:
- InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle);
- virtual ~InputWindowHandle();
-
- InputWindowInfo* mInfo;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_WINDOW_H
diff --git a/widget/gonk/libui/KeyCharacterMap.cpp b/widget/gonk/libui/KeyCharacterMap.cpp
deleted file mode 100644
index cec0666ce..000000000
--- a/widget/gonk/libui/KeyCharacterMap.cpp
+++ /dev/null
@@ -1,1153 +0,0 @@
-/*
- * 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 "KeyCharacterMap"
-#include "cutils_log.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include "android_keycodes.h"
-#include "Keyboard.h"
-#include "KeyCharacterMap.h"
-
-#if HAVE_ANDROID_OS
-#include <binder/Parcel.h>
-#endif
-
-#include <utils/Errors.h>
-#include "Tokenizer.h"
-#include <utils/Timers.h>
-
-// Enables debug output for the parser.
-#define DEBUG_PARSER 0
-
-// Enables debug output for parser performance.
-#define DEBUG_PARSER_PERFORMANCE 0
-
-// Enables debug output for mapping.
-#define DEBUG_MAPPING 0
-
-
-namespace android {
-
-static const char* WHITESPACE = " \t\r";
-static const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r,:";
-
-struct Modifier {
- const char* label;
- int32_t metaState;
-};
-static const Modifier modifiers[] = {
- { "shift", AMETA_SHIFT_ON },
- { "lshift", AMETA_SHIFT_LEFT_ON },
- { "rshift", AMETA_SHIFT_RIGHT_ON },
- { "alt", AMETA_ALT_ON },
- { "lalt", AMETA_ALT_LEFT_ON },
- { "ralt", AMETA_ALT_RIGHT_ON },
- { "ctrl", AMETA_CTRL_ON },
- { "lctrl", AMETA_CTRL_LEFT_ON },
- { "rctrl", AMETA_CTRL_RIGHT_ON },
- { "meta", AMETA_META_ON },
- { "lmeta", AMETA_META_LEFT_ON },
- { "rmeta", AMETA_META_RIGHT_ON },
- { "sym", AMETA_SYM_ON },
- { "fn", AMETA_FUNCTION_ON },
- { "capslock", AMETA_CAPS_LOCK_ON },
- { "numlock", AMETA_NUM_LOCK_ON },
- { "scrolllock", AMETA_SCROLL_LOCK_ON },
-};
-
-#if DEBUG_MAPPING
-static String8 toString(const char16_t* chars, size_t numChars) {
- String8 result;
- for (size_t i = 0; i < numChars; i++) {
- result.appendFormat(i == 0 ? "%d" : ", %d", chars[i]);
- }
- return result;
-}
-#endif
-
-
-// --- KeyCharacterMap ---
-
-sp<KeyCharacterMap> KeyCharacterMap::sEmpty = new KeyCharacterMap();
-
-KeyCharacterMap::KeyCharacterMap() :
- mType(KEYBOARD_TYPE_UNKNOWN) {
-}
-
-KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) :
- RefBase(), mType(other.mType), mKeysByScanCode(other.mKeysByScanCode),
- mKeysByUsageCode(other.mKeysByUsageCode) {
- for (size_t i = 0; i < other.mKeys.size(); i++) {
- mKeys.add(other.mKeys.keyAt(i), new Key(*other.mKeys.valueAt(i)));
- }
-}
-
-KeyCharacterMap::~KeyCharacterMap() {
- for (size_t i = 0; i < mKeys.size(); i++) {
- Key* key = mKeys.editValueAt(i);
- delete key;
- }
-}
-
-status_t KeyCharacterMap::load(const String8& filename,
- Format format, sp<KeyCharacterMap>* outMap) {
- outMap->clear();
-
- Tokenizer* tokenizer;
- status_t status = Tokenizer::open(filename, &tokenizer);
- if (status) {
- ALOGE("Error %d opening key character map file %s.", status, filename.string());
- } else {
- status = load(tokenizer, format, outMap);
- delete tokenizer;
- }
- return status;
-}
-
-status_t KeyCharacterMap::loadContents(const String8& filename, const char* contents,
- Format format, sp<KeyCharacterMap>* outMap) {
- outMap->clear();
-
- Tokenizer* tokenizer;
- status_t status = Tokenizer::fromContents(filename, contents, &tokenizer);
- if (status) {
- ALOGE("Error %d opening key character map.", status);
- } else {
- status = load(tokenizer, format, outMap);
- delete tokenizer;
- }
- return status;
-}
-
-status_t KeyCharacterMap::load(Tokenizer* tokenizer,
- Format format, sp<KeyCharacterMap>* outMap) {
- status_t status = OK;
- sp<KeyCharacterMap> map = new KeyCharacterMap();
- if (!map.get()) {
- ALOGE("Error allocating key character map.");
- status = NO_MEMORY;
- } else {
-#if DEBUG_PARSER_PERFORMANCE
- nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
-#endif
- Parser parser(map.get(), tokenizer, format);
- status = parser.parse();
-#if DEBUG_PARSER_PERFORMANCE
- nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
- ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.",
- tokenizer->getFilename().string(), tokenizer->getLineNumber(),
- elapsedTime / 1000000.0);
-#endif
- if (!status) {
- *outMap = map;
- }
- }
- return status;
-}
-
-sp<KeyCharacterMap> KeyCharacterMap::combine(const sp<KeyCharacterMap>& base,
- const sp<KeyCharacterMap>& overlay) {
- if (overlay == NULL) {
- return base;
- }
- if (base == NULL) {
- return overlay;
- }
-
- sp<KeyCharacterMap> map = new KeyCharacterMap(*base.get());
- for (size_t i = 0; i < overlay->mKeys.size(); i++) {
- int32_t keyCode = overlay->mKeys.keyAt(i);
- Key* key = overlay->mKeys.valueAt(i);
- ssize_t oldIndex = map->mKeys.indexOfKey(keyCode);
- if (oldIndex >= 0) {
- delete map->mKeys.valueAt(oldIndex);
- map->mKeys.editValueAt(oldIndex) = new Key(*key);
- } else {
- map->mKeys.add(keyCode, new Key(*key));
- }
- }
-
- for (size_t i = 0; i < overlay->mKeysByScanCode.size(); i++) {
- map->mKeysByScanCode.replaceValueFor(overlay->mKeysByScanCode.keyAt(i),
- overlay->mKeysByScanCode.valueAt(i));
- }
-
- for (size_t i = 0; i < overlay->mKeysByUsageCode.size(); i++) {
- map->mKeysByUsageCode.replaceValueFor(overlay->mKeysByUsageCode.keyAt(i),
- overlay->mKeysByUsageCode.valueAt(i));
- }
- return map;
-}
-
-sp<KeyCharacterMap> KeyCharacterMap::empty() {
- return sEmpty;
-}
-
-int32_t KeyCharacterMap::getKeyboardType() const {
- return mType;
-}
-
-char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const {
- char16_t result = 0;
- const Key* key;
- if (getKey(keyCode, &key)) {
- result = key->label;
- }
-#if DEBUG_MAPPING
- ALOGD("getDisplayLabel: keyCode=%d ~ Result %d.", keyCode, result);
-#endif
- return result;
-}
-
-char16_t KeyCharacterMap::getNumber(int32_t keyCode) const {
- char16_t result = 0;
- const Key* key;
- if (getKey(keyCode, &key)) {
- result = key->number;
- }
-#if DEBUG_MAPPING
- ALOGD("getNumber: keyCode=%d ~ Result %d.", keyCode, result);
-#endif
- return result;
-}
-
-char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const {
- char16_t result = 0;
- const Key* key;
- const Behavior* behavior;
- if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
- result = behavior->character;
- }
-#if DEBUG_MAPPING
- ALOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result);
-#endif
- return result;
-}
-
-bool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState,
- FallbackAction* outFallbackAction) const {
- outFallbackAction->keyCode = 0;
- outFallbackAction->metaState = 0;
-
- bool result = false;
- const Key* key;
- const Behavior* behavior;
- if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
- if (behavior->fallbackKeyCode) {
- outFallbackAction->keyCode = behavior->fallbackKeyCode;
- outFallbackAction->metaState = metaState & ~behavior->metaState;
- result = true;
- }
- }
-#if DEBUG_MAPPING
- ALOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, "
- "fallback keyCode=%d, fallback metaState=0x%08x.",
- keyCode, metaState, result ? "true" : "false",
- outFallbackAction->keyCode, outFallbackAction->metaState);
-#endif
- return result;
-}
-
-char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars,
- int32_t metaState) const {
- char16_t result = 0;
- const Key* key;
- if (getKey(keyCode, &key)) {
- // Try to find the most general behavior that maps to this character.
- // For example, the base key behavior will usually be last in the list.
- // However, if we find a perfect meta state match for one behavior then use that one.
- for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) {
- if (behavior->character) {
- for (size_t i = 0; i < numChars; i++) {
- if (behavior->character == chars[i]) {
- result = behavior->character;
- if ((behavior->metaState & metaState) == behavior->metaState) {
- goto ExactMatch;
- }
- break;
- }
- }
- }
- }
- ExactMatch: ;
- }
-#if DEBUG_MAPPING
- ALOGD("getMatch: keyCode=%d, chars=[%s], metaState=0x%08x ~ Result %d.",
- keyCode, toString(chars, numChars).string(), metaState, result);
-#endif
- return result;
-}
-
-bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t numChars,
- Vector<KeyEvent>& outEvents) const {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-
- for (size_t i = 0; i < numChars; i++) {
- int32_t keyCode, metaState;
- char16_t ch = chars[i];
- if (!findKey(ch, &keyCode, &metaState)) {
-#if DEBUG_MAPPING
- ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Failed to find mapping for character %d.",
- deviceId, toString(chars, numChars).string(), ch);
-#endif
- return false;
- }
-
- int32_t currentMetaState = 0;
- addMetaKeys(outEvents, deviceId, metaState, true, now, &currentMetaState);
- addKey(outEvents, deviceId, keyCode, currentMetaState, true, now);
- addKey(outEvents, deviceId, keyCode, currentMetaState, false, now);
- addMetaKeys(outEvents, deviceId, metaState, false, now, &currentMetaState);
- }
-#if DEBUG_MAPPING
- ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.",
- deviceId, toString(chars, numChars).string(), int32_t(outEvents.size()));
- for (size_t i = 0; i < outEvents.size(); i++) {
- ALOGD(" Key: keyCode=%d, metaState=0x%08x, %s.",
- outEvents[i].getKeyCode(), outEvents[i].getMetaState(),
- outEvents[i].getAction() == AKEY_EVENT_ACTION_DOWN ? "down" : "up");
- }
-#endif
- return true;
-}
-
-status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const {
- if (usageCode) {
- ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
- if (index >= 0) {
-#if DEBUG_MAPPING
- ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
- scanCode, usageCode, *outKeyCode);
-#endif
- *outKeyCode = mKeysByUsageCode.valueAt(index);
- return OK;
- }
- }
- if (scanCode) {
- ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
- if (index >= 0) {
-#if DEBUG_MAPPING
- ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
- scanCode, usageCode, *outKeyCode);
-#endif
- *outKeyCode = mKeysByScanCode.valueAt(index);
- return OK;
- }
- }
-
-#if DEBUG_MAPPING
- ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
-#endif
- *outKeyCode = AKEYCODE_UNKNOWN;
- return NAME_NOT_FOUND;
-}
-
-bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
- ssize_t index = mKeys.indexOfKey(keyCode);
- if (index >= 0) {
- *outKey = mKeys.valueAt(index);
- return true;
- }
- return false;
-}
-
-bool KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState,
- const Key** outKey, const Behavior** outBehavior) const {
- const Key* key;
- if (getKey(keyCode, &key)) {
- const Behavior* behavior = key->firstBehavior;
- while (behavior) {
- if (matchesMetaState(metaState, behavior->metaState)) {
- *outKey = key;
- *outBehavior = behavior;
- return true;
- }
- behavior = behavior->next;
- }
- }
- return false;
-}
-
-bool KeyCharacterMap::matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState) {
- // Behavior must have at least the set of meta states specified.
- // And if the key event has CTRL, ALT or META then the behavior must exactly
- // match those, taking into account that a behavior can specify that it handles
- // one, both or either of a left/right modifier pair.
- if ((eventMetaState & behaviorMetaState) == behaviorMetaState) {
- const int32_t EXACT_META_STATES =
- AMETA_CTRL_ON | AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON
- | AMETA_ALT_ON | AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON
- | AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON;
- int32_t unmatchedMetaState = eventMetaState & ~behaviorMetaState & EXACT_META_STATES;
- if (behaviorMetaState & AMETA_CTRL_ON) {
- unmatchedMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON);
- } else if (behaviorMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
- unmatchedMetaState &= ~AMETA_CTRL_ON;
- }
- if (behaviorMetaState & AMETA_ALT_ON) {
- unmatchedMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON);
- } else if (behaviorMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
- unmatchedMetaState &= ~AMETA_ALT_ON;
- }
- if (behaviorMetaState & AMETA_META_ON) {
- unmatchedMetaState &= ~(AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
- } else if (behaviorMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) {
- unmatchedMetaState &= ~AMETA_META_ON;
- }
- return !unmatchedMetaState;
- }
- return false;
-}
-
-bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const {
- if (!ch) {
- return false;
- }
-
- for (size_t i = 0; i < mKeys.size(); i++) {
- const Key* key = mKeys.valueAt(i);
-
- // Try to find the most general behavior that maps to this character.
- // For example, the base key behavior will usually be last in the list.
- const Behavior* found = NULL;
- for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) {
- if (behavior->character == ch) {
- found = behavior;
- }
- }
- if (found) {
- *outKeyCode = mKeys.keyAt(i);
- *outMetaState = found->metaState;
- return true;
- }
- }
- return false;
-}
-
-void KeyCharacterMap::addKey(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) {
- outEvents.push();
- KeyEvent& event = outEvents.editTop();
- event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD,
- down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
- 0, keyCode, 0, metaState, 0, time, time);
-}
-
-void KeyCharacterMap::addMetaKeys(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
- int32_t* currentMetaState) {
- // Add and remove meta keys symmetrically.
- if (down) {
- addLockedMetaKey(outEvents, deviceId, metaState, time,
- AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState);
- addLockedMetaKey(outEvents, deviceId, metaState, time,
- AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState);
- addLockedMetaKey(outEvents, deviceId, metaState, time,
- AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState);
-
- addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
- AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON,
- AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON,
- AMETA_SHIFT_ON, currentMetaState);
- addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
- AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON,
- AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON,
- AMETA_ALT_ON, currentMetaState);
- addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
- AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON,
- AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON,
- AMETA_CTRL_ON, currentMetaState);
- addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
- AKEYCODE_META_LEFT, AMETA_META_LEFT_ON,
- AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON,
- AMETA_META_ON, currentMetaState);
-
- addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
- AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState);
- addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
- AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState);
- } else {
- addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
- AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState);
- addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
- AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState);
-
- addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
- AKEYCODE_META_LEFT, AMETA_META_LEFT_ON,
- AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON,
- AMETA_META_ON, currentMetaState);
- addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
- AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON,
- AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON,
- AMETA_CTRL_ON, currentMetaState);
- addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
- AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON,
- AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON,
- AMETA_ALT_ON, currentMetaState);
- addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
- AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON,
- AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON,
- AMETA_SHIFT_ON, currentMetaState);
-
- addLockedMetaKey(outEvents, deviceId, metaState, time,
- AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState);
- addLockedMetaKey(outEvents, deviceId, metaState, time,
- AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState);
- addLockedMetaKey(outEvents, deviceId, metaState, time,
- AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState);
- }
-}
-
-bool KeyCharacterMap::addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
- int32_t keyCode, int32_t keyMetaState,
- int32_t* currentMetaState) {
- if ((metaState & keyMetaState) == keyMetaState) {
- *currentMetaState = updateMetaState(keyCode, down, *currentMetaState);
- addKey(outEvents, deviceId, keyCode, *currentMetaState, down, time);
- return true;
- }
- return false;
-}
-
-void KeyCharacterMap::addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
- int32_t leftKeyCode, int32_t leftKeyMetaState,
- int32_t rightKeyCode, int32_t rightKeyMetaState,
- int32_t eitherKeyMetaState,
- int32_t* currentMetaState) {
- bool specific = false;
- specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time,
- leftKeyCode, leftKeyMetaState, currentMetaState);
- specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time,
- rightKeyCode, rightKeyMetaState, currentMetaState);
-
- if (!specific) {
- addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time,
- leftKeyCode, eitherKeyMetaState, currentMetaState);
- }
-}
-
-void KeyCharacterMap::addLockedMetaKey(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t metaState, nsecs_t time,
- int32_t keyCode, int32_t keyMetaState,
- int32_t* currentMetaState) {
- if ((metaState & keyMetaState) == keyMetaState) {
- *currentMetaState = updateMetaState(keyCode, true, *currentMetaState);
- addKey(outEvents, deviceId, keyCode, *currentMetaState, true, time);
- *currentMetaState = updateMetaState(keyCode, false, *currentMetaState);
- addKey(outEvents, deviceId, keyCode, *currentMetaState, false, time);
- }
-}
-
-#if HAVE_ANDROID_OS
-sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) {
- sp<KeyCharacterMap> map = new KeyCharacterMap();
- map->mType = parcel->readInt32();
- size_t numKeys = parcel->readInt32();
- if (parcel->errorCheck()) {
- return NULL;
- }
-
- for (size_t i = 0; i < numKeys; i++) {
- int32_t keyCode = parcel->readInt32();
- char16_t label = parcel->readInt32();
- char16_t number = parcel->readInt32();
- if (parcel->errorCheck()) {
- return NULL;
- }
-
- Key* key = new Key();
- key->label = label;
- key->number = number;
- map->mKeys.add(keyCode, key);
-
- Behavior* lastBehavior = NULL;
- while (parcel->readInt32()) {
- int32_t metaState = parcel->readInt32();
- char16_t character = parcel->readInt32();
- int32_t fallbackKeyCode = parcel->readInt32();
- if (parcel->errorCheck()) {
- return NULL;
- }
-
- Behavior* behavior = new Behavior();
- behavior->metaState = metaState;
- behavior->character = character;
- behavior->fallbackKeyCode = fallbackKeyCode;
- if (lastBehavior) {
- lastBehavior->next = behavior;
- } else {
- key->firstBehavior = behavior;
- }
- lastBehavior = behavior;
- }
-
- if (parcel->errorCheck()) {
- return NULL;
- }
- }
- return map;
-}
-
-void KeyCharacterMap::writeToParcel(Parcel* parcel) const {
- parcel->writeInt32(mType);
-
- size_t numKeys = mKeys.size();
- parcel->writeInt32(numKeys);
- for (size_t i = 0; i < numKeys; i++) {
- int32_t keyCode = mKeys.keyAt(i);
- const Key* key = mKeys.valueAt(i);
- parcel->writeInt32(keyCode);
- parcel->writeInt32(key->label);
- parcel->writeInt32(key->number);
- for (const Behavior* behavior = key->firstBehavior; behavior != NULL;
- behavior = behavior->next) {
- parcel->writeInt32(1);
- parcel->writeInt32(behavior->metaState);
- parcel->writeInt32(behavior->character);
- parcel->writeInt32(behavior->fallbackKeyCode);
- }
- parcel->writeInt32(0);
- }
-}
-#endif
-
-
-// --- KeyCharacterMap::Key ---
-
-KeyCharacterMap::Key::Key() :
- label(0), number(0), firstBehavior(NULL) {
-}
-
-KeyCharacterMap::Key::Key(const Key& other) :
- label(other.label), number(other.number),
- firstBehavior(other.firstBehavior ? new Behavior(*other.firstBehavior) : NULL) {
-}
-
-KeyCharacterMap::Key::~Key() {
- Behavior* behavior = firstBehavior;
- while (behavior) {
- Behavior* next = behavior->next;
- delete behavior;
- behavior = next;
- }
-}
-
-
-// --- KeyCharacterMap::Behavior ---
-
-KeyCharacterMap::Behavior::Behavior() :
- next(NULL), metaState(0), character(0), fallbackKeyCode(0) {
-}
-
-KeyCharacterMap::Behavior::Behavior(const Behavior& other) :
- next(other.next ? new Behavior(*other.next) : NULL),
- metaState(other.metaState), character(other.character),
- fallbackKeyCode(other.fallbackKeyCode) {
-}
-
-
-// --- KeyCharacterMap::Parser ---
-
-KeyCharacterMap::Parser::Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format) :
- mMap(map), mTokenizer(tokenizer), mFormat(format), mState(STATE_TOP) {
-}
-
-KeyCharacterMap::Parser::~Parser() {
-}
-
-status_t KeyCharacterMap::Parser::parse() {
- while (!mTokenizer->isEof()) {
-#if DEBUG_PARSER
- ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
- mTokenizer->peekRemainderOfLine().string());
-#endif
-
- mTokenizer->skipDelimiters(WHITESPACE);
-
- if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
- switch (mState) {
- case STATE_TOP: {
- String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
- if (keywordToken == "type") {
- mTokenizer->skipDelimiters(WHITESPACE);
- status_t status = parseType();
- if (status) return status;
- } else if (keywordToken == "map") {
- mTokenizer->skipDelimiters(WHITESPACE);
- status_t status = parseMap();
- if (status) return status;
- } else if (keywordToken == "key") {
- mTokenizer->skipDelimiters(WHITESPACE);
- status_t status = parseKey();
- if (status) return status;
- } else {
- ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
- keywordToken.string());
- return BAD_VALUE;
- }
- break;
- }
-
- case STATE_KEY: {
- status_t status = parseKeyProperty();
- if (status) return status;
- break;
- }
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
- ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
- mTokenizer->getLocation().string(),
- mTokenizer->peekRemainderOfLine().string());
- return BAD_VALUE;
- }
- }
-
- mTokenizer->nextLine();
- }
-
- if (mState != STATE_TOP) {
- ALOGE("%s: Unterminated key description at end of file.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
-
- if (mMap->mType == KEYBOARD_TYPE_UNKNOWN) {
- ALOGE("%s: Keyboard layout missing required keyboard 'type' declaration.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
-
- if (mFormat == FORMAT_BASE) {
- if (mMap->mType == KEYBOARD_TYPE_OVERLAY) {
- ALOGE("%s: Base keyboard layout must specify a keyboard 'type' other than 'OVERLAY'.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- } else if (mFormat == FORMAT_OVERLAY) {
- if (mMap->mType != KEYBOARD_TYPE_OVERLAY) {
- ALOGE("%s: Overlay keyboard layout missing required keyboard "
- "'type OVERLAY' declaration.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- }
-
- return NO_ERROR;
-}
-
-status_t KeyCharacterMap::Parser::parseType() {
- if (mMap->mType != KEYBOARD_TYPE_UNKNOWN) {
- ALOGE("%s: Duplicate keyboard 'type' declaration.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
-
- KeyboardType type;
- String8 typeToken = mTokenizer->nextToken(WHITESPACE);
- if (typeToken == "NUMERIC") {
- type = KEYBOARD_TYPE_NUMERIC;
- } else if (typeToken == "PREDICTIVE") {
- type = KEYBOARD_TYPE_PREDICTIVE;
- } else if (typeToken == "ALPHA") {
- type = KEYBOARD_TYPE_ALPHA;
- } else if (typeToken == "FULL") {
- type = KEYBOARD_TYPE_FULL;
- } else if (typeToken == "SPECIAL_FUNCTION") {
- type = KEYBOARD_TYPE_SPECIAL_FUNCTION;
- } else if (typeToken == "OVERLAY") {
- type = KEYBOARD_TYPE_OVERLAY;
- } else {
- ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().string(),
- typeToken.string());
- return BAD_VALUE;
- }
-
-#if DEBUG_PARSER
- ALOGD("Parsed type: type=%d.", type);
-#endif
- mMap->mType = type;
- return NO_ERROR;
-}
-
-status_t KeyCharacterMap::Parser::parseMap() {
- String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
- if (keywordToken == "key") {
- mTokenizer->skipDelimiters(WHITESPACE);
- return parseMapKey();
- }
- ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(),
- keywordToken.string());
- return BAD_VALUE;
-}
-
-status_t KeyCharacterMap::Parser::parseMapKey() {
- String8 codeToken = mTokenizer->nextToken(WHITESPACE);
- bool mapUsage = false;
- if (codeToken == "usage") {
- mapUsage = true;
- mTokenizer->skipDelimiters(WHITESPACE);
- codeToken = mTokenizer->nextToken(WHITESPACE);
- }
-
- char* end;
- int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
- if (*end) {
- ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
- mapUsage ? "usage" : "scan code", codeToken.string());
- return BAD_VALUE;
- }
- KeyedVector<int32_t, int32_t>& map =
- mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
- if (map.indexOfKey(code) >= 0) {
- ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
- mapUsage ? "usage" : "scan code", codeToken.string());
- return BAD_VALUE;
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
- int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string());
- if (!keyCode) {
- ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
- keyCodeToken.string());
- return BAD_VALUE;
- }
-
-#if DEBUG_PARSER
- ALOGD("Parsed map key %s: code=%d, keyCode=%d.",
- mapUsage ? "usage" : "scan code", code, keyCode);
-#endif
- map.add(code, keyCode);
- return NO_ERROR;
-}
-
-status_t KeyCharacterMap::Parser::parseKey() {
- String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
- int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string());
- if (!keyCode) {
- ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
- keyCodeToken.string());
- return BAD_VALUE;
- }
- if (mMap->mKeys.indexOfKey(keyCode) >= 0) {
- ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().string(),
- keyCodeToken.string());
- return BAD_VALUE;
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 openBraceToken = mTokenizer->nextToken(WHITESPACE);
- if (openBraceToken != "{") {
- ALOGE("%s: Expected '{' after key code label, got '%s'.",
- mTokenizer->getLocation().string(), openBraceToken.string());
- return BAD_VALUE;
- }
-
-#if DEBUG_PARSER
- ALOGD("Parsed beginning of key: keyCode=%d.", keyCode);
-#endif
- mKeyCode = keyCode;
- mMap->mKeys.add(keyCode, new Key());
- mState = STATE_KEY;
- return NO_ERROR;
-}
-
-status_t KeyCharacterMap::Parser::parseKeyProperty() {
- Key* key = mMap->mKeys.valueFor(mKeyCode);
- String8 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
- if (token == "}") {
- mState = STATE_TOP;
- return finishKey(key);
- }
-
- Vector<Property> properties;
-
- // Parse all comma-delimited property names up to the first colon.
- for (;;) {
- if (token == "label") {
- properties.add(Property(PROPERTY_LABEL));
- } else if (token == "number") {
- properties.add(Property(PROPERTY_NUMBER));
- } else {
- int32_t metaState;
- status_t status = parseModifier(token, &metaState);
- if (status) {
- ALOGE("%s: Expected a property name or modifier, got '%s'.",
- mTokenizer->getLocation().string(), token.string());
- return status;
- }
- properties.add(Property(PROPERTY_META, metaState));
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- if (!mTokenizer->isEol()) {
- char ch = mTokenizer->nextChar();
- if (ch == ':') {
- break;
- } else if (ch == ',') {
- mTokenizer->skipDelimiters(WHITESPACE);
- token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
- continue;
- }
- }
-
- ALOGE("%s: Expected ',' or ':' after property name.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
-
- // Parse behavior after the colon.
- mTokenizer->skipDelimiters(WHITESPACE);
-
- Behavior behavior;
- bool haveCharacter = false;
- bool haveFallback = false;
-
- do {
- char ch = mTokenizer->peekChar();
- if (ch == '\'') {
- char16_t character;
- status_t status = parseCharacterLiteral(&character);
- if (status || !character) {
- ALOGE("%s: Invalid character literal for key.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- if (haveCharacter) {
- ALOGE("%s: Cannot combine multiple character literals or 'none'.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- behavior.character = character;
- haveCharacter = true;
- } else {
- token = mTokenizer->nextToken(WHITESPACE);
- if (token == "none") {
- if (haveCharacter) {
- ALOGE("%s: Cannot combine multiple character literals or 'none'.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- haveCharacter = true;
- } else if (token == "fallback") {
- mTokenizer->skipDelimiters(WHITESPACE);
- token = mTokenizer->nextToken(WHITESPACE);
- int32_t keyCode = getKeyCodeByLabel(token.string());
- if (!keyCode) {
- ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.",
- mTokenizer->getLocation().string(),
- token.string());
- return BAD_VALUE;
- }
- if (haveFallback) {
- ALOGE("%s: Cannot combine multiple fallback key codes.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- behavior.fallbackKeyCode = keyCode;
- haveFallback = true;
- } else {
- ALOGE("%s: Expected a key behavior after ':'.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- } while (!mTokenizer->isEol() && mTokenizer->peekChar() != '#');
-
- // Add the behavior.
- for (size_t i = 0; i < properties.size(); i++) {
- const Property& property = properties.itemAt(i);
- switch (property.property) {
- case PROPERTY_LABEL:
- if (key->label) {
- ALOGE("%s: Duplicate label for key.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- key->label = behavior.character;
-#if DEBUG_PARSER
- ALOGD("Parsed key label: keyCode=%d, label=%d.", mKeyCode, key->label);
-#endif
- break;
- case PROPERTY_NUMBER:
- if (key->number) {
- ALOGE("%s: Duplicate number for key.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- key->number = behavior.character;
-#if DEBUG_PARSER
- ALOGD("Parsed key number: keyCode=%d, number=%d.", mKeyCode, key->number);
-#endif
- break;
- case PROPERTY_META: {
- for (Behavior* b = key->firstBehavior; b; b = b->next) {
- if (b->metaState == property.metaState) {
- ALOGE("%s: Duplicate key behavior for modifier.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
- }
- Behavior* newBehavior = new Behavior(behavior);
- newBehavior->metaState = property.metaState;
- newBehavior->next = key->firstBehavior;
- key->firstBehavior = newBehavior;
-#if DEBUG_PARSER
- ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d.", mKeyCode,
- newBehavior->metaState, newBehavior->character, newBehavior->fallbackKeyCode);
-#endif
- break;
- }
- }
- }
- return NO_ERROR;
-}
-
-status_t KeyCharacterMap::Parser::finishKey(Key* key) {
- // Fill in default number property.
- if (!key->number) {
- char16_t digit = 0;
- char16_t symbol = 0;
- for (Behavior* b = key->firstBehavior; b; b = b->next) {
- char16_t ch = b->character;
- if (ch) {
- if (ch >= '0' && ch <= '9') {
- digit = ch;
- } else if (ch == '(' || ch == ')' || ch == '#' || ch == '*'
- || ch == '-' || ch == '+' || ch == ',' || ch == '.'
- || ch == '\'' || ch == ':' || ch == ';' || ch == '/') {
- symbol = ch;
- }
- }
- }
- key->number = digit ? digit : symbol;
- }
- return NO_ERROR;
-}
-
-status_t KeyCharacterMap::Parser::parseModifier(const String8& token, int32_t* outMetaState) {
- if (token == "base") {
- *outMetaState = 0;
- return NO_ERROR;
- }
-
- int32_t combinedMeta = 0;
-
- const char* str = token.string();
- const char* start = str;
- for (const char* cur = str; ; cur++) {
- char ch = *cur;
- if (ch == '+' || ch == '\0') {
- size_t len = cur - start;
- int32_t metaState = 0;
- for (size_t i = 0; i < sizeof(modifiers) / sizeof(Modifier); i++) {
- if (strlen(modifiers[i].label) == len
- && strncmp(modifiers[i].label, start, len) == 0) {
- metaState = modifiers[i].metaState;
- break;
- }
- }
- if (!metaState) {
- return BAD_VALUE;
- }
- if (combinedMeta & metaState) {
- ALOGE("%s: Duplicate modifier combination '%s'.",
- mTokenizer->getLocation().string(), token.string());
- return BAD_VALUE;
- }
-
- combinedMeta |= metaState;
- start = cur + 1;
-
- if (ch == '\0') {
- break;
- }
- }
- }
- *outMetaState = combinedMeta;
- return NO_ERROR;
-}
-
-status_t KeyCharacterMap::Parser::parseCharacterLiteral(char16_t* outCharacter) {
- char ch = mTokenizer->nextChar();
- if (ch != '\'') {
- goto Error;
- }
-
- ch = mTokenizer->nextChar();
- if (ch == '\\') {
- // Escape sequence.
- ch = mTokenizer->nextChar();
- if (ch == 'n') {
- *outCharacter = '\n';
- } else if (ch == 't') {
- *outCharacter = '\t';
- } else if (ch == '\\') {
- *outCharacter = '\\';
- } else if (ch == '\'') {
- *outCharacter = '\'';
- } else if (ch == '"') {
- *outCharacter = '"';
- } else if (ch == 'u') {
- *outCharacter = 0;
- for (int i = 0; i < 4; i++) {
- ch = mTokenizer->nextChar();
- int digit;
- if (ch >= '0' && ch <= '9') {
- digit = ch - '0';
- } else if (ch >= 'A' && ch <= 'F') {
- digit = ch - 'A' + 10;
- } else if (ch >= 'a' && ch <= 'f') {
- digit = ch - 'a' + 10;
- } else {
- goto Error;
- }
- *outCharacter = (*outCharacter << 4) | digit;
- }
- } else {
- goto Error;
- }
- } else if (ch >= 32 && ch <= 126 && ch != '\'') {
- // ASCII literal character.
- *outCharacter = ch;
- } else {
- goto Error;
- }
-
- ch = mTokenizer->nextChar();
- if (ch != '\'') {
- goto Error;
- }
-
- // Ensure that we consumed the entire token.
- if (mTokenizer->nextToken(WHITESPACE).isEmpty()) {
- return NO_ERROR;
- }
-
-Error:
- ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().string());
- return BAD_VALUE;
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/KeyCharacterMap.h b/widget/gonk/libui/KeyCharacterMap.h
deleted file mode 100644
index c7a684105..000000000
--- a/widget/gonk/libui/KeyCharacterMap.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _ANDROIDFW_KEY_CHARACTER_MAP_H
-#define _ANDROIDFW_KEY_CHARACTER_MAP_H
-
-#include <stdint.h>
-
-#if HAVE_ANDROID_OS
-#include <binder/IBinder.h>
-#endif
-
-#include "Input.h"
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include "Tokenizer.h"
-#include <utils/String8.h>
-#include <utils/Unicode.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-/**
- * Describes a mapping from Android key codes to characters.
- * Also specifies other functions of the keyboard such as the keyboard type
- * and key modifier semantics.
- *
- * This object is immutable after it has been loaded.
- */
-class KeyCharacterMap : public RefBase {
-public:
- enum KeyboardType {
- KEYBOARD_TYPE_UNKNOWN = 0,
- KEYBOARD_TYPE_NUMERIC = 1,
- KEYBOARD_TYPE_PREDICTIVE = 2,
- KEYBOARD_TYPE_ALPHA = 3,
- KEYBOARD_TYPE_FULL = 4,
- KEYBOARD_TYPE_SPECIAL_FUNCTION = 5,
- KEYBOARD_TYPE_OVERLAY = 6,
- };
-
- enum Format {
- // Base keyboard layout, may contain device-specific options, such as "type" declaration.
- FORMAT_BASE = 0,
- // Overlay keyboard layout, more restrictive, may be published by applications,
- // cannot override device-specific options.
- FORMAT_OVERLAY = 1,
- // Either base or overlay layout ok.
- FORMAT_ANY = 2,
- };
-
- // Substitute key code and meta state for fallback action.
- struct FallbackAction {
- int32_t keyCode;
- int32_t metaState;
- };
-
- /* Loads a key character map from a file. */
- static status_t load(const String8& filename, Format format, sp<KeyCharacterMap>* outMap);
-
- /* Loads a key character map from its string contents. */
- static status_t loadContents(const String8& filename,
- const char* contents, Format format, sp<KeyCharacterMap>* outMap);
-
- /* Combines a base key character map and an overlay. */
- static sp<KeyCharacterMap> combine(const sp<KeyCharacterMap>& base,
- const sp<KeyCharacterMap>& overlay);
-
- /* Returns an empty key character map. */
- static sp<KeyCharacterMap> empty();
-
- /* Gets the keyboard type. */
- int32_t getKeyboardType() const;
-
- /* Gets the primary character for this key as in the label physically printed on it.
- * Returns 0 if none (eg. for non-printing keys). */
- char16_t getDisplayLabel(int32_t keyCode) const;
-
- /* Gets the Unicode character for the number or symbol generated by the key
- * when the keyboard is used as a dialing pad.
- * Returns 0 if no number or symbol is generated.
- */
- char16_t getNumber(int32_t keyCode) const;
-
- /* Gets the Unicode character generated by the key and meta key modifiers.
- * Returns 0 if no character is generated.
- */
- char16_t getCharacter(int32_t keyCode, int32_t metaState) const;
-
- /* Gets the fallback action to use by default if the application does not
- * handle the specified key.
- * Returns true if an action was available, false if none.
- */
- bool getFallbackAction(int32_t keyCode, int32_t metaState,
- FallbackAction* outFallbackAction) const;
-
- /* Gets the first matching Unicode character that can be generated by the key,
- * preferring the one with the specified meta key modifiers.
- * Returns 0 if no matching character is generated.
- */
- char16_t getMatch(int32_t keyCode, const char16_t* chars,
- size_t numChars, int32_t metaState) const;
-
- /* Gets a sequence of key events that could plausibly generate the specified
- * character sequence. Returns false if some of the characters cannot be generated.
- */
- bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars,
- Vector<KeyEvent>& outEvents) const;
-
- /* Maps a scan code and usage code to a key code, in case this key map overrides
- * the mapping in some way. */
- status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const;
-
-#if HAVE_ANDROID_OS
- /* Reads a key map from a parcel. */
- static sp<KeyCharacterMap> readFromParcel(Parcel* parcel);
-
- /* Writes a key map to a parcel. */
- void writeToParcel(Parcel* parcel) const;
-#endif
-
-protected:
- virtual ~KeyCharacterMap();
-
-private:
- struct Behavior {
- Behavior();
- Behavior(const Behavior& other);
-
- /* The next behavior in the list, or NULL if none. */
- Behavior* next;
-
- /* The meta key modifiers for this behavior. */
- int32_t metaState;
-
- /* The character to insert. */
- char16_t character;
-
- /* The fallback keycode if the key is not handled. */
- int32_t fallbackKeyCode;
- };
-
- struct Key {
- Key();
- Key(const Key& other);
- ~Key();
-
- /* The single character label printed on the key, or 0 if none. */
- char16_t label;
-
- /* The number or symbol character generated by the key, or 0 if none. */
- char16_t number;
-
- /* The list of key behaviors sorted from most specific to least specific
- * meta key binding. */
- Behavior* firstBehavior;
- };
-
- class Parser {
- enum State {
- STATE_TOP = 0,
- STATE_KEY = 1,
- };
-
- enum {
- PROPERTY_LABEL = 1,
- PROPERTY_NUMBER = 2,
- PROPERTY_META = 3,
- };
-
- struct Property {
- inline Property(int32_t property = 0, int32_t metaState = 0) :
- property(property), metaState(metaState) { }
-
- int32_t property;
- int32_t metaState;
- };
-
- KeyCharacterMap* mMap;
- Tokenizer* mTokenizer;
- Format mFormat;
- State mState;
- int32_t mKeyCode;
-
- public:
- Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format);
- ~Parser();
- status_t parse();
-
- private:
- status_t parseType();
- status_t parseMap();
- status_t parseMapKey();
- status_t parseKey();
- status_t parseKeyProperty();
- status_t finishKey(Key* key);
- status_t parseModifier(const String8& token, int32_t* outMetaState);
- status_t parseCharacterLiteral(char16_t* outCharacter);
- };
-
- static sp<KeyCharacterMap> sEmpty;
-
- KeyedVector<int32_t, Key*> mKeys;
- int mType;
-
- KeyedVector<int32_t, int32_t> mKeysByScanCode;
- KeyedVector<int32_t, int32_t> mKeysByUsageCode;
-
- KeyCharacterMap();
- KeyCharacterMap(const KeyCharacterMap& other);
-
- bool getKey(int32_t keyCode, const Key** outKey) const;
- bool getKeyBehavior(int32_t keyCode, int32_t metaState,
- const Key** outKey, const Behavior** outBehavior) const;
- static bool matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState);
-
- bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const;
-
- static status_t load(Tokenizer* tokenizer, Format format, sp<KeyCharacterMap>* outMap);
-
- static void addKey(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time);
- static void addMetaKeys(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
- int32_t* currentMetaState);
- static bool addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
- int32_t keyCode, int32_t keyMetaState,
- int32_t* currentMetaState);
- static void addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
- int32_t leftKeyCode, int32_t leftKeyMetaState,
- int32_t rightKeyCode, int32_t rightKeyMetaState,
- int32_t eitherKeyMetaState,
- int32_t* currentMetaState);
- static void addLockedMetaKey(Vector<KeyEvent>& outEvents,
- int32_t deviceId, int32_t metaState, nsecs_t time,
- int32_t keyCode, int32_t keyMetaState,
- int32_t* currentMetaState);
-};
-
-} // namespace android
-
-#endif // _ANDROIDFW_KEY_CHARACTER_MAP_H
diff --git a/widget/gonk/libui/KeyLayoutMap.cpp b/widget/gonk/libui/KeyLayoutMap.cpp
deleted file mode 100644
index 8af4b84e0..000000000
--- a/widget/gonk/libui/KeyLayoutMap.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * 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 "KeyLayoutMap"
-#include "cutils_log.h"
-
-#include <stdlib.h>
-#include "android_keycodes.h"
-#include "Keyboard.h"
-#include "KeyLayoutMap.h"
-#include <utils/Errors.h>
-#include "Tokenizer.h"
-#include <utils/Timers.h>
-
-// Enables debug output for the parser.
-#define DEBUG_PARSER 0
-
-// Enables debug output for parser performance.
-#define DEBUG_PARSER_PERFORMANCE 0
-
-// Enables debug output for mapping.
-#define DEBUG_MAPPING 0
-
-
-namespace android {
-
-static const char* WHITESPACE = " \t\r";
-
-// --- KeyLayoutMap ---
-
-KeyLayoutMap::KeyLayoutMap() {
-}
-
-KeyLayoutMap::~KeyLayoutMap() {
-}
-
-status_t KeyLayoutMap::load(const String8& filename, sp<KeyLayoutMap>* outMap) {
- outMap->clear();
-
- Tokenizer* tokenizer;
- status_t status = Tokenizer::open(filename, &tokenizer);
- if (status) {
- ALOGE("Error %d opening key layout map file %s.", status, filename.string());
- } else {
- sp<KeyLayoutMap> map = new KeyLayoutMap();
- if (!map.get()) {
- ALOGE("Error allocating key layout map.");
- status = NO_MEMORY;
- } else {
-#if DEBUG_PARSER_PERFORMANCE
- nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
-#endif
- Parser parser(map.get(), tokenizer);
- status = parser.parse();
-#if DEBUG_PARSER_PERFORMANCE
- nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
- ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.",
- tokenizer->getFilename().string(), tokenizer->getLineNumber(),
- elapsedTime / 1000000.0);
-#endif
- if (!status) {
- *outMap = map;
- }
- }
- delete tokenizer;
- }
- return status;
-}
-
-status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode,
- int32_t* outKeyCode, uint32_t* outFlags) const {
- const Key* key = getKey(scanCode, usageCode);
- if (!key) {
-#if DEBUG_MAPPING
- ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
-#endif
- *outKeyCode = AKEYCODE_UNKNOWN;
- *outFlags = 0;
- return NAME_NOT_FOUND;
- }
-
- *outKeyCode = key->keyCode;
- *outFlags = key->flags;
-
-#if DEBUG_MAPPING
- ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d, outFlags=0x%08x.",
- scanCode, usageCode, *outKeyCode, *outFlags);
-#endif
- return NO_ERROR;
-}
-
-const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const {
- if (usageCode) {
- ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
- if (index >= 0) {
- return &mKeysByUsageCode.valueAt(index);
- }
- }
- if (scanCode) {
- ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
- if (index >= 0) {
- return &mKeysByScanCode.valueAt(index);
- }
- }
- return NULL;
-}
-
-status_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const {
- const size_t N = mKeysByScanCode.size();
- for (size_t i=0; i<N; i++) {
- if (mKeysByScanCode.valueAt(i).keyCode == keyCode) {
- outScanCodes->add(mKeysByScanCode.keyAt(i));
- }
- }
- return NO_ERROR;
-}
-
-status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const {
- ssize_t index = mAxes.indexOfKey(scanCode);
- if (index < 0) {
-#if DEBUG_MAPPING
- ALOGD("mapAxis: scanCode=%d ~ Failed.", scanCode);
-#endif
- return NAME_NOT_FOUND;
- }
-
- *outAxisInfo = mAxes.valueAt(index);
-
-#if DEBUG_MAPPING
- ALOGD("mapAxis: scanCode=%d ~ Result mode=%d, axis=%d, highAxis=%d, "
- "splitValue=%d, flatOverride=%d.",
- scanCode,
- outAxisInfo->mode, outAxisInfo->axis, outAxisInfo->highAxis,
- outAxisInfo->splitValue, outAxisInfo->flatOverride);
-#endif
- return NO_ERROR;
-}
-
-status_t KeyLayoutMap::findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const {
- const size_t N = mLedsByScanCode.size();
- for (size_t i = 0; i < N; i++) {
- if (mLedsByScanCode.valueAt(i).ledCode == ledCode) {
- *outScanCode = mLedsByScanCode.keyAt(i);
-#if DEBUG_MAPPING
- ALOGD("findScanCodeForLed: ledCode=%d, scanCode=%d.", ledCode, *outScanCode);
-#endif
- return NO_ERROR;
- }
- }
-#if DEBUG_MAPPING
- ALOGD("findScanCodeForLed: ledCode=%d ~ Not found.", ledCode);
-#endif
- return NAME_NOT_FOUND;
-}
-
-status_t KeyLayoutMap::findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const {
- const size_t N = mLedsByUsageCode.size();
- for (size_t i = 0; i < N; i++) {
- if (mLedsByUsageCode.valueAt(i).ledCode == ledCode) {
- *outUsageCode = mLedsByUsageCode.keyAt(i);
-#if DEBUG_MAPPING
- ALOGD("findUsageForLed: ledCode=%d, usage=%x.", ledCode, *outUsageCode);
-#endif
- return NO_ERROR;
- }
- }
-#if DEBUG_MAPPING
- ALOGD("findUsageForLed: ledCode=%d ~ Not found.", ledCode);
-#endif
- return NAME_NOT_FOUND;
-}
-
-
-// --- KeyLayoutMap::Parser ---
-
-KeyLayoutMap::Parser::Parser(KeyLayoutMap* map, Tokenizer* tokenizer) :
- mMap(map), mTokenizer(tokenizer) {
-}
-
-KeyLayoutMap::Parser::~Parser() {
-}
-
-status_t KeyLayoutMap::Parser::parse() {
- while (!mTokenizer->isEof()) {
-#if DEBUG_PARSER
- ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
- mTokenizer->peekRemainderOfLine().string());
-#endif
-
- mTokenizer->skipDelimiters(WHITESPACE);
-
- if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
- String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
- if (keywordToken == "key") {
- mTokenizer->skipDelimiters(WHITESPACE);
- status_t status = parseKey();
- if (status) return status;
- } else if (keywordToken == "axis") {
- mTokenizer->skipDelimiters(WHITESPACE);
- status_t status = parseAxis();
- if (status) return status;
- } else if (keywordToken == "led") {
- mTokenizer->skipDelimiters(WHITESPACE);
- status_t status = parseLed();
- if (status) return status;
- } else {
- ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
- keywordToken.string());
- return BAD_VALUE;
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
- ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
- mTokenizer->getLocation().string(),
- mTokenizer->peekRemainderOfLine().string());
- return BAD_VALUE;
- }
- }
-
- mTokenizer->nextLine();
- }
- return NO_ERROR;
-}
-
-status_t KeyLayoutMap::Parser::parseKey() {
- String8 codeToken = mTokenizer->nextToken(WHITESPACE);
- bool mapUsage = false;
- if (codeToken == "usage") {
- mapUsage = true;
- mTokenizer->skipDelimiters(WHITESPACE);
- codeToken = mTokenizer->nextToken(WHITESPACE);
- }
-
- char* end;
- int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
- if (*end) {
- ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
- mapUsage ? "usage" : "scan code", codeToken.string());
- return BAD_VALUE;
- }
- KeyedVector<int32_t, Key>& map =
- mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
- if (map.indexOfKey(code) >= 0) {
- ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
- mapUsage ? "usage" : "scan code", codeToken.string());
- return BAD_VALUE;
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
- int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string());
- if (!keyCode) {
- ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
- keyCodeToken.string());
- return BAD_VALUE;
- }
-
- uint32_t flags = 0;
- for (;;) {
- mTokenizer->skipDelimiters(WHITESPACE);
- if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break;
-
- String8 flagToken = mTokenizer->nextToken(WHITESPACE);
- uint32_t flag = getKeyFlagByLabel(flagToken.string());
- if (!flag) {
- ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(),
- flagToken.string());
- return BAD_VALUE;
- }
- if (flags & flag) {
- ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(),
- flagToken.string());
- return BAD_VALUE;
- }
- flags |= flag;
- }
-
-#if DEBUG_PARSER
- ALOGD("Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.",
- mapUsage ? "usage" : "scan code", code, keyCode, flags);
-#endif
- Key key;
- key.keyCode = keyCode;
- key.flags = flags;
- map.add(code, key);
- return NO_ERROR;
-}
-
-status_t KeyLayoutMap::Parser::parseAxis() {
- String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE);
- char* end;
- int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0));
- if (*end) {
- ALOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(),
- scanCodeToken.string());
- return BAD_VALUE;
- }
- if (mMap->mAxes.indexOfKey(scanCode) >= 0) {
- ALOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(),
- scanCodeToken.string());
- return BAD_VALUE;
- }
-
- AxisInfo axisInfo;
-
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 token = mTokenizer->nextToken(WHITESPACE);
- if (token == "invert") {
- axisInfo.mode = AxisInfo::MODE_INVERT;
-
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 axisToken = mTokenizer->nextToken(WHITESPACE);
- axisInfo.axis = getAxisByLabel(axisToken.string());
- if (axisInfo.axis < 0) {
- ALOGE("%s: Expected inverted axis label, got '%s'.",
- mTokenizer->getLocation().string(), axisToken.string());
- return BAD_VALUE;
- }
- } else if (token == "split") {
- axisInfo.mode = AxisInfo::MODE_SPLIT;
-
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 splitToken = mTokenizer->nextToken(WHITESPACE);
- axisInfo.splitValue = int32_t(strtol(splitToken.string(), &end, 0));
- if (*end) {
- ALOGE("%s: Expected split value, got '%s'.",
- mTokenizer->getLocation().string(), splitToken.string());
- return BAD_VALUE;
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE);
- axisInfo.axis = getAxisByLabel(lowAxisToken.string());
- if (axisInfo.axis < 0) {
- ALOGE("%s: Expected low axis label, got '%s'.",
- mTokenizer->getLocation().string(), lowAxisToken.string());
- return BAD_VALUE;
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 highAxisToken = mTokenizer->nextToken(WHITESPACE);
- axisInfo.highAxis = getAxisByLabel(highAxisToken.string());
- if (axisInfo.highAxis < 0) {
- ALOGE("%s: Expected high axis label, got '%s'.",
- mTokenizer->getLocation().string(), highAxisToken.string());
- return BAD_VALUE;
- }
- } else {
- axisInfo.axis = getAxisByLabel(token.string());
- if (axisInfo.axis < 0) {
- ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.",
- mTokenizer->getLocation().string(), token.string());
- return BAD_VALUE;
- }
- }
-
- for (;;) {
- mTokenizer->skipDelimiters(WHITESPACE);
- if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') {
- break;
- }
- String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
- if (keywordToken == "flat") {
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 flatToken = mTokenizer->nextToken(WHITESPACE);
- axisInfo.flatOverride = int32_t(strtol(flatToken.string(), &end, 0));
- if (*end) {
- ALOGE("%s: Expected flat value, got '%s'.",
- mTokenizer->getLocation().string(), flatToken.string());
- return BAD_VALUE;
- }
- } else {
- ALOGE("%s: Expected keyword 'flat', got '%s'.",
- mTokenizer->getLocation().string(), keywordToken.string());
- return BAD_VALUE;
- }
- }
-
-#if DEBUG_PARSER
- ALOGD("Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, "
- "splitValue=%d, flatOverride=%d.",
- scanCode,
- axisInfo.mode, axisInfo.axis, axisInfo.highAxis,
- axisInfo.splitValue, axisInfo.flatOverride);
-#endif
- mMap->mAxes.add(scanCode, axisInfo);
- return NO_ERROR;
-}
-
-status_t KeyLayoutMap::Parser::parseLed() {
- String8 codeToken = mTokenizer->nextToken(WHITESPACE);
- bool mapUsage = false;
- if (codeToken == "usage") {
- mapUsage = true;
- mTokenizer->skipDelimiters(WHITESPACE);
- codeToken = mTokenizer->nextToken(WHITESPACE);
- }
- char* end;
- int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
- if (*end) {
- ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().string(),
- mapUsage ? "usage" : "scan code", codeToken.string());
- return BAD_VALUE;
- }
-
- KeyedVector<int32_t, Led>& map = mapUsage ? mMap->mLedsByUsageCode : mMap->mLedsByScanCode;
- if (map.indexOfKey(code) >= 0) {
- ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().string(),
- mapUsage ? "usage" : "scan code", codeToken.string());
- return BAD_VALUE;
- }
-
- mTokenizer->skipDelimiters(WHITESPACE);
- String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE);
- int32_t ledCode = getLedByLabel(ledCodeToken.string());
- if (ledCode < 0) {
- ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(),
- ledCodeToken.string());
- return BAD_VALUE;
- }
-
-#if DEBUG_PARSER
- ALOGD("Parsed led %s: code=%d, ledCode=%d.",
- mapUsage ? "usage" : "scan code", code, ledCode);
-#endif
-
- Led led;
- led.ledCode = ledCode;
- map.add(code, led);
- return NO_ERROR;
-}
-};
diff --git a/widget/gonk/libui/KeyLayoutMap.h b/widget/gonk/libui/KeyLayoutMap.h
deleted file mode 100644
index 8a6113447..000000000
--- a/widget/gonk/libui/KeyLayoutMap.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _ANDROIDFW_KEY_LAYOUT_MAP_H
-#define _ANDROIDFW_KEY_LAYOUT_MAP_H
-
-#include <stdint.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include "Tokenizer.h"
-#include <utils/RefBase.h>
-
-namespace android {
-
-struct AxisInfo {
- enum Mode {
- // Axis value is reported directly.
- MODE_NORMAL = 0,
- // Axis value should be inverted before reporting.
- MODE_INVERT = 1,
- // Axis value should be split into two axes
- MODE_SPLIT = 2,
- };
-
- // Axis mode.
- Mode mode;
-
- // Axis id.
- // When split, this is the axis used for values smaller than the split position.
- int32_t axis;
-
- // When split, this is the axis used for values after higher than the split position.
- int32_t highAxis;
-
- // The split value, or 0 if not split.
- int32_t splitValue;
-
- // The flat value, or -1 if none.
- int32_t flatOverride;
-
- AxisInfo() : mode(MODE_NORMAL), axis(-1), highAxis(-1), splitValue(0), flatOverride(-1) {
- }
-};
-
-/**
- * Describes a mapping from keyboard scan codes and joystick axes to Android key codes and axes.
- *
- * This object is immutable after it has been loaded.
- */
-class KeyLayoutMap : public RefBase {
-public:
- static status_t load(const String8& filename, sp<KeyLayoutMap>* outMap);
-
- status_t mapKey(int32_t scanCode, int32_t usageCode,
- int32_t* outKeyCode, uint32_t* outFlags) const;
- status_t findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const;
- status_t findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const;
- status_t findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const;
-
- status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const;
-
-protected:
- virtual ~KeyLayoutMap();
-
-private:
- struct Key {
- int32_t keyCode;
- uint32_t flags;
- };
-
- struct Led {
- int32_t ledCode;
- };
-
-
- KeyedVector<int32_t, Key> mKeysByScanCode;
- KeyedVector<int32_t, Key> mKeysByUsageCode;
- KeyedVector<int32_t, AxisInfo> mAxes;
- KeyedVector<int32_t, Led> mLedsByScanCode;
- KeyedVector<int32_t, Led> mLedsByUsageCode;
-
- KeyLayoutMap();
-
- const Key* getKey(int32_t scanCode, int32_t usageCode) const;
-
- class Parser {
- KeyLayoutMap* mMap;
- Tokenizer* mTokenizer;
-
- public:
- Parser(KeyLayoutMap* map, Tokenizer* tokenizer);
- ~Parser();
- status_t parse();
-
- private:
- status_t parseKey();
- status_t parseAxis();
- status_t parseLed();
- };
-};
-
-} // namespace android
-
-#endif // _ANDROIDFW_KEY_LAYOUT_MAP_H
diff --git a/widget/gonk/libui/Keyboard.cpp b/widget/gonk/libui/Keyboard.cpp
deleted file mode 100644
index 62bb53b7b..000000000
--- a/widget/gonk/libui/Keyboard.cpp
+++ /dev/null
@@ -1,300 +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.
- */
-
-#define LOG_TAG "Keyboard"
-#include "cutils_log.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include "Keyboard.h"
-#include "KeycodeLabels.h"
-#include "KeyLayoutMap.h"
-#include "KeyCharacterMap.h"
-#include "InputDevice.h"
-#include <utils/Errors.h>
-#include <cutils/properties.h>
-
-namespace android {
-
-// --- KeyMap ---
-
-KeyMap::KeyMap() {
-}
-
-KeyMap::~KeyMap() {
-}
-
-status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,
- const PropertyMap* deviceConfiguration) {
- // Use the configured key layout if available.
- if (deviceConfiguration) {
- String8 keyLayoutName;
- if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
- keyLayoutName)) {
- status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName);
- if (status == NAME_NOT_FOUND) {
- ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
- "it was not found.",
- deviceIdenfifier.name.string(), keyLayoutName.string());
- }
- }
-
- String8 keyCharacterMapName;
- if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
- keyCharacterMapName)) {
- status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName);
- if (status == NAME_NOT_FOUND) {
- ALOGE("Configuration for keyboard device '%s' requested keyboard character "
- "map '%s' but it was not found.",
- deviceIdenfifier.name.string(), keyLayoutName.string());
- }
- }
-
- if (isComplete()) {
- return OK;
- }
- }
-
- // Try searching by device identifier.
- if (probeKeyMap(deviceIdenfifier, String8::empty())) {
- return OK;
- }
-
- // Fall back on the Generic key map.
- // TODO Apply some additional heuristics here to figure out what kind of
- // generic key map to use (US English, etc.) for typical external keyboards.
- if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {
- return OK;
- }
-
- // Try the Virtual key map as a last resort.
- if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {
- return OK;
- }
-
- // Give up!
- ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
- deviceIdenfifier.name.string());
- return NAME_NOT_FOUND;
-}
-
-bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,
- const String8& keyMapName) {
- if (!haveKeyLayout()) {
- loadKeyLayout(deviceIdentifier, keyMapName);
- }
- if (!haveKeyCharacterMap()) {
- loadKeyCharacterMap(deviceIdentifier, keyMapName);
- }
- return isComplete();
-}
-
-status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name) {
- String8 path(getPath(deviceIdentifier, name,
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
- if (path.isEmpty()) {
- return NAME_NOT_FOUND;
- }
-
- status_t status = KeyLayoutMap::load(path, &keyLayoutMap);
- if (status) {
- return status;
- }
-
- keyLayoutFile.setTo(path);
- return OK;
-}
-
-status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name) {
- String8 path(getPath(deviceIdentifier, name,
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
- if (path.isEmpty()) {
- return NAME_NOT_FOUND;
- }
-
- status_t status = KeyCharacterMap::load(path,
- KeyCharacterMap::FORMAT_BASE, &keyCharacterMap);
- if (status) {
- return status;
- }
-
- keyCharacterMapFile.setTo(path);
- return OK;
-}
-
-String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name, InputDeviceConfigurationFileType type) {
- return name.isEmpty()
- ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)
- : getInputDeviceConfigurationFilePathByName(name, type);
-}
-
-
-// --- Global functions ---
-
-bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier,
- const PropertyMap* deviceConfiguration, const KeyMap* keyMap) {
- if (!keyMap->haveKeyCharacterMap()
- || keyMap->keyCharacterMap->getKeyboardType()
- == KeyCharacterMap::KEYBOARD_TYPE_SPECIAL_FUNCTION) {
- return false;
- }
-
- if (deviceConfiguration) {
- bool builtIn = false;
- if (deviceConfiguration->tryGetProperty(String8("keyboard.builtIn"), builtIn)
- && builtIn) {
- return true;
- }
- }
-
- return strstr(deviceIdentifier.name.string(), "-keypad");
-}
-
-static int lookupValueByLabel(const char* literal, const KeycodeLabel *list) {
- while (list->literal) {
- if (strcmp(literal, list->literal) == 0) {
- return list->value;
- }
- list++;
- }
- return list->value;
-}
-
-static const char* lookupLabelByValue(int value, const KeycodeLabel *list) {
- while (list->literal) {
- if (list->value == value) {
- return list->literal;
- }
- list++;
- }
- return NULL;
-}
-
-int32_t getKeyCodeByLabel(const char* label) {
- return int32_t(lookupValueByLabel(label, KEYCODES));
-}
-
-uint32_t getKeyFlagByLabel(const char* label) {
- return uint32_t(lookupValueByLabel(label, FLAGS));
-}
-
-int32_t getAxisByLabel(const char* label) {
- return int32_t(lookupValueByLabel(label, AXES));
-}
-
-const char* getAxisLabel(int32_t axisId) {
- return lookupLabelByValue(axisId, AXES);
-}
-
-int32_t getLedByLabel(const char* label) {
- return int32_t(lookupValueByLabel(label, LEDS));
-}
-static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
- int32_t newMetaState;
- if (down) {
- newMetaState = oldMetaState | mask;
- } else {
- newMetaState = oldMetaState &
- ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON);
- }
-
- if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
- newMetaState |= AMETA_ALT_ON;
- }
-
- if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
- newMetaState |= AMETA_SHIFT_ON;
- }
-
- if (newMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
- newMetaState |= AMETA_CTRL_ON;
- }
-
- if (newMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) {
- newMetaState |= AMETA_META_ON;
- }
- return newMetaState;
-}
-
-static int32_t toggleLockedMetaState(int32_t mask, bool down, int32_t oldMetaState) {
- if (down) {
- return oldMetaState;
- } else {
- return oldMetaState ^ mask;
- }
-}
-
-int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
- switch (keyCode) {
- case AKEYCODE_ALT_LEFT:
- return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState);
- case AKEYCODE_ALT_RIGHT:
- return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState);
- case AKEYCODE_SHIFT_LEFT:
- return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState);
- case AKEYCODE_SHIFT_RIGHT:
- return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState);
- case AKEYCODE_SYM:
- return setEphemeralMetaState(AMETA_SYM_ON, down, oldMetaState);
- case AKEYCODE_FUNCTION:
- return setEphemeralMetaState(AMETA_FUNCTION_ON, down, oldMetaState);
- case AKEYCODE_CTRL_LEFT:
- return setEphemeralMetaState(AMETA_CTRL_LEFT_ON, down, oldMetaState);
- case AKEYCODE_CTRL_RIGHT:
- return setEphemeralMetaState(AMETA_CTRL_RIGHT_ON, down, oldMetaState);
- case AKEYCODE_META_LEFT:
- return setEphemeralMetaState(AMETA_META_LEFT_ON, down, oldMetaState);
- case AKEYCODE_META_RIGHT:
- return setEphemeralMetaState(AMETA_META_RIGHT_ON, down, oldMetaState);
- case AKEYCODE_CAPS_LOCK:
- return toggleLockedMetaState(AMETA_CAPS_LOCK_ON, down, oldMetaState);
- case AKEYCODE_NUM_LOCK:
- return toggleLockedMetaState(AMETA_NUM_LOCK_ON, down, oldMetaState);
- case AKEYCODE_SCROLL_LOCK:
- return toggleLockedMetaState(AMETA_SCROLL_LOCK_ON, down, oldMetaState);
- default:
- return oldMetaState;
- }
-}
-
-bool isMetaKey(int32_t keyCode) {
- switch (keyCode) {
- case AKEYCODE_ALT_LEFT:
- case AKEYCODE_ALT_RIGHT:
- case AKEYCODE_SHIFT_LEFT:
- case AKEYCODE_SHIFT_RIGHT:
- case AKEYCODE_SYM:
- case AKEYCODE_FUNCTION:
- case AKEYCODE_CTRL_LEFT:
- case AKEYCODE_CTRL_RIGHT:
- case AKEYCODE_META_LEFT:
- case AKEYCODE_META_RIGHT:
- case AKEYCODE_CAPS_LOCK:
- case AKEYCODE_NUM_LOCK:
- case AKEYCODE_SCROLL_LOCK:
- return true;
- default:
- return false;
- }
-}
-
-
-} // namespace android
diff --git a/widget/gonk/libui/Keyboard.h b/widget/gonk/libui/Keyboard.h
deleted file mode 100644
index 65921b25b..000000000
--- a/widget/gonk/libui/Keyboard.h
+++ /dev/null
@@ -1,122 +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 _ANDROIDFW_KEYBOARD_H
-#define _ANDROIDFW_KEYBOARD_H
-
-#include "Input.h"
-#include "InputDevice.h"
-#include <utils/Errors.h>
-#include <utils/String8.h>
-#include <utils/PropertyMap.h>
-
-namespace android {
-
-enum {
- /* Device id of the built in keyboard. */
- DEVICE_ID_BUILT_IN_KEYBOARD = 0,
-
- /* Device id of a generic virtual keyboard with a full layout that can be used
- * to synthesize key events. */
- DEVICE_ID_VIRTUAL_KEYBOARD = -1,
-};
-
-class KeyLayoutMap;
-class KeyCharacterMap;
-
-/**
- * Loads the key layout map and key character map for a keyboard device.
- */
-class KeyMap {
-public:
- String8 keyLayoutFile;
- sp<KeyLayoutMap> keyLayoutMap;
-
- String8 keyCharacterMapFile;
- sp<KeyCharacterMap> keyCharacterMap;
-
- KeyMap();
- ~KeyMap();
-
- status_t load(const InputDeviceIdentifier& deviceIdenfier,
- const PropertyMap* deviceConfiguration);
-
- inline bool haveKeyLayout() const {
- return !keyLayoutFile.isEmpty();
- }
-
- inline bool haveKeyCharacterMap() const {
- return !keyCharacterMapFile.isEmpty();
- }
-
- inline bool isComplete() const {
- return haveKeyLayout() && haveKeyCharacterMap();
- }
-
-private:
- bool probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, const String8& name);
- status_t loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, const String8& name);
- status_t loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name);
- String8 getPath(const InputDeviceIdentifier& deviceIdentifier,
- const String8& name, InputDeviceConfigurationFileType type);
-};
-
-/**
- * Returns true if the keyboard is eligible for use as a built-in keyboard.
- */
-extern bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier,
- const PropertyMap* deviceConfiguration, const KeyMap* keyMap);
-
-/**
- * Gets a key code by its short form label, eg. "HOME".
- * Returns 0 if unknown.
- */
-extern int32_t getKeyCodeByLabel(const char* label);
-
-/**
- * Gets a key flag by its short form label, eg. "WAKE".
- * Returns 0 if unknown.
- */
-extern uint32_t getKeyFlagByLabel(const char* label);
-
-/**
- * Gets a axis by its short form label, eg. "X".
- * Returns -1 if unknown.
- */
-extern int32_t getAxisByLabel(const char* label);
-
-/**
- * Gets a axis label by its id.
- * Returns NULL if unknown.
- */
-extern const char* getAxisLabel(int32_t axisId);
-
-extern int32_t getLedByLabel(const char* label);
-
-/**
- * Updates a meta state field when a key is pressed or released.
- */
-extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
-
-/**
- * Returns true if a key is a meta key like ALT or CAPS_LOCK.
- */
-extern bool isMetaKey(int32_t keyCode);
-
-} // namespace android
-
-#endif // _ANDROIDFW_KEYBOARD_H
diff --git a/widget/gonk/libui/KeycodeLabels.h b/widget/gonk/libui/KeycodeLabels.h
deleted file mode 100644
index 9f994597b..000000000
--- a/widget/gonk/libui/KeycodeLabels.h
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _ANDROIDFW_KEYCODE_LABELS_H
-#define _ANDROIDFW_KEYCODE_LABELS_H
-
-#include "android_keycodes.h"
-
-struct KeycodeLabel {
- const char *literal;
- int value;
-};
-
-static const KeycodeLabel KEYCODES[] = {
- { "SOFT_LEFT", 1 },
- { "SOFT_RIGHT", 2 },
- { "HOME", 3 },
- { "BACK", 4 },
- { "CALL", 5 },
- { "ENDCALL", 6 },
- { "0", 7 },
- { "1", 8 },
- { "2", 9 },
- { "3", 10 },
- { "4", 11 },
- { "5", 12 },
- { "6", 13 },
- { "7", 14 },
- { "8", 15 },
- { "9", 16 },
- { "STAR", 17 },
- { "POUND", 18 },
- { "DPAD_UP", 19 },
- { "DPAD_DOWN", 20 },
- { "DPAD_LEFT", 21 },
- { "DPAD_RIGHT", 22 },
- { "DPAD_CENTER", 23 },
- { "VOLUME_UP", 24 },
- { "VOLUME_DOWN", 25 },
- { "POWER", 26 },
- { "CAMERA", 27 },
- { "CLEAR", 28 },
- { "A", 29 },
- { "B", 30 },
- { "C", 31 },
- { "D", 32 },
- { "E", 33 },
- { "F", 34 },
- { "G", 35 },
- { "H", 36 },
- { "I", 37 },
- { "J", 38 },
- { "K", 39 },
- { "L", 40 },
- { "M", 41 },
- { "N", 42 },
- { "O", 43 },
- { "P", 44 },
- { "Q", 45 },
- { "R", 46 },
- { "S", 47 },
- { "T", 48 },
- { "U", 49 },
- { "V", 50 },
- { "W", 51 },
- { "X", 52 },
- { "Y", 53 },
- { "Z", 54 },
- { "COMMA", 55 },
- { "PERIOD", 56 },
- { "ALT_LEFT", 57 },
- { "ALT_RIGHT", 58 },
- { "SHIFT_LEFT", 59 },
- { "SHIFT_RIGHT", 60 },
- { "TAB", 61 },
- { "SPACE", 62 },
- { "SYM", 63 },
- { "EXPLORER", 64 },
- { "ENVELOPE", 65 },
- { "ENTER", 66 },
- { "DEL", 67 },
- { "GRAVE", 68 },
- { "MINUS", 69 },
- { "EQUALS", 70 },
- { "LEFT_BRACKET", 71 },
- { "RIGHT_BRACKET", 72 },
- { "BACKSLASH", 73 },
- { "SEMICOLON", 74 },
- { "APOSTROPHE", 75 },
- { "SLASH", 76 },
- { "AT", 77 },
- { "NUM", 78 },
- { "HEADSETHOOK", 79 },
- { "FOCUS", 80 },
- { "PLUS", 81 },
- { "MENU", 82 },
- { "NOTIFICATION", 83 },
- { "SEARCH", 84 },
- { "MEDIA_PLAY_PAUSE", 85 },
- { "MEDIA_STOP", 86 },
- { "MEDIA_NEXT", 87 },
- { "MEDIA_PREVIOUS", 88 },
- { "MEDIA_REWIND", 89 },
- { "MEDIA_FAST_FORWARD", 90 },
- { "MUTE", 91 },
- { "PAGE_UP", 92 },
- { "PAGE_DOWN", 93 },
- { "PICTSYMBOLS", 94 },
- { "SWITCH_CHARSET", 95 },
- { "BUTTON_A", 96 },
- { "BUTTON_B", 97 },
- { "BUTTON_C", 98 },
- { "BUTTON_X", 99 },
- { "BUTTON_Y", 100 },
- { "BUTTON_Z", 101 },
- { "BUTTON_L1", 102 },
- { "BUTTON_R1", 103 },
- { "BUTTON_L2", 104 },
- { "BUTTON_R2", 105 },
- { "BUTTON_THUMBL", 106 },
- { "BUTTON_THUMBR", 107 },
- { "BUTTON_START", 108 },
- { "BUTTON_SELECT", 109 },
- { "BUTTON_MODE", 110 },
- { "ESCAPE", 111 },
- { "FORWARD_DEL", 112 },
- { "CTRL_LEFT", 113 },
- { "CTRL_RIGHT", 114 },
- { "CAPS_LOCK", 115 },
- { "SCROLL_LOCK", 116 },
- { "META_LEFT", 117 },
- { "META_RIGHT", 118 },
- { "FUNCTION", 119 },
- { "SYSRQ", 120 },
- { "BREAK", 121 },
- { "MOVE_HOME", 122 },
- { "MOVE_END", 123 },
- { "INSERT", 124 },
- { "FORWARD", 125 },
- { "MEDIA_PLAY", 126 },
- { "MEDIA_PAUSE", 127 },
- { "MEDIA_CLOSE", 128 },
- { "MEDIA_EJECT", 129 },
- { "MEDIA_RECORD", 130 },
- { "F1", 131 },
- { "F2", 132 },
- { "F3", 133 },
- { "F4", 134 },
- { "F5", 135 },
- { "F6", 136 },
- { "F7", 137 },
- { "F8", 138 },
- { "F9", 139 },
- { "F10", 140 },
- { "F11", 141 },
- { "F12", 142 },
- { "NUM_LOCK", 143 },
- { "NUMPAD_0", 144 },
- { "NUMPAD_1", 145 },
- { "NUMPAD_2", 146 },
- { "NUMPAD_3", 147 },
- { "NUMPAD_4", 148 },
- { "NUMPAD_5", 149 },
- { "NUMPAD_6", 150 },
- { "NUMPAD_7", 151 },
- { "NUMPAD_8", 152 },
- { "NUMPAD_9", 153 },
- { "NUMPAD_DIVIDE", 154 },
- { "NUMPAD_MULTIPLY", 155 },
- { "NUMPAD_SUBTRACT", 156 },
- { "NUMPAD_ADD", 157 },
- { "NUMPAD_DOT", 158 },
- { "NUMPAD_COMMA", 159 },
- { "NUMPAD_ENTER", 160 },
- { "NUMPAD_EQUALS", 161 },
- { "NUMPAD_LEFT_PAREN", 162 },
- { "NUMPAD_RIGHT_PAREN", 163 },
- { "VOLUME_MUTE", 164 },
- { "INFO", 165 },
- { "CHANNEL_UP", 166 },
- { "CHANNEL_DOWN", 167 },
- { "ZOOM_IN", 168 },
- { "ZOOM_OUT", 169 },
- { "TV", 170 },
- { "WINDOW", 171 },
- { "GUIDE", 172 },
- { "DVR", 173 },
- { "BOOKMARK", 174 },
- { "CAPTIONS", 175 },
- { "SETTINGS", 176 },
- { "TV_POWER", 177 },
- { "TV_INPUT", 178 },
- { "STB_POWER", 179 },
- { "STB_INPUT", 180 },
- { "AVR_POWER", 181 },
- { "AVR_INPUT", 182 },
- { "PROG_RED", 183 },
- { "PROG_GREEN", 184 },
- { "PROG_YELLOW", 185 },
- { "PROG_BLUE", 186 },
- { "APP_SWITCH", 187 },
- { "BUTTON_1", 188 },
- { "BUTTON_2", 189 },
- { "BUTTON_3", 190 },
- { "BUTTON_4", 191 },
- { "BUTTON_5", 192 },
- { "BUTTON_6", 193 },
- { "BUTTON_7", 194 },
- { "BUTTON_8", 195 },
- { "BUTTON_9", 196 },
- { "BUTTON_10", 197 },
- { "BUTTON_11", 198 },
- { "BUTTON_12", 199 },
- { "BUTTON_13", 200 },
- { "BUTTON_14", 201 },
- { "BUTTON_15", 202 },
- { "BUTTON_16", 203 },
- { "LANGUAGE_SWITCH", 204 },
- { "MANNER_MODE", 205 },
- { "3D_MODE", 206 },
- { "CONTACTS", 207 },
- { "CALENDAR", 208 },
- { "MUSIC", 209 },
- { "CALCULATOR", 210 },
- { "ZENKAKU_HANKAKU", 211 },
- { "EISU", 212 },
- { "MUHENKAN", 213 },
- { "HENKAN", 214 },
- { "KATAKANA_HIRAGANA", 215 },
- { "YEN", 216 },
- { "RO", 217 },
- { "KANA", 218 },
- { "ASSIST", 219 },
- { "BRIGHTNESS_DOWN", 220 },
- { "BRIGHTNESS_UP", 221 },
- { "MEDIA_AUDIO_TRACK", 222 },
- { "SLEEP", 223 },
- { "WAKEUP", 224 },
- { "PAIRING", 225 },
- { "MEDIA_TOP_MENU", 226 },
- { "11", 227 },
- { "12", 228 },
- { "LAST_CHANNEL", 229 },
- { "TV_DATA_SERVICE", 230 },
- { "VOICE_ASSIST", 231 },
- { "TV_RADIO_SERVICE", 232 },
- { "TV_TELETEXT", 233 },
- { "TV_NUMBER_ENTRY", 234 },
- { "TV_TERRESTRIAL_ANALOG", 235 },
- { "TV_TERRESTRIAL_DIGITAL", 236 },
- { "TV_SATELLITE", 237 },
- { "TV_SATELLITE_BS", 238 },
- { "TV_SATELLITE_CS", 239 },
- { "TV_SATELLITE_SERVICE", 240 },
- { "TV_NETWORK", 241 },
- { "TV_ANTENNA_CABLE", 242 },
- { "TV_INPUT_HDMI_1", 243 },
- { "TV_INPUT_HDMI_2", 244 },
- { "TV_INPUT_HDMI_3", 245 },
- { "TV_INPUT_HDMI_4", 246 },
- { "TV_INPUT_COMPOSITE_1", 247 },
- { "TV_INPUT_COMPOSITE_2", 248 },
- { "TV_INPUT_COMPONENT_1", 249 },
- { "TV_INPUT_COMPONENT_2", 250 },
- { "TV_INPUT_VGA_1", 251 },
- { "TV_AUDIO_DESCRIPTION", 252 },
- { "TV_AUDIO_DESCRIPTION_MIX_UP", 253 },
- { "TV_AUDIO_DESCRIPTION_MIX_DOWN", 254 },
- { "TV_ZOOM_MODE", 255 },
- { "TV_CONTENTS_MENU", 256 },
- { "TV_MEDIA_CONTEXT_MENU", 257 },
- { "TV_TIMER_PROGRAMMING", 258 },
- { "HELP", 259 },
-
- // NOTE: If you add a new keycode here you must also add it to several other files.
- // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
-
- { NULL, 0 }
-};
-
-// NOTE: If you edit these flags, also edit policy flags in Input.h.
-static const KeycodeLabel FLAGS[] = {
- { "WAKE", 0x00000001 },
- { "WAKE_DROPPED", 0x00000002 },
- { "SHIFT", 0x00000004 },
- { "CAPS_LOCK", 0x00000008 },
- { "ALT", 0x00000010 },
- { "ALT_GR", 0x00000020 },
- { "MENU", 0x00000040 },
- { "LAUNCHER", 0x00000080 },
- { "VIRTUAL", 0x00000100 },
- { "FUNCTION", 0x00000200 },
- { NULL, 0 }
-};
-
-static const KeycodeLabel AXES[] = {
- { "X", 0 },
- { "Y", 1 },
- { "PRESSURE", 2 },
- { "SIZE", 3 },
- { "TOUCH_MAJOR", 4 },
- { "TOUCH_MINOR", 5 },
- { "TOOL_MAJOR", 6 },
- { "TOOL_MINOR", 7 },
- { "ORIENTATION", 8 },
- { "VSCROLL", 9 },
- { "HSCROLL", 10 },
- { "Z", 11 },
- { "RX", 12 },
- { "RY", 13 },
- { "RZ", 14 },
- { "HAT_X", 15 },
- { "HAT_Y", 16 },
- { "LTRIGGER", 17 },
- { "RTRIGGER", 18 },
- { "THROTTLE", 19 },
- { "RUDDER", 20 },
- { "WHEEL", 21 },
- { "GAS", 22 },
- { "BRAKE", 23 },
- { "DISTANCE", 24 },
- { "TILT", 25 },
- { "GENERIC_1", 32 },
- { "GENERIC_2", 33 },
- { "GENERIC_3", 34 },
- { "GENERIC_4", 35 },
- { "GENERIC_5", 36 },
- { "GENERIC_6", 37 },
- { "GENERIC_7", 38 },
- { "GENERIC_8", 39 },
- { "GENERIC_9", 40 },
- { "GENERIC_10", 41 },
- { "GENERIC_11", 42 },
- { "GENERIC_12", 43 },
- { "GENERIC_13", 44 },
- { "GENERIC_14", 45 },
- { "GENERIC_15", 46 },
- { "GENERIC_16", 47 },
-
- // NOTE: If you add a new axis here you must also add it to several other files.
- // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
-
- { NULL, -1 }
-};
-
-static const KeycodeLabel LEDS[] = {
- { "NUM_LOCK", 1},
- { "CAPS_LOCK", 2},
- { "SCROLL_LOCK", 3},
- { "COMPOSE", 4},
- { "KANA", 5},
- { "SLEEP", 6},
- { "SUSPEND", 7},
- { "MUTE", 8},
- { "MISC", 9},
- { "MAIL", 10},
- { "CHARGING", 11},
- { "CONTROLLER_1", 12},
- { "CONTROLLER_2", 13},
- { "CONTROLLER_3", 14},
- { "CONTROLLER_4", 15},
-
- // NOTE: If you add new LEDs here, you must also add them to Input.h
- { NULL, 0 }
-};
-
-#endif // _ANDROIDFW_KEYCODE_LABELS_H
diff --git a/widget/gonk/libui/PointerController.cpp b/widget/gonk/libui/PointerController.cpp
deleted file mode 100644
index ff80a0a9f..000000000
--- a/widget/gonk/libui/PointerController.cpp
+++ /dev/null
@@ -1,604 +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.
- */
-
-#define LOG_TAG "PointerController"
-
-//#define LOG_NDEBUG 0
-
-// Log debug messages about pointer updates
-#define DEBUG_POINTER_UPDATES 0
-
-#include "PointerController.h"
-
-#include "cutils_log.h"
-
-#include <SkBitmap.h>
-#include <SkCanvas.h>
-#include <SkColor.h>
-#include <SkPaint.h>
-#include <SkXfermode.h>
-
-namespace android {
-
-// --- PointerController ---
-
-// Time to wait before starting the fade when the pointer is inactive.
-static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
-static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
-
-// Time to wait between animation frames.
-static const nsecs_t ANIMATION_FRAME_INTERVAL = 1000000000LL / 60;
-
-// Time to spend fading out the spot completely.
-static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
-
-// Time to spend fading out the pointer completely.
-static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
-
-
-// --- PointerController ---
-
-PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
- const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
- mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
- mHandler = new WeakMessageHandler(this);
-
- AutoMutex _l(mLock);
-
- mLocked.animationPending = false;
-
- mLocked.displayWidth = -1;
- mLocked.displayHeight = -1;
- mLocked.displayOrientation = DISPLAY_ORIENTATION_0;
-
- mLocked.presentation = PRESENTATION_POINTER;
- mLocked.presentationChanged = false;
-
- mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
-
- mLocked.pointerFadeDirection = 0;
- mLocked.pointerX = 0;
- mLocked.pointerY = 0;
- mLocked.pointerAlpha = 0.0f; // pointer is initially faded
- mLocked.pointerSprite = mSpriteController->createSprite();
- mLocked.pointerIconChanged = false;
-
- mLocked.buttonState = 0;
-
- loadResources();
-}
-
-PointerController::~PointerController() {
- mLooper->removeMessages(mHandler);
-
- AutoMutex _l(mLock);
-
- mLocked.pointerSprite.clear();
-
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- delete mLocked.spots.itemAt(i);
- }
- mLocked.spots.clear();
- mLocked.recycledSprites.clear();
-}
-
-bool PointerController::getBounds(float* outMinX, float* outMinY,
- float* outMaxX, float* outMaxY) const {
- AutoMutex _l(mLock);
-
- return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
-}
-
-bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
- float* outMaxX, float* outMaxY) const {
- if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) {
- return false;
- }
-
- *outMinX = 0;
- *outMinY = 0;
- switch (mLocked.displayOrientation) {
- case DISPLAY_ORIENTATION_90:
- case DISPLAY_ORIENTATION_270:
- *outMaxX = mLocked.displayHeight - 1;
- *outMaxY = mLocked.displayWidth - 1;
- break;
- default:
- *outMaxX = mLocked.displayWidth - 1;
- *outMaxY = mLocked.displayHeight - 1;
- break;
- }
- return true;
-}
-
-void PointerController::move(float deltaX, float deltaY) {
-#if DEBUG_POINTER_UPDATES
- ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
-#endif
- if (deltaX == 0.0f && deltaY == 0.0f) {
- return;
- }
-
- AutoMutex _l(mLock);
-
- setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
-}
-
-void PointerController::setButtonState(int32_t buttonState) {
-#if DEBUG_POINTER_UPDATES
- ALOGD("Set button state 0x%08x", buttonState);
-#endif
- AutoMutex _l(mLock);
-
- if (mLocked.buttonState != buttonState) {
- mLocked.buttonState = buttonState;
- }
-}
-
-int32_t PointerController::getButtonState() const {
- AutoMutex _l(mLock);
-
- return mLocked.buttonState;
-}
-
-void PointerController::setPosition(float x, float y) {
-#if DEBUG_POINTER_UPDATES
- ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
-#endif
- AutoMutex _l(mLock);
-
- setPositionLocked(x, y);
-}
-
-void PointerController::setPositionLocked(float x, float y) {
- float minX, minY, maxX, maxY;
- if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
- if (x <= minX) {
- mLocked.pointerX = minX;
- } else if (x >= maxX) {
- mLocked.pointerX = maxX;
- } else {
- mLocked.pointerX = x;
- }
- if (y <= minY) {
- mLocked.pointerY = minY;
- } else if (y >= maxY) {
- mLocked.pointerY = maxY;
- } else {
- mLocked.pointerY = y;
- }
- updatePointerLocked();
- }
-}
-
-void PointerController::getPosition(float* outX, float* outY) const {
- AutoMutex _l(mLock);
-
- *outX = mLocked.pointerX;
- *outY = mLocked.pointerY;
-}
-
-void PointerController::fade(Transition transition) {
- AutoMutex _l(mLock);
-
- // Remove the inactivity timeout, since we are fading now.
- removeInactivityTimeoutLocked();
-
- // Start fading.
- if (transition == TRANSITION_IMMEDIATE) {
- mLocked.pointerFadeDirection = 0;
- mLocked.pointerAlpha = 0.0f;
- updatePointerLocked();
- } else {
- mLocked.pointerFadeDirection = -1;
- startAnimationLocked();
- }
-}
-
-void PointerController::unfade(Transition transition) {
- AutoMutex _l(mLock);
-
- // Always reset the inactivity timer.
- resetInactivityTimeoutLocked();
-
- // Start unfading.
- if (transition == TRANSITION_IMMEDIATE) {
- mLocked.pointerFadeDirection = 0;
- mLocked.pointerAlpha = 1.0f;
- updatePointerLocked();
- } else {
- mLocked.pointerFadeDirection = 1;
- startAnimationLocked();
- }
-}
-
-void PointerController::setPresentation(Presentation presentation) {
- AutoMutex _l(mLock);
-
- if (mLocked.presentation != presentation) {
- mLocked.presentation = presentation;
- mLocked.presentationChanged = true;
-
- if (presentation != PRESENTATION_SPOT) {
- fadeOutAndReleaseAllSpotsLocked();
- }
-
- updatePointerLocked();
- }
-}
-
-void PointerController::setSpots(const PointerCoords* spotCoords,
- const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
-#if DEBUG_POINTER_UPDATES
- ALOGD("setSpots: idBits=%08x", spotIdBits.value);
- for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.firstMarkedBit();
- idBits.clearBit(id);
- const PointerCoords& c = spotCoords[spotIdToIndex[id]];
- ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f", id,
- c.getAxisValue(AMOTION_EVENT_AXIS_X),
- c.getAxisValue(AMOTION_EVENT_AXIS_Y),
- c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
- }
-#endif
-
- AutoMutex _l(mLock);
-
- mSpriteController->openTransaction();
-
- // Add or move spots for fingers that are down.
- for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const PointerCoords& c = spotCoords[spotIdToIndex[id]];
- const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
- ? mResources.spotTouch : mResources.spotHover;
- float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
- float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
-
- Spot* spot = getSpotLocked(id);
- if (!spot) {
- spot = createAndAddSpotLocked(id);
- }
-
- spot->updateSprite(&icon, x, y);
- }
-
- // Remove spots for fingers that went up.
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- Spot* spot = mLocked.spots.itemAt(i);
- if (spot->id != Spot::INVALID_ID
- && !spotIdBits.hasBit(spot->id)) {
- fadeOutAndReleaseSpotLocked(spot);
- }
- }
-
- mSpriteController->closeTransaction();
-}
-
-void PointerController::clearSpots() {
-#if DEBUG_POINTER_UPDATES
- ALOGD("clearSpots");
-#endif
-
- AutoMutex _l(mLock);
-
- fadeOutAndReleaseAllSpotsLocked();
-}
-
-void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
- AutoMutex _l(mLock);
-
- if (mLocked.inactivityTimeout != inactivityTimeout) {
- mLocked.inactivityTimeout = inactivityTimeout;
- resetInactivityTimeoutLocked();
- }
-}
-
-void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) {
- AutoMutex _l(mLock);
-
- // Adjust to use the display's unrotated coordinate frame.
- if (orientation == DISPLAY_ORIENTATION_90
- || orientation == DISPLAY_ORIENTATION_270) {
- int32_t temp = height;
- height = width;
- width = temp;
- }
-
- if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
- mLocked.displayWidth = width;
- mLocked.displayHeight = height;
-
- float minX, minY, maxX, maxY;
- if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
- mLocked.pointerX = (minX + maxX) * 0.5f;
- mLocked.pointerY = (minY + maxY) * 0.5f;
- } else {
- mLocked.pointerX = 0;
- mLocked.pointerY = 0;
- }
-
- fadeOutAndReleaseAllSpotsLocked();
- }
-
- if (mLocked.displayOrientation != orientation) {
- // Apply offsets to convert from the pixel top-left corner position to the pixel center.
- // This creates an invariant frame of reference that we can easily rotate when
- // taking into account that the pointer may be located at fractional pixel offsets.
- float x = mLocked.pointerX + 0.5f;
- float y = mLocked.pointerY + 0.5f;
- float temp;
-
- // Undo the previous rotation.
- switch (mLocked.displayOrientation) {
- case DISPLAY_ORIENTATION_90:
- temp = x;
- x = mLocked.displayWidth - y;
- y = temp;
- break;
- case DISPLAY_ORIENTATION_180:
- x = mLocked.displayWidth - x;
- y = mLocked.displayHeight - y;
- break;
- case DISPLAY_ORIENTATION_270:
- temp = x;
- x = y;
- y = mLocked.displayHeight - temp;
- break;
- }
-
- // Perform the new rotation.
- switch (orientation) {
- case DISPLAY_ORIENTATION_90:
- temp = x;
- x = y;
- y = mLocked.displayWidth - temp;
- break;
- case DISPLAY_ORIENTATION_180:
- x = mLocked.displayWidth - x;
- y = mLocked.displayHeight - y;
- break;
- case DISPLAY_ORIENTATION_270:
- temp = x;
- x = mLocked.displayHeight - y;
- y = temp;
- break;
- }
-
- // Apply offsets to convert from the pixel center to the pixel top-left corner position
- // and save the results.
- mLocked.pointerX = x - 0.5f;
- mLocked.pointerY = y - 0.5f;
- mLocked.displayOrientation = orientation;
- }
-
- updatePointerLocked();
-}
-
-void PointerController::setPointerIcon(const SpriteIcon& icon) {
- AutoMutex _l(mLock);
-
- mLocked.pointerIcon = icon.copy();
- mLocked.pointerIconChanged = true;
-
- updatePointerLocked();
-}
-
-void PointerController::handleMessage(const Message& message) {
- switch (message.what) {
- case MSG_ANIMATE:
- doAnimate();
- break;
- case MSG_INACTIVITY_TIMEOUT:
- doInactivityTimeout();
- break;
- }
-}
-
-void PointerController::doAnimate() {
- AutoMutex _l(mLock);
-
- bool keepAnimating = false;
- mLocked.animationPending = false;
- nsecs_t frameDelay = systemTime(SYSTEM_TIME_MONOTONIC) - mLocked.animationTime;
-
- // Animate pointer fade.
- if (mLocked.pointerFadeDirection < 0) {
- mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
- if (mLocked.pointerAlpha <= 0.0f) {
- mLocked.pointerAlpha = 0.0f;
- mLocked.pointerFadeDirection = 0;
- } else {
- keepAnimating = true;
- }
- updatePointerLocked();
- } else if (mLocked.pointerFadeDirection > 0) {
- mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
- if (mLocked.pointerAlpha >= 1.0f) {
- mLocked.pointerAlpha = 1.0f;
- mLocked.pointerFadeDirection = 0;
- } else {
- keepAnimating = true;
- }
- updatePointerLocked();
- }
-
- // Animate spots that are fading out and being removed.
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- Spot* spot = mLocked.spots.itemAt(i);
- if (spot->id == Spot::INVALID_ID) {
- spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
- if (spot->alpha <= 0) {
- mLocked.spots.removeAt(i--);
- releaseSpotLocked(spot);
- } else {
- spot->sprite->setAlpha(spot->alpha);
- keepAnimating = true;
- }
- }
- }
-
- if (keepAnimating) {
- startAnimationLocked();
- }
-}
-
-void PointerController::doInactivityTimeout() {
- fade(TRANSITION_GRADUAL);
-}
-
-void PointerController::startAnimationLocked() {
- if (!mLocked.animationPending) {
- mLocked.animationPending = true;
- mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
- mLooper->sendMessageDelayed(ANIMATION_FRAME_INTERVAL, mHandler, Message(MSG_ANIMATE));
- }
-}
-
-void PointerController::resetInactivityTimeoutLocked() {
- mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
-
- nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT
- ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
- mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
-}
-
-void PointerController::removeInactivityTimeoutLocked() {
- mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
-}
-
-void PointerController::updatePointerLocked() {
- mSpriteController->openTransaction();
-
- mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
- mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
-
- if (mLocked.pointerAlpha > 0) {
- mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
- mLocked.pointerSprite->setVisible(true);
- } else {
- mLocked.pointerSprite->setVisible(false);
- }
-
- if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
- mLocked.pointerSprite->setIcon(mLocked.presentation == PRESENTATION_POINTER
- ? mLocked.pointerIcon : mResources.spotAnchor);
- mLocked.pointerIconChanged = false;
- mLocked.presentationChanged = false;
- }
-
- mSpriteController->closeTransaction();
-}
-
-PointerController::Spot* PointerController::getSpotLocked(uint32_t id) {
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- Spot* spot = mLocked.spots.itemAt(i);
- if (spot->id == id) {
- return spot;
- }
- }
- return NULL;
-}
-
-PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id) {
- // Remove spots until we have fewer than MAX_SPOTS remaining.
- while (mLocked.spots.size() >= MAX_SPOTS) {
- Spot* spot = removeFirstFadingSpotLocked();
- if (!spot) {
- spot = mLocked.spots.itemAt(0);
- mLocked.spots.removeAt(0);
- }
- releaseSpotLocked(spot);
- }
-
- // Obtain a sprite from the recycled pool.
- sp<Sprite> sprite;
- if (! mLocked.recycledSprites.isEmpty()) {
- sprite = mLocked.recycledSprites.top();
- mLocked.recycledSprites.pop();
- } else {
- sprite = mSpriteController->createSprite();
- }
-
- // Return the new spot.
- Spot* spot = new Spot(id, sprite);
- mLocked.spots.push(spot);
- return spot;
-}
-
-PointerController::Spot* PointerController::removeFirstFadingSpotLocked() {
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- Spot* spot = mLocked.spots.itemAt(i);
- if (spot->id == Spot::INVALID_ID) {
- mLocked.spots.removeAt(i);
- return spot;
- }
- }
- return NULL;
-}
-
-void PointerController::releaseSpotLocked(Spot* spot) {
- spot->sprite->clearIcon();
-
- if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
- mLocked.recycledSprites.push(spot->sprite);
- }
-
- delete spot;
-}
-
-void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
- if (spot->id != Spot::INVALID_ID) {
- spot->id = Spot::INVALID_ID;
- startAnimationLocked();
- }
-}
-
-void PointerController::fadeOutAndReleaseAllSpotsLocked() {
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- Spot* spot = mLocked.spots.itemAt(i);
- fadeOutAndReleaseSpotLocked(spot);
- }
-}
-
-void PointerController::loadResources() {
- mPolicy->loadPointerResources(&mResources);
-}
-
-
-// --- PointerController::Spot ---
-
-void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y) {
- sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
- sprite->setAlpha(alpha);
- sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
- sprite->setPosition(x, y);
-
- this->x = x;
- this->y = y;
-
- if (icon != lastIcon) {
- lastIcon = icon;
- if (icon) {
- sprite->setIcon(*icon);
- sprite->setVisible(true);
- } else {
- sprite->setVisible(false);
- }
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/PointerController.h b/widget/gonk/libui/PointerController.h
deleted file mode 100644
index eb48d9a1f..000000000
--- a/widget/gonk/libui/PointerController.h
+++ /dev/null
@@ -1,266 +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_POINTER_CONTROLLER_H
-#define _UI_POINTER_CONTROLLER_H
-
-#include "SpriteController.h"
-
-#include <ui/DisplayInfo.h>
-#include "Input.h"
-#include <utils/BitSet.h>
-#include <utils/RefBase.h>
-#include <utils/Looper.h>
-#include <utils/String8.h>
-
-#include <SkBitmap.h>
-
-namespace android {
-
-/**
- * Interface for tracking a mouse / touch pad pointer and touch pad spots.
- *
- * The spots are sprites on screen that visually represent the positions of
- * fingers
- *
- * The pointer controller is responsible for providing synchronization and for tracking
- * display orientation changes if needed.
- */
-class PointerControllerInterface : public virtual RefBase {
-protected:
- PointerControllerInterface() { }
- virtual ~PointerControllerInterface() { }
-
-public:
- /* Gets the bounds of the region that the pointer can traverse.
- * Returns true if the bounds are available. */
- virtual bool getBounds(float* outMinX, float* outMinY,
- float* outMaxX, float* outMaxY) const = 0;
-
- /* Move the pointer. */
- virtual void move(float deltaX, float deltaY) = 0;
-
- /* Sets a mask that indicates which buttons are pressed. */
- virtual void setButtonState(int32_t buttonState) = 0;
-
- /* Gets a mask that indicates which buttons are pressed. */
- virtual int32_t getButtonState() const = 0;
-
- /* Sets the absolute location of the pointer. */
- virtual void setPosition(float x, float y) = 0;
-
- /* Gets the absolute location of the pointer. */
- virtual void getPosition(float* outX, float* outY) const = 0;
-
- enum Transition {
- // Fade/unfade immediately.
- TRANSITION_IMMEDIATE,
- // Fade/unfade gradually.
- TRANSITION_GRADUAL,
- };
-
- /* Fades the pointer out now. */
- virtual void fade(Transition transition) = 0;
-
- /* Makes the pointer visible if it has faded out.
- * The pointer never unfades itself automatically. This method must be called
- * by the client whenever the pointer is moved or a button is pressed and it
- * wants to ensure that the pointer becomes visible again. */
- virtual void unfade(Transition transition) = 0;
-
- enum Presentation {
- // Show the mouse pointer.
- PRESENTATION_POINTER,
- // Show spots and a spot anchor in place of the mouse pointer.
- PRESENTATION_SPOT,
- };
-
- /* Sets the mode of the pointer controller. */
- virtual void setPresentation(Presentation presentation) = 0;
-
- /* Sets the spots for the current gesture.
- * The spots are not subject to the inactivity timeout like the pointer
- * itself it since they are expected to remain visible for so long as
- * the fingers are on the touch pad.
- *
- * The values of the AMOTION_EVENT_AXIS_PRESSURE axis is significant.
- * For spotCoords, pressure != 0 indicates that the spot's location is being
- * pressed (not hovering).
- */
- virtual void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
- BitSet32 spotIdBits) = 0;
-
- /* Removes all spots. */
- virtual void clearSpots() = 0;
-};
-
-
-/*
- * Pointer resources.
- */
-struct PointerResources {
- SpriteIcon spotHover;
- SpriteIcon spotTouch;
- SpriteIcon spotAnchor;
-};
-
-
-/*
- * Pointer controller policy interface.
- *
- * The pointer controller policy is used by the pointer controller 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 PointerControllerPolicyInterface : public virtual RefBase {
-protected:
- PointerControllerPolicyInterface() { }
- virtual ~PointerControllerPolicyInterface() { }
-
-public:
- virtual void loadPointerResources(PointerResources* outResources) = 0;
-};
-
-
-/*
- * Tracks pointer movements and draws the pointer sprite to a surface.
- *
- * Handles pointer acceleration and animation.
- */
-class PointerController : public PointerControllerInterface, public MessageHandler {
-protected:
- virtual ~PointerController();
-
-public:
- enum InactivityTimeout {
- INACTIVITY_TIMEOUT_NORMAL = 0,
- INACTIVITY_TIMEOUT_SHORT = 1,
- };
-
- PointerController(const sp<PointerControllerPolicyInterface>& policy,
- const sp<Looper>& looper, const sp<SpriteController>& spriteController);
-
- virtual bool getBounds(float* outMinX, float* outMinY,
- float* outMaxX, float* outMaxY) const;
- virtual void move(float deltaX, float deltaY);
- virtual void setButtonState(int32_t buttonState);
- virtual int32_t getButtonState() const;
- virtual void setPosition(float x, float y);
- virtual void getPosition(float* outX, float* outY) const;
- virtual void fade(Transition transition);
- virtual void unfade(Transition transition);
-
- virtual void setPresentation(Presentation presentation);
- virtual void setSpots(const PointerCoords* spotCoords,
- const uint32_t* spotIdToIndex, BitSet32 spotIdBits);
- virtual void clearSpots();
-
- void setDisplayViewport(int32_t width, int32_t height, int32_t orientation);
- void setPointerIcon(const SpriteIcon& icon);
- void setInactivityTimeout(InactivityTimeout inactivityTimeout);
-
-private:
- static const size_t MAX_RECYCLED_SPRITES = 12;
- static const size_t MAX_SPOTS = 12;
-
- enum {
- MSG_ANIMATE,
- MSG_INACTIVITY_TIMEOUT,
- };
-
- struct Spot {
- static const uint32_t INVALID_ID = 0xffffffff;
-
- uint32_t id;
- sp<Sprite> sprite;
- float alpha;
- float scale;
- float x, y;
-
- inline Spot(uint32_t id, const sp<Sprite>& sprite)
- : id(id), sprite(sprite), alpha(1.0f), scale(1.0f),
- x(0.0f), y(0.0f), lastIcon(NULL) { }
-
- void updateSprite(const SpriteIcon* icon, float x, float y);
-
- private:
- const SpriteIcon* lastIcon;
- };
-
- mutable Mutex mLock;
-
- sp<PointerControllerPolicyInterface> mPolicy;
- sp<Looper> mLooper;
- sp<SpriteController> mSpriteController;
- sp<WeakMessageHandler> mHandler;
-
- PointerResources mResources;
-
- struct Locked {
- bool animationPending;
- nsecs_t animationTime;
-
- int32_t displayWidth;
- int32_t displayHeight;
- int32_t displayOrientation;
-
- InactivityTimeout inactivityTimeout;
-
- Presentation presentation;
- bool presentationChanged;
-
- int32_t pointerFadeDirection;
- float pointerX;
- float pointerY;
- float pointerAlpha;
- sp<Sprite> pointerSprite;
- SpriteIcon pointerIcon;
- bool pointerIconChanged;
-
- int32_t buttonState;
-
- Vector<Spot*> spots;
- Vector<sp<Sprite> > recycledSprites;
- } mLocked;
-
- bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
- void setPositionLocked(float x, float y);
-
- void handleMessage(const Message& message);
- void doAnimate();
- void doInactivityTimeout();
-
- void startAnimationLocked();
-
- void resetInactivityTimeoutLocked();
- void removeInactivityTimeoutLocked();
- void updatePointerLocked();
-
- Spot* getSpotLocked(uint32_t id);
- Spot* createAndAddSpotLocked(uint32_t id);
- Spot* removeFirstFadingSpotLocked();
- void releaseSpotLocked(Spot* spot);
- void fadeOutAndReleaseSpotLocked(Spot* spot);
- void fadeOutAndReleaseAllSpotsLocked();
-
- void loadResources();
-};
-
-} // namespace android
-
-#endif // _UI_POINTER_CONTROLLER_H
diff --git a/widget/gonk/libui/PowerManager.h b/widget/gonk/libui/PowerManager.h
deleted file mode 100644
index ba98db07c..000000000
--- a/widget/gonk/libui/PowerManager.h
+++ /dev/null
@@ -1,33 +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 _ANDROIDFW_POWER_MANAGER_H
-#define _ANDROIDFW_POWER_MANAGER_H
-
-
-namespace android {
-
-enum {
- USER_ACTIVITY_EVENT_OTHER = 0,
- USER_ACTIVITY_EVENT_BUTTON = 1,
- USER_ACTIVITY_EVENT_TOUCH = 2,
-
- USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_TOUCH, // Last valid event code.
-};
-
-} // namespace android
-
-#endif // _ANDROIDFW_POWER_MANAGER_H
diff --git a/widget/gonk/libui/SpriteController.cpp b/widget/gonk/libui/SpriteController.cpp
deleted file mode 100644
index 8677476b1..000000000
--- a/widget/gonk/libui/SpriteController.cpp
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Sprites"
-
-//#define LOG_NDEBUG 0
-
-#include "SpriteController.h"
-
-#include "cutils_log.h"
-#include <utils/String8.h>
-#ifdef HAVE_ANDROID_OS
-#include <gui/Surface.h>
-#endif
-
-#include <SkBitmap.h>
-#include <SkCanvas.h>
-#include <SkColor.h>
-#include <SkPaint.h>
-#include <SkXfermode.h>
-#include <android/native_window.h>
-
-namespace android {
-
-// --- SpriteController ---
-
-SpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
- mLooper(looper), mOverlayLayer(overlayLayer) {
-#ifdef HAVE_ANDROID_OS
- mHandler = new WeakMessageHandler(this);
-#endif
-
- mLocked.transactionNestingCount = 0;
- mLocked.deferredSpriteUpdate = false;
-}
-
-SpriteController::~SpriteController() {
-#ifdef HAVE_ANDROID_OS
- mLooper->removeMessages(mHandler);
-
- if (mSurfaceComposerClient != NULL) {
- mSurfaceComposerClient->dispose();
- mSurfaceComposerClient.clear();
- }
-#endif
-}
-
-sp<Sprite> SpriteController::createSprite() {
- return new SpriteImpl(this);
-}
-
-void SpriteController::openTransaction() {
- AutoMutex _l(mLock);
-
- mLocked.transactionNestingCount += 1;
-}
-
-void SpriteController::closeTransaction() {
- AutoMutex _l(mLock);
-
- LOG_ALWAYS_FATAL_IF(mLocked.transactionNestingCount == 0,
- "Sprite closeTransaction() called but there is no open sprite transaction");
-
- mLocked.transactionNestingCount -= 1;
- if (mLocked.transactionNestingCount == 0 && mLocked.deferredSpriteUpdate) {
- mLocked.deferredSpriteUpdate = false;
-#ifdef HAVE_ANDROID_OS
- mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
-#endif
- }
-}
-
-void SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
- bool wasEmpty = mLocked.invalidatedSprites.isEmpty();
- mLocked.invalidatedSprites.push(sprite);
- if (wasEmpty) {
- if (mLocked.transactionNestingCount != 0) {
- mLocked.deferredSpriteUpdate = true;
- } else {
-#ifdef HAVE_ANDROID_OS
- mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
-#endif
- }
- }
-}
-
-#ifdef HAVE_ANDROID_OS
-void SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
- bool wasEmpty = mLocked.disposedSurfaces.isEmpty();
- mLocked.disposedSurfaces.push(surfaceControl);
- if (wasEmpty) {
- mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
- }
-}
-
-void SpriteController::handleMessage(const Message& message) {
- switch (message.what) {
- case MSG_UPDATE_SPRITES:
- doUpdateSprites();
- break;
- case MSG_DISPOSE_SURFACES:
- doDisposeSurfaces();
- break;
- }
-}
-#endif
-
-void SpriteController::doUpdateSprites() {
- // Collect information about sprite updates.
- // Each sprite update record includes a reference to its associated sprite so we can
- // be certain the sprites will not be deleted while this function runs. Sprites
- // may invalidate themselves again during this time but we will handle those changes
- // in the next iteration.
- Vector<SpriteUpdate> updates;
- size_t numSprites;
- { // acquire lock
- AutoMutex _l(mLock);
-
- numSprites = mLocked.invalidatedSprites.size();
- for (size_t i = 0; i < numSprites; i++) {
- const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites.itemAt(i);
-
- updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
- sprite->resetDirtyLocked();
- }
- mLocked.invalidatedSprites.clear();
- } // release lock
-
- // Create missing surfaces.
- bool surfaceChanged = false;
-#ifdef HAVE_ANDROID_OS
- for (size_t i = 0; i < numSprites; i++) {
- SpriteUpdate& update = updates.editItemAt(i);
- if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
- update.state.surfaceWidth = update.state.icon.bitmap.width();
- update.state.surfaceHeight = update.state.icon.bitmap.height();
- update.state.surfaceDrawn = false;
- update.state.surfaceVisible = false;
- update.state.surfaceControl = obtainSurface(
- update.state.surfaceWidth, update.state.surfaceHeight);
- if (update.state.surfaceControl != NULL) {
- update.surfaceChanged = surfaceChanged = true;
- }
- }
- }
-#endif
-
- // Resize sprites if needed, inside a global transaction.
-#ifdef HAVE_ANDROID_OS
- bool haveGlobalTransaction = false;
- for (size_t i = 0; i < numSprites; i++) {
- SpriteUpdate& update = updates.editItemAt(i);
- if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) {
- int32_t desiredWidth = update.state.icon.bitmap.width();
- int32_t desiredHeight = update.state.icon.bitmap.height();
- if (update.state.surfaceWidth < desiredWidth
- || update.state.surfaceHeight < desiredHeight) {
- if (!haveGlobalTransaction) {
- SurfaceComposerClient::openGlobalTransaction();
- haveGlobalTransaction = true;
- }
-
- status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight);
- if (status) {
- ALOGE("Error %d resizing sprite surface from %dx%d to %dx%d",
- status, update.state.surfaceWidth, update.state.surfaceHeight,
- desiredWidth, desiredHeight);
- } else {
- update.state.surfaceWidth = desiredWidth;
- update.state.surfaceHeight = desiredHeight;
- update.state.surfaceDrawn = false;
- update.surfaceChanged = surfaceChanged = true;
-
- if (update.state.surfaceVisible) {
- status = update.state.surfaceControl->hide();
- if (status) {
- ALOGE("Error %d hiding sprite surface after resize.", status);
- } else {
- update.state.surfaceVisible = false;
- }
- }
- }
- }
- }
- }
-#endif
-#ifdef HAVE_ANDROID_OS
- if (haveGlobalTransaction) {
- SurfaceComposerClient::closeGlobalTransaction();
- }
-#endif
-
- // Redraw sprites if needed.
- for (size_t i = 0; i < numSprites; i++) {
- SpriteUpdate& update = updates.editItemAt(i);
-
- if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) {
- update.state.surfaceDrawn = false;
- update.surfaceChanged = surfaceChanged = true;
- }
-
-#ifdef HAVE_ANDROID_OS
- if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
- && update.state.wantSurfaceVisible()) {
- sp<Surface> surface = update.state.surfaceControl->getSurface();
- ANativeWindow_Buffer outBuffer;
- status_t status = surface->lock(&outBuffer, NULL);
- if (status) {
- ALOGE("Error %d locking sprite surface before drawing.", status);
- } else {
- SkBitmap surfaceBitmap;
- ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
- surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config,
- outBuffer.width, outBuffer.height, bpr);
- surfaceBitmap.setPixels(outBuffer.bits);
-
- SkCanvas surfaceCanvas(surfaceBitmap);
-
- SkPaint paint;
- paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint);
-
- if (outBuffer.width > uint32_t(update.state.icon.bitmap.width())) {
- paint.setColor(0); // transparent fill color
- surfaceCanvas.drawRectCoords(update.state.icon.bitmap.width(), 0,
- outBuffer.width, update.state.icon.bitmap.height(), paint);
- }
- if (outBuffer.height > uint32_t(update.state.icon.bitmap.height())) {
- paint.setColor(0); // transparent fill color
- surfaceCanvas.drawRectCoords(0, update.state.icon.bitmap.height(),
- outBuffer.width, outBuffer.height, paint);
- }
-
- status = surface->unlockAndPost();
- if (status) {
- ALOGE("Error %d unlocking and posting sprite surface after drawing.", status);
- } else {
- update.state.surfaceDrawn = true;
- update.surfaceChanged = surfaceChanged = true;
- }
- }
- }
-#endif
- }
-
-#ifdef HAVE_ANDROID_OS
- // Set sprite surface properties and make them visible.
- bool haveTransaction = false;
- for (size_t i = 0; i < numSprites; i++) {
- SpriteUpdate& update = updates.editItemAt(i);
- bool wantSurfaceVisibleAndDrawn = update.state.wantSurfaceVisible()
- && update.state.surfaceDrawn;
- bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible;
- bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible;
- if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
- || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
- | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
- | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
- status_t status;
- if (!haveTransaction) {
- SurfaceComposerClient::openGlobalTransaction();
- haveTransaction = true;
- }
-
- if (wantSurfaceVisibleAndDrawn
- && (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) {
- status = update.state.surfaceControl->setAlpha(update.state.alpha);
- if (status) {
- ALOGE("Error %d setting sprite surface alpha.", status);
- }
- }
-
- if (wantSurfaceVisibleAndDrawn
- && (becomingVisible || (update.state.dirty & (DIRTY_POSITION
- | DIRTY_HOTSPOT)))) {
- status = update.state.surfaceControl->setPosition(
- update.state.positionX - update.state.icon.hotSpotX,
- update.state.positionY - update.state.icon.hotSpotY);
- if (status) {
- ALOGE("Error %d setting sprite surface position.", status);
- }
- }
-
- if (wantSurfaceVisibleAndDrawn
- && (becomingVisible
- || (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) {
- status = update.state.surfaceControl->setMatrix(
- update.state.transformationMatrix.dsdx,
- update.state.transformationMatrix.dtdx,
- update.state.transformationMatrix.dsdy,
- update.state.transformationMatrix.dtdy);
- if (status) {
- ALOGE("Error %d setting sprite surface transformation matrix.", status);
- }
- }
-
- int32_t surfaceLayer = mOverlayLayer + update.state.layer;
- if (wantSurfaceVisibleAndDrawn
- && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
- status = update.state.surfaceControl->setLayer(surfaceLayer);
- if (status) {
- ALOGE("Error %d setting sprite surface layer.", status);
- }
- }
-
- if (becomingVisible) {
- status = update.state.surfaceControl->show();
- if (status) {
- ALOGE("Error %d showing sprite surface.", status);
- } else {
- update.state.surfaceVisible = true;
- update.surfaceChanged = surfaceChanged = true;
- }
- } else if (becomingHidden) {
- status = update.state.surfaceControl->hide();
- if (status) {
- ALOGE("Error %d hiding sprite surface.", status);
- } else {
- update.state.surfaceVisible = false;
- update.surfaceChanged = surfaceChanged = true;
- }
- }
- }
- }
-#endif
-
-#ifdef HAVE_ANDROID_OS
- if (haveTransaction) {
- SurfaceComposerClient::closeGlobalTransaction();
- }
-#endif
-
-#ifdef HAVE_ANDROID_OS
- // If any surfaces were changed, write back the new surface properties to the sprites.
- if (surfaceChanged) { // acquire lock
- AutoMutex _l(mLock);
-
- for (size_t i = 0; i < numSprites; i++) {
- const SpriteUpdate& update = updates.itemAt(i);
-
- if (update.surfaceChanged) {
- update.sprite->setSurfaceLocked(update.state.surfaceControl,
- update.state.surfaceWidth, update.state.surfaceHeight,
- update.state.surfaceDrawn, update.state.surfaceVisible);
- }
- }
- } // release lock
-#endif
-
- // Clear the sprite update vector outside the lock. It is very important that
- // we do not clear sprite references inside the lock since we could be releasing
- // the last remaining reference to the sprite here which would result in the
- // sprite being deleted and the lock being reacquired by the sprite destructor
- // while already held.
- updates.clear();
-}
-
-void SpriteController::doDisposeSurfaces() {
-#ifdef HAVE_ANDROID_OS
- // Collect disposed surfaces.
- Vector<sp<SurfaceControl> > disposedSurfaces;
- { // acquire lock
- AutoMutex _l(mLock);
-
- disposedSurfaces = mLocked.disposedSurfaces;
- mLocked.disposedSurfaces.clear();
- } // release lock
-
- // Release the last reference to each surface outside of the lock.
- // We don't want the surfaces to be deleted while we are holding our lock.
- disposedSurfaces.clear();
-#endif
-}
-
-void SpriteController::ensureSurfaceComposerClient() {
-#ifdef HAVE_ANDROID_OS
- if (mSurfaceComposerClient == NULL) {
- mSurfaceComposerClient = new SurfaceComposerClient();
- }
-#endif
-}
-
-#ifdef HAVE_ANDROID_OS
-sp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height) {
- ensureSurfaceComposerClient();
-
- sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
- String8("Sprite"), width, height, PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eHidden);
- if (surfaceControl == NULL || !surfaceControl->isValid()) {
- ALOGE("Error creating sprite surface.");
- return NULL;
- }
- return surfaceControl;
-}
-#endif
-
-
-// --- SpriteController::SpriteImpl ---
-
-SpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) :
- mController(controller) {
-}
-
-SpriteController::SpriteImpl::~SpriteImpl() {
- AutoMutex _m(mController->mLock);
-
-#ifdef HAVE_ANDROID_OS
- // Let the controller take care of deleting the last reference to sprite
- // surfaces so that we do not block the caller on an IPC here.
- if (mLocked.state.surfaceControl != NULL) {
- mController->disposeSurfaceLocked(mLocked.state.surfaceControl);
- mLocked.state.surfaceControl.clear();
- }
-#endif
-}
-
-void SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) {
- AutoMutex _l(mController->mLock);
-
-#ifdef HAVE_ANDROID_OS
- uint32_t dirty;
- if (icon.isValid()) {
- icon.bitmap.copyTo(&mLocked.state.icon.bitmap, SkBitmap::kARGB_8888_Config);
-
- if (!mLocked.state.icon.isValid()
- || mLocked.state.icon.hotSpotX != icon.hotSpotX
- || mLocked.state.icon.hotSpotY != icon.hotSpotY) {
- mLocked.state.icon.hotSpotX = icon.hotSpotX;
- mLocked.state.icon.hotSpotY = icon.hotSpotY;
- dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
- } else {
- dirty = DIRTY_BITMAP;
- }
- } else if (mLocked.state.icon.isValid()) {
- mLocked.state.icon.bitmap.reset();
- dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
- } else {
- return; // setting to invalid icon and already invalid so nothing to do
- }
-
- invalidateLocked(dirty);
-#endif
-}
-
-void SpriteController::SpriteImpl::setVisible(bool visible) {
- AutoMutex _l(mController->mLock);
-
- if (mLocked.state.visible != visible) {
- mLocked.state.visible = visible;
- invalidateLocked(DIRTY_VISIBILITY);
- }
-}
-
-void SpriteController::SpriteImpl::setPosition(float x, float y) {
- AutoMutex _l(mController->mLock);
-
- if (mLocked.state.positionX != x || mLocked.state.positionY != y) {
- mLocked.state.positionX = x;
- mLocked.state.positionY = y;
- invalidateLocked(DIRTY_POSITION);
- }
-}
-
-void SpriteController::SpriteImpl::setLayer(int32_t layer) {
- AutoMutex _l(mController->mLock);
-
- if (mLocked.state.layer != layer) {
- mLocked.state.layer = layer;
- invalidateLocked(DIRTY_LAYER);
- }
-}
-
-void SpriteController::SpriteImpl::setAlpha(float alpha) {
- AutoMutex _l(mController->mLock);
-
- if (mLocked.state.alpha != alpha) {
- mLocked.state.alpha = alpha;
- invalidateLocked(DIRTY_ALPHA);
- }
-}
-
-void SpriteController::SpriteImpl::setTransformationMatrix(
- const SpriteTransformationMatrix& matrix) {
- AutoMutex _l(mController->mLock);
-
- if (mLocked.state.transformationMatrix != matrix) {
- mLocked.state.transformationMatrix = matrix;
- invalidateLocked(DIRTY_TRANSFORMATION_MATRIX);
- }
-}
-
-void SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
- bool wasDirty = mLocked.state.dirty;
- mLocked.state.dirty |= dirty;
-
- if (!wasDirty) {
- mController->invalidateSpriteLocked(this);
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/SpriteController.h b/widget/gonk/libui/SpriteController.h
deleted file mode 100644
index 4926095ec..000000000
--- a/widget/gonk/libui/SpriteController.h
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_SPRITES_H
-#define _UI_SPRITES_H
-
-#include <utils/RefBase.h>
-#include <utils/Looper.h>
-
-#ifdef HAVE_ANDROID_OS
-#include <gui/SurfaceComposerClient.h>
-#endif
-
-#include <SkBitmap.h>
-
-namespace android {
-
-/*
- * Transformation matrix for a sprite.
- */
-struct SpriteTransformationMatrix {
- inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { }
- inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) :
- dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { }
-
- float dsdx;
- float dtdx;
- float dsdy;
- float dtdy;
-
- inline bool operator== (const SpriteTransformationMatrix& other) {
- return dsdx == other.dsdx
- && dtdx == other.dtdx
- && dsdy == other.dsdy
- && dtdy == other.dtdy;
- }
-
- inline bool operator!= (const SpriteTransformationMatrix& other) {
- return !(*this == other);
- }
-};
-
-/*
- * Icon that a sprite displays, including its hotspot.
- */
-struct SpriteIcon {
- inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { }
-#ifdef HAVE_ANDROID_OS
- inline SpriteIcon(const SkBitmap& bitmap, float hotSpotX, float hotSpotY) :
- bitmap(bitmap), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
-
- SkBitmap bitmap;
-#endif
- float hotSpotX;
- float hotSpotY;
-
- inline SpriteIcon copy() const {
-#ifdef HAVE_ANDROID_OS
- SkBitmap bitmapCopy;
- bitmap.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config);
- return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY);
-#else
- return SpriteIcon();
-#endif
- }
-
- inline void reset() {
-#ifdef HAVE_ANDROID_OS
- bitmap.reset();
- hotSpotX = 0;
- hotSpotY = 0;
-#endif
- }
-
- inline bool isValid() const {
-#ifdef HAVE_ANDROID_OS
- return !bitmap.isNull() && !bitmap.empty();
-#else
- return false;
-#endif
- }
-};
-
-/*
- * A sprite is a simple graphical object that is displayed on-screen above other layers.
- * The basic sprite class is an interface.
- * The implementation is provided by the sprite controller.
- */
-class Sprite : public RefBase {
-protected:
- Sprite() { }
- virtual ~Sprite() { }
-
-public:
- enum {
- // The base layer for pointer sprites.
- BASE_LAYER_POINTER = 0, // reserve space for 1 pointer
-
- // The base layer for spot sprites.
- BASE_LAYER_SPOT = 1, // reserve space for MAX_POINTER_ID spots
- };
-
- /* Sets the bitmap that is drawn by the sprite.
- * The sprite retains a copy of the bitmap for subsequent rendering. */
- virtual void setIcon(const SpriteIcon& icon) = 0;
-
- inline void clearIcon() {
- setIcon(SpriteIcon());
- }
-
- /* Sets whether the sprite is visible. */
- virtual void setVisible(bool visible) = 0;
-
- /* Sets the sprite position on screen, relative to the sprite's hot spot. */
- virtual void setPosition(float x, float y) = 0;
-
- /* Sets the layer of the sprite, relative to the system sprite overlay layer.
- * Layer 0 is the overlay layer, > 0 appear above this layer. */
- virtual void setLayer(int32_t layer) = 0;
-
- /* Sets the sprite alpha blend ratio between 0.0 and 1.0. */
- virtual void setAlpha(float alpha) = 0;
-
- /* Sets the sprite transformation matrix. */
- virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 0;
-};
-
-/*
- * Displays sprites on the screen.
- *
- * This interface is used by PointerController and SpotController to draw pointers or
- * spot representations of fingers. It is not intended for general purpose use
- * by other components.
- *
- * All sprite position updates and rendering is performed asynchronously.
- *
- * Clients are responsible for animating sprites by periodically updating their properties.
- */
-class SpriteController : public MessageHandler {
-protected:
- virtual ~SpriteController();
-
-public:
- SpriteController(const sp<Looper>& looper, int32_t overlayLayer);
-
- /* Creates a new sprite, initially invisible. */
- sp<Sprite> createSprite();
-
- /* Opens or closes a transaction to perform a batch of sprite updates as part of
- * a single operation such as setPosition and setAlpha. It is not necessary to
- * open a transaction when updating a single property.
- * Calls to openTransaction() nest and must be matched by an equal number
- * of calls to closeTransaction(). */
- void openTransaction();
- void closeTransaction();
-
-private:
- enum {
- MSG_UPDATE_SPRITES,
- MSG_DISPOSE_SURFACES,
- };
-
- enum {
- DIRTY_BITMAP = 1 << 0,
- DIRTY_ALPHA = 1 << 1,
- DIRTY_POSITION = 1 << 2,
- DIRTY_TRANSFORMATION_MATRIX = 1 << 3,
- DIRTY_LAYER = 1 << 4,
- DIRTY_VISIBILITY = 1 << 5,
- DIRTY_HOTSPOT = 1 << 6,
- };
-
- /* Describes the state of a sprite.
- * This structure is designed so that it can be copied during updates so that
- * surfaces can be resized and redrawn without blocking the client by holding a lock
- * on the sprites for a long time.
- * Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */
- struct SpriteState {
- inline SpriteState() :
- dirty(0), visible(false),
- positionX(0), positionY(0), layer(0), alpha(1.0f),
- surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) {
- }
-
- uint32_t dirty;
-
- SpriteIcon icon;
- bool visible;
- float positionX;
- float positionY;
- int32_t layer;
- float alpha;
- SpriteTransformationMatrix transformationMatrix;
-
-#ifdef HAVE_ANDROID_OS
- sp<SurfaceControl> surfaceControl;
-#endif
- int32_t surfaceWidth;
- int32_t surfaceHeight;
- bool surfaceDrawn;
- bool surfaceVisible;
-
- inline bool wantSurfaceVisible() const {
- return visible && alpha > 0.0f && icon.isValid();
- }
- };
-
- /* Client interface for a sprite.
- * Requests acquire a lock on the controller, update local state and request the
- * controller to invalidate the sprite.
- * The real heavy lifting of creating, resizing and redrawing surfaces happens
- * asynchronously with no locks held except in short critical section to copy
- * the sprite state before the work and update the sprite surface control afterwards.
- */
- class SpriteImpl : public Sprite {
- protected:
- virtual ~SpriteImpl();
-
- public:
- SpriteImpl(const sp<SpriteController> controller);
-
- virtual void setIcon(const SpriteIcon& icon);
- virtual void setVisible(bool visible);
- virtual void setPosition(float x, float y);
- virtual void setLayer(int32_t layer);
- virtual void setAlpha(float alpha);
- virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix);
-
- inline const SpriteState& getStateLocked() const {
- return mLocked.state;
- }
-
- inline void resetDirtyLocked() {
- mLocked.state.dirty = 0;
- }
-
-#ifdef HAVE_ANDROID_OS
- inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl,
- int32_t width, int32_t height, bool drawn, bool visible) {
- mLocked.state.surfaceControl = surfaceControl;
- mLocked.state.surfaceWidth = width;
- mLocked.state.surfaceHeight = height;
- mLocked.state.surfaceDrawn = drawn;
- mLocked.state.surfaceVisible = visible;
- }
-#endif
-
- private:
- sp<SpriteController> mController;
-
- struct Locked {
- SpriteState state;
- } mLocked; // guarded by mController->mLock
-
- void invalidateLocked(uint32_t dirty);
- };
-
- /* Stores temporary information collected during the sprite update cycle. */
- struct SpriteUpdate {
- inline SpriteUpdate() : surfaceChanged(false) { }
- inline SpriteUpdate(const sp<SpriteImpl> sprite, const SpriteState& state) :
- sprite(sprite), state(state), surfaceChanged(false) {
- }
-
- sp<SpriteImpl> sprite;
- SpriteState state;
- bool surfaceChanged;
- };
-
- mutable Mutex mLock;
-
- sp<Looper> mLooper;
- const int32_t mOverlayLayer;
-#ifdef HAVE_ANDROID_OS
- sp<WeakMessageHandler> mHandler;
-
- sp<SurfaceComposerClient> mSurfaceComposerClient;
-#endif
-
- struct Locked {
- Vector<sp<SpriteImpl> > invalidatedSprites;
-#ifdef HAVE_ANDROID_OS
- Vector<sp<SurfaceControl> > disposedSurfaces;
-#endif
- uint32_t transactionNestingCount;
- bool deferredSpriteUpdate;
- } mLocked; // guarded by mLock
-
- void invalidateSpriteLocked(const sp<SpriteImpl>& sprite);
-#ifdef HAVE_ANDROID_OS
- void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl);
-
- void handleMessage(const Message& message);
-#endif
- void doUpdateSprites();
- void doDisposeSurfaces();
-
- void ensureSurfaceComposerClient();
-#ifdef HAVE_ANDROID_OS
- sp<SurfaceControl> obtainSurface(int32_t width, int32_t height);
-#endif
-};
-
-} // namespace android
-
-#endif // _UI_SPRITES_H
diff --git a/widget/gonk/libui/Tokenizer.cpp b/widget/gonk/libui/Tokenizer.cpp
deleted file mode 100644
index 2f585cb4e..000000000
--- a/widget/gonk/libui/Tokenizer.cpp
+++ /dev/null
@@ -1,175 +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.
- */
-
-#define LOG_TAG "Tokenizer"
-#include "cutils_log.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "Tokenizer.h"
-
-// Enables debug output for the tokenizer.
-#define DEBUG_TOKENIZER 0
-
-
-namespace android {
-
-static inline bool isDelimiter(char ch, const char* delimiters) {
- return strchr(delimiters, ch) != NULL;
-}
-
-Tokenizer::Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
- bool ownBuffer, size_t length) :
- mFilename(filename), mFileMap(fileMap),
- mBuffer(buffer), mOwnBuffer(ownBuffer), mLength(length),
- mCurrent(buffer), mLineNumber(1) {
-}
-
-Tokenizer::~Tokenizer() {
- if (mFileMap) {
- mFileMap->release();
- }
- if (mOwnBuffer) {
- delete[] mBuffer;
- }
-}
-
-status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) {
- *outTokenizer = NULL;
-
- int result = NO_ERROR;
- int fd = ::open(filename.string(), O_RDONLY);
- if (fd < 0) {
- result = -errno;
- ALOGE("Error opening file '%s', %s.", filename.string(), strerror(errno));
- } else {
- struct stat stat;
- if (fstat(fd, &stat)) {
- result = -errno;
- ALOGE("Error getting size of file '%s', %s.", filename.string(), strerror(errno));
- } else {
- size_t length = size_t(stat.st_size);
-
- FileMap* fileMap = new FileMap();
- bool ownBuffer = false;
- char* buffer;
- if (fileMap->create(NULL, fd, 0, length, true)) {
- fileMap->advise(FileMap::SEQUENTIAL);
- buffer = static_cast<char*>(fileMap->getDataPtr());
- } else {
- fileMap->release();
- fileMap = NULL;
-
- // Fall back to reading into a buffer since we can't mmap files in sysfs.
- // The length we obtained from stat is wrong too (it will always be 4096)
- // so we must trust that read will read the entire file.
- buffer = new char[length];
- ownBuffer = true;
- ssize_t nrd = read(fd, buffer, length);
- if (nrd < 0) {
- result = -errno;
- ALOGE("Error reading file '%s', %s.", filename.string(), strerror(errno));
- delete[] buffer;
- buffer = NULL;
- } else {
- length = size_t(nrd);
- }
- }
-
- if (!result) {
- *outTokenizer = new Tokenizer(filename, fileMap, buffer, ownBuffer, length);
- }
- }
- close(fd);
- }
- return result;
-}
-
-status_t Tokenizer::fromContents(const String8& filename,
- const char* contents, Tokenizer** outTokenizer) {
- *outTokenizer = new Tokenizer(filename, NULL,
- const_cast<char*>(contents), false, strlen(contents));
- return OK;
-}
-
-String8 Tokenizer::getLocation() const {
- String8 result;
- result.appendFormat("%s:%d", mFilename.string(), mLineNumber);
- return result;
-}
-
-String8 Tokenizer::peekRemainderOfLine() const {
- const char* end = getEnd();
- const char* eol = mCurrent;
- while (eol != end) {
- char ch = *eol;
- if (ch == '\n') {
- break;
- }
- eol += 1;
- }
- return String8(mCurrent, eol - mCurrent);
-}
-
-String8 Tokenizer::nextToken(const char* delimiters) {
-#if DEBUG_TOKENIZER
- ALOGD("nextToken");
-#endif
- const char* end = getEnd();
- const char* tokenStart = mCurrent;
- while (mCurrent != end) {
- char ch = *mCurrent;
- if (ch == '\n' || isDelimiter(ch, delimiters)) {
- break;
- }
- mCurrent += 1;
- }
- return String8(tokenStart, mCurrent - tokenStart);
-}
-
-void Tokenizer::nextLine() {
-#if DEBUG_TOKENIZER
- ALOGD("nextLine");
-#endif
- const char* end = getEnd();
- while (mCurrent != end) {
- char ch = *(mCurrent++);
- if (ch == '\n') {
- mLineNumber += 1;
- break;
- }
- }
-}
-
-void Tokenizer::skipDelimiters(const char* delimiters) {
-#if DEBUG_TOKENIZER
- ALOGD("skipDelimiters");
-#endif
- const char* end = getEnd();
- while (mCurrent != end) {
- char ch = *mCurrent;
- if (ch == '\n' || !isDelimiter(ch, delimiters)) {
- break;
- }
- mCurrent += 1;
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/Tokenizer.h b/widget/gonk/libui/Tokenizer.h
deleted file mode 100644
index bb25f374c..000000000
--- a/widget/gonk/libui/Tokenizer.h
+++ /dev/null
@@ -1,136 +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 _UTILS_TOKENIZER_H
-#define _UTILS_TOKENIZER_H
-
-#include <assert.h>
-#include <utils/Errors.h>
-#include <utils/FileMap.h>
-#include <utils/String8.h>
-
-namespace android {
-
-/**
- * A simple tokenizer for loading and parsing ASCII text files line by line.
- */
-class Tokenizer {
- Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
- bool ownBuffer, size_t length);
-
-public:
- ~Tokenizer();
-
- /**
- * Opens a file and maps it into memory.
- *
- * Returns NO_ERROR and a tokenizer for the file, if successful.
- * Otherwise returns an error and sets outTokenizer to NULL.
- */
- static status_t open(const String8& filename, Tokenizer** outTokenizer);
-
- /**
- * Prepares to tokenize the contents of a string.
- *
- * Returns NO_ERROR and a tokenizer for the string, if successful.
- * Otherwise returns an error and sets outTokenizer to NULL.
- */
- static status_t fromContents(const String8& filename,
- const char* contents, Tokenizer** outTokenizer);
-
- /**
- * Returns true if at the end of the file.
- */
- inline bool isEof() const { return mCurrent == getEnd(); }
-
- /**
- * Returns true if at the end of the line or end of the file.
- */
- inline bool isEol() const { return isEof() || *mCurrent == '\n'; }
-
- /**
- * Gets the name of the file.
- */
- inline String8 getFilename() const { return mFilename; }
-
- /**
- * Gets a 1-based line number index for the current position.
- */
- inline int32_t getLineNumber() const { return mLineNumber; }
-
- /**
- * Formats a location string consisting of the filename and current line number.
- * Returns a string like "MyFile.txt:33".
- */
- String8 getLocation() const;
-
- /**
- * Gets the character at the current position.
- * Returns null at end of file.
- */
- inline char peekChar() const { return isEof() ? '\0' : *mCurrent; }
-
- /**
- * Gets the remainder of the current line as a string, excluding the newline character.
- */
- String8 peekRemainderOfLine() const;
-
- /**
- * Gets the character at the current position and advances past it.
- * Returns null at end of file.
- */
- inline char nextChar() { return isEof() ? '\0' : *(mCurrent++); }
-
- /**
- * Gets the next token on this line stopping at the specified delimiters
- * or the end of the line whichever comes first and advances past it.
- * Also stops at embedded nulls.
- * Returns the token or an empty string if the current character is a delimiter
- * or is at the end of the line.
- */
- String8 nextToken(const char* delimiters);
-
- /**
- * Advances to the next line.
- * Does nothing if already at the end of the file.
- */
- void nextLine();
-
- /**
- * Skips over the specified delimiters in the line.
- * Also skips embedded nulls.
- */
- void skipDelimiters(const char* delimiters);
-
-private:
- Tokenizer(const Tokenizer& other); // not copyable
-
- String8 mFilename;
- FileMap* mFileMap;
- char* mBuffer;
- bool mOwnBuffer;
- size_t mLength;
-
- const char* mCurrent;
- int32_t mLineNumber;
-
- inline const char* getEnd() const { return mBuffer + mLength; }
-
-};
-
-} // namespace android
-
-#endif // _UTILS_TOKENIZER_H
diff --git a/widget/gonk/libui/Trace.h b/widget/gonk/libui/Trace.h
deleted file mode 100644
index 24fbfb602..000000000
--- a/widget/gonk/libui/Trace.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_TRACE_H
-#define ANDROID_TRACE_H
-
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cutils/compiler.h>
-#include <utils/threads.h>
-#include "cutils_trace.h"
-
-// See <cutils/trace.h> for more ATRACE_* macros.
-
-// ATRACE_NAME traces the beginning and end of the current scope. To trace
-// the correct start and end times this macro should be declared first in the
-// scope body.
-#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)
-// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
-#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
-
-namespace android {
-
-class ScopedTrace {
-public:
-inline ScopedTrace(uint64_t tag, const char* name)
- : mTag(tag) {
-#ifdef HAVE_ANDROID_OS
- atrace_begin(mTag,name);
-#endif
-}
-
-inline ~ScopedTrace() {
-#ifdef HAVE_ANDROID_OS
- atrace_end(mTag);
-#endif
-}
-
-private:
- uint64_t mTag;
-};
-
-}; // namespace android
-
-#endif // ANDROID_TRACE_H
diff --git a/widget/gonk/libui/VelocityControl.cpp b/widget/gonk/libui/VelocityControl.cpp
deleted file mode 100644
index 31365a220..000000000
--- a/widget/gonk/libui/VelocityControl.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "VelocityControl"
-//#define LOG_NDEBUG 0
-
-// Log debug messages about acceleration.
-#define DEBUG_ACCELERATION 0
-
-#include <math.h>
-#include <limits.h>
-
-#include "VelocityControl.h"
-#include <utils/BitSet.h>
-#include <utils/Timers.h>
-
-namespace android {
-
-// --- VelocityControl ---
-
-const nsecs_t VelocityControl::STOP_TIME;
-
-VelocityControl::VelocityControl() {
- reset();
-}
-
-void VelocityControl::setParameters(const VelocityControlParameters& parameters) {
- mParameters = parameters;
- reset();
-}
-
-void VelocityControl::reset() {
- mLastMovementTime = LLONG_MIN;
- mRawPosition.x = 0;
- mRawPosition.y = 0;
- mVelocityTracker.clear();
-}
-
-void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
- if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
- if (eventTime >= mLastMovementTime + STOP_TIME) {
-#if DEBUG_ACCELERATION
- ALOGD("VelocityControl: stopped, last movement was %0.3fms ago",
- (eventTime - mLastMovementTime) * 0.000001f);
-#endif
- reset();
- }
-
- mLastMovementTime = eventTime;
- if (deltaX) {
- mRawPosition.x += *deltaX;
- }
- if (deltaY) {
- mRawPosition.y += *deltaY;
- }
- mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), &mRawPosition);
-
- float vx, vy;
- float scale = mParameters.scale;
- if (mVelocityTracker.getVelocity(0, &vx, &vy)) {
- float speed = hypotf(vx, vy) * scale;
- if (speed >= mParameters.highThreshold) {
- // Apply full acceleration above the high speed threshold.
- scale *= mParameters.acceleration;
- } else if (speed > mParameters.lowThreshold) {
- // Linearly interpolate the acceleration to apply between the low and high
- // speed thresholds.
- scale *= 1 + (speed - mParameters.lowThreshold)
- / (mParameters.highThreshold - mParameters.lowThreshold)
- * (mParameters.acceleration - 1);
- }
-
-#if DEBUG_ACCELERATION
- ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
- "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
- mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
- mParameters.acceleration,
- vx, vy, speed, scale / mParameters.scale);
-#endif
- } else {
-#if DEBUG_ACCELERATION
- ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
- mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
- mParameters.acceleration);
-#endif
- }
-
- if (deltaX) {
- *deltaX *= scale;
- }
- if (deltaY) {
- *deltaY *= scale;
- }
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/VelocityControl.h b/widget/gonk/libui/VelocityControl.h
deleted file mode 100644
index 8a2c695d6..000000000
--- a/widget/gonk/libui/VelocityControl.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _ANDROIDFW_VELOCITY_CONTROL_H
-#define _ANDROIDFW_VELOCITY_CONTROL_H
-
-#include "Input.h"
-#include "VelocityTracker.h"
-#include <utils/Timers.h>
-
-namespace android {
-
-/*
- * Specifies parameters that govern pointer or wheel acceleration.
- */
-struct VelocityControlParameters {
- // A scale factor that is multiplied with the raw velocity deltas
- // prior to applying any other velocity control factors. The scale
- // factor should be used to adapt the input device resolution
- // (eg. counts per inch) to the output device resolution (eg. pixels per inch).
- //
- // Must be a positive value.
- // Default is 1.0 (no scaling).
- float scale;
-
- // The scaled speed at which acceleration begins to be applied.
- // This value establishes the upper bound of a low speed regime for
- // small precise motions that are performed without any acceleration.
- //
- // Must be a non-negative value.
- // Default is 0.0 (no low threshold).
- float lowThreshold;
-
- // The scaled speed at which maximum acceleration is applied.
- // The difference between highThreshold and lowThreshold controls
- // the range of speeds over which the acceleration factor is interpolated.
- // The wider the range, the smoother the acceleration.
- //
- // Must be a non-negative value greater than or equal to lowThreshold.
- // Default is 0.0 (no high threshold).
- float highThreshold;
-
- // The acceleration factor.
- // When the speed is above the low speed threshold, the velocity will scaled
- // by an interpolated value between 1.0 and this amount.
- //
- // Must be a positive greater than or equal to 1.0.
- // Default is 1.0 (no acceleration).
- float acceleration;
-
- VelocityControlParameters() :
- scale(1.0f), lowThreshold(0.0f), highThreshold(0.0f), acceleration(1.0f) {
- }
-
- VelocityControlParameters(float scale, float lowThreshold,
- float highThreshold, float acceleration) :
- scale(scale), lowThreshold(lowThreshold),
- highThreshold(highThreshold), acceleration(acceleration) {
- }
-};
-
-/*
- * Implements mouse pointer and wheel speed control and acceleration.
- */
-class VelocityControl {
-public:
- VelocityControl();
-
- /* Sets the various parameters. */
- void setParameters(const VelocityControlParameters& parameters);
-
- /* Resets the current movement counters to zero.
- * This has the effect of nullifying any acceleration. */
- void reset();
-
- /* Translates a raw movement delta into an appropriately
- * scaled / accelerated delta based on the current velocity. */
- void move(nsecs_t eventTime, float* deltaX, float* deltaY);
-
-private:
- // If no movements are received within this amount of time,
- // we assume the movement has stopped and reset the movement counters.
- static const nsecs_t STOP_TIME = 500 * 1000000; // 500 ms
-
- VelocityControlParameters mParameters;
-
- nsecs_t mLastMovementTime;
- VelocityTracker::Position mRawPosition;
- VelocityTracker mVelocityTracker;
-};
-
-} // namespace android
-
-#endif // _ANDROIDFW_VELOCITY_CONTROL_H
diff --git a/widget/gonk/libui/VelocityTracker.cpp b/widget/gonk/libui/VelocityTracker.cpp
deleted file mode 100644
index 11a8bf7fc..000000000
--- a/widget/gonk/libui/VelocityTracker.cpp
+++ /dev/null
@@ -1,929 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "VelocityTracker"
-//#define LOG_NDEBUG 0
-#include "cutils_log.h"
-
-// Log debug messages about velocity tracking.
-#define DEBUG_VELOCITY 0
-
-// Log debug messages about the progress of the algorithm itself.
-#define DEBUG_STRATEGY 0
-
-#include <math.h>
-#include <limits.h>
-
-#include "VelocityTracker.h"
-#include <utils/BitSet.h>
-#include <utils/String8.h>
-#include <utils/Timers.h>
-
-#include <cutils/properties.h>
-
-namespace android {
-
-// Nanoseconds per milliseconds.
-static const nsecs_t NANOS_PER_MS = 1000000;
-
-// Threshold for determining that a pointer has stopped moving.
-// Some input devices do not send ACTION_MOVE events in the case where a pointer has
-// stopped. We need to detect this case so that we can accurately predict the
-// velocity after the pointer starts moving again.
-static const nsecs_t ASSUME_POINTER_STOPPED_TIME = 40 * NANOS_PER_MS;
-
-
-static float vectorDot(const float* a, const float* b, uint32_t m) {
- float r = 0;
- while (m--) {
- r += *(a++) * *(b++);
- }
- return r;
-}
-
-static float vectorNorm(const float* a, uint32_t m) {
- float r = 0;
- while (m--) {
- float t = *(a++);
- r += t * t;
- }
- return sqrtf(r);
-}
-
-#if DEBUG_STRATEGY || DEBUG_VELOCITY
-static String8 vectorToString(const float* a, uint32_t m) {
- String8 str;
- str.append("[");
- while (m--) {
- str.appendFormat(" %f", *(a++));
- if (m) {
- str.append(",");
- }
- }
- str.append(" ]");
- return str;
-}
-
-static String8 matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) {
- String8 str;
- str.append("[");
- for (size_t i = 0; i < m; i++) {
- if (i) {
- str.append(",");
- }
- str.append(" [");
- for (size_t j = 0; j < n; j++) {
- if (j) {
- str.append(",");
- }
- str.appendFormat(" %f", a[rowMajor ? i * n + j : j * m + i]);
- }
- str.append(" ]");
- }
- str.append(" ]");
- return str;
-}
-#endif
-
-
-// --- VelocityTracker ---
-
-// The default velocity tracker strategy.
-// Although other strategies are available for testing and comparison purposes,
-// this is the strategy that applications will actually use. Be very careful
-// when adjusting the default strategy because it can dramatically affect
-// (often in a bad way) the user experience.
-const char* VelocityTracker::DEFAULT_STRATEGY = "lsq2";
-
-VelocityTracker::VelocityTracker(const char* strategy) :
- mLastEventTime(0), mCurrentPointerIdBits(0), mActivePointerId(-1) {
- char value[PROPERTY_VALUE_MAX];
-
- // Allow the default strategy to be overridden using a system property for debugging.
- if (!strategy) {
- int length = property_get("debug.velocitytracker.strategy", value, NULL);
- if (length > 0) {
- strategy = value;
- } else {
- strategy = DEFAULT_STRATEGY;
- }
- }
-
- // Configure the strategy.
- if (!configureStrategy(strategy)) {
- ALOGD("Unrecognized velocity tracker strategy name '%s'.", strategy);
- if (!configureStrategy(DEFAULT_STRATEGY)) {
- LOG_ALWAYS_FATAL("Could not create the default velocity tracker strategy '%s'!",
- strategy);
- }
- }
-}
-
-VelocityTracker::~VelocityTracker() {
- delete mStrategy;
-}
-
-bool VelocityTracker::configureStrategy(const char* strategy) {
- mStrategy = createStrategy(strategy);
- return mStrategy != NULL;
-}
-
-VelocityTrackerStrategy* VelocityTracker::createStrategy(const char* strategy) {
- if (!strcmp("lsq1", strategy)) {
- // 1st order least squares. Quality: POOR.
- // Frequently underfits the touch data especially when the finger accelerates
- // or changes direction. Often underestimates velocity. The direction
- // is overly influenced by historical touch points.
- return new LeastSquaresVelocityTrackerStrategy(1);
- }
- if (!strcmp("lsq2", strategy)) {
- // 2nd order least squares. Quality: VERY GOOD.
- // Pretty much ideal, but can be confused by certain kinds of touch data,
- // particularly if the panel has a tendency to generate delayed,
- // duplicate or jittery touch coordinates when the finger is released.
- return new LeastSquaresVelocityTrackerStrategy(2);
- }
- if (!strcmp("lsq3", strategy)) {
- // 3rd order least squares. Quality: UNUSABLE.
- // Frequently overfits the touch data yielding wildly divergent estimates
- // of the velocity when the finger is released.
- return new LeastSquaresVelocityTrackerStrategy(3);
- }
- if (!strcmp("wlsq2-delta", strategy)) {
- // 2nd order weighted least squares, delta weighting. Quality: EXPERIMENTAL
- return new LeastSquaresVelocityTrackerStrategy(2,
- LeastSquaresVelocityTrackerStrategy::WEIGHTING_DELTA);
- }
- if (!strcmp("wlsq2-central", strategy)) {
- // 2nd order weighted least squares, central weighting. Quality: EXPERIMENTAL
- return new LeastSquaresVelocityTrackerStrategy(2,
- LeastSquaresVelocityTrackerStrategy::WEIGHTING_CENTRAL);
- }
- if (!strcmp("wlsq2-recent", strategy)) {
- // 2nd order weighted least squares, recent weighting. Quality: EXPERIMENTAL
- return new LeastSquaresVelocityTrackerStrategy(2,
- LeastSquaresVelocityTrackerStrategy::WEIGHTING_RECENT);
- }
- if (!strcmp("int1", strategy)) {
- // 1st order integrating filter. Quality: GOOD.
- // Not as good as 'lsq2' because it cannot estimate acceleration but it is
- // more tolerant of errors. Like 'lsq1', this strategy tends to underestimate
- // the velocity of a fling but this strategy tends to respond to changes in
- // direction more quickly and accurately.
- return new IntegratingVelocityTrackerStrategy(1);
- }
- if (!strcmp("int2", strategy)) {
- // 2nd order integrating filter. Quality: EXPERIMENTAL.
- // For comparison purposes only. Unlike 'int1' this strategy can compensate
- // for acceleration but it typically overestimates the effect.
- return new IntegratingVelocityTrackerStrategy(2);
- }
- if (!strcmp("legacy", strategy)) {
- // Legacy velocity tracker algorithm. Quality: POOR.
- // For comparison purposes only. This algorithm is strongly influenced by
- // old data points, consistently underestimates velocity and takes a very long
- // time to adjust to changes in direction.
- return new LegacyVelocityTrackerStrategy();
- }
- return NULL;
-}
-
-void VelocityTracker::clear() {
- mCurrentPointerIdBits.clear();
- mActivePointerId = -1;
-
- mStrategy->clear();
-}
-
-void VelocityTracker::clearPointers(BitSet32 idBits) {
- BitSet32 remainingIdBits(mCurrentPointerIdBits.value & ~idBits.value);
- mCurrentPointerIdBits = remainingIdBits;
-
- if (mActivePointerId >= 0 && idBits.hasBit(mActivePointerId)) {
- mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1;
- }
-
- mStrategy->clearPointers(idBits);
-}
-
-void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) {
- while (idBits.count() > MAX_POINTERS) {
- idBits.clearLastMarkedBit();
- }
-
- if ((mCurrentPointerIdBits.value & idBits.value)
- && eventTime >= mLastEventTime + ASSUME_POINTER_STOPPED_TIME) {
-#if DEBUG_VELOCITY
- ALOGD("VelocityTracker: stopped for %0.3f ms, clearing state.",
- (eventTime - mLastEventTime) * 0.000001f);
-#endif
- // We have not received any movements for too long. Assume that all pointers
- // have stopped.
- mStrategy->clear();
- }
- mLastEventTime = eventTime;
-
- mCurrentPointerIdBits = idBits;
- if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) {
- mActivePointerId = idBits.isEmpty() ? -1 : idBits.firstMarkedBit();
- }
-
- mStrategy->addMovement(eventTime, idBits, positions);
-
-#if DEBUG_VELOCITY
- ALOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d",
- eventTime, idBits.value, mActivePointerId);
- for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) {
- uint32_t id = iterBits.firstMarkedBit();
- uint32_t index = idBits.getIndexOfBit(id);
- iterBits.clearBit(id);
- Estimator estimator;
- getEstimator(id, &estimator);
- ALOGD(" %d: position (%0.3f, %0.3f), "
- "estimator (degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f)",
- id, positions[index].x, positions[index].y,
- int(estimator.degree),
- vectorToString(estimator.xCoeff, estimator.degree + 1).string(),
- vectorToString(estimator.yCoeff, estimator.degree + 1).string(),
- estimator.confidence);
- }
-#endif
-}
-
-void VelocityTracker::addMovement(const MotionEvent* event) {
- int32_t actionMasked = event->getActionMasked();
-
- switch (actionMasked) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_HOVER_ENTER:
- // Clear all pointers on down before adding the new movement.
- clear();
- break;
- case AMOTION_EVENT_ACTION_POINTER_DOWN: {
- // Start a new movement trace for a pointer that just went down.
- // We do this on down instead of on up because the client may want to query the
- // final velocity for a pointer that just went up.
- BitSet32 downIdBits;
- downIdBits.markBit(event->getPointerId(event->getActionIndex()));
- clearPointers(downIdBits);
- break;
- }
- case AMOTION_EVENT_ACTION_MOVE:
- case AMOTION_EVENT_ACTION_HOVER_MOVE:
- break;
- default:
- // Ignore all other actions because they do not convey any new information about
- // pointer movement. We also want to preserve the last known velocity of the pointers.
- // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position
- // of the pointers that went up. ACTION_POINTER_UP does include the new position of
- // pointers that remained down but we will also receive an ACTION_MOVE with this
- // information if any of them actually moved. Since we don't know how many pointers
- // will be going up at once it makes sense to just wait for the following ACTION_MOVE
- // before adding the movement.
- return;
- }
-
- size_t pointerCount = event->getPointerCount();
- if (pointerCount > MAX_POINTERS) {
- pointerCount = MAX_POINTERS;
- }
-
- BitSet32 idBits;
- for (size_t i = 0; i < pointerCount; i++) {
- idBits.markBit(event->getPointerId(i));
- }
-
- uint32_t pointerIndex[MAX_POINTERS];
- for (size_t i = 0; i < pointerCount; i++) {
- pointerIndex[i] = idBits.getIndexOfBit(event->getPointerId(i));
- }
-
- nsecs_t eventTime;
- Position positions[pointerCount];
-
- size_t historySize = event->getHistorySize();
- for (size_t h = 0; h < historySize; h++) {
- eventTime = event->getHistoricalEventTime(h);
- for (size_t i = 0; i < pointerCount; i++) {
- uint32_t index = pointerIndex[i];
- positions[index].x = event->getHistoricalX(i, h);
- positions[index].y = event->getHistoricalY(i, h);
- }
- addMovement(eventTime, idBits, positions);
- }
-
- eventTime = event->getEventTime();
- for (size_t i = 0; i < pointerCount; i++) {
- uint32_t index = pointerIndex[i];
- positions[index].x = event->getX(i);
- positions[index].y = event->getY(i);
- }
- addMovement(eventTime, idBits, positions);
-}
-
-bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
- Estimator estimator;
- if (getEstimator(id, &estimator) && estimator.degree >= 1) {
- *outVx = estimator.xCoeff[1];
- *outVy = estimator.yCoeff[1];
- return true;
- }
- *outVx = 0;
- *outVy = 0;
- return false;
-}
-
-bool VelocityTracker::getEstimator(uint32_t id, Estimator* outEstimator) const {
- return mStrategy->getEstimator(id, outEstimator);
-}
-
-
-// --- LeastSquaresVelocityTrackerStrategy ---
-
-const nsecs_t LeastSquaresVelocityTrackerStrategy::HORIZON;
-const uint32_t LeastSquaresVelocityTrackerStrategy::HISTORY_SIZE;
-
-LeastSquaresVelocityTrackerStrategy::LeastSquaresVelocityTrackerStrategy(
- uint32_t degree, Weighting weighting) :
- mDegree(degree), mWeighting(weighting) {
- clear();
-}
-
-LeastSquaresVelocityTrackerStrategy::~LeastSquaresVelocityTrackerStrategy() {
-}
-
-void LeastSquaresVelocityTrackerStrategy::clear() {
- mIndex = 0;
- mMovements[0].idBits.clear();
-}
-
-void LeastSquaresVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
- BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
- mMovements[mIndex].idBits = remainingIdBits;
-}
-
-void LeastSquaresVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
- const VelocityTracker::Position* positions) {
- if (++mIndex == HISTORY_SIZE) {
- mIndex = 0;
- }
-
- Movement& movement = mMovements[mIndex];
- movement.eventTime = eventTime;
- movement.idBits = idBits;
- uint32_t count = idBits.count();
- for (uint32_t i = 0; i < count; i++) {
- movement.positions[i] = positions[i];
- }
-}
-
-/**
- * Solves a linear least squares problem to obtain a N degree polynomial that fits
- * the specified input data as nearly as possible.
- *
- * Returns true if a solution is found, false otherwise.
- *
- * The input consists of two vectors of data points X and Y with indices 0..m-1
- * along with a weight vector W of the same size.
- *
- * The output is a vector B with indices 0..n that describes a polynomial
- * that fits the data, such the sum of W[i] * W[i] * abs(Y[i] - (B[0] + B[1] X[i]
- * + B[2] X[i]^2 ... B[n] X[i]^n)) for all i between 0 and m-1 is minimized.
- *
- * Accordingly, the weight vector W should be initialized by the caller with the
- * reciprocal square root of the variance of the error in each input data point.
- * In other words, an ideal choice for W would be W[i] = 1 / var(Y[i]) = 1 / stddev(Y[i]).
- * The weights express the relative importance of each data point. If the weights are
- * all 1, then the data points are considered to be of equal importance when fitting
- * the polynomial. It is a good idea to choose weights that diminish the importance
- * of data points that may have higher than usual error margins.
- *
- * Errors among data points are assumed to be independent. W is represented here
- * as a vector although in the literature it is typically taken to be a diagonal matrix.
- *
- * That is to say, the function that generated the input data can be approximated
- * by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n.
- *
- * The coefficient of determination (R^2) is also returned to describe the goodness
- * of fit of the model for the given data. It is a value between 0 and 1, where 1
- * indicates perfect correspondence.
- *
- * This function first expands the X vector to a m by n matrix A such that
- * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n, then
- * multiplies it by w[i]./
- *
- * Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q
- * and an m by n upper triangular matrix R. Because R is upper triangular (lower
- * part is all zeroes), we can simplify the decomposition into an m by n matrix
- * Q1 and a n by n matrix R1 such that A = Q1 R1.
- *
- * Finally we solve the system of linear equations given by R1 B = (Qtranspose W Y)
- * to find B.
- *
- * For efficiency, we lay out A and Q column-wise in memory because we frequently
- * operate on the column vectors. Conversely, we lay out R row-wise.
- *
- * http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares
- * http://en.wikipedia.org/wiki/Gram-Schmidt
- */
-static bool solveLeastSquares(const float* x, const float* y,
- const float* w, uint32_t m, uint32_t n, float* outB, float* outDet) {
-#if DEBUG_STRATEGY
- ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n),
- vectorToString(x, m).string(), vectorToString(y, m).string(),
- vectorToString(w, m).string());
-#endif
-
- // Expand the X vector to a matrix A, pre-multiplied by the weights.
- float a[n][m]; // column-major order
- for (uint32_t h = 0; h < m; h++) {
- a[0][h] = w[h];
- for (uint32_t i = 1; i < n; i++) {
- a[i][h] = a[i - 1][h] * x[h];
- }
- }
-#if DEBUG_STRATEGY
- ALOGD(" - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).string());
-#endif
-
- // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
- float q[n][m]; // orthonormal basis, column-major order
- float r[n][n]; // upper triangular matrix, row-major order
- for (uint32_t j = 0; j < n; j++) {
- for (uint32_t h = 0; h < m; h++) {
- q[j][h] = a[j][h];
- }
- for (uint32_t i = 0; i < j; i++) {
- float dot = vectorDot(&q[j][0], &q[i][0], m);
- for (uint32_t h = 0; h < m; h++) {
- q[j][h] -= dot * q[i][h];
- }
- }
-
- float norm = vectorNorm(&q[j][0], m);
- if (norm < 0.000001f) {
- // vectors are linearly dependent or zero so no solution
-#if DEBUG_STRATEGY
- ALOGD(" - no solution, norm=%f", norm);
-#endif
- return false;
- }
-
- float invNorm = 1.0f / norm;
- for (uint32_t h = 0; h < m; h++) {
- q[j][h] *= invNorm;
- }
- for (uint32_t i = 0; i < n; i++) {
- r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m);
- }
- }
-#if DEBUG_STRATEGY
- ALOGD(" - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).string());
- ALOGD(" - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).string());
-
- // calculate QR, if we factored A correctly then QR should equal A
- float qr[n][m];
- for (uint32_t h = 0; h < m; h++) {
- for (uint32_t i = 0; i < n; i++) {
- qr[i][h] = 0;
- for (uint32_t j = 0; j < n; j++) {
- qr[i][h] += q[j][h] * r[j][i];
- }
- }
- }
- ALOGD(" - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).string());
-#endif
-
- // Solve R B = Qt W Y to find B. This is easy because R is upper triangular.
- // We just work from bottom-right to top-left calculating B's coefficients.
- float wy[m];
- for (uint32_t h = 0; h < m; h++) {
- wy[h] = y[h] * w[h];
- }
- for (uint32_t i = n; i-- != 0; ) {
- outB[i] = vectorDot(&q[i][0], wy, m);
- for (uint32_t j = n - 1; j > i; j--) {
- outB[i] -= r[i][j] * outB[j];
- }
- outB[i] /= r[i][i];
- }
-#if DEBUG_STRATEGY
- ALOGD(" - b=%s", vectorToString(outB, n).string());
-#endif
-
- // Calculate the coefficient of determination as 1 - (SSerr / SStot) where
- // SSerr is the residual sum of squares (variance of the error),
- // and SStot is the total sum of squares (variance of the data) where each
- // has been weighted.
- float ymean = 0;
- for (uint32_t h = 0; h < m; h++) {
- ymean += y[h];
- }
- ymean /= m;
-
- float sserr = 0;
- float sstot = 0;
- for (uint32_t h = 0; h < m; h++) {
- float err = y[h] - outB[0];
- float term = 1;
- for (uint32_t i = 1; i < n; i++) {
- term *= x[h];
- err -= term * outB[i];
- }
- sserr += w[h] * w[h] * err * err;
- float var = y[h] - ymean;
- sstot += w[h] * w[h] * var * var;
- }
- *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
-#if DEBUG_STRATEGY
- ALOGD(" - sserr=%f", sserr);
- ALOGD(" - sstot=%f", sstot);
- ALOGD(" - det=%f", *outDet);
-#endif
- return true;
-}
-
-bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
- VelocityTracker::Estimator* outEstimator) const {
- outEstimator->clear();
-
- // Iterate over movement samples in reverse time order and collect samples.
- float x[HISTORY_SIZE];
- float y[HISTORY_SIZE];
- float w[HISTORY_SIZE];
- float time[HISTORY_SIZE];
- uint32_t m = 0;
- uint32_t index = mIndex;
- const Movement& newestMovement = mMovements[mIndex];
- do {
- const Movement& movement = mMovements[index];
- if (!movement.idBits.hasBit(id)) {
- break;
- }
-
- nsecs_t age = newestMovement.eventTime - movement.eventTime;
- if (age > HORIZON) {
- break;
- }
-
- const VelocityTracker::Position& position = movement.getPosition(id);
- x[m] = position.x;
- y[m] = position.y;
- w[m] = chooseWeight(index);
- time[m] = -age * 0.000000001f;
- index = (index == 0 ? HISTORY_SIZE : index) - 1;
- } while (++m < HISTORY_SIZE);
-
- if (m == 0) {
- return false; // no data
- }
-
- // Calculate a least squares polynomial fit.
- uint32_t degree = mDegree;
- if (degree > m - 1) {
- degree = m - 1;
- }
- if (degree >= 1) {
- float xdet, ydet;
- uint32_t n = degree + 1;
- if (solveLeastSquares(time, x, w, m, n, outEstimator->xCoeff, &xdet)
- && solveLeastSquares(time, y, w, m, n, outEstimator->yCoeff, &ydet)) {
- outEstimator->time = newestMovement.eventTime;
- outEstimator->degree = degree;
- outEstimator->confidence = xdet * ydet;
-#if DEBUG_STRATEGY
- ALOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f",
- int(outEstimator->degree),
- vectorToString(outEstimator->xCoeff, n).string(),
- vectorToString(outEstimator->yCoeff, n).string(),
- outEstimator->confidence);
-#endif
- return true;
- }
- }
-
- // No velocity data available for this pointer, but we do have its current position.
- outEstimator->xCoeff[0] = x[0];
- outEstimator->yCoeff[0] = y[0];
- outEstimator->time = newestMovement.eventTime;
- outEstimator->degree = 0;
- outEstimator->confidence = 1;
- return true;
-}
-
-float LeastSquaresVelocityTrackerStrategy::chooseWeight(uint32_t index) const {
- switch (mWeighting) {
- case WEIGHTING_DELTA: {
- // Weight points based on how much time elapsed between them and the next
- // point so that points that "cover" a shorter time span are weighed less.
- // delta 0ms: 0.5
- // delta 10ms: 1.0
- if (index == mIndex) {
- return 1.0f;
- }
- uint32_t nextIndex = (index + 1) % HISTORY_SIZE;
- float deltaMillis = (mMovements[nextIndex].eventTime- mMovements[index].eventTime)
- * 0.000001f;
- if (deltaMillis < 0) {
- return 0.5f;
- }
- if (deltaMillis < 10) {
- return 0.5f + deltaMillis * 0.05;
- }
- return 1.0f;
- }
-
- case WEIGHTING_CENTRAL: {
- // Weight points based on their age, weighing very recent and very old points less.
- // age 0ms: 0.5
- // age 10ms: 1.0
- // age 50ms: 1.0
- // age 60ms: 0.5
- float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime)
- * 0.000001f;
- if (ageMillis < 0) {
- return 0.5f;
- }
- if (ageMillis < 10) {
- return 0.5f + ageMillis * 0.05;
- }
- if (ageMillis < 50) {
- return 1.0f;
- }
- if (ageMillis < 60) {
- return 0.5f + (60 - ageMillis) * 0.05;
- }
- return 0.5f;
- }
-
- case WEIGHTING_RECENT: {
- // Weight points based on their age, weighing older points less.
- // age 0ms: 1.0
- // age 50ms: 1.0
- // age 100ms: 0.5
- float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime)
- * 0.000001f;
- if (ageMillis < 50) {
- return 1.0f;
- }
- if (ageMillis < 100) {
- return 0.5f + (100 - ageMillis) * 0.01f;
- }
- return 0.5f;
- }
-
- case WEIGHTING_NONE:
- default:
- return 1.0f;
- }
-}
-
-
-// --- IntegratingVelocityTrackerStrategy ---
-
-IntegratingVelocityTrackerStrategy::IntegratingVelocityTrackerStrategy(uint32_t degree) :
- mDegree(degree) {
-}
-
-IntegratingVelocityTrackerStrategy::~IntegratingVelocityTrackerStrategy() {
-}
-
-void IntegratingVelocityTrackerStrategy::clear() {
- mPointerIdBits.clear();
-}
-
-void IntegratingVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
- mPointerIdBits.value &= ~idBits.value;
-}
-
-void IntegratingVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
- const VelocityTracker::Position* positions) {
- uint32_t index = 0;
- for (BitSet32 iterIdBits(idBits); !iterIdBits.isEmpty();) {
- uint32_t id = iterIdBits.clearFirstMarkedBit();
- State& state = mPointerState[id];
- const VelocityTracker::Position& position = positions[index++];
- if (mPointerIdBits.hasBit(id)) {
- updateState(state, eventTime, position.x, position.y);
- } else {
- initState(state, eventTime, position.x, position.y);
- }
- }
-
- mPointerIdBits = idBits;
-}
-
-bool IntegratingVelocityTrackerStrategy::getEstimator(uint32_t id,
- VelocityTracker::Estimator* outEstimator) const {
- outEstimator->clear();
-
- if (mPointerIdBits.hasBit(id)) {
- const State& state = mPointerState[id];
- populateEstimator(state, outEstimator);
- return true;
- }
-
- return false;
-}
-
-void IntegratingVelocityTrackerStrategy::initState(State& state,
- nsecs_t eventTime, float xpos, float ypos) const {
- state.updateTime = eventTime;
- state.degree = 0;
-
- state.xpos = xpos;
- state.xvel = 0;
- state.xaccel = 0;
- state.ypos = ypos;
- state.yvel = 0;
- state.yaccel = 0;
-}
-
-void IntegratingVelocityTrackerStrategy::updateState(State& state,
- nsecs_t eventTime, float xpos, float ypos) const {
- const nsecs_t MIN_TIME_DELTA = 2 * NANOS_PER_MS;
- const float FILTER_TIME_CONSTANT = 0.010f; // 10 milliseconds
-
- if (eventTime <= state.updateTime + MIN_TIME_DELTA) {
- return;
- }
-
- float dt = (eventTime - state.updateTime) * 0.000000001f;
- state.updateTime = eventTime;
-
- float xvel = (xpos - state.xpos) / dt;
- float yvel = (ypos - state.ypos) / dt;
- if (state.degree == 0) {
- state.xvel = xvel;
- state.yvel = yvel;
- state.degree = 1;
- } else {
- float alpha = dt / (FILTER_TIME_CONSTANT + dt);
- if (mDegree == 1) {
- state.xvel += (xvel - state.xvel) * alpha;
- state.yvel += (yvel - state.yvel) * alpha;
- } else {
- float xaccel = (xvel - state.xvel) / dt;
- float yaccel = (yvel - state.yvel) / dt;
- if (state.degree == 1) {
- state.xaccel = xaccel;
- state.yaccel = yaccel;
- state.degree = 2;
- } else {
- state.xaccel += (xaccel - state.xaccel) * alpha;
- state.yaccel += (yaccel - state.yaccel) * alpha;
- }
- state.xvel += (state.xaccel * dt) * alpha;
- state.yvel += (state.yaccel * dt) * alpha;
- }
- }
- state.xpos = xpos;
- state.ypos = ypos;
-}
-
-void IntegratingVelocityTrackerStrategy::populateEstimator(const State& state,
- VelocityTracker::Estimator* outEstimator) const {
- outEstimator->time = state.updateTime;
- outEstimator->confidence = 1.0f;
- outEstimator->degree = state.degree;
- outEstimator->xCoeff[0] = state.xpos;
- outEstimator->xCoeff[1] = state.xvel;
- outEstimator->xCoeff[2] = state.xaccel / 2;
- outEstimator->yCoeff[0] = state.ypos;
- outEstimator->yCoeff[1] = state.yvel;
- outEstimator->yCoeff[2] = state.yaccel / 2;
-}
-
-
-// --- LegacyVelocityTrackerStrategy ---
-
-const nsecs_t LegacyVelocityTrackerStrategy::HORIZON;
-const uint32_t LegacyVelocityTrackerStrategy::HISTORY_SIZE;
-const nsecs_t LegacyVelocityTrackerStrategy::MIN_DURATION;
-
-LegacyVelocityTrackerStrategy::LegacyVelocityTrackerStrategy() {
- clear();
-}
-
-LegacyVelocityTrackerStrategy::~LegacyVelocityTrackerStrategy() {
-}
-
-void LegacyVelocityTrackerStrategy::clear() {
- mIndex = 0;
- mMovements[0].idBits.clear();
-}
-
-void LegacyVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
- BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
- mMovements[mIndex].idBits = remainingIdBits;
-}
-
-void LegacyVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
- const VelocityTracker::Position* positions) {
- if (++mIndex == HISTORY_SIZE) {
- mIndex = 0;
- }
-
- Movement& movement = mMovements[mIndex];
- movement.eventTime = eventTime;
- movement.idBits = idBits;
- uint32_t count = idBits.count();
- for (uint32_t i = 0; i < count; i++) {
- movement.positions[i] = positions[i];
- }
-}
-
-bool LegacyVelocityTrackerStrategy::getEstimator(uint32_t id,
- VelocityTracker::Estimator* outEstimator) const {
- outEstimator->clear();
-
- const Movement& newestMovement = mMovements[mIndex];
- if (!newestMovement.idBits.hasBit(id)) {
- return false; // no data
- }
-
- // Find the oldest sample that contains the pointer and that is not older than HORIZON.
- nsecs_t minTime = newestMovement.eventTime - HORIZON;
- uint32_t oldestIndex = mIndex;
- uint32_t numTouches = 1;
- do {
- uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1;
- const Movement& nextOldestMovement = mMovements[nextOldestIndex];
- if (!nextOldestMovement.idBits.hasBit(id)
- || nextOldestMovement.eventTime < minTime) {
- break;
- }
- oldestIndex = nextOldestIndex;
- } while (++numTouches < HISTORY_SIZE);
-
- // Calculate an exponentially weighted moving average of the velocity estimate
- // at different points in time measured relative to the oldest sample.
- // This is essentially an IIR filter. Newer samples are weighted more heavily
- // than older samples. Samples at equal time points are weighted more or less
- // equally.
- //
- // One tricky problem is that the sample data may be poorly conditioned.
- // Sometimes samples arrive very close together in time which can cause us to
- // overestimate the velocity at that time point. Most samples might be measured
- // 16ms apart but some consecutive samples could be only 0.5sm apart because
- // the hardware or driver reports them irregularly or in bursts.
- float accumVx = 0;
- float accumVy = 0;
- uint32_t index = oldestIndex;
- uint32_t samplesUsed = 0;
- const Movement& oldestMovement = mMovements[oldestIndex];
- const VelocityTracker::Position& oldestPosition = oldestMovement.getPosition(id);
- nsecs_t lastDuration = 0;
-
- while (numTouches-- > 1) {
- if (++index == HISTORY_SIZE) {
- index = 0;
- }
- const Movement& movement = mMovements[index];
- nsecs_t duration = movement.eventTime - oldestMovement.eventTime;
-
- // If the duration between samples is small, we may significantly overestimate
- // the velocity. Consequently, we impose a minimum duration constraint on the
- // samples that we include in the calculation.
- if (duration >= MIN_DURATION) {
- const VelocityTracker::Position& position = movement.getPosition(id);
- float scale = 1000000000.0f / duration; // one over time delta in seconds
- float vx = (position.x - oldestPosition.x) * scale;
- float vy = (position.y - oldestPosition.y) * scale;
- accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
- accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
- lastDuration = duration;
- samplesUsed += 1;
- }
- }
-
- // Report velocity.
- const VelocityTracker::Position& newestPosition = newestMovement.getPosition(id);
- outEstimator->time = newestMovement.eventTime;
- outEstimator->confidence = 1;
- outEstimator->xCoeff[0] = newestPosition.x;
- outEstimator->yCoeff[0] = newestPosition.y;
- if (samplesUsed) {
- outEstimator->xCoeff[1] = accumVx;
- outEstimator->yCoeff[1] = accumVy;
- outEstimator->degree = 1;
- } else {
- outEstimator->degree = 0;
- }
- return true;
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/VelocityTracker.h b/widget/gonk/libui/VelocityTracker.h
deleted file mode 100644
index fd077d438..000000000
--- a/widget/gonk/libui/VelocityTracker.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _ANDROIDFW_VELOCITY_TRACKER_H
-#define _ANDROIDFW_VELOCITY_TRACKER_H
-
-#include "Input.h"
-#include <utils/Timers.h>
-#include <utils/BitSet.h>
-
-namespace android {
-
-class VelocityTrackerStrategy;
-
-/*
- * Calculates the velocity of pointer movements over time.
- */
-class VelocityTracker {
-public:
- struct Position {
- float x, y;
- };
-
- struct Estimator {
- static const size_t MAX_DEGREE = 4;
-
- // Estimator time base.
- nsecs_t time;
-
- // Polynomial coefficients describing motion in X and Y.
- float xCoeff[MAX_DEGREE + 1], yCoeff[MAX_DEGREE + 1];
-
- // Polynomial degree (number of coefficients), or zero if no information is
- // available.
- uint32_t degree;
-
- // Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit).
- float confidence;
-
- inline void clear() {
- time = 0;
- degree = 0;
- confidence = 0;
- for (size_t i = 0; i <= MAX_DEGREE; i++) {
- xCoeff[i] = 0;
- yCoeff[i] = 0;
- }
- }
- };
-
- // Creates a velocity tracker using the specified strategy.
- // If strategy is NULL, uses the default strategy for the platform.
- VelocityTracker(const char* strategy = NULL);
-
- ~VelocityTracker();
-
- // Resets the velocity tracker state.
- void clear();
-
- // Resets the velocity tracker state for specific pointers.
- // Call this method when some pointers have changed and may be reusing
- // an id that was assigned to a different pointer earlier.
- void clearPointers(BitSet32 idBits);
-
- // Adds movement information for a set of pointers.
- // The idBits bitfield specifies the pointer ids of the pointers whose positions
- // are included in the movement.
- // The positions array contains position information for each pointer in order by
- // increasing id. Its size should be equal to the number of one bits in idBits.
- void addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions);
-
- // Adds movement information for all pointers in a MotionEvent, including historical samples.
- void addMovement(const MotionEvent* event);
-
- // Gets the velocity of the specified pointer id in position units per second.
- // Returns false and sets the velocity components to zero if there is
- // insufficient movement information for the pointer.
- bool getVelocity(uint32_t id, float* outVx, float* outVy) const;
-
- // Gets an estimator for the recent movements of the specified pointer id.
- // Returns false and clears the estimator if there is no information available
- // about the pointer.
- bool getEstimator(uint32_t id, Estimator* outEstimator) const;
-
- // Gets the active pointer id, or -1 if none.
- inline int32_t getActivePointerId() const { return mActivePointerId; }
-
- // Gets a bitset containing all pointer ids from the most recent movement.
- inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; }
-
-private:
- static const char* DEFAULT_STRATEGY;
-
- nsecs_t mLastEventTime;
- BitSet32 mCurrentPointerIdBits;
- int32_t mActivePointerId;
- VelocityTrackerStrategy* mStrategy;
-
- bool configureStrategy(const char* strategy);
-
- static VelocityTrackerStrategy* createStrategy(const char* strategy);
-};
-
-
-/*
- * Implements a particular velocity tracker algorithm.
- */
-class VelocityTrackerStrategy {
-protected:
- VelocityTrackerStrategy() { }
-
-public:
- virtual ~VelocityTrackerStrategy() { }
-
- virtual void clear() = 0;
- virtual void clearPointers(BitSet32 idBits) = 0;
- virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
- const VelocityTracker::Position* positions) = 0;
- virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const = 0;
-};
-
-
-/*
- * Velocity tracker algorithm based on least-squares linear regression.
- */
-class LeastSquaresVelocityTrackerStrategy : public VelocityTrackerStrategy {
-public:
- enum Weighting {
- // No weights applied. All data points are equally reliable.
- WEIGHTING_NONE,
-
- // Weight by time delta. Data points clustered together are weighted less.
- WEIGHTING_DELTA,
-
- // Weight such that points within a certain horizon are weighed more than those
- // outside of that horizon.
- WEIGHTING_CENTRAL,
-
- // Weight such that points older than a certain amount are weighed less.
- WEIGHTING_RECENT,
- };
-
- // Degree must be no greater than Estimator::MAX_DEGREE.
- LeastSquaresVelocityTrackerStrategy(uint32_t degree, Weighting weighting = WEIGHTING_NONE);
- virtual ~LeastSquaresVelocityTrackerStrategy();
-
- virtual void clear();
- virtual void clearPointers(BitSet32 idBits);
- virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
- const VelocityTracker::Position* positions);
- virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
-
-private:
- // Sample horizon.
- // We don't use too much history by default since we want to react to quick
- // changes in direction.
- static const nsecs_t HORIZON = 100 * 1000000; // 100 ms
-
- // Number of samples to keep.
- static const uint32_t HISTORY_SIZE = 20;
-
- struct Movement {
- nsecs_t eventTime;
- BitSet32 idBits;
- VelocityTracker::Position positions[MAX_POINTERS];
-
- inline const VelocityTracker::Position& getPosition(uint32_t id) const {
- return positions[idBits.getIndexOfBit(id)];
- }
- };
-
- float chooseWeight(uint32_t index) const;
-
- const uint32_t mDegree;
- const Weighting mWeighting;
- uint32_t mIndex;
- Movement mMovements[HISTORY_SIZE];
-};
-
-
-/*
- * Velocity tracker algorithm that uses an IIR filter.
- */
-class IntegratingVelocityTrackerStrategy : public VelocityTrackerStrategy {
-public:
- // Degree must be 1 or 2.
- IntegratingVelocityTrackerStrategy(uint32_t degree);
- ~IntegratingVelocityTrackerStrategy();
-
- virtual void clear();
- virtual void clearPointers(BitSet32 idBits);
- virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
- const VelocityTracker::Position* positions);
- virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
-
-private:
- // Current state estimate for a particular pointer.
- struct State {
- nsecs_t updateTime;
- uint32_t degree;
-
- float xpos, xvel, xaccel;
- float ypos, yvel, yaccel;
- };
-
- const uint32_t mDegree;
- BitSet32 mPointerIdBits;
- State mPointerState[MAX_POINTER_ID + 1];
-
- void initState(State& state, nsecs_t eventTime, float xpos, float ypos) const;
- void updateState(State& state, nsecs_t eventTime, float xpos, float ypos) const;
- void populateEstimator(const State& state, VelocityTracker::Estimator* outEstimator) const;
-};
-
-
-/*
- * Velocity tracker strategy used prior to ICS.
- */
-class LegacyVelocityTrackerStrategy : public VelocityTrackerStrategy {
-public:
- LegacyVelocityTrackerStrategy();
- virtual ~LegacyVelocityTrackerStrategy();
-
- virtual void clear();
- virtual void clearPointers(BitSet32 idBits);
- virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
- const VelocityTracker::Position* positions);
- virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
-
-private:
- // Oldest sample to consider when calculating the velocity.
- static const nsecs_t HORIZON = 200 * 1000000; // 100 ms
-
- // Number of samples to keep.
- static const uint32_t HISTORY_SIZE = 20;
-
- // The minimum duration between samples when estimating velocity.
- static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms
-
- struct Movement {
- nsecs_t eventTime;
- BitSet32 idBits;
- VelocityTracker::Position positions[MAX_POINTERS];
-
- inline const VelocityTracker::Position& getPosition(uint32_t id) const {
- return positions[idBits.getIndexOfBit(id)];
- }
- };
-
- uint32_t mIndex;
- Movement mMovements[HISTORY_SIZE];
-};
-
-} // namespace android
-
-#endif // _ANDROIDFW_VELOCITY_TRACKER_H
diff --git a/widget/gonk/libui/VirtualKeyMap.cpp b/widget/gonk/libui/VirtualKeyMap.cpp
deleted file mode 100644
index 444ab3718..000000000
--- a/widget/gonk/libui/VirtualKeyMap.cpp
+++ /dev/null
@@ -1,171 +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.
- */
-
-#define LOG_TAG "VirtualKeyMap"
-#include "cutils_log.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include "VirtualKeyMap.h"
-#include <utils/Errors.h>
-#include "Tokenizer.h"
-#include <utils/Timers.h>
-
-// Enables debug output for the parser.
-#define DEBUG_PARSER 0
-
-// Enables debug output for parser performance.
-#define DEBUG_PARSER_PERFORMANCE 0
-
-
-namespace android {
-
-static const char* WHITESPACE = " \t\r";
-static const char* WHITESPACE_OR_FIELD_DELIMITER = " \t\r:";
-
-
-// --- VirtualKeyMap ---
-
-VirtualKeyMap::VirtualKeyMap() {
-}
-
-VirtualKeyMap::~VirtualKeyMap() {
-}
-
-status_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) {
- *outMap = NULL;
-
- Tokenizer* tokenizer;
- status_t status = Tokenizer::open(filename, &tokenizer);
- if (status) {
- ALOGE("Error %d opening virtual key map file %s.", status, filename.string());
- } else {
- VirtualKeyMap* map = new VirtualKeyMap();
- if (!map) {
- ALOGE("Error allocating virtual key map.");
- status = NO_MEMORY;
- } else {
-#if DEBUG_PARSER_PERFORMANCE
- nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
-#endif
- Parser parser(map, tokenizer);
- status = parser.parse();
-#if DEBUG_PARSER_PERFORMANCE
- nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
- ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.",
- tokenizer->getFilename().string(), tokenizer->getLineNumber(),
- elapsedTime / 1000000.0);
-#endif
- if (status) {
- delete map;
- } else {
- *outMap = map;
- }
- }
- delete tokenizer;
- }
- return status;
-}
-
-
-// --- VirtualKeyMap::Parser ---
-
-VirtualKeyMap::Parser::Parser(VirtualKeyMap* map, Tokenizer* tokenizer) :
- mMap(map), mTokenizer(tokenizer) {
-}
-
-VirtualKeyMap::Parser::~Parser() {
-}
-
-status_t VirtualKeyMap::Parser::parse() {
- while (!mTokenizer->isEof()) {
-#if DEBUG_PARSER
- ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
- mTokenizer->peekRemainderOfLine().string());
-#endif
-
- mTokenizer->skipDelimiters(WHITESPACE);
-
- if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
- // Multiple keys can appear on one line or they can be broken up across multiple lines.
- do {
- String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
- if (token != "0x01") {
- ALOGE("%s: Unknown virtual key type, expected 0x01.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
-
- VirtualKeyDefinition defn;
- bool success = parseNextIntField(&defn.scanCode)
- && parseNextIntField(&defn.centerX)
- && parseNextIntField(&defn.centerY)
- && parseNextIntField(&defn.width)
- && parseNextIntField(&defn.height);
- if (!success) {
- ALOGE("%s: Expected 5 colon-delimited integers in virtual key definition.",
- mTokenizer->getLocation().string());
- return BAD_VALUE;
- }
-
-#if DEBUG_PARSER
- ALOGD("Parsed virtual key: scanCode=%d, centerX=%d, centerY=%d, "
- "width=%d, height=%d",
- defn.scanCode, defn.centerX, defn.centerY, defn.width, defn.height);
-#endif
- mMap->mVirtualKeys.push(defn);
- } while (consumeFieldDelimiterAndSkipWhitespace());
-
- if (!mTokenizer->isEol()) {
- ALOGE("%s: Expected end of line, got '%s'.",
- mTokenizer->getLocation().string(),
- mTokenizer->peekRemainderOfLine().string());
- return BAD_VALUE;
- }
- }
-
- mTokenizer->nextLine();
- }
-
- return NO_ERROR;
-}
-
-bool VirtualKeyMap::Parser::consumeFieldDelimiterAndSkipWhitespace() {
- mTokenizer->skipDelimiters(WHITESPACE);
- if (mTokenizer->peekChar() == ':') {
- mTokenizer->nextChar();
- mTokenizer->skipDelimiters(WHITESPACE);
- return true;
- }
- return false;
-}
-
-bool VirtualKeyMap::Parser::parseNextIntField(int32_t* outValue) {
- if (!consumeFieldDelimiterAndSkipWhitespace()) {
- return false;
- }
-
- String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
- char* end;
- *outValue = strtol(token.string(), &end, 0);
- if (token.isEmpty() || *end != '\0') {
- ALOGE("Expected an integer, got '%s'.", token.string());
- return false;
- }
- return true;
-}
-
-} // namespace android
diff --git a/widget/gonk/libui/VirtualKeyMap.h b/widget/gonk/libui/VirtualKeyMap.h
deleted file mode 100644
index 79d61a536..000000000
--- a/widget/gonk/libui/VirtualKeyMap.h
+++ /dev/null
@@ -1,81 +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 _ANDROIDFW_VIRTUAL_KEY_MAP_H
-#define _ANDROIDFW_VIRTUAL_KEY_MAP_H
-
-#include <stdint.h>
-
-#include "Input.h"
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include "Tokenizer.h"
-#include <utils/String8.h>
-#include <utils/Unicode.h>
-
-namespace android {
-
-/* Describes a virtual key. */
-struct VirtualKeyDefinition {
- int32_t scanCode;
-
- // configured position data, specified in display coords
- int32_t centerX;
- int32_t centerY;
- int32_t width;
- int32_t height;
-};
-
-
-/**
- * Describes a collection of virtual keys on a touch screen in terms of
- * virtual scan codes and hit rectangles.
- *
- * This object is immutable after it has been loaded.
- */
-class VirtualKeyMap {
-public:
- ~VirtualKeyMap();
-
- static status_t load(const String8& filename, VirtualKeyMap** outMap);
-
- inline const Vector<VirtualKeyDefinition>& getVirtualKeys() const {
- return mVirtualKeys;
- }
-
-private:
- class Parser {
- VirtualKeyMap* mMap;
- Tokenizer* mTokenizer;
-
- public:
- Parser(VirtualKeyMap* map, Tokenizer* tokenizer);
- ~Parser();
- status_t parse();
-
- private:
- bool consumeFieldDelimiterAndSkipWhitespace();
- bool parseNextIntField(int32_t* outValue);
- };
-
- Vector<VirtualKeyDefinition> mVirtualKeys;
-
- VirtualKeyMap();
-};
-
-} // namespace android
-
-#endif // _ANDROIDFW_KEY_CHARACTER_MAP_H
diff --git a/widget/gonk/libui/android_input.h b/widget/gonk/libui/android_input.h
deleted file mode 100644
index 00e81b28d..000000000
--- a/widget/gonk/libui/android_input.h
+++ /dev/null
@@ -1,850 +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 _ANDROID_INPUT_H
-#define _ANDROID_INPUT_H
-
-/******************************************************************
- *
- * IMPORTANT NOTICE:
- *
- * This file is part of Android's set of stable system headers
- * exposed by the Android NDK (Native Development Kit).
- *
- * Third-party source AND binary code relies on the definitions
- * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
- *
- * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
- * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
- * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
- * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
- */
-
-/*
- * Structures and functions to receive and process input events in
- * native code.
- *
- * NOTE: These functions MUST be implemented by /system/lib/libui.so
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-#include "android_keycodes.h"
-#include <android/looper.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Key states (may be returned by queries about the current state of a
- * particular key code, scan code or switch).
- */
-enum {
- /* The key state is unknown or the requested key itself is not supported. */
- AKEY_STATE_UNKNOWN = -1,
-
- /* The key is up. */
- AKEY_STATE_UP = 0,
-
- /* The key is down. */
- AKEY_STATE_DOWN = 1,
-
- /* The key is down but is a virtual key press that is being emulated by the system. */
- AKEY_STATE_VIRTUAL = 2
-};
-
-/*
- * Meta key / modifer state.
- */
-enum {
- /* No meta keys are pressed. */
- AMETA_NONE = 0,
-
- /* This mask is used to check whether one of the ALT meta keys is pressed. */
- AMETA_ALT_ON = 0x02,
-
- /* This mask is used to check whether the left ALT meta key is pressed. */
- AMETA_ALT_LEFT_ON = 0x10,
-
- /* This mask is used to check whether the right ALT meta key is pressed. */
- AMETA_ALT_RIGHT_ON = 0x20,
-
- /* This mask is used to check whether one of the SHIFT meta keys is pressed. */
- AMETA_SHIFT_ON = 0x01,
-
- /* This mask is used to check whether the left SHIFT meta key is pressed. */
- AMETA_SHIFT_LEFT_ON = 0x40,
-
- /* This mask is used to check whether the right SHIFT meta key is pressed. */
- AMETA_SHIFT_RIGHT_ON = 0x80,
-
- /* This mask is used to check whether the SYM meta key is pressed. */
- AMETA_SYM_ON = 0x04,
-
- /* This mask is used to check whether the FUNCTION meta key is pressed. */
- AMETA_FUNCTION_ON = 0x08,
-
- /* This mask is used to check whether one of the CTRL meta keys is pressed. */
- AMETA_CTRL_ON = 0x1000,
-
- /* This mask is used to check whether the left CTRL meta key is pressed. */
- AMETA_CTRL_LEFT_ON = 0x2000,
-
- /* This mask is used to check whether the right CTRL meta key is pressed. */
- AMETA_CTRL_RIGHT_ON = 0x4000,
-
- /* This mask is used to check whether one of the META meta keys is pressed. */
- AMETA_META_ON = 0x10000,
-
- /* This mask is used to check whether the left META meta key is pressed. */
- AMETA_META_LEFT_ON = 0x20000,
-
- /* This mask is used to check whether the right META meta key is pressed. */
- AMETA_META_RIGHT_ON = 0x40000,
-
- /* This mask is used to check whether the CAPS LOCK meta key is on. */
- AMETA_CAPS_LOCK_ON = 0x100000,
-
- /* This mask is used to check whether the NUM LOCK meta key is on. */
- AMETA_NUM_LOCK_ON = 0x200000,
-
- /* This mask is used to check whether the SCROLL LOCK meta key is on. */
- AMETA_SCROLL_LOCK_ON = 0x400000,
-};
-
-/*
- * Input events.
- *
- * Input events are opaque structures. Use the provided accessors functions to
- * read their properties.
- */
-struct AInputEvent;
-typedef struct AInputEvent AInputEvent;
-
-/*
- * Input event types.
- */
-enum {
- /* Indicates that the input event is a key event. */
- AINPUT_EVENT_TYPE_KEY = 1,
-
- /* Indicates that the input event is a motion event. */
- AINPUT_EVENT_TYPE_MOTION = 2
-};
-
-/*
- * Key event actions.
- */
-enum {
- /* The key has been pressed down. */
- AKEY_EVENT_ACTION_DOWN = 0,
-
- /* The key has been released. */
- AKEY_EVENT_ACTION_UP = 1,
-
- /* Multiple duplicate key events have occurred in a row, or a complex string is
- * being delivered. The repeat_count property of the key event contains the number
- * of times the given key code should be executed.
- */
- AKEY_EVENT_ACTION_MULTIPLE = 2
-};
-
-/*
- * Key event flags.
- */
-enum {
- /* This mask is set if the device woke because of this key event. */
- AKEY_EVENT_FLAG_WOKE_HERE = 0x1,
-
- /* This mask is set if the key event was generated by a software keyboard. */
- AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2,
-
- /* This mask is set if we don't want the key event to cause us to leave touch mode. */
- AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4,
-
- /* This mask is set if an event was known to come from a trusted part
- * of the system. That is, the event is known to come from the user,
- * and could not have been spoofed by a third party component. */
- AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8,
-
- /* This mask is used for compatibility, to identify enter keys that are
- * coming from an IME whose enter key has been auto-labelled "next" or
- * "done". This allows TextView to dispatch these as normal enter keys
- * for old applications, but still do the appropriate action when
- * receiving them. */
- AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10,
-
- /* When associated with up key events, this indicates that the key press
- * has been canceled. Typically this is used with virtual touch screen
- * keys, where the user can slide from the virtual key area on to the
- * display: in that case, the application will receive a canceled up
- * event and should not perform the action normally associated with the
- * key. Note that for this to work, the application can not perform an
- * action for a key until it receives an up or the long press timeout has
- * expired. */
- AKEY_EVENT_FLAG_CANCELED = 0x20,
-
- /* This key event was generated by a virtual (on-screen) hard key area.
- * Typically this is an area of the touchscreen, outside of the regular
- * display, dedicated to "hardware" buttons. */
- AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40,
-
- /* This flag is set for the first key repeat that occurs after the
- * long press timeout. */
- AKEY_EVENT_FLAG_LONG_PRESS = 0x80,
-
- /* Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long
- * press action was executed while it was down. */
- AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100,
-
- /* Set for AKEY_EVENT_ACTION_UP when this event's key code is still being
- * tracked from its initial down. That is, somebody requested that tracking
- * started on the key down and a long press has not caused
- * the tracking to be canceled. */
- AKEY_EVENT_FLAG_TRACKING = 0x200,
-
- /* Set when a key event has been synthesized to implement default behavior
- * for an event that the application did not handle.
- * Fallback key events are generated by unhandled trackball motions
- * (to emulate a directional keypad) and by certain unhandled key presses
- * that are declared in the key map (such as special function numeric keypad
- * keys when numlock is off). */
- AKEY_EVENT_FLAG_FALLBACK = 0x400,
-};
-
-/*
- * Motion event actions.
- */
-
-/* Bit shift for the action bits holding the pointer index as
- * defined by AMOTION_EVENT_ACTION_POINTER_INDEX_MASK.
- */
-#define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT 8
-
-enum {
- /* Bit mask of the parts of the action code that are the action itself.
- */
- AMOTION_EVENT_ACTION_MASK = 0xff,
-
- /* Bits in the action code that represent a pointer index, used with
- * AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting
- * down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer
- * index where the data for the pointer going up or down can be found.
- */
- AMOTION_EVENT_ACTION_POINTER_INDEX_MASK = 0xff00,
-
- /* A pressed gesture has started, the motion contains the initial starting location.
- */
- AMOTION_EVENT_ACTION_DOWN = 0,
-
- /* A pressed gesture has finished, the motion contains the final release location
- * as well as any intermediate points since the last down or move event.
- */
- AMOTION_EVENT_ACTION_UP = 1,
-
- /* A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
- * AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as
- * any intermediate points since the last down or move event.
- */
- AMOTION_EVENT_ACTION_MOVE = 2,
-
- /* The current gesture has been aborted.
- * You will not receive any more points in it. You should treat this as
- * an up event, but not perform any action that you normally would.
- */
- AMOTION_EVENT_ACTION_CANCEL = 3,
-
- /* A movement has happened outside of the normal bounds of the UI element.
- * This does not provide a full gesture, but only the initial location of the movement/touch.
- */
- AMOTION_EVENT_ACTION_OUTSIDE = 4,
-
- /* A non-primary pointer has gone down.
- * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
- */
- AMOTION_EVENT_ACTION_POINTER_DOWN = 5,
-
- /* A non-primary pointer has gone up.
- * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
- */
- AMOTION_EVENT_ACTION_POINTER_UP = 6,
-
- /* A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
- * The motion contains the most recent point, as well as any intermediate points since
- * the last hover move event.
- */
- AMOTION_EVENT_ACTION_HOVER_MOVE = 7,
-
- /* The motion event contains relative vertical and/or horizontal scroll offsets.
- * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL
- * and AMOTION_EVENT_AXIS_HSCROLL.
- * The pointer may or may not be down when this event is dispatched.
- * This action is always delivered to the winder under the pointer, which
- * may not be the window currently touched.
- */
- AMOTION_EVENT_ACTION_SCROLL = 8,
-
- /* The pointer is not down but has entered the boundaries of a window or view.
- */
- AMOTION_EVENT_ACTION_HOVER_ENTER = 9,
-
- /* The pointer is not down but has exited the boundaries of a window or view.
- */
- AMOTION_EVENT_ACTION_HOVER_EXIT = 10,
-};
-
-/*
- * Motion event flags.
- */
-enum {
- /* This flag indicates that the window that received this motion event is partly
- * or wholly obscured by another visible window above it. This flag is set to true
- * even if the event did not directly pass through the obscured area.
- * A security sensitive application can check this flag to identify situations in which
- * a malicious application may have covered up part of its content for the purpose
- * of misleading the user or hijacking touches. An appropriate response might be
- * to drop the suspect touches or to take additional precautions to confirm the user's
- * actual intent.
- */
- AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1,
-};
-
-/*
- * Motion event edge touch flags.
- */
-enum {
- /* No edges intersected */
- AMOTION_EVENT_EDGE_FLAG_NONE = 0,
-
- /* Flag indicating the motion event intersected the top edge of the screen. */
- AMOTION_EVENT_EDGE_FLAG_TOP = 0x01,
-
- /* Flag indicating the motion event intersected the bottom edge of the screen. */
- AMOTION_EVENT_EDGE_FLAG_BOTTOM = 0x02,
-
- /* Flag indicating the motion event intersected the left edge of the screen. */
- AMOTION_EVENT_EDGE_FLAG_LEFT = 0x04,
-
- /* Flag indicating the motion event intersected the right edge of the screen. */
- AMOTION_EVENT_EDGE_FLAG_RIGHT = 0x08
-};
-
-/*
- * Constants that identify each individual axis of a motion event.
- * Refer to the documentation on the MotionEvent class for descriptions of each axis.
- */
-enum {
- AMOTION_EVENT_AXIS_X = 0,
- AMOTION_EVENT_AXIS_Y = 1,
- AMOTION_EVENT_AXIS_PRESSURE = 2,
- AMOTION_EVENT_AXIS_SIZE = 3,
- AMOTION_EVENT_AXIS_TOUCH_MAJOR = 4,
- AMOTION_EVENT_AXIS_TOUCH_MINOR = 5,
- AMOTION_EVENT_AXIS_TOOL_MAJOR = 6,
- AMOTION_EVENT_AXIS_TOOL_MINOR = 7,
- AMOTION_EVENT_AXIS_ORIENTATION = 8,
- AMOTION_EVENT_AXIS_VSCROLL = 9,
- AMOTION_EVENT_AXIS_HSCROLL = 10,
- AMOTION_EVENT_AXIS_Z = 11,
- AMOTION_EVENT_AXIS_RX = 12,
- AMOTION_EVENT_AXIS_RY = 13,
- AMOTION_EVENT_AXIS_RZ = 14,
- AMOTION_EVENT_AXIS_HAT_X = 15,
- AMOTION_EVENT_AXIS_HAT_Y = 16,
- AMOTION_EVENT_AXIS_LTRIGGER = 17,
- AMOTION_EVENT_AXIS_RTRIGGER = 18,
- AMOTION_EVENT_AXIS_THROTTLE = 19,
- AMOTION_EVENT_AXIS_RUDDER = 20,
- AMOTION_EVENT_AXIS_WHEEL = 21,
- AMOTION_EVENT_AXIS_GAS = 22,
- AMOTION_EVENT_AXIS_BRAKE = 23,
- AMOTION_EVENT_AXIS_DISTANCE = 24,
- AMOTION_EVENT_AXIS_TILT = 25,
- AMOTION_EVENT_AXIS_GENERIC_1 = 32,
- AMOTION_EVENT_AXIS_GENERIC_2 = 33,
- AMOTION_EVENT_AXIS_GENERIC_3 = 34,
- AMOTION_EVENT_AXIS_GENERIC_4 = 35,
- AMOTION_EVENT_AXIS_GENERIC_5 = 36,
- AMOTION_EVENT_AXIS_GENERIC_6 = 37,
- AMOTION_EVENT_AXIS_GENERIC_7 = 38,
- AMOTION_EVENT_AXIS_GENERIC_8 = 39,
- AMOTION_EVENT_AXIS_GENERIC_9 = 40,
- AMOTION_EVENT_AXIS_GENERIC_10 = 41,
- AMOTION_EVENT_AXIS_GENERIC_11 = 42,
- AMOTION_EVENT_AXIS_GENERIC_12 = 43,
- AMOTION_EVENT_AXIS_GENERIC_13 = 44,
- AMOTION_EVENT_AXIS_GENERIC_14 = 45,
- AMOTION_EVENT_AXIS_GENERIC_15 = 46,
- AMOTION_EVENT_AXIS_GENERIC_16 = 47,
-
- // NOTE: If you add a new axis here you must also add it to several other files.
- // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
-};
-
-/*
- * Constants that identify buttons that are associated with motion events.
- * Refer to the documentation on the MotionEvent class for descriptions of each button.
- */
-enum {
- AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0,
- AMOTION_EVENT_BUTTON_SECONDARY = 1 << 1,
- AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
- AMOTION_EVENT_BUTTON_BACK = 1 << 3,
- AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
-};
-
-/*
- * Constants that identify tool types.
- * Refer to the documentation on the MotionEvent class for descriptions of each tool type.
- */
-enum {
- AMOTION_EVENT_TOOL_TYPE_UNKNOWN = 0,
- AMOTION_EVENT_TOOL_TYPE_FINGER = 1,
- AMOTION_EVENT_TOOL_TYPE_STYLUS = 2,
- AMOTION_EVENT_TOOL_TYPE_MOUSE = 3,
- AMOTION_EVENT_TOOL_TYPE_ERASER = 4,
-};
-
-/*
- * Input sources.
- *
- * Refer to the documentation on android.view.InputDevice for more details about input sources
- * and their correct interpretation.
- */
-enum {
- AINPUT_SOURCE_CLASS_MASK = 0x000000ff,
-
- AINPUT_SOURCE_CLASS_NONE = 0x00000000,
- AINPUT_SOURCE_CLASS_BUTTON = 0x00000001,
- AINPUT_SOURCE_CLASS_POINTER = 0x00000002,
- AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004,
- AINPUT_SOURCE_CLASS_POSITION = 0x00000008,
- AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010,
-};
-
-enum {
- AINPUT_SOURCE_UNKNOWN = 0x00000000,
-
- AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON,
- AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON,
- AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON,
- AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
- AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
- AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER,
- AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
- AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
- AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
- AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
-
- AINPUT_SOURCE_ANY = 0xffffff00,
-};
-
-/*
- * Keyboard types.
- *
- * Refer to the documentation on android.view.InputDevice for more details.
- */
-enum {
- AINPUT_KEYBOARD_TYPE_NONE = 0,
- AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC = 1,
- AINPUT_KEYBOARD_TYPE_ALPHABETIC = 2,
-};
-
-/*
- * Constants used to retrieve information about the range of motion for a particular
- * coordinate of a motion event.
- *
- * Refer to the documentation on android.view.InputDevice for more details about input sources
- * and their correct interpretation.
- *
- * DEPRECATION NOTICE: These constants are deprecated. Use AMOTION_EVENT_AXIS_* constants instead.
- */
-enum {
- AINPUT_MOTION_RANGE_X = AMOTION_EVENT_AXIS_X,
- AINPUT_MOTION_RANGE_Y = AMOTION_EVENT_AXIS_Y,
- AINPUT_MOTION_RANGE_PRESSURE = AMOTION_EVENT_AXIS_PRESSURE,
- AINPUT_MOTION_RANGE_SIZE = AMOTION_EVENT_AXIS_SIZE,
- AINPUT_MOTION_RANGE_TOUCH_MAJOR = AMOTION_EVENT_AXIS_TOUCH_MAJOR,
- AINPUT_MOTION_RANGE_TOUCH_MINOR = AMOTION_EVENT_AXIS_TOUCH_MINOR,
- AINPUT_MOTION_RANGE_TOOL_MAJOR = AMOTION_EVENT_AXIS_TOOL_MAJOR,
- AINPUT_MOTION_RANGE_TOOL_MINOR = AMOTION_EVENT_AXIS_TOOL_MINOR,
- AINPUT_MOTION_RANGE_ORIENTATION = AMOTION_EVENT_AXIS_ORIENTATION,
-} __attribute__ ((deprecated));
-
-
-/*
- * Input event accessors.
- *
- * Note that most functions can only be used on input events that are of a given type.
- * Calling these functions on input events of other types will yield undefined behavior.
- */
-
-/*** Accessors for all input events. ***/
-
-/* Get the input event type. */
-int32_t AInputEvent_getType(const AInputEvent* event);
-
-/* Get the id for the device that an input event came from.
- *
- * Input events can be generated by multiple different input devices.
- * Use the input device id to obtain information about the input
- * device that was responsible for generating a particular event.
- *
- * An input device id of 0 indicates that the event didn't come from a physical device;
- * other numbers are arbitrary and you shouldn't depend on the values.
- * Use the provided input device query API to obtain information about input devices.
- */
-int32_t AInputEvent_getDeviceId(const AInputEvent* event);
-
-/* Get the input event source. */
-int32_t AInputEvent_getSource(const AInputEvent* event);
-
-/*** Accessors for key events only. ***/
-
-/* Get the key event action. */
-int32_t AKeyEvent_getAction(const AInputEvent* key_event);
-
-/* Get the key event flags. */
-int32_t AKeyEvent_getFlags(const AInputEvent* key_event);
-
-/* Get the key code of the key event.
- * This is the physical key that was pressed, not the Unicode character. */
-int32_t AKeyEvent_getKeyCode(const AInputEvent* key_event);
-
-/* Get the hardware key id of this key event.
- * These values are not reliable and vary from device to device. */
-int32_t AKeyEvent_getScanCode(const AInputEvent* key_event);
-
-/* Get the meta key state. */
-int32_t AKeyEvent_getMetaState(const AInputEvent* key_event);
-
-/* Get the repeat count of the event.
- * For both key up an key down events, this is the number of times the key has
- * repeated with the first down starting at 0 and counting up from there. For
- * multiple key events, this is the number of down/up pairs that have occurred. */
-int32_t AKeyEvent_getRepeatCount(const AInputEvent* key_event);
-
-/* Get the time of the most recent key down event, in the
- * java.lang.System.nanoTime() time base. If this is a down event,
- * this will be the same as eventTime.
- * Note that when chording keys, this value is the down time of the most recently
- * pressed key, which may not be the same physical key of this event. */
-int64_t AKeyEvent_getDownTime(const AInputEvent* key_event);
-
-/* Get the time this event occurred, in the
- * java.lang.System.nanoTime() time base. */
-int64_t AKeyEvent_getEventTime(const AInputEvent* key_event);
-
-/*** Accessors for motion events only. ***/
-
-/* Get the combined motion event action code and pointer index. */
-int32_t AMotionEvent_getAction(const AInputEvent* motion_event);
-
-/* Get the motion event flags. */
-int32_t AMotionEvent_getFlags(const AInputEvent* motion_event);
-
-/* Get the state of any meta / modifier keys that were in effect when the
- * event was generated. */
-int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
-
-/* Get the button state of all buttons that are pressed. */
-int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
-
-/* Get a bitfield indicating which edges, if any, were touched by this motion event.
- * For touch events, clients can use this to determine if the user's finger was
- * touching the edge of the display. */
-int32_t AMotionEvent_getEdgeFlags(const AInputEvent* motion_event);
-
-/* Get the time when the user originally pressed down to start a stream of
- * position events, in the java.lang.System.nanoTime() time base. */
-int64_t AMotionEvent_getDownTime(const AInputEvent* motion_event);
-
-/* Get the time when this specific event was generated,
- * in the java.lang.System.nanoTime() time base. */
-int64_t AMotionEvent_getEventTime(const AInputEvent* motion_event);
-
-/* Get the X coordinate offset.
- * For touch events on the screen, this is the delta that was added to the raw
- * screen coordinates to adjust for the absolute position of the containing windows
- * and views. */
-float AMotionEvent_getXOffset(const AInputEvent* motion_event);
-
-/* Get the precision of the Y coordinates being reported.
- * For touch events on the screen, this is the delta that was added to the raw
- * screen coordinates to adjust for the absolute position of the containing windows
- * and views. */
-float AMotionEvent_getYOffset(const AInputEvent* motion_event);
-
-/* Get the precision of the X coordinates being reported.
- * You can multiply this number with an X coordinate sample to find the
- * actual hardware value of the X coordinate. */
-float AMotionEvent_getXPrecision(const AInputEvent* motion_event);
-
-/* Get the precision of the Y coordinates being reported.
- * You can multiply this number with a Y coordinate sample to find the
- * actual hardware value of the Y coordinate. */
-float AMotionEvent_getYPrecision(const AInputEvent* motion_event);
-
-/* Get the number of pointers of data contained in this event.
- * Always >= 1. */
-size_t AMotionEvent_getPointerCount(const AInputEvent* motion_event);
-
-/* Get the pointer identifier associated with a particular pointer
- * data index in this event. The identifier tells you the actual pointer
- * number associated with the data, accounting for individual pointers
- * going up and down since the start of the current gesture. */
-int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index);
-
-/* 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);
-
-/* Get the original raw X coordinate of this event.
- * For touch events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views. */
-float AMotionEvent_getRawX(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the original raw X coordinate of this event.
- * For touch events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views. */
-float AMotionEvent_getRawY(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current X coordinate of this event for the given pointer index.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getX(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current Y coordinate of this event for the given pointer index.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getY(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current pressure of this event for the given pointer index.
- * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
- * although values higher than 1 may be generated depending on the calibration of
- * the input device. */
-float AMotionEvent_getPressure(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current scaled value of the approximate size for the given pointer index.
- * This represents some approximation of the area of the screen being
- * pressed; the actual value in pixels corresponding to the
- * touch is normalized with the device specific range of values
- * and scaled to a value between 0 and 1. The value of size can be used to
- * determine fat touch events. */
-float AMotionEvent_getSize(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current length of the major axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index. */
-float AMotionEvent_getTouchMajor(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current length of the minor axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index. */
-float AMotionEvent_getTouchMinor(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current length of the major axis of an ellipse that describes the size
- * of the approaching tool for the given pointer index.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
-float AMotionEvent_getToolMajor(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current length of the minor axis of an ellipse that describes the size
- * of the approaching tool for the given pointer index.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
-float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current orientation of the touch area and tool area in radians clockwise from
- * vertical for the given pointer index.
- * An angle of 0 degrees indicates that the major axis of contact is oriented
- * upwards, is perfectly circular or is of unknown orientation. A positive angle
- * indicates that the major axis of contact is oriented to the right. A negative angle
- * indicates that the major axis of contact is oriented to the left.
- * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
- * (finger pointing fully right). */
-float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
-
-/* 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);
-
-/* Get the number of historical points in this event. These are movements that
- * have occurred between this event and the previous event. This only applies
- * to AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0.
- * Historical samples are indexed from oldest to newest. */
-size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event);
-
-/* Get the time that a historical movement occurred between this event and
- * the previous event, in the java.lang.System.nanoTime() time base. */
-int64_t AMotionEvent_getHistoricalEventTime(AInputEvent* motion_event,
- size_t history_index);
-
-/* Get the historical raw X coordinate of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * For touch events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getHistoricalRawX(const AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the historical raw Y coordinate of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * For touch events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getHistoricalRawY(const AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the historical X coordinate of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getHistoricalX(AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the historical Y coordinate of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getHistoricalY(AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the historical pressure of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
- * although values higher than 1 may be generated depending on the calibration of
- * the input device. */
-float AMotionEvent_getHistoricalPressure(AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the current scaled value of the approximate size for the given pointer index that
- * occurred between this event and the previous motion event.
- * This represents some approximation of the area of the screen being
- * pressed; the actual value in pixels corresponding to the
- * touch is normalized with the device specific range of values
- * and scaled to a value between 0 and 1. The value of size can be used to
- * determine fat touch events. */
-float AMotionEvent_getHistoricalSize(AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the historical length of the major axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index that
- * occurred between this event and the previous motion event. */
-float AMotionEvent_getHistoricalTouchMajor(const AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the historical length of the minor axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index that
- * occurred between this event and the previous motion event. */
-float AMotionEvent_getHistoricalTouchMinor(const AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the historical length of the major axis of an ellipse that describes the size
- * of the approaching tool for the given pointer index that
- * occurred between this event and the previous motion event.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
-float AMotionEvent_getHistoricalToolMajor(const AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the historical length of the minor axis of an ellipse that describes the size
- * of the approaching tool for the given pointer index that
- * occurred between this event and the previous motion event.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
-float AMotionEvent_getHistoricalToolMinor(const AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* Get the historical orientation of the touch area and tool area in radians clockwise from
- * vertical for the given pointer index that
- * occurred between this event and the previous motion event.
- * An angle of 0 degrees indicates that the major axis of contact is oriented
- * upwards, is perfectly circular or is of unknown orientation. A positive angle
- * indicates that the major axis of contact is oriented to the right. A negative angle
- * indicates that the major axis of contact is oriented to the left.
- * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
- * (finger pointing fully right). */
-float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
- size_t history_index);
-
-/* 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);
-
-
-/*
- * Input queue
- *
- * An input queue is the facility through which you retrieve input
- * events.
- */
-struct AInputQueue;
-typedef struct AInputQueue AInputQueue;
-
-/*
- * Add this input queue to a looper for processing. See
- * ALooper_addFd() for information on the ident, callback, and data params.
- */
-void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
- int ident, ALooper_callbackFunc callback, void* data);
-
-/*
- * Remove the input queue from the looper it is currently attached to.
- */
-void AInputQueue_detachLooper(AInputQueue* queue);
-
-/*
- * Returns true if there are one or more events available in the
- * input queue. Returns 1 if the queue has events; 0 if
- * it does not have events; and a negative value if there is an error.
- */
-int32_t AInputQueue_hasEvents(AInputQueue* queue);
-
-/*
- * Returns the next available event from the queue. Returns a negative
- * value if no events are available or an error has occurred.
- */
-int32_t AInputQueue_getEvent(AInputQueue* queue, AInputEvent** outEvent);
-
-/*
- * Sends the key for standard pre-dispatching -- that is, possibly deliver
- * it to the current IME to be consumed before the app. Returns 0 if it
- * was not pre-dispatched, meaning you can process it right now. If non-zero
- * is returned, you must abandon the current event processing and allow the
- * event to appear again in the event queue (if it does not get consumed during
- * pre-dispatching).
- */
-int32_t AInputQueue_preDispatchEvent(AInputQueue* queue, AInputEvent* event);
-
-/*
- * Report that dispatching has finished with the given event.
- * This must be called after receiving an event with AInputQueue_get_event().
- */
-void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _ANDROID_INPUT_H
diff --git a/widget/gonk/libui/android_keycodes.h b/widget/gonk/libui/android_keycodes.h
deleted file mode 100644
index 9e63d1d01..000000000
--- a/widget/gonk/libui/android_keycodes.h
+++ /dev/null
@@ -1,315 +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 _ANDROID_KEYCODES_H
-#define _ANDROID_KEYCODES_H
-
-/******************************************************************
- *
- * IMPORTANT NOTICE:
- *
- * This file is part of Android's set of stable system headers
- * exposed by the Android NDK (Native Development Kit).
- *
- * Third-party source AND binary code relies on the definitions
- * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
- *
- * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
- * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
- * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
- * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
- */
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Key codes.
- */
-enum {
- AKEYCODE_UNKNOWN = 0,
- AKEYCODE_SOFT_LEFT = 1,
- AKEYCODE_SOFT_RIGHT = 2,
- AKEYCODE_HOME = 3,
- AKEYCODE_BACK = 4,
- AKEYCODE_CALL = 5,
- AKEYCODE_ENDCALL = 6,
- AKEYCODE_0 = 7,
- AKEYCODE_1 = 8,
- AKEYCODE_2 = 9,
- AKEYCODE_3 = 10,
- AKEYCODE_4 = 11,
- AKEYCODE_5 = 12,
- AKEYCODE_6 = 13,
- AKEYCODE_7 = 14,
- AKEYCODE_8 = 15,
- AKEYCODE_9 = 16,
- AKEYCODE_STAR = 17,
- AKEYCODE_POUND = 18,
- AKEYCODE_DPAD_UP = 19,
- AKEYCODE_DPAD_DOWN = 20,
- AKEYCODE_DPAD_LEFT = 21,
- AKEYCODE_DPAD_RIGHT = 22,
- AKEYCODE_DPAD_CENTER = 23,
- AKEYCODE_VOLUME_UP = 24,
- AKEYCODE_VOLUME_DOWN = 25,
- AKEYCODE_POWER = 26,
- AKEYCODE_CAMERA = 27,
- AKEYCODE_CLEAR = 28,
- AKEYCODE_A = 29,
- AKEYCODE_B = 30,
- AKEYCODE_C = 31,
- AKEYCODE_D = 32,
- AKEYCODE_E = 33,
- AKEYCODE_F = 34,
- AKEYCODE_G = 35,
- AKEYCODE_H = 36,
- AKEYCODE_I = 37,
- AKEYCODE_J = 38,
- AKEYCODE_K = 39,
- AKEYCODE_L = 40,
- AKEYCODE_M = 41,
- AKEYCODE_N = 42,
- AKEYCODE_O = 43,
- AKEYCODE_P = 44,
- AKEYCODE_Q = 45,
- AKEYCODE_R = 46,
- AKEYCODE_S = 47,
- AKEYCODE_T = 48,
- AKEYCODE_U = 49,
- AKEYCODE_V = 50,
- AKEYCODE_W = 51,
- AKEYCODE_X = 52,
- AKEYCODE_Y = 53,
- AKEYCODE_Z = 54,
- AKEYCODE_COMMA = 55,
- AKEYCODE_PERIOD = 56,
- AKEYCODE_ALT_LEFT = 57,
- AKEYCODE_ALT_RIGHT = 58,
- AKEYCODE_SHIFT_LEFT = 59,
- AKEYCODE_SHIFT_RIGHT = 60,
- AKEYCODE_TAB = 61,
- AKEYCODE_SPACE = 62,
- AKEYCODE_SYM = 63,
- AKEYCODE_EXPLORER = 64,
- AKEYCODE_ENVELOPE = 65,
- AKEYCODE_ENTER = 66,
- AKEYCODE_DEL = 67,
- AKEYCODE_GRAVE = 68,
- AKEYCODE_MINUS = 69,
- AKEYCODE_EQUALS = 70,
- AKEYCODE_LEFT_BRACKET = 71,
- AKEYCODE_RIGHT_BRACKET = 72,
- AKEYCODE_BACKSLASH = 73,
- AKEYCODE_SEMICOLON = 74,
- AKEYCODE_APOSTROPHE = 75,
- AKEYCODE_SLASH = 76,
- AKEYCODE_AT = 77,
- AKEYCODE_NUM = 78,
- AKEYCODE_HEADSETHOOK = 79,
- AKEYCODE_FOCUS = 80, // *Camera* focus
- AKEYCODE_PLUS = 81,
- AKEYCODE_MENU = 82,
- AKEYCODE_NOTIFICATION = 83,
- AKEYCODE_SEARCH = 84,
- AKEYCODE_MEDIA_PLAY_PAUSE= 85,
- AKEYCODE_MEDIA_STOP = 86,
- AKEYCODE_MEDIA_NEXT = 87,
- AKEYCODE_MEDIA_PREVIOUS = 88,
- AKEYCODE_MEDIA_REWIND = 89,
- AKEYCODE_MEDIA_FAST_FORWARD = 90,
- AKEYCODE_MUTE = 91,
- AKEYCODE_PAGE_UP = 92,
- AKEYCODE_PAGE_DOWN = 93,
- AKEYCODE_PICTSYMBOLS = 94,
- AKEYCODE_SWITCH_CHARSET = 95,
- AKEYCODE_BUTTON_A = 96,
- AKEYCODE_BUTTON_B = 97,
- AKEYCODE_BUTTON_C = 98,
- AKEYCODE_BUTTON_X = 99,
- AKEYCODE_BUTTON_Y = 100,
- AKEYCODE_BUTTON_Z = 101,
- AKEYCODE_BUTTON_L1 = 102,
- AKEYCODE_BUTTON_R1 = 103,
- AKEYCODE_BUTTON_L2 = 104,
- AKEYCODE_BUTTON_R2 = 105,
- AKEYCODE_BUTTON_THUMBL = 106,
- AKEYCODE_BUTTON_THUMBR = 107,
- AKEYCODE_BUTTON_START = 108,
- AKEYCODE_BUTTON_SELECT = 109,
- AKEYCODE_BUTTON_MODE = 110,
- AKEYCODE_ESCAPE = 111,
- AKEYCODE_FORWARD_DEL = 112,
- AKEYCODE_CTRL_LEFT = 113,
- AKEYCODE_CTRL_RIGHT = 114,
- AKEYCODE_CAPS_LOCK = 115,
- AKEYCODE_SCROLL_LOCK = 116,
- AKEYCODE_META_LEFT = 117,
- AKEYCODE_META_RIGHT = 118,
- AKEYCODE_FUNCTION = 119,
- AKEYCODE_SYSRQ = 120,
- AKEYCODE_BREAK = 121,
- AKEYCODE_MOVE_HOME = 122,
- AKEYCODE_MOVE_END = 123,
- AKEYCODE_INSERT = 124,
- AKEYCODE_FORWARD = 125,
- AKEYCODE_MEDIA_PLAY = 126,
- AKEYCODE_MEDIA_PAUSE = 127,
- AKEYCODE_MEDIA_CLOSE = 128,
- AKEYCODE_MEDIA_EJECT = 129,
- AKEYCODE_MEDIA_RECORD = 130,
- AKEYCODE_F1 = 131,
- AKEYCODE_F2 = 132,
- AKEYCODE_F3 = 133,
- AKEYCODE_F4 = 134,
- AKEYCODE_F5 = 135,
- AKEYCODE_F6 = 136,
- AKEYCODE_F7 = 137,
- AKEYCODE_F8 = 138,
- AKEYCODE_F9 = 139,
- AKEYCODE_F10 = 140,
- AKEYCODE_F11 = 141,
- AKEYCODE_F12 = 142,
- AKEYCODE_NUM_LOCK = 143,
- AKEYCODE_NUMPAD_0 = 144,
- AKEYCODE_NUMPAD_1 = 145,
- AKEYCODE_NUMPAD_2 = 146,
- AKEYCODE_NUMPAD_3 = 147,
- AKEYCODE_NUMPAD_4 = 148,
- AKEYCODE_NUMPAD_5 = 149,
- AKEYCODE_NUMPAD_6 = 150,
- AKEYCODE_NUMPAD_7 = 151,
- AKEYCODE_NUMPAD_8 = 152,
- AKEYCODE_NUMPAD_9 = 153,
- AKEYCODE_NUMPAD_DIVIDE = 154,
- AKEYCODE_NUMPAD_MULTIPLY = 155,
- AKEYCODE_NUMPAD_SUBTRACT = 156,
- AKEYCODE_NUMPAD_ADD = 157,
- AKEYCODE_NUMPAD_DOT = 158,
- AKEYCODE_NUMPAD_COMMA = 159,
- AKEYCODE_NUMPAD_ENTER = 160,
- AKEYCODE_NUMPAD_EQUALS = 161,
- AKEYCODE_NUMPAD_LEFT_PAREN = 162,
- AKEYCODE_NUMPAD_RIGHT_PAREN = 163,
- AKEYCODE_VOLUME_MUTE = 164,
- AKEYCODE_INFO = 165,
- AKEYCODE_CHANNEL_UP = 166,
- AKEYCODE_CHANNEL_DOWN = 167,
- AKEYCODE_ZOOM_IN = 168,
- AKEYCODE_ZOOM_OUT = 169,
- AKEYCODE_TV = 170,
- AKEYCODE_WINDOW = 171,
- AKEYCODE_GUIDE = 172,
- AKEYCODE_DVR = 173,
- AKEYCODE_BOOKMARK = 174,
- AKEYCODE_CAPTIONS = 175,
- AKEYCODE_SETTINGS = 176,
- AKEYCODE_TV_POWER = 177,
- AKEYCODE_TV_INPUT = 178,
- AKEYCODE_STB_POWER = 179,
- AKEYCODE_STB_INPUT = 180,
- AKEYCODE_AVR_POWER = 181,
- AKEYCODE_AVR_INPUT = 182,
- AKEYCODE_PROG_RED = 183,
- AKEYCODE_PROG_GREEN = 184,
- AKEYCODE_PROG_YELLOW = 185,
- AKEYCODE_PROG_BLUE = 186,
- AKEYCODE_APP_SWITCH = 187,
- AKEYCODE_BUTTON_1 = 188,
- AKEYCODE_BUTTON_2 = 189,
- AKEYCODE_BUTTON_3 = 190,
- AKEYCODE_BUTTON_4 = 191,
- AKEYCODE_BUTTON_5 = 192,
- AKEYCODE_BUTTON_6 = 193,
- AKEYCODE_BUTTON_7 = 194,
- AKEYCODE_BUTTON_8 = 195,
- AKEYCODE_BUTTON_9 = 196,
- AKEYCODE_BUTTON_10 = 197,
- AKEYCODE_BUTTON_11 = 198,
- AKEYCODE_BUTTON_12 = 199,
- AKEYCODE_BUTTON_13 = 200,
- AKEYCODE_BUTTON_14 = 201,
- AKEYCODE_BUTTON_15 = 202,
- AKEYCODE_BUTTON_16 = 203,
- AKEYCODE_LANGUAGE_SWITCH = 204,
- AKEYCODE_MANNER_MODE = 205,
- AKEYCODE_3D_MODE = 206,
- AKEYCODE_CONTACTS = 207,
- AKEYCODE_CALENDAR = 208,
- AKEYCODE_MUSIC = 209,
- AKEYCODE_CALCULATOR = 210,
- AKEYCODE_ZENKAKU_HANKAKU = 211,
- AKEYCODE_EISU = 212,
- AKEYCODE_MUHENKAN = 213,
- AKEYCODE_HENKAN = 214,
- AKEYCODE_KATAKANA_HIRAGANA = 215,
- AKEYCODE_YEN = 216,
- AKEYCODE_RO = 217,
- AKEYCODE_KANA = 218,
- AKEYCODE_ASSIST = 219,
- AKEYCODE_BRIGHTNESS_DOWN = 220,
- AKEYCODE_BRIGHTNESS_UP = 221,
- AKEYCODE_MEDIA_AUDIO_TRACK = 222,
- AKEYCODE_SLEEP = 223,
- AKEYCODE_WAKEUP = 224,
- AKEYCODE_PAIRING = 225,
- AKEYCODE_MEDIA_TOP_MENU = 226,
- AKEYCODE_11 = 227,
- AKEYCODE_12 = 228,
- AKEYCODE_LAST_CHANNEL = 229,
- AKEYCODE_TV_DATA_SERVICE = 230,
- AKEYCODE_VOICE_ASSIST = 231,
- AKEYCODE_TV_RADIO_SERVICE = 232,
- AKEYCODE_TV_TELETEXT = 233,
- AKEYCODE_TV_NUMBER_ENTRY = 234,
- AKEYCODE_TV_TERRESTRIAL_ANALOG = 235,
- AKEYCODE_TV_TERRESTRIAL_DIGITAL = 236,
- AKEYCODE_TV_SATELLITE = 237,
- AKEYCODE_TV_SATELLITE_BS = 238,
- AKEYCODE_TV_SATELLITE_CS = 239,
- AKEYCODE_TV_SATELLITE_SERVICE = 240,
- AKEYCODE_TV_NETWORK = 241,
- AKEYCODE_TV_ANTENNA_CABLE = 242,
- AKEYCODE_TV_INPUT_HDMI_1 = 243,
- AKEYCODE_TV_INPUT_HDMI_2 = 244,
- AKEYCODE_TV_INPUT_HDMI_3 = 245,
- AKEYCODE_TV_INPUT_HDMI_4 = 246,
- AKEYCODE_TV_INPUT_COMPOSITE_1 = 247,
- AKEYCODE_TV_INPUT_COMPOSITE_2 = 248,
- AKEYCODE_TV_INPUT_COMPONENT_1 = 249,
- AKEYCODE_TV_INPUT_COMPONENT_2 = 250,
- AKEYCODE_TV_INPUT_VGA_1 = 251,
- AKEYCODE_TV_AUDIO_DESCRIPTION = 252,
- AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253,
- AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254,
- AKEYCODE_TV_ZOOM_MODE = 255,
- AKEYCODE_TV_CONTENTS_MENU = 256,
- AKEYCODE_TV_MEDIA_CONTEXT_MENU = 257,
- AKEYCODE_TV_TIMER_PROGRAMMING = 258,
- AKEYCODE_HELP = 259,
-
- // NOTE: If you add a new keycode here you must also add it to several other files.
- // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _ANDROID_KEYCODES_H
diff --git a/widget/gonk/libui/cutils_log.h b/widget/gonk/libui/cutils_log.h
deleted file mode 100644
index f4252c867..000000000
--- a/widget/gonk/libui/cutils_log.h
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-// C/C++ logging functions. See the logging documentation for API details.
-//
-// We'd like these to be available from C code (in case we import some from
-// somewhere), so this has a C interface.
-//
-// The output will be correct when the log file is shared between multiple
-// threads and/or multiple processes so long as the operating system
-// supports O_APPEND. These calls have mutex-protected data structures
-// and so are NOT reentrant. Do not use LOG in a signal handler.
-//
-#if !defined(_LIBS_CUTILS_LOG_H) && !defined(_LIBS_LOG_LOG_H)
-#define _LIBS_LOG_LOG_H
-#define _LIBS_CUTILS_LOG_H
-
-#include <stdio.h>
-#include <time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#ifdef HAVE_PTHREADS
-#include <pthread.h>
-#endif
-#include <stdarg.h>
-
-#if ANDROID_VERSION >= 19
-#include <log/uio.h>
-#include <log/logd.h>
-#else
-#include <cutils/uio.h>
-#include <cutils/logd.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Normally we strip ALOGV (VERBOSE messages) from release builds.
- * You can modify this (for example with "#define LOG_NDEBUG 0"
- * at the top of your source file) to change that behavior.
- */
-#ifndef LOG_NDEBUG
-#ifdef NDEBUG
-#define LOG_NDEBUG 1
-#else
-#define LOG_NDEBUG 0
-#endif
-#endif
-
-/*
- * This is the local tag used for the following simplified
- * logging macros. You can change this preprocessor definition
- * before using the other macros to change the tag.
- */
-#ifndef LOG_TAG
-#define LOG_TAG NULL
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Simplified macro to send a verbose log message using the current LOG_TAG.
- */
-#ifndef ALOGV
-#if LOG_NDEBUG
-#define ALOGV(...) ((void)0)
-#else
-#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
-#endif
-#endif
-
-#define CONDITION(cond) (__builtin_expect((cond)!=0, 0))
-
-#ifndef ALOGV_IF
-#if LOG_NDEBUG
-#define ALOGV_IF(cond, ...) ((void)0)
-#else
-#define ALOGV_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-#endif
-
-/*
- * Simplified macro to send a debug log message using the current LOG_TAG.
- */
-#ifndef ALOGD
-#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGD_IF
-#define ALOGD_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an info log message using the current LOG_TAG.
- */
-#ifndef ALOGI
-#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGI_IF
-#define ALOGI_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send a warning log message using the current LOG_TAG.
- */
-#ifndef ALOGW
-#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGW_IF
-#define ALOGW_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an error log message using the current LOG_TAG.
- */
-#ifndef ALOGE
-#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGE_IF
-#define ALOGE_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * verbose priority.
- */
-#ifndef IF_ALOGV
-#if LOG_NDEBUG
-#define IF_ALOGV() if (false)
-#else
-#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG)
-#endif
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * debug priority.
- */
-#ifndef IF_ALOGD
-#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG)
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * info priority.
- */
-#ifndef IF_ALOGI
-#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG)
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * warn priority.
- */
-#ifndef IF_ALOGW
-#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG)
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * error priority.
- */
-#ifndef IF_ALOGE
-#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG)
-#endif
-
-
-// ---------------------------------------------------------------------
-
-/*
- * Simplified macro to send a verbose system log message using the current LOG_TAG.
- */
-#ifndef SLOGV
-#if LOG_NDEBUG
-#define SLOGV(...) ((void)0)
-#else
-#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
-#endif
-#endif
-
-#define CONDITION(cond) (__builtin_expect((cond)!=0, 0))
-
-#ifndef SLOGV_IF
-#if LOG_NDEBUG
-#define SLOGV_IF(cond, ...) ((void)0)
-#else
-#define SLOGV_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-#endif
-
-/*
- * Simplified macro to send a debug system log message using the current LOG_TAG.
- */
-#ifndef SLOGD
-#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef SLOGD_IF
-#define SLOGD_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an info system log message using the current LOG_TAG.
- */
-#ifndef SLOGI
-#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef SLOGI_IF
-#define SLOGI_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send a warning system log message using the current LOG_TAG.
- */
-#ifndef SLOGW
-#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef SLOGW_IF
-#define SLOGW_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an error system log message using the current LOG_TAG.
- */
-#ifndef SLOGE
-#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef SLOGE_IF
-#define SLOGE_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Simplified macro to send a verbose radio log message using the current LOG_TAG.
- */
-#ifndef RLOGV
-#if LOG_NDEBUG
-#define RLOGV(...) ((void)0)
-#else
-#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
-#endif
-#endif
-
-#define CONDITION(cond) (__builtin_expect((cond)!=0, 0))
-
-#ifndef RLOGV_IF
-#if LOG_NDEBUG
-#define RLOGV_IF(cond, ...) ((void)0)
-#else
-#define RLOGV_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-#endif
-
-/*
- * Simplified macro to send a debug radio log message using the current LOG_TAG.
- */
-#ifndef RLOGD
-#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGD_IF
-#define RLOGD_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an info radio log message using the current LOG_TAG.
- */
-#ifndef RLOGI
-#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGI_IF
-#define RLOGI_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send a warning radio log message using the current LOG_TAG.
- */
-#ifndef RLOGW
-#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGW_IF
-#define RLOGW_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an error radio log message using the current LOG_TAG.
- */
-#ifndef RLOGE
-#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGE_IF
-#define RLOGE_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-
-// ---------------------------------------------------------------------
-
-/*
- * Log a fatal error. If the given condition fails, this stops program
- * execution like a normal assertion, but also generating the given message.
- * It is NOT stripped from release builds. Note that the condition test
- * is -inverted- from the normal assert() semantics.
- */
-#ifndef LOG_ALWAYS_FATAL_IF
-#define LOG_ALWAYS_FATAL_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-#ifndef LOG_ALWAYS_FATAL
-#define LOG_ALWAYS_FATAL(...) \
- ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
-#endif
-
-/*
- * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
- * are stripped out of release builds.
- */
-#if LOG_NDEBUG
-
-#ifndef LOG_FATAL_IF
-#define LOG_FATAL_IF(cond, ...) ((void)0)
-#endif
-#ifndef LOG_FATAL
-#define LOG_FATAL(...) ((void)0)
-#endif
-
-#else
-
-#ifndef LOG_FATAL_IF
-#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
-#endif
-#ifndef LOG_FATAL
-#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
-#endif
-
-#endif
-
-/*
- * Assertion that generates a log message when the assertion fails.
- * Stripped out of release builds. Uses the current LOG_TAG.
- */
-#ifndef ALOG_ASSERT
-#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
-//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Basic log message macro.
- *
- * Example:
- * ALOG(LOG_WARN, NULL, "Failed with error %d", errno);
- *
- * The second argument may be NULL or "" to indicate the "global" tag.
- */
-#ifndef ALOG
-#define ALOG(priority, tag, ...) \
- LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
-#endif
-
-/*
- * Log macro that allows you to specify a number for the priority.
- */
-#ifndef LOG_PRI
-#define LOG_PRI(priority, tag, ...) \
- android_printLog(priority, tag, __VA_ARGS__)
-#endif
-
-/*
- * Log macro that allows you to pass in a varargs ("args" is a va_list).
- */
-#ifndef LOG_PRI_VA
-#define LOG_PRI_VA(priority, tag, fmt, args) \
- android_vprintLog(priority, NULL, tag, fmt, args)
-#endif
-
-/*
- * Conditional given a desired logging priority and tag.
- */
-#ifndef IF_ALOG
-#define IF_ALOG(priority, tag) \
- if (android_testLog(ANDROID_##priority, tag))
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Event logging.
- */
-
-/*
- * Event log entry types. These must match up with the declarations in
- * java/android/android/util/EventLog.java.
- */
-typedef enum {
- EVENT_TYPE_INT = 0,
- EVENT_TYPE_LONG = 1,
- EVENT_TYPE_STRING = 2,
- EVENT_TYPE_LIST = 3,
-} AndroidEventLogType;
-
-
-#ifndef LOG_EVENT_INT
-#define LOG_EVENT_INT(_tag, _value) { \
- int intBuf = _value; \
- (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf, \
- sizeof(intBuf)); \
- }
-#endif
-#ifndef LOG_EVENT_LONG
-#define LOG_EVENT_LONG(_tag, _value) { \
- long long longBuf = _value; \
- (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf, \
- sizeof(longBuf)); \
- }
-#endif
-#ifndef LOG_EVENT_STRING
-#define LOG_EVENT_STRING(_tag, _value) \
- ((void) 0) /* not implemented -- must combine len with string */
-#endif
-/* TODO: something for LIST */
-
-/*
- * ===========================================================================
- *
- * The stuff in the rest of this file should not be used directly.
- */
-
-#define android_printLog(prio, tag, fmt...) \
- __android_log_print(prio, tag, fmt)
-
-#define android_vprintLog(prio, cond, tag, fmt...) \
- __android_log_vprint(prio, tag, fmt)
-
-/* XXX Macros to work around syntax errors in places where format string
- * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF
- * (happens only in debug builds).
- */
-
-/* Returns 2nd arg. Used to substitute default value if caller's vararg list
- * is empty.
- */
-#define __android_second(dummy, second, ...) second
-
-/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
- * returns nothing.
- */
-#define __android_rest(first, ...) , ## __VA_ARGS__
-
-#define android_printAssert(cond, tag, fmt...) \
- __android_log_assert(cond, tag, \
- __android_second(0, ## fmt, NULL) __android_rest(fmt))
-
-#define android_writeLog(prio, tag, text) \
- __android_log_write(prio, tag, text)
-
-#define android_bWriteLog(tag, payload, len) \
- __android_log_bwrite(tag, payload, len)
-#define android_btWriteLog(tag, type, payload, len) \
- __android_log_btwrite(tag, type, payload, len)
-
-// TODO: remove these prototypes and their users
-#define android_testLog(prio, tag) (1)
-#define android_writevLog(vec,num) do{}while(0)
-#define android_write1Log(str,len) do{}while (0)
-#define android_setMinPriority(tag, prio) do{}while(0)
-//#define android_logToCallback(func) do{}while(0)
-#define android_logToFile(tag, file) (0)
-#define android_logToFd(tag, fd) (0)
-
-typedef enum {
- LOG_ID_MAIN = 0,
- LOG_ID_RADIO = 1,
- LOG_ID_EVENTS = 2,
- LOG_ID_SYSTEM = 3,
-
- LOG_ID_MAX
-} log_id_t;
-
-/*
- * Send a simple string to the log.
- */
-int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text);
-int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _LIBS_CUTILS_LOG_H
diff --git a/widget/gonk/libui/cutils_trace.h b/widget/gonk/libui/cutils_trace.h
deleted file mode 100644
index 29034cab5..000000000
--- a/widget/gonk/libui/cutils_trace.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _LIBS_CUTILS_TRACE_H
-#define _LIBS_CUTILS_TRACE_H
-
-#include <sys/cdefs.h>
-#include <sys/types.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <cutils/compiler.h>
-
-#ifdef ANDROID_SMP
-#include <cutils/atomic-inline.h>
-#else
-#include <cutils/atomic.h>
-#endif
-
-__BEGIN_DECLS
-
-/**
- * The ATRACE_TAG macro can be defined before including this header to trace
- * using one of the tags defined below. It must be defined to one of the
- * following ATRACE_TAG_* macros. The trace tag is used to filter tracing in
- * userland to avoid some of the runtime cost of tracing when it is not desired.
- *
- * Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
- * being enabled - this should ONLY be done for debug code, as userland tracing
- * has a performance cost even when the trace is not being recorded. Defining
- * ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
- * in the tracing always being disabled.
- *
- * ATRACE_TAG_HAL should be bitwise ORed with the relevant tags for tracing
- * within a hardware module. For example a camera hardware module would set:
- * #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
- *
- * Keep these in sync with frameworks/base/core/java/android/os/Trace.java.
- */
-#define ATRACE_TAG_NEVER 0 // This tag is never enabled.
-#define ATRACE_TAG_ALWAYS (1<<0) // This tag is always enabled.
-#define ATRACE_TAG_GRAPHICS (1<<1)
-#define ATRACE_TAG_INPUT (1<<2)
-#define ATRACE_TAG_VIEW (1<<3)
-#define ATRACE_TAG_WEBVIEW (1<<4)
-#define ATRACE_TAG_WINDOW_MANAGER (1<<5)
-#define ATRACE_TAG_ACTIVITY_MANAGER (1<<6)
-#define ATRACE_TAG_SYNC_MANAGER (1<<7)
-#define ATRACE_TAG_AUDIO (1<<8)
-#define ATRACE_TAG_VIDEO (1<<9)
-#define ATRACE_TAG_CAMERA (1<<10)
-#define ATRACE_TAG_HAL (1<<11)
-#define ATRACE_TAG_APP (1<<12)
-#define ATRACE_TAG_RESOURCES (1<<13)
-#define ATRACE_TAG_DALVIK (1<<14)
-#define ATRACE_TAG_LAST ATRACE_TAG_DALVIK
-
-// Reserved for initialization.
-#define ATRACE_TAG_NOT_READY (1LL<<63)
-
-#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
-
-#ifndef ATRACE_TAG
-#define ATRACE_TAG ATRACE_TAG_NEVER
-#elif ATRACE_TAG > ATRACE_TAG_VALID_MASK
-#error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
-#endif
-
-#ifdef HAVE_ANDROID_OS
-/**
- * Maximum size of a message that can be logged to the trace buffer.
- * Note this message includes a tag, the pid, and the string given as the name.
- * Names should be kept short to get the most use of the trace buffer.
- */
-#define ATRACE_MESSAGE_LENGTH 1024
-
-/**
- * Opens the trace file for writing and reads the property for initial tags.
- * The atrace.tags.enableflags property sets the tags to trace.
- * This function should not be explicitly called, the first call to any normal
- * trace function will cause it to be run safely.
- */
-void atrace_setup();
-
-/**
- * If tracing is ready, set atrace_enabled_tags to the system property
- * debug.atrace.tags.enableflags. Can be used as a sysprop change callback.
- */
-void atrace_update_tags();
-
-/**
- * Set whether the process is debuggable. By default the process is not
- * considered debuggable. If the process is not debuggable then application-
- * level tracing is not allowed unless the ro.debuggable system property is
- * set to '1'.
- */
-void atrace_set_debuggable(bool debuggable);
-
-/**
- * Set whether tracing is enabled for the current process. This is used to
- * prevent tracing within the Zygote process.
- */
-void atrace_set_tracing_enabled(bool enabled);
-
-/**
- * Flag indicating whether setup has been completed, initialized to 0.
- * Nonzero indicates setup has completed.
- * Note: This does NOT indicate whether or not setup was successful.
- */
-extern volatile int32_t atrace_is_ready;
-
-/**
- * Set of ATRACE_TAG flags to trace for, initialized to ATRACE_TAG_NOT_READY.
- * A value of zero indicates setup has failed.
- * Any other nonzero value indicates setup has succeeded, and tracing is on.
- */
-extern uint64_t atrace_enabled_tags;
-
-/**
- * Handle to the kernel's trace buffer, initialized to -1.
- * Any other value indicates setup has succeeded, and is a valid fd for tracing.
- */
-extern int atrace_marker_fd;
-
-/**
- * atrace_init readies the process for tracing by opening the trace_marker file.
- * Calling any trace function causes this to be run, so calling it is optional.
- * This can be explicitly run to avoid setup delay on first trace function.
- */
-#define ATRACE_INIT() atrace_init()
-static inline void atrace_init()
-{
- if (CC_UNLIKELY(!android_atomic_acquire_load(&atrace_is_ready))) {
- atrace_setup();
- }
-}
-
-/**
- * Get the mask of all tags currently enabled.
- * It can be used as a guard condition around more expensive trace calculations.
- * Every trace function calls this, which ensures atrace_init is run.
- */
-#define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags()
-static inline uint64_t atrace_get_enabled_tags()
-{
- atrace_init();
- return atrace_enabled_tags;
-}
-
-/**
- * Test if a given tag is currently enabled.
- * Returns nonzero if the tag is enabled, otherwise zero.
- * It can be used as a guard condition around more expensive trace calculations.
- */
-#define ATRACE_ENABLED() atrace_is_tag_enabled(ATRACE_TAG)
-static inline uint64_t atrace_is_tag_enabled(uint64_t tag)
-{
- return atrace_get_enabled_tags() & tag;
-}
-
-/**
- * Trace the beginning of a context. name is used to identify the context.
- * This is often used to time function execution.
- */
-#define ATRACE_BEGIN(name) atrace_begin(ATRACE_TAG, name)
-static inline void atrace_begin(uint64_t tag, const char* name)
-{
- if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- char buf[ATRACE_MESSAGE_LENGTH];
- size_t len;
-
- len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "B|%d|%s", getpid(), name);
- write(atrace_marker_fd, buf, len);
- }
-}
-
-/**
- * Trace the end of a context.
- * This should match up (and occur after) a corresponding ATRACE_BEGIN.
- */
-#define ATRACE_END() atrace_end(ATRACE_TAG)
-static inline void atrace_end(uint64_t tag)
-{
- if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- char c = 'E';
- write(atrace_marker_fd, &c, 1);
- }
-}
-
-/**
- * Trace the beginning of an asynchronous event. Unlike ATRACE_BEGIN/ATRACE_END
- * contexts, asynchronous events do not need to be nested. The name describes
- * the event, and the cookie provides a unique identifier for distinguishing
- * simultaneous events. The name and cookie used to begin an event must be
- * used to end it.
- */
-#define ATRACE_ASYNC_BEGIN(name, cookie) \
- atrace_async_begin(ATRACE_TAG, name, cookie)
-static inline void atrace_async_begin(uint64_t tag, const char* name,
- int32_t cookie)
-{
- if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- char buf[ATRACE_MESSAGE_LENGTH];
- size_t len;
-
- len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "S|%d|%s|%d", getpid(),
- name, cookie);
- write(atrace_marker_fd, buf, len);
- }
-}
-
-/**
- * Trace the end of an asynchronous event.
- * This should have a corresponding ATRACE_ASYNC_BEGIN.
- */
-#define ATRACE_ASYNC_END(name, cookie) atrace_async_end(ATRACE_TAG, name, cookie)
-static inline void atrace_async_end(uint64_t tag, const char* name,
- int32_t cookie)
-{
- if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- char buf[ATRACE_MESSAGE_LENGTH];
- size_t len;
-
- len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "F|%d|%s|%d", getpid(),
- name, cookie);
- write(atrace_marker_fd, buf, len);
- }
-}
-
-
-/**
- * Traces an integer counter value. name is used to identify the counter.
- * This can be used to track how a value changes over time.
- */
-#define ATRACE_INT(name, value) atrace_int(ATRACE_TAG, name, value)
-static inline void atrace_int(uint64_t tag, const char* name, int32_t value)
-{
- if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- char buf[ATRACE_MESSAGE_LENGTH];
- size_t len;
-
- len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%d",
- getpid(), name, value);
- write(atrace_marker_fd, buf, len);
- }
-}
-
-#else // not HAVE_ANDROID_OS
-
-#define ATRACE_INIT()
-#define ATRACE_GET_ENABLED_TAGS()
-#define ATRACE_ENABLED()
-#define ATRACE_BEGIN(name)
-#define ATRACE_END()
-#define ATRACE_ASYNC_BEGIN(name, cookie)
-#define ATRACE_ASYNC_END(name, cookie)
-#define ATRACE_INT(name, value)
-
-#endif // not HAVE_ANDROID_OS
-
-__END_DECLS
-
-#endif // _LIBS_CUTILS_TRACE_H
diff --git a/widget/gonk/libui/linux_input.h b/widget/gonk/libui/linux_input.h
deleted file mode 100644
index 2ba14973f..000000000
--- a/widget/gonk/libui/linux_input.h
+++ /dev/null
@@ -1,1029 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _INPUT_H
-#define _INPUT_H
-#include <sys/time.h>
-#include <sys/ioctl.h>
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#include <sys/types.h>
-#include <linux/types.h>
-struct input_event {
- struct timeval time;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 type;
- __u16 code;
- __s32 value;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EV_VERSION 0x010001
-struct input_id {
- __u16 bustype;
- __u16 vendor;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 product;
- __u16 version;
-};
-struct input_absinfo {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __s32 value;
- __s32 minimum;
- __s32 maximum;
- __s32 fuzz;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __s32 flat;
- __s32 resolution;
-};
-struct input_keymap_entry {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define INPUT_KEYMAP_BY_INDEX (1 << 0)
- __u8 flags;
- __u8 len;
- __u16 index;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u32 keycode;
- __u8 scancode[32];
-};
-#define EVIOCGVERSION _IOR('E', 0x01, int)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EVIOCGID _IOR('E', 0x02, struct input_id)
-#define EVIOCGREP _IOR('E', 0x03, unsigned int[2])
-#define EVIOCSREP _IOW('E', 0x03, unsigned int[2])
-#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2])
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EVIOCGKEYCODE_V2 _IOR('E', 0x04, struct input_keymap_entry)
-#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2])
-#define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry)
-#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len)
-#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len)
-#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len)
-#define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len)
-#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len)
-#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len)
-#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + (ev), len)
-#define EVIOCGABS(abs) _IOR('E', 0x40 + (abs), struct input_absinfo)
-#define EVIOCSABS(abs) _IOW('E', 0xc0 + (abs), struct input_absinfo)
-#define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EVIOCRMFF _IOW('E', 0x81, int)
-#define EVIOCGEFFECTS _IOR('E', 0x84, int)
-#define EVIOCGRAB _IOW('E', 0x90, int)
-#define EVIOCGSUSPENDBLOCK _IOR('E', 0x91, int)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
-#define EVIOCSCLOCKID _IOW('E', 0xa0, int)
-#define INPUT_PROP_POINTER 0x00
-#define INPUT_PROP_DIRECT 0x01
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define INPUT_PROP_BUTTONPAD 0x02
-#define INPUT_PROP_SEMI_MT 0x03
-#define INPUT_PROP_MAX 0x1f
-#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EV_SYN 0x00
-#define EV_KEY 0x01
-#define EV_REL 0x02
-#define EV_ABS 0x03
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EV_MSC 0x04
-#define EV_SW 0x05
-#define EV_LED 0x11
-#define EV_SND 0x12
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EV_REP 0x14
-#define EV_FF 0x15
-#define EV_PWR 0x16
-#define EV_FF_STATUS 0x17
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define EV_MAX 0x1f
-#define EV_CNT (EV_MAX+1)
-#define SYN_REPORT 0
-#define SYN_CONFIG 1
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SYN_MT_REPORT 2
-#define SYN_DROPPED 3
-#define SYN_TIME_SEC 4
-#define SYN_TIME_NSEC 5
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_RESERVED 0
-#define KEY_ESC 1
-#define KEY_1 2
-#define KEY_2 3
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_3 4
-#define KEY_4 5
-#define KEY_5 6
-#define KEY_6 7
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_7 8
-#define KEY_8 9
-#define KEY_9 10
-#define KEY_0 11
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_MINUS 12
-#define KEY_EQUAL 13
-#define KEY_BACKSPACE 14
-#define KEY_TAB 15
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_Q 16
-#define KEY_W 17
-#define KEY_E 18
-#define KEY_R 19
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_T 20
-#define KEY_Y 21
-#define KEY_U 22
-#define KEY_I 23
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_O 24
-#define KEY_P 25
-#define KEY_LEFTBRACE 26
-#define KEY_RIGHTBRACE 27
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_ENTER 28
-#define KEY_LEFTCTRL 29
-#define KEY_A 30
-#define KEY_S 31
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_D 32
-#define KEY_F 33
-#define KEY_G 34
-#define KEY_H 35
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_J 36
-#define KEY_K 37
-#define KEY_L 38
-#define KEY_SEMICOLON 39
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_APOSTROPHE 40
-#define KEY_GRAVE 41
-#define KEY_LEFTSHIFT 42
-#define KEY_BACKSLASH 43
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_Z 44
-#define KEY_X 45
-#define KEY_C 46
-#define KEY_V 47
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_B 48
-#define KEY_N 49
-#define KEY_M 50
-#define KEY_COMMA 51
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_DOT 52
-#define KEY_SLASH 53
-#define KEY_RIGHTSHIFT 54
-#define KEY_KPASTERISK 55
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_LEFTALT 56
-#define KEY_SPACE 57
-#define KEY_CAPSLOCK 58
-#define KEY_F1 59
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_F2 60
-#define KEY_F3 61
-#define KEY_F4 62
-#define KEY_F5 63
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_F6 64
-#define KEY_F7 65
-#define KEY_F8 66
-#define KEY_F9 67
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_F10 68
-#define KEY_NUMLOCK 69
-#define KEY_SCROLLLOCK 70
-#define KEY_KP7 71
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_KP8 72
-#define KEY_KP9 73
-#define KEY_KPMINUS 74
-#define KEY_KP4 75
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_KP5 76
-#define KEY_KP6 77
-#define KEY_KPPLUS 78
-#define KEY_KP1 79
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_KP2 80
-#define KEY_KP3 81
-#define KEY_KP0 82
-#define KEY_KPDOT 83
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_ZENKAKUHANKAKU 85
-#define KEY_102ND 86
-#define KEY_F11 87
-#define KEY_F12 88
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_RO 89
-#define KEY_KATAKANA 90
-#define KEY_HIRAGANA 91
-#define KEY_HENKAN 92
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_KATAKANAHIRAGANA 93
-#define KEY_MUHENKAN 94
-#define KEY_KPJPCOMMA 95
-#define KEY_KPENTER 96
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_RIGHTCTRL 97
-#define KEY_KPSLASH 98
-#define KEY_SYSRQ 99
-#define KEY_RIGHTALT 100
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_LINEFEED 101
-#define KEY_HOME 102
-#define KEY_UP 103
-#define KEY_PAGEUP 104
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_LEFT 105
-#define KEY_RIGHT 106
-#define KEY_END 107
-#define KEY_DOWN 108
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_PAGEDOWN 109
-#define KEY_INSERT 110
-#define KEY_DELETE 111
-#define KEY_MACRO 112
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_MUTE 113
-#define KEY_VOLUMEDOWN 114
-#define KEY_VOLUMEUP 115
-#define KEY_POWER 116
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_KPEQUAL 117
-#define KEY_KPPLUSMINUS 118
-#define KEY_PAUSE 119
-#define KEY_SCALE 120
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_KPCOMMA 121
-#define KEY_HANGEUL 122
-#define KEY_HANGUEL KEY_HANGEUL
-#define KEY_HANJA 123
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_YEN 124
-#define KEY_LEFTMETA 125
-#define KEY_RIGHTMETA 126
-#define KEY_COMPOSE 127
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_STOP 128
-#define KEY_AGAIN 129
-#define KEY_PROPS 130
-#define KEY_UNDO 131
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FRONT 132
-#define KEY_COPY 133
-#define KEY_OPEN 134
-#define KEY_PASTE 135
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FIND 136
-#define KEY_CUT 137
-#define KEY_HELP 138
-#define KEY_MENU 139
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_CALC 140
-#define KEY_SETUP 141
-#define KEY_SLEEP 142
-#define KEY_WAKEUP 143
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FILE 144
-#define KEY_SENDFILE 145
-#define KEY_DELETEFILE 146
-#define KEY_XFER 147
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_PROG1 148
-#define KEY_PROG2 149
-#define KEY_WWW 150
-#define KEY_MSDOS 151
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_COFFEE 152
-#define KEY_SCREENLOCK KEY_COFFEE
-#define KEY_DIRECTION 153
-#define KEY_CYCLEWINDOWS 154
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_MAIL 155
-#define KEY_BOOKMARKS 156
-#define KEY_COMPUTER 157
-#define KEY_BACK 158
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FORWARD 159
-#define KEY_CLOSECD 160
-#define KEY_EJECTCD 161
-#define KEY_EJECTCLOSECD 162
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_NEXTSONG 163
-#define KEY_PLAYPAUSE 164
-#define KEY_PREVIOUSSONG 165
-#define KEY_STOPCD 166
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_RECORD 167
-#define KEY_REWIND 168
-#define KEY_PHONE 169
-#define KEY_ISO 170
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_CONFIG 171
-#define KEY_HOMEPAGE 172
-#define KEY_REFRESH 173
-#define KEY_EXIT 174
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_MOVE 175
-#define KEY_EDIT 176
-#define KEY_SCROLLUP 177
-#define KEY_SCROLLDOWN 178
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_KPLEFTPAREN 179
-#define KEY_KPRIGHTPAREN 180
-#define KEY_NEW 181
-#define KEY_REDO 182
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_F13 183
-#define KEY_F14 184
-#define KEY_F15 185
-#define KEY_F16 186
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_F17 187
-#define KEY_F18 188
-#define KEY_F19 189
-#define KEY_F20 190
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_F21 191
-#define KEY_F22 192
-#define KEY_F23 193
-#define KEY_F24 194
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_PLAYCD 200
-#define KEY_PAUSECD 201
-#define KEY_PROG3 202
-#define KEY_PROG4 203
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_DASHBOARD 204
-#define KEY_SUSPEND 205
-#define KEY_CLOSE 206
-#define KEY_PLAY 207
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FASTFORWARD 208
-#define KEY_BASSBOOST 209
-#define KEY_PRINT 210
-#define KEY_HP 211
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_CAMERA 212
-#define KEY_SOUND 213
-#define KEY_QUESTION 214
-#define KEY_EMAIL 215
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_CHAT 216
-#define KEY_SEARCH 217
-#define KEY_CONNECT 218
-#define KEY_FINANCE 219
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_SPORT 220
-#define KEY_SHOP 221
-#define KEY_ALTERASE 222
-#define KEY_CANCEL 223
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_BRIGHTNESSDOWN 224
-#define KEY_BRIGHTNESSUP 225
-#define KEY_MEDIA 226
-#define KEY_SWITCHVIDEOMODE 227
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_KBDILLUMTOGGLE 228
-#define KEY_KBDILLUMDOWN 229
-#define KEY_KBDILLUMUP 230
-#define KEY_SEND 231
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_REPLY 232
-#define KEY_FORWARDMAIL 233
-#define KEY_SAVE 234
-#define KEY_DOCUMENTS 235
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_BATTERY 236
-#define KEY_BLUETOOTH 237
-#define KEY_WLAN 238
-#define KEY_UWB 239
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_UNKNOWN 240
-#define KEY_VIDEO_NEXT 241
-#define KEY_VIDEO_PREV 242
-#define KEY_BRIGHTNESS_CYCLE 243
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_BRIGHTNESS_ZERO 244
-#define KEY_DISPLAY_OFF 245
-#define KEY_WIMAX 246
-#define KEY_RFKILL 247
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_MICMUTE 248
-#define BTN_MISC 0x100
-#define BTN_0 0x100
-#define BTN_1 0x101
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_2 0x102
-#define BTN_3 0x103
-#define BTN_4 0x104
-#define BTN_5 0x105
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_6 0x106
-#define BTN_7 0x107
-#define BTN_8 0x108
-#define BTN_9 0x109
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_MOUSE 0x110
-#define BTN_LEFT 0x110
-#define BTN_RIGHT 0x111
-#define BTN_MIDDLE 0x112
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_SIDE 0x113
-#define BTN_EXTRA 0x114
-#define BTN_FORWARD 0x115
-#define BTN_BACK 0x116
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TASK 0x117
-#define BTN_JOYSTICK 0x120
-#define BTN_TRIGGER 0x120
-#define BTN_THUMB 0x121
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_THUMB2 0x122
-#define BTN_TOP 0x123
-#define BTN_TOP2 0x124
-#define BTN_PINKIE 0x125
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_BASE 0x126
-#define BTN_BASE2 0x127
-#define BTN_BASE3 0x128
-#define BTN_BASE4 0x129
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_BASE5 0x12a
-#define BTN_BASE6 0x12b
-#define BTN_DEAD 0x12f
-#define BTN_GAMEPAD 0x130
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_A 0x130
-#define BTN_B 0x131
-#define BTN_C 0x132
-#define BTN_X 0x133
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_Y 0x134
-#define BTN_Z 0x135
-#define BTN_TL 0x136
-#define BTN_TR 0x137
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TL2 0x138
-#define BTN_TR2 0x139
-#define BTN_SELECT 0x13a
-#define BTN_START 0x13b
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_MODE 0x13c
-#define BTN_THUMBL 0x13d
-#define BTN_THUMBR 0x13e
-#define BTN_DIGI 0x140
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TOOL_PEN 0x140
-#define BTN_TOOL_RUBBER 0x141
-#define BTN_TOOL_BRUSH 0x142
-#define BTN_TOOL_PENCIL 0x143
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TOOL_AIRBRUSH 0x144
-#define BTN_TOOL_FINGER 0x145
-#define BTN_TOOL_MOUSE 0x146
-#define BTN_TOOL_LENS 0x147
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TOOL_QUINTTAP 0x148
-#define BTN_TOUCH 0x14a
-#define BTN_STYLUS 0x14b
-#define BTN_STYLUS2 0x14c
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TOOL_DOUBLETAP 0x14d
-#define BTN_TOOL_TRIPLETAP 0x14e
-#define BTN_TOOL_QUADTAP 0x14f
-#define BTN_WHEEL 0x150
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_GEAR_DOWN 0x150
-#define BTN_GEAR_UP 0x151
-#define KEY_OK 0x160
-#define KEY_SELECT 0x161
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_GOTO 0x162
-#define KEY_CLEAR 0x163
-#define KEY_POWER2 0x164
-#define KEY_OPTION 0x165
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_INFO 0x166
-#define KEY_TIME 0x167
-#define KEY_VENDOR 0x168
-#define KEY_ARCHIVE 0x169
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_PROGRAM 0x16a
-#define KEY_CHANNEL 0x16b
-#define KEY_FAVORITES 0x16c
-#define KEY_EPG 0x16d
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_PVR 0x16e
-#define KEY_MHP 0x16f
-#define KEY_LANGUAGE 0x170
-#define KEY_TITLE 0x171
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_SUBTITLE 0x172
-#define KEY_ANGLE 0x173
-#define KEY_ZOOM 0x174
-#define KEY_MODE 0x175
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_KEYBOARD 0x176
-#define KEY_SCREEN 0x177
-#define KEY_PC 0x178
-#define KEY_TV 0x179
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_TV2 0x17a
-#define KEY_VCR 0x17b
-#define KEY_VCR2 0x17c
-#define KEY_SAT 0x17d
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_SAT2 0x17e
-#define KEY_CD 0x17f
-#define KEY_TAPE 0x180
-#define KEY_RADIO 0x181
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_TUNER 0x182
-#define KEY_PLAYER 0x183
-#define KEY_TEXT 0x184
-#define KEY_DVD 0x185
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_AUX 0x186
-#define KEY_MP3 0x187
-#define KEY_AUDIO 0x188
-#define KEY_VIDEO 0x189
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_DIRECTORY 0x18a
-#define KEY_LIST 0x18b
-#define KEY_MEMO 0x18c
-#define KEY_CALENDAR 0x18d
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_RED 0x18e
-#define KEY_GREEN 0x18f
-#define KEY_YELLOW 0x190
-#define KEY_BLUE 0x191
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_CHANNELUP 0x192
-#define KEY_CHANNELDOWN 0x193
-#define KEY_FIRST 0x194
-#define KEY_LAST 0x195
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_AB 0x196
-#define KEY_NEXT 0x197
-#define KEY_RESTART 0x198
-#define KEY_SLOW 0x199
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_SHUFFLE 0x19a
-#define KEY_BREAK 0x19b
-#define KEY_PREVIOUS 0x19c
-#define KEY_DIGITS 0x19d
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_TEEN 0x19e
-#define KEY_TWEN 0x19f
-#define KEY_VIDEOPHONE 0x1a0
-#define KEY_GAMES 0x1a1
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_ZOOMIN 0x1a2
-#define KEY_ZOOMOUT 0x1a3
-#define KEY_ZOOMRESET 0x1a4
-#define KEY_WORDPROCESSOR 0x1a5
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_EDITOR 0x1a6
-#define KEY_SPREADSHEET 0x1a7
-#define KEY_GRAPHICSEDITOR 0x1a8
-#define KEY_PRESENTATION 0x1a9
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_DATABASE 0x1aa
-#define KEY_NEWS 0x1ab
-#define KEY_VOICEMAIL 0x1ac
-#define KEY_ADDRESSBOOK 0x1ad
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_MESSENGER 0x1ae
-#define KEY_DISPLAYTOGGLE 0x1af
-#define KEY_SPELLCHECK 0x1b0
-#define KEY_LOGOFF 0x1b1
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_DOLLAR 0x1b2
-#define KEY_EURO 0x1b3
-#define KEY_FRAMEBACK 0x1b4
-#define KEY_FRAMEFORWARD 0x1b5
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_CONTEXT_MENU 0x1b6
-#define KEY_MEDIA_REPEAT 0x1b7
-#define KEY_10CHANNELSUP 0x1b8
-#define KEY_10CHANNELSDOWN 0x1b9
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_IMAGES 0x1ba
-#define KEY_DEL_EOL 0x1c0
-#define KEY_DEL_EOS 0x1c1
-#define KEY_INS_LINE 0x1c2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_DEL_LINE 0x1c3
-#define KEY_FN 0x1d0
-#define KEY_FN_ESC 0x1d1
-#define KEY_FN_F1 0x1d2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FN_F2 0x1d3
-#define KEY_FN_F3 0x1d4
-#define KEY_FN_F4 0x1d5
-#define KEY_FN_F5 0x1d6
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FN_F6 0x1d7
-#define KEY_FN_F7 0x1d8
-#define KEY_FN_F8 0x1d9
-#define KEY_FN_F9 0x1da
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FN_F10 0x1db
-#define KEY_FN_F11 0x1dc
-#define KEY_FN_F12 0x1dd
-#define KEY_FN_1 0x1de
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FN_2 0x1df
-#define KEY_FN_D 0x1e0
-#define KEY_FN_E 0x1e1
-#define KEY_FN_F 0x1e2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_FN_S 0x1e3
-#define KEY_FN_B 0x1e4
-#define KEY_BRL_DOT1 0x1f1
-#define KEY_BRL_DOT2 0x1f2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_BRL_DOT3 0x1f3
-#define KEY_BRL_DOT4 0x1f4
-#define KEY_BRL_DOT5 0x1f5
-#define KEY_BRL_DOT6 0x1f6
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_BRL_DOT7 0x1f7
-#define KEY_BRL_DOT8 0x1f8
-#define KEY_BRL_DOT9 0x1f9
-#define KEY_BRL_DOT10 0x1fa
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_NUMERIC_0 0x200
-#define KEY_NUMERIC_1 0x201
-#define KEY_NUMERIC_2 0x202
-#define KEY_NUMERIC_3 0x203
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_NUMERIC_4 0x204
-#define KEY_NUMERIC_5 0x205
-#define KEY_NUMERIC_6 0x206
-#define KEY_NUMERIC_7 0x207
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_NUMERIC_8 0x208
-#define KEY_NUMERIC_9 0x209
-#define KEY_NUMERIC_STAR 0x20a
-#define KEY_NUMERIC_POUND 0x20b
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_CAMERA_SNAPSHOT 0x2fe
-#define KEY_CAMERA_FOCUS 0x210
-#define KEY_WPS_BUTTON 0x211
-#define KEY_TOUCHPAD_TOGGLE 0x212
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_TOUCHPAD_ON 0x213
-#define KEY_TOUCHPAD_OFF 0x214
-#define KEY_CAMERA_ZOOMIN 0x215
-#define KEY_CAMERA_ZOOMOUT 0x216
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define KEY_CAMERA_UP 0x217
-#define KEY_CAMERA_DOWN 0x218
-#define KEY_CAMERA_LEFT 0x219
-#define KEY_CAMERA_RIGHT 0x21a
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY 0x2c0
-#define BTN_TRIGGER_HAPPY1 0x2c0
-#define BTN_TRIGGER_HAPPY2 0x2c1
-#define BTN_TRIGGER_HAPPY3 0x2c2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY4 0x2c3
-#define BTN_TRIGGER_HAPPY5 0x2c4
-#define BTN_TRIGGER_HAPPY6 0x2c5
-#define BTN_TRIGGER_HAPPY7 0x2c6
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY8 0x2c7
-#define BTN_TRIGGER_HAPPY9 0x2c8
-#define BTN_TRIGGER_HAPPY10 0x2c9
-#define BTN_TRIGGER_HAPPY11 0x2ca
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY12 0x2cb
-#define BTN_TRIGGER_HAPPY13 0x2cc
-#define BTN_TRIGGER_HAPPY14 0x2cd
-#define BTN_TRIGGER_HAPPY15 0x2ce
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY16 0x2cf
-#define BTN_TRIGGER_HAPPY17 0x2d0
-#define BTN_TRIGGER_HAPPY18 0x2d1
-#define BTN_TRIGGER_HAPPY19 0x2d2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY20 0x2d3
-#define BTN_TRIGGER_HAPPY21 0x2d4
-#define BTN_TRIGGER_HAPPY22 0x2d5
-#define BTN_TRIGGER_HAPPY23 0x2d6
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY24 0x2d7
-#define BTN_TRIGGER_HAPPY25 0x2d8
-#define BTN_TRIGGER_HAPPY26 0x2d9
-#define BTN_TRIGGER_HAPPY27 0x2da
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY28 0x2db
-#define BTN_TRIGGER_HAPPY29 0x2dc
-#define BTN_TRIGGER_HAPPY30 0x2dd
-#define BTN_TRIGGER_HAPPY31 0x2de
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY32 0x2df
-#define BTN_TRIGGER_HAPPY33 0x2e0
-#define BTN_TRIGGER_HAPPY34 0x2e1
-#define BTN_TRIGGER_HAPPY35 0x2e2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY36 0x2e3
-#define BTN_TRIGGER_HAPPY37 0x2e4
-#define BTN_TRIGGER_HAPPY38 0x2e5
-#define BTN_TRIGGER_HAPPY39 0x2e6
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BTN_TRIGGER_HAPPY40 0x2e7
-#define KEY_MIN_INTERESTING KEY_MUTE
-#define KEY_MAX 0x2ff
-#define KEY_CNT (KEY_MAX+1)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define REL_X 0x00
-#define REL_Y 0x01
-#define REL_Z 0x02
-#define REL_RX 0x03
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define REL_RY 0x04
-#define REL_RZ 0x05
-#define REL_HWHEEL 0x06
-#define REL_DIAL 0x07
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define REL_WHEEL 0x08
-#define REL_MISC 0x09
-#define REL_MAX 0x0f
-#define REL_CNT (REL_MAX+1)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_X 0x00
-#define ABS_Y 0x01
-#define ABS_Z 0x02
-#define ABS_RX 0x03
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_RY 0x04
-#define ABS_RZ 0x05
-#define ABS_THROTTLE 0x06
-#define ABS_RUDDER 0x07
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_WHEEL 0x08
-#define ABS_GAS 0x09
-#define ABS_BRAKE 0x0a
-#define ABS_HAT0X 0x10
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_HAT0Y 0x11
-#define ABS_HAT1X 0x12
-#define ABS_HAT1Y 0x13
-#define ABS_HAT2X 0x14
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_HAT2Y 0x15
-#define ABS_HAT3X 0x16
-#define ABS_HAT3Y 0x17
-#define ABS_PRESSURE 0x18
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_DISTANCE 0x19
-#define ABS_TILT_X 0x1a
-#define ABS_TILT_Y 0x1b
-#define ABS_TOOL_WIDTH 0x1c
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_VOLUME 0x20
-#define ABS_MISC 0x28
-#define ABS_MT_SLOT 0x2f
-#define ABS_MT_TOUCH_MAJOR 0x30
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_MT_TOUCH_MINOR 0x31
-#define ABS_MT_WIDTH_MAJOR 0x32
-#define ABS_MT_WIDTH_MINOR 0x33
-#define ABS_MT_ORIENTATION 0x34
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_MT_POSITION_X 0x35
-#define ABS_MT_POSITION_Y 0x36
-#define ABS_MT_TOOL_TYPE 0x37
-#define ABS_MT_BLOB_ID 0x38
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_MT_TRACKING_ID 0x39
-#define ABS_MT_PRESSURE 0x3a
-#define ABS_MT_DISTANCE 0x3b
-#define ABS_MAX 0x3f
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ABS_CNT (ABS_MAX+1)
-#define SW_LID 0x00
-#define SW_TABLET_MODE 0x01
-#define SW_HEADPHONE_INSERT 0x02
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SW_RFKILL_ALL 0x03
-#define SW_RADIO SW_RFKILL_ALL
-#define SW_MICROPHONE_INSERT 0x04
-#define SW_DOCK 0x05
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SW_LINEOUT_INSERT 0x06
-#define SW_JACK_PHYSICAL_INSERT 0x07
-#define SW_VIDEOOUT_INSERT 0x08
-#define SW_CAMERA_LENS_COVER 0x09
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SW_KEYPAD_SLIDE 0x0a
-#define SW_FRONT_PROXIMITY 0x0b
-#define SW_ROTATE_LOCK 0x0c
-#define SW_LINEIN_INSERT 0x0d
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SW_HPHL_OVERCURRENT 0x0e
-#define SW_HPHR_OVERCURRENT 0x0f
-#define SW_UNSUPPORT_INSERT 0x10
-#define SW_MAX 0x20
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SW_CNT (SW_MAX+1)
-#define MSC_SERIAL 0x00
-#define MSC_PULSELED 0x01
-#define MSC_GESTURE 0x02
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MSC_RAW 0x03
-#define MSC_SCAN 0x04
-#define MSC_MAX 0x07
-#define MSC_CNT (MSC_MAX+1)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define LED_NUML 0x00
-#define LED_CAPSL 0x01
-#define LED_SCROLLL 0x02
-#define LED_COMPOSE 0x03
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define LED_KANA 0x04
-#define LED_SLEEP 0x05
-#define LED_SUSPEND 0x06
-#define LED_MUTE 0x07
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define LED_MISC 0x08
-#define LED_MAIL 0x09
-#define LED_CHARGING 0x0a
-#define LED_MAX 0x0f
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define LED_CNT (LED_MAX+1)
-#define REP_DELAY 0x00
-#define REP_PERIOD 0x01
-#define REP_MAX 0x01
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define REP_CNT (REP_MAX+1)
-#define SND_CLICK 0x00
-#define SND_BELL 0x01
-#define SND_TONE 0x02
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SND_MAX 0x07
-#define SND_CNT (SND_MAX+1)
-#define ID_BUS 0
-#define ID_VENDOR 1
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ID_PRODUCT 2
-#define ID_VERSION 3
-#define BUS_PCI 0x01
-#define BUS_ISAPNP 0x02
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BUS_USB 0x03
-#define BUS_HIL 0x04
-#define BUS_BLUETOOTH 0x05
-#define BUS_VIRTUAL 0x06
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BUS_ISA 0x10
-#define BUS_I8042 0x11
-#define BUS_XTKBD 0x12
-#define BUS_RS232 0x13
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BUS_GAMEPORT 0x14
-#define BUS_PARPORT 0x15
-#define BUS_AMIGA 0x16
-#define BUS_ADB 0x17
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BUS_I2C 0x18
-#define BUS_HOST 0x19
-#define BUS_GSC 0x1A
-#define BUS_ATARI 0x1B
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BUS_SPI 0x1C
-#define MT_TOOL_FINGER 0
-#define MT_TOOL_PEN 1
-#define MT_TOOL_MAX 1
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define FF_STATUS_STOPPED 0x00
-#define FF_STATUS_PLAYING 0x01
-#define FF_STATUS_MAX 0x01
-struct ff_replay {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 length;
- __u16 delay;
-};
-struct ff_trigger {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 button;
- __u16 interval;
-};
-struct ff_envelope {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 attack_length;
- __u16 attack_level;
- __u16 fade_length;
- __u16 fade_level;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-struct ff_constant_effect {
- __s16 level;
- struct ff_envelope envelope;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-struct ff_ramp_effect {
- __s16 start_level;
- __s16 end_level;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct ff_envelope envelope;
-};
-struct ff_condition_effect {
- __u16 right_saturation;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 left_saturation;
- __s16 right_coeff;
- __s16 left_coeff;
- __u16 deadband;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __s16 center;
-};
-struct ff_periodic_effect {
- __u16 waveform;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 period;
- __s16 magnitude;
- __s16 offset;
- __u16 phase;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct ff_envelope envelope;
- __u32 custom_len;
- __s16 __user *custom_data;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct ff_rumble_effect {
- __u16 strong_magnitude;
- __u16 weak_magnitude;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct ff_effect {
- __u16 type;
- __s16 id;
- __u16 direction;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct ff_trigger trigger;
- struct ff_replay replay;
- union {
- struct ff_constant_effect constant;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct ff_ramp_effect ramp;
- struct ff_periodic_effect periodic;
- struct ff_condition_effect condition[2];
- struct ff_rumble_effect rumble;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- } u;
-};
-#define FF_RUMBLE 0x50
-#define FF_PERIODIC 0x51
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define FF_CONSTANT 0x52
-#define FF_SPRING 0x53
-#define FF_FRICTION 0x54
-#define FF_DAMPER 0x55
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define FF_INERTIA 0x56
-#define FF_RAMP 0x57
-#define FF_EFFECT_MIN FF_RUMBLE
-#define FF_EFFECT_MAX FF_RAMP
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define FF_SQUARE 0x58
-#define FF_TRIANGLE 0x59
-#define FF_SINE 0x5a
-#define FF_SAW_UP 0x5b
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define FF_SAW_DOWN 0x5c
-#define FF_CUSTOM 0x5d
-#define FF_WAVEFORM_MIN FF_SQUARE
-#define FF_WAVEFORM_MAX FF_CUSTOM
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define FF_GAIN 0x60
-#define FF_AUTOCENTER 0x61
-#define FF_MAX 0x7f
-#define FF_CNT (FF_MAX+1)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
diff --git a/widget/gonk/libui/sha1.c b/widget/gonk/libui/sha1.c
deleted file mode 100644
index 40a4ecaa3..000000000
--- a/widget/gonk/libui/sha1.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/* $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $ */
-/* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */
-
-/*
- * SHA-1 in C
- * By Steve Reid <steve@edmweb.com>
- * 100% Public Domain
- *
- * Test Vectors (from FIPS PUB 180-1)
- * "abc"
- * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
- * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
- * A million repetitions of "a"
- * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
- */
-
-#define SHA1HANDSOFF /* Copies data before messing with it. */
-
-#include <sys/cdefs.h>
-
-#if defined(_KERNEL) || defined(_STANDALONE)
-__KERNEL_RCSID(0, "$NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $");
-
-#include <lib/libkern/libkern.h>
-
-#else
-
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#include <string.h>
-
-#endif
-
-#include <sys/types.h>
-#include "sha1.h"
-
-#define _DIAGASSERT assert
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#if !HAVE_SHA1_H
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/*
- * blk0() and blk() perform the initial expand.
- * I got the idea of expanding during the round function from SSLeay
- */
-#if BYTE_ORDER == LITTLE_ENDIAN
-# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
- |(rol(block->l[i],8)&0x00FF00FF))
-#else
-# define blk0(i) block->l[i]
-#endif
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
- ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/*
- * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
- */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-
-#if !defined(_KERNEL) && !defined(_STANDALONE)
-#if defined(__weak_alias)
-__weak_alias(SHA1Transform,_SHA1Transform)
-__weak_alias(SHA1Init,_SHA1Init)
-__weak_alias(SHA1Update,_SHA1Update)
-__weak_alias(SHA1Final,_SHA1Final)
-#endif
-#endif
-
-typedef union {
- uint8_t c[64];
- uint32_t l[16];
-} CHAR64LONG16;
-
-/* old sparc64 gcc could not compile this */
-#undef SPARC64_GCC_WORKAROUND
-#if defined(__sparc64__) && defined(__GNUC__) && __GNUC__ < 3
-#define SPARC64_GCC_WORKAROUND
-#endif
-
-#ifdef SPARC64_GCC_WORKAROUND
-void do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *);
-void do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *);
-void do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *);
-void do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *);
-
-#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i)
-#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i)
-#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i)
-#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i)
-#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i)
-
-void
-do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block)
-{
- nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2); nR0(c,d,e,a,b, 3);
- nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5); nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7);
- nR0(c,d,e,a,b, 8); nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11);
- nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14); nR0(a,b,c,d,e,15);
- nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17); nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19);
-}
-
-void
-do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block)
-{
- nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22); nR2(c,d,e,a,b,23);
- nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25); nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27);
- nR2(c,d,e,a,b,28); nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31);
- nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34); nR2(a,b,c,d,e,35);
- nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37); nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39);
-}
-
-void
-do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block)
-{
- nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42); nR3(c,d,e,a,b,43);
- nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45); nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47);
- nR3(c,d,e,a,b,48); nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51);
- nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54); nR3(a,b,c,d,e,55);
- nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57); nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59);
-}
-
-void
-do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block)
-{
- nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62); nR4(c,d,e,a,b,63);
- nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65); nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67);
- nR4(c,d,e,a,b,68); nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71);
- nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74); nR4(a,b,c,d,e,75);
- nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77); nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79);
-}
-#endif
-
-/*
- * Hash a single 512-bit block. This is the core of the algorithm.
- */
-void SHA1Transform(uint32_t state[5], const uint8_t buffer[64])
-{
- uint32_t a, b, c, d, e;
- CHAR64LONG16 *block;
-
-#ifdef SHA1HANDSOFF
- CHAR64LONG16 workspace;
-#endif
-
- _DIAGASSERT(buffer != 0);
- _DIAGASSERT(state != 0);
-
-#ifdef SHA1HANDSOFF
- block = &workspace;
- (void)memcpy(block, buffer, 64);
-#else
- block = (CHAR64LONG16 *)(void *)buffer;
-#endif
-
- /* Copy context->state[] to working vars */
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
-
-#ifdef SPARC64_GCC_WORKAROUND
- do_R01(&a, &b, &c, &d, &e, block);
- do_R2(&a, &b, &c, &d, &e, block);
- do_R3(&a, &b, &c, &d, &e, block);
- do_R4(&a, &b, &c, &d, &e, block);
-#else
- /* 4 rounds of 20 operations each. Loop unrolled. */
- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
- R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
- R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-#endif
-
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
-
- /* Wipe variables */
- a = b = c = d = e = 0;
-}
-
-
-/*
- * SHA1Init - Initialize new context
- */
-void SHA1Init(SHA1_CTX *context)
-{
-
- _DIAGASSERT(context != 0);
-
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = context->count[1] = 0;
-}
-
-
-/*
- * Run your data through this.
- */
-void SHA1Update(SHA1_CTX *context, const uint8_t *data, unsigned int len)
-{
- unsigned int i, j;
-
- _DIAGASSERT(context != 0);
- _DIAGASSERT(data != 0);
-
- j = context->count[0];
- if ((context->count[0] += len << 3) < j)
- context->count[1] += (len>>29)+1;
- j = (j >> 3) & 63;
- if ((j + len) > 63) {
- (void)memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64)
- SHA1Transform(context->state, &data[i]);
- j = 0;
- } else {
- i = 0;
- }
- (void)memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/*
- * Add padding and return the message digest.
- */
-void SHA1Final(uint8_t digest[20], SHA1_CTX *context)
-{
- unsigned int i;
- uint8_t finalcount[8];
-
- _DIAGASSERT(digest != 0);
- _DIAGASSERT(context != 0);
-
- for (i = 0; i < 8; i++) {
- finalcount[i] = (uint8_t)((context->count[(i >= 4 ? 0 : 1)]
- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
- }
- SHA1Update(context, (const uint8_t *)"\200", 1);
- while ((context->count[0] & 504) != 448)
- SHA1Update(context, (const uint8_t *)"\0", 1);
- SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
-
- if (digest) {
- for (i = 0; i < 20; i++)
- digest[i] = (uint8_t)
- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- }
-}
-
-#endif /* HAVE_SHA1_H */
diff --git a/widget/gonk/libui/sha1.h b/widget/gonk/libui/sha1.h
deleted file mode 100644
index f7ada46a5..000000000
--- a/widget/gonk/libui/sha1.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* $NetBSD: sha1.h,v 1.13 2005/12/26 18:41:36 perry Exp $ */
-
-/*
- * SHA-1 in C
- * By Steve Reid <steve@edmweb.com>
- * 100% Public Domain
- */
-
-#ifndef _SYS_SHA1_H_
-#define _SYS_SHA1_H_
-
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#define SHA1_DIGEST_LENGTH 20
-#define SHA1_DIGEST_STRING_LENGTH 41
-
-typedef struct {
- uint32_t state[5];
- uint32_t count[2];
- u_char buffer[64];
-} SHA1_CTX;
-
-__BEGIN_DECLS
-void SHA1Transform(uint32_t[5], const u_char[64]);
-void SHA1Init(SHA1_CTX *);
-void SHA1Update(SHA1_CTX *, const u_char *, u_int);
-void SHA1Final(u_char[SHA1_DIGEST_LENGTH], SHA1_CTX *);
-__END_DECLS
-
-#endif /* _SYS_SHA1_H_ */
diff --git a/widget/gonk/moz.build b/widget/gonk/moz.build
deleted file mode 100644
index d539dd9a0..000000000
--- a/widget/gonk/moz.build
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# Copyright 2013 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-EXPORTS += [
- 'GeckoTouchDispatcher.h',
- 'GonkPermission.h',
- 'OrientationObserver.h',
-]
-
-DIRS += ['libdisplay', 'nativewindow']
-
-# libui files
-SOURCES += ['libui/' + src for src in [
- 'EventHub.cpp',
- 'Input.cpp',
- 'InputApplication.cpp',
- 'InputDevice.cpp',
- 'InputDispatcher.cpp',
- 'InputListener.cpp',
- 'InputReader.cpp',
- 'InputTransport.cpp',
- 'InputWindow.cpp',
- 'Keyboard.cpp',
- 'KeyCharacterMap.cpp',
- 'KeyLayoutMap.cpp',
- 'PointerController.cpp',
- 'sha1.c',
- 'SpriteController.cpp',
- 'Tokenizer.cpp',
- 'VelocityControl.cpp',
- 'VelocityTracker.cpp',
- 'VirtualKeyMap.cpp',
-]]
-
-# HwcHAL files
-if CONFIG['ANDROID_VERSION'] >= '17':
- SOURCES += [
- 'hwchal/HwcHAL.cpp',
- ]
-
-SOURCES += [
- 'GeckoTouchDispatcher.cpp',
- 'GfxInfo.cpp',
- 'GonkClipboardData.cpp',
- 'GonkMemoryPressureMonitoring.cpp',
- 'GonkPermission.cpp',
- 'HwcComposer2D.cpp',
- 'HwcUtils.cpp',
- 'nsAppShell.cpp',
- 'nsClipboard.cpp',
- 'nsIdleServiceGonk.cpp',
- 'nsLookAndFeel.cpp',
- 'nsScreenManagerGonk.cpp',
- 'nsWidgetFactory.cpp',
- 'nsWindow.cpp',
- 'OrientationObserver.cpp',
- 'ProcessOrientation.cpp',
- 'WidgetTraceEvent.cpp'
-]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-FINAL_LIBRARY = 'xul'
-
-LOCAL_INCLUDES += [
- '/dom/system/android',
- '/gfx/skia/skia/include/config',
- '/gfx/skia/skia/include/core',
- '/image',
- '/widget',
-]
-
-DEFINES['HAVE_OFF64_T'] = True
-DEFINES['SK_BUILD_FOR_ANDROID_NDK'] = True
-DEFINES['HAVE_POSIX_CLOCKS'] = True
-
-LOCAL_INCLUDES += [
- '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/native/opengl/include',
- 'hardware/libhardware/include',
- 'hardware/libhardware_legacy/include',
- ]
-]
diff --git a/widget/gonk/nativewindow/FakeSurfaceComposer.cpp b/widget/gonk/nativewindow/FakeSurfaceComposer.cpp
deleted file mode 100644
index 7e4a2a9d8..000000000
--- a/widget/gonk/nativewindow/FakeSurfaceComposer.cpp
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "FakeSurfaceComposer"
-//#define LOG_NDEBUG 0
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <cutils/atomic.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-#include <private/android_filesystem_config.h>
-
-#include <gui/IDisplayEventConnection.h>
-#include <gui/GraphicBufferAlloc.h>
-#include <gui/Surface.h>
-#include <ui/DisplayInfo.h>
-
-#if ANDROID_VERSION >= 21
-#include <ui/Rect.h>
-#endif
-
-#include "../libdisplay/GonkDisplay.h"
-#include "../nsScreenManagerGonk.h"
-#include "FakeSurfaceComposer.h"
-#include "gfxPrefs.h"
-#include "MainThreadUtils.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/layers/CompositorBridgeParent.h"
-#include "mozilla/layers/CompositorThread.h"
-#include "nsProxyRelease.h"
-#include "nsThreadUtils.h"
-
-using namespace mozilla;
-
-namespace android {
-
-/* static */
-void FakeSurfaceComposer::instantiate() {
- defaultServiceManager()->addService(
- String16("SurfaceFlinger"), new FakeSurfaceComposer());
-}
-
-FakeSurfaceComposer::FakeSurfaceComposer()
- : BnSurfaceComposer()
-{
-}
-
-FakeSurfaceComposer::~FakeSurfaceComposer()
-{
-}
-
-status_t FakeSurfaceComposer::onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags)
-{
- switch (code) {
- case CREATE_CONNECTION:
- case CREATE_DISPLAY:
- case SET_TRANSACTION_STATE:
- case CAPTURE_SCREEN:
- {
- // codes that require permission check
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- // Accept request only when uid is root.
- if (uid != AID_ROOT) {
- ALOGE("Permission Denial: "
- "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- break;
- }
- }
-
- return BnSurfaceComposer::onTransact(code, data, reply, flags);
-}
-
-sp<ISurfaceComposerClient> FakeSurfaceComposer::createConnection()
-{
- return nullptr;
-}
-
-sp<IGraphicBufferAlloc> FakeSurfaceComposer::createGraphicBufferAlloc()
-{
- sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
- return gba;
-}
-
-class DestroyDisplayRunnable : public Runnable {
-public:
- DestroyDisplayRunnable(FakeSurfaceComposer* aComposer, ssize_t aIndex)
- : mComposer(aComposer), mIndex(aIndex) { }
- NS_IMETHOD Run() override {
- MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
- Mutex::Autolock _l(mComposer->mStateLock);
- RefPtr<nsScreenManagerGonk> screenManager =
- nsScreenManagerGonk::GetInstance();
- screenManager->RemoveScreen(GonkDisplay::DISPLAY_VIRTUAL);
- mComposer->mDisplays.removeItemsAt(mIndex);
- return NS_OK;
- }
- sp<FakeSurfaceComposer> mComposer;
- ssize_t mIndex;
-};
-
-sp<IBinder> FakeSurfaceComposer::createDisplay(const String8& displayName,
- bool secure)
-{
-#if ANDROID_VERSION >= 19
- class DisplayToken : public BBinder {
- sp<FakeSurfaceComposer> composer;
- virtual ~DisplayToken() {
- MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
- // no more references, this display must be terminated
- Mutex::Autolock _l(composer->mStateLock);
- ssize_t idx = composer->mDisplays.indexOfKey(this);
- if (idx >= 0) {
- nsCOMPtr<nsIRunnable> task(new DestroyDisplayRunnable(composer.get(), idx));
- NS_DispatchToMainThread(task);
- }
- }
- public:
- DisplayToken(const sp<FakeSurfaceComposer>& composer)
- : composer(composer) {
- }
- };
-
- sp<BBinder> token = new DisplayToken(this);
-
- Mutex::Autolock _l(mStateLock);
- DisplayDeviceState info(HWC_DISPLAY_VIRTUAL);
- info.displayName = displayName;
- info.displayId = GonkDisplay::DISPLAY_VIRTUAL;
- info.isSecure = secure;
- mDisplays.add(token, info);
- return token;
-#else
- return nullptr;
-#endif
-}
-
-#if ANDROID_VERSION >= 19
-void FakeSurfaceComposer::destroyDisplay(const sp<IBinder>& display)
-{
- Mutex::Autolock _l(mStateLock);
-
- ssize_t idx = mDisplays.indexOfKey(display);
- if (idx < 0) {
- ALOGW("destroyDisplay: invalid display token");
- return;
- }
-
- nsCOMPtr<nsIRunnable> task(new DestroyDisplayRunnable(this, idx));
- NS_DispatchToMainThread(task);
-}
-#endif
-
-sp<IBinder> FakeSurfaceComposer::getBuiltInDisplay(int32_t id)
-{
- // support only primary display
- if (uint32_t(id) != HWC_DISPLAY_PRIMARY) {
- return NULL;
- }
-
- if (!mPrimaryDisplay.get()) {
- mPrimaryDisplay = new BBinder();
- }
- return mPrimaryDisplay;
-}
-
-void FakeSurfaceComposer::setTransactionState(
- const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays,
- uint32_t flags)
-{
- Mutex::Autolock _l(mStateLock);
- size_t count = displays.size();
- for (size_t i=0 ; i<count ; i++) {
- const DisplayState& s(displays[i]);
- setDisplayStateLocked(s);
- }
-}
-
-uint32_t FakeSurfaceComposer::setDisplayStateLocked(const DisplayState& s)
-{
- ssize_t dpyIdx = mDisplays.indexOfKey(s.token);
- if (dpyIdx < 0) {
- return 0;
- }
-
- uint32_t flags = 0;
- DisplayDeviceState& disp(mDisplays.editValueAt(dpyIdx));
-
- if (!disp.isValid()) {
- return 0;
- }
-
- const uint32_t what = s.what;
- if (what & DisplayState::eSurfaceChanged) {
- if (disp.surface->asBinder() != s.surface->asBinder()) {
- disp.surface = s.surface;
- flags |= eDisplayTransactionNeeded;
- }
- }
- if (what & DisplayState::eLayerStackChanged) {
- if (disp.layerStack != s.layerStack) {
- disp.layerStack = s.layerStack;
- flags |= eDisplayTransactionNeeded;
- }
- }
- if (what & DisplayState::eDisplayProjectionChanged) {
- if (disp.orientation != s.orientation) {
- disp.orientation = s.orientation;
- flags |= eDisplayTransactionNeeded;
- }
- if (disp.frame != s.frame) {
- disp.frame = s.frame;
- flags |= eDisplayTransactionNeeded;
- }
- if (disp.viewport != s.viewport) {
- disp.viewport = s.viewport;
- flags |= eDisplayTransactionNeeded;
- }
- }
-#if ANDROID_VERSION >= 21
- if (what & DisplayState::eDisplaySizeChanged) {
- if (disp.width != s.width) {
- disp.width = s.width;
- flags |= eDisplayTransactionNeeded;
- }
- if (disp.height != s.height) {
- disp.height = s.height;
- flags |= eDisplayTransactionNeeded;
- }
- }
-#endif
-
- if (what & DisplayState::eSurfaceChanged) {
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([&]() {
- MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
- RefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance();
- screenManager->AddScreen(GonkDisplay::DISPLAY_VIRTUAL, disp.surface.get());
- });
- NS_DispatchToMainThread(runnable, NS_DISPATCH_SYNC);
- }
-
- return flags;
-}
-
-void FakeSurfaceComposer::bootFinished()
-{
-}
-
-bool FakeSurfaceComposer::authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const {
- return false;
-}
-
-sp<IDisplayEventConnection> FakeSurfaceComposer::createDisplayEventConnection() {
- return nullptr;
-}
-
-// ---------------------------------------------------------------------------
-// Capture screen into an IGraphiBufferProducer
-// ---------------------------------------------------------------------------
-
-class Barrier {
-public:
- inline Barrier() : state(CLOSED) { }
- inline ~Barrier() { }
-
- // Release any threads waiting at the Barrier.
- // Provides release semantics: preceding loads and stores will be visible
- // to other threads before they wake up.
- void open() {
- Mutex::Autolock _l(lock);
- state = OPENED;
- cv.broadcast();
- }
-
- // Reset the Barrier, so wait() will block until open() has been called.
- void close() {
- Mutex::Autolock _l(lock);
- state = CLOSED;
- }
-
- // Wait until the Barrier is OPEN.
- // Provides acquire semantics: no subsequent loads or stores will occur
- // until wait() returns.
- void wait() const {
- Mutex::Autolock _l(lock);
- while (state == CLOSED) {
- cv.wait(lock);
- }
- }
-private:
- enum { OPENED, CLOSED };
- mutable Mutex lock;
- mutable Condition cv;
- volatile int state;
-};
-
-/* The code below is here to handle b/8734824
- *
- * We create a IGraphicBufferProducer wrapper that forwards all calls
- * to the calling binder thread, where they are executed. This allows
- * the calling thread to be reused (on the other side) and not
- * depend on having "enough" binder threads to handle the requests.
- *
- */
-
-class GraphicProducerWrapper : public BBinder, public MessageHandler {
- sp<IGraphicBufferProducer> impl;
- sp<Looper> looper;
- status_t result;
- bool exitPending;
- bool exitRequested;
- mutable Barrier barrier;
- volatile int32_t memoryBarrier;
- uint32_t code;
- Parcel const* data;
- Parcel* reply;
-
- enum {
- MSG_API_CALL,
- MSG_EXIT
- };
-
- /*
- * this is called by our "fake" BpGraphicBufferProducer. We package the
- * data and reply Parcel and forward them to the calling thread.
- */
- virtual status_t transact(uint32_t code,
- const Parcel& data, Parcel* reply, uint32_t flags) {
- this->code = code;
- this->data = &data;
- this->reply = reply;
- android_atomic_acquire_store(0, &memoryBarrier);
- if (exitPending) {
- // if we've exited, we run the message synchronously right here
- handleMessage(Message(MSG_API_CALL));
- } else {
- barrier.close();
- looper->sendMessage(this, Message(MSG_API_CALL));
- barrier.wait();
- }
- return NO_ERROR;
- }
-
- /*
- * here we run on the binder calling thread. All we've got to do is
- * call the real BpGraphicBufferProducer.
- */
- virtual void handleMessage(const Message& message) {
- android_atomic_release_load(&memoryBarrier);
- if (message.what == MSG_API_CALL) {
- impl->asBinder()->transact(code, data[0], reply);
- barrier.open();
- } else if (message.what == MSG_EXIT) {
- exitRequested = true;
- }
- }
-
-public:
- GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl) :
- impl(impl), looper(new Looper(true)), result(NO_ERROR),
- exitPending(false), exitRequested(false) {
- }
-
- status_t waitForResponse() {
- do {
- looper->pollOnce(-1);
- } while (!exitRequested);
- return result;
- }
-
- void exit(status_t result) {
- this->result = result;
- exitPending = true;
- looper->sendMessage(this, Message(MSG_EXIT));
- }
-};
-
-status_t
-FakeSurfaceComposer::captureScreen(const sp<IBinder>& display
- , const sp<IGraphicBufferProducer>& producer
-#if ANDROID_VERSION >= 21
- , Rect sourceCrop
-#endif
- , uint32_t reqWidth
- , uint32_t reqHeight
- , uint32_t minLayerZ
- , uint32_t maxLayerZ
-#if ANDROID_VERSION >= 21
- , bool useIdentityTransform
- , Rotation rotation
-#elif ANDROID_VERSION < 19
- , bool isCpuConsumer
-#endif
- )
-{
- if (display == 0 || producer == 0) {
- return BAD_VALUE;
- }
-
- // Limit only to primary display
- if (display != mPrimaryDisplay) {
- return BAD_VALUE;
- }
-
- // this creates a "fake" BBinder which will serve as a "fake" remote
- // binder to receive the marshaled calls and forward them to the
- // real remote (a BpGraphicBufferProducer)
- sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer);
- // the asInterface() call below creates our "fake" BpGraphicBufferProducer
- // which does the marshaling work forwards to our "fake remote" above.
- sp<IGraphicBufferProducer> fakeProducer = IGraphicBufferProducer::asInterface(wrapper);
-
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([&]() {
- captureScreenImp(fakeProducer, reqWidth, reqHeight, wrapper.get());
- });
- NS_DispatchToMainThread(runnable);
-
- status_t result = wrapper->waitForResponse();
-
- return result;
-}
-
-class RunnableCallTask final : public Runnable
-{
-public:
- explicit RunnableCallTask(nsIRunnable* aRunnable)
- : mRunnable(aRunnable) {}
-
- NS_IMETHOD Run() override
- {
- return mRunnable->Run();
- }
-protected:
- nsCOMPtr<nsIRunnable> mRunnable;
-};
-
-void
-FakeSurfaceComposer::captureScreenImp(const sp<IGraphicBufferProducer>& producer,
- uint32_t reqWidth,
- uint32_t reqHeight,
- const sp<GraphicProducerWrapper>& wrapper)
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(wrapper.get());
-
- RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen();
-
- // get screen geometry
- nsIntRect screenBounds = screen->GetNaturalBounds().ToUnknownRect();
- const uint32_t hw_w = screenBounds.width;
- const uint32_t hw_h = screenBounds.height;
-
- if (reqWidth > hw_w || reqHeight > hw_h) {
- ALOGE("size mismatch (%d, %d) > (%d, %d)",
- reqWidth, reqHeight, hw_w, hw_h);
- static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(BAD_VALUE);
- return;
- }
-
- reqWidth = (!reqWidth) ? hw_w : reqWidth;
- reqHeight = (!reqHeight) ? hw_h : reqHeight;
-
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([screen, reqWidth, reqHeight, producer, wrapper]() {
- // create a surface (because we're a producer, and we need to
- // dequeue/queue a buffer)
- sp<Surface> sur = new Surface(producer);
- ANativeWindow* window = sur.get();
- // The closure makes screen const and we can't call forget() on it.
- RefPtr<nsScreenGonk> screenAlias = screen;
-
- if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != NO_ERROR) {
- static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(BAD_VALUE);
- NS_ReleaseOnMainThread(screenAlias.forget());
- return;
- }
- uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
-
- int err = 0;
- err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
- err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
- err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
- err |= native_window_set_usage(window, usage);
-
- status_t result = NO_ERROR;
- if (err == NO_ERROR) {
- ANativeWindowBuffer* buffer;
- result = native_window_dequeue_buffer_and_wait(window, &buffer);
- if (result == NO_ERROR) {
- nsresult rv = screen->MakeSnapshot(buffer);
- if (rv != NS_OK) {
- result = INVALID_OPERATION;
- }
- window->queueBuffer(window, buffer, -1);
- }
- } else {
- result = BAD_VALUE;
- }
- native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
- static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
- NS_ReleaseOnMainThread(screenAlias.forget());
- });
-
- layers::CompositorThreadHolder::Loop()->PostTask(
- MakeAndAddRef<RunnableCallTask>(runnable));
-}
-
-#if ANDROID_VERSION >= 21
-void
-FakeSurfaceComposer::setPowerMode(const sp<IBinder>& display, int mode)
-{
-}
-
-status_t
-FakeSurfaceComposer::getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs)
-{
- if (configs == NULL) {
- return BAD_VALUE;
- }
-
- // Limit DisplayConfigs only to primary display
- if (!display.get() || display != mPrimaryDisplay) {
- return NAME_NOT_FOUND;
- }
-
- configs->clear();
- DisplayInfo info = DisplayInfo();
-
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([&]() {
- MOZ_ASSERT(NS_IsMainThread());
- getPrimaryDisplayInfo(&info);
- });
- NS_DispatchToMainThread(runnable, NS_DISPATCH_SYNC);
-
- configs->push_back(info);
- return NO_ERROR;
-}
-
-status_t
-FakeSurfaceComposer::getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats)
-{
- return INVALID_OPERATION;
-}
-
-int
-FakeSurfaceComposer::getActiveConfig(const sp<IBinder>& display)
-{
- // Only support primary display.
- if (display.get() && (display == mPrimaryDisplay)) {
- return 0;
- }
- return INVALID_OPERATION;
-}
-
-status_t
-FakeSurfaceComposer::setActiveConfig(const sp<IBinder>& display, int id)
-{
- return INVALID_OPERATION;
-}
-
-status_t
-FakeSurfaceComposer::clearAnimationFrameStats()
-{
- return INVALID_OPERATION;
-}
-
-status_t
-FakeSurfaceComposer::getAnimationFrameStats(FrameStats* outStats) const
-{
- return INVALID_OPERATION;
-}
-#else
-void
-FakeSurfaceComposer::blank(const sp<IBinder>& display)
-{
-}
-
-void
-FakeSurfaceComposer::unblank(const sp<IBinder>& display)
-{
-}
-
-status_t
-FakeSurfaceComposer::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info)
-{
- if (info == NULL) {
- return BAD_VALUE;
- }
-
- // Limit DisplayConfigs only to primary display
- if (!display.get() || display != mPrimaryDisplay) {
- return NAME_NOT_FOUND;
- }
-
- nsCOMPtr<nsIRunnable> runnable =
- NS_NewRunnableFunction([&]() {
- MOZ_ASSERT(NS_IsMainThread());
- getPrimaryDisplayInfo(info);
- });
- NS_DispatchToMainThread(runnable, NS_DISPATCH_SYNC);
-
- return NO_ERROR;
-}
-#endif
-
-#define VSYNC_EVENT_PHASE_OFFSET_NS 0
-#define SF_VSYNC_EVENT_PHASE_OFFSET_NS 0
-
-void
-FakeSurfaceComposer::getPrimaryDisplayInfo(DisplayInfo* info)
-{
- MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
-
- // Implementation mimic android SurfaceFlinger::getDisplayConfigs().
-
- class Density {
- static int getDensityFromProperty(char const* propName) {
- char property[PROPERTY_VALUE_MAX];
- int density = 0;
- if (property_get(propName, property, NULL) > 0) {
- density = atoi(property);
- }
- return density;
- }
- public:
- static int getEmuDensity() {
- return getDensityFromProperty("qemu.sf.lcd_density"); }
- static int getBuildDensity() {
- return getDensityFromProperty("ro.sf.lcd_density"); }
- };
-
- RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen();
-
- float xdpi = screen->GetDpi();
- float ydpi = screen->GetDpi();
- int fps = 60; // XXX set a value from hwc hal
- nsIntRect screenBounds = screen->GetNaturalBounds().ToUnknownRect();
-
- // The density of the device is provided by a build property
- float density = Density::getBuildDensity() / 160.0f;
- if (density == 0) {
- // the build doesn't provide a density -- this is wrong!
- // use xdpi instead
- ALOGE("ro.sf.lcd_density must be defined as a build property");
- density = xdpi / 160.0f;
- }
- info->density = density;
- info->orientation = screen->EffectiveScreenRotation();
-
- info->w = screenBounds.width;
- info->h = screenBounds.height;
- info->xdpi = xdpi;
- info->ydpi = ydpi;
- info->fps = fps;
-#if ANDROID_VERSION >= 21
- info->appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS;
-
- // This is how far in advance a buffer must be queued for
- // presentation at a given time. If you want a buffer to appear
- // on the screen at time N, you must submit the buffer before
- // (N - presentationDeadline).
- //
- // Normally it's one full refresh period (to give SF a chance to
- // latch the buffer), but this can be reduced by configuring a
- // DispSync offset. Any additional delays introduced by the hardware
- // composer or panel must be accounted for here.
- //
- // We add an additional 1ms to allow for processing time and
- // differences between the ideal and actual refresh rate.
- info->presentationDeadline =
- (1e9 / fps) - SF_VSYNC_EVENT_PHASE_OFFSET_NS + 1000000;
-#endif
- // All non-virtual displays are currently considered secure.
- info->secure = true;
-}
-
-}; // namespace android
diff --git a/widget/gonk/nativewindow/FakeSurfaceComposer.h b/widget/gonk/nativewindow/FakeSurfaceComposer.h
deleted file mode 100644
index 97a717444..000000000
--- a/widget/gonk/nativewindow/FakeSurfaceComposer.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_FAKE_SURFACE_COMPOSER_H
-#define NATIVEWINDOW_FAKE_SURFACE_COMPOSER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/Looper.h>
-
-#include <binder/BinderService.h>
-
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/ISurfaceComposerClient.h>
-#include <hardware/hwcomposer.h>
-#include <private/gui/LayerState.h>
-#include <utils/KeyedVector.h>
-
-class nsIWidget;
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class GraphicProducerWrapper;
-class IGraphicBufferAlloc;
-
-enum {
- eTransactionNeeded = 0x01,
- eTraversalNeeded = 0x02,
- eDisplayTransactionNeeded = 0x04,
- eTransactionMask = 0x07
-};
-
-class FakeSurfaceComposer : public BinderService<FakeSurfaceComposer>,
- public BnSurfaceComposer
-{
-public:
- static char const* getServiceName() {
- return "FakeSurfaceComposer";
- }
-
- // Instantiate FakeSurfaceComposer and register to service manager.
- // If service manager is not present, wait until service manager becomes present.
- static void instantiate();
-
-#if ANDROID_VERSION >= 19
- virtual void destroyDisplay(const sp<android::IBinder>& display);
-#endif
-
-#if ANDROID_VERSION >= 21
- virtual status_t captureScreen(const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- uint32_t minLayerZ, uint32_t maxLayerZ,
- bool useIdentityTransform,
- Rotation rotation = eRotateNone);
-#elif ANDROID_VERSION >= 19
- virtual status_t captureScreen(const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- uint32_t reqWidth, uint32_t reqHeight,
- uint32_t minLayerZ, uint32_t maxLayerZ);
-#else
- virtual status_t captureScreen(const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- uint32_t reqWidth, uint32_t reqHeight,
- uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer);
-#endif
-
-private:
- FakeSurfaceComposer();
- // We're reference counted, never destroy FakeSurfaceComposer directly
- virtual ~FakeSurfaceComposer();
-
- /* ------------------------------------------------------------------------
- * IBinder interface
- */
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
-
- /* ------------------------------------------------------------------------
- * ISurfaceComposer interface
- */
- virtual sp<ISurfaceComposerClient> createConnection();
- virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
- virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
- virtual sp<IBinder> getBuiltInDisplay(int32_t id);
- virtual void setTransactionState(const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags);
- virtual void bootFinished();
- virtual bool authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const;
- virtual sp<IDisplayEventConnection> createDisplayEventConnection();
-#if ANDROID_VERSION >= 21
- virtual void setPowerMode(const sp<IBinder>& display, int mode);
- virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs);
- virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats);
- virtual int getActiveConfig(const sp<IBinder>& display);
- virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
- virtual status_t clearAnimationFrameStats();
- virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
-#elif ANDROID_VERSION >= 17
- // called when screen needs to turn off
- virtual void blank(const sp<IBinder>& display);
- // called when screen is turning back on
- virtual void unblank(const sp<IBinder>& display);
- virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info);
-#endif
- void getPrimaryDisplayInfo(DisplayInfo* info);
-
- /* ------------------------------------------------------------------------
- * Transactions
- */
- uint32_t setDisplayStateLocked(const DisplayState& s);
-
- void captureScreenImp(const sp<IGraphicBufferProducer>& producer,
- uint32_t reqWidth,
- uint32_t reqHeight,
- const sp<GraphicProducerWrapper>& wrapper);
-
- sp<IBinder> mPrimaryDisplay;
-
- struct DisplayDeviceState {
- enum {
- NO_LAYER_STACK = 0xFFFFFFFF,
- };
- DisplayDeviceState()
- : type(-1), displayId(-1), width(0), height(0) {
- }
- DisplayDeviceState(int type)
- : type(type), displayId(-1), layerStack(NO_LAYER_STACK), orientation(0), width(0), height(0) {
- viewport.makeInvalid();
- frame.makeInvalid();
- }
- bool isValid() const { return type >= 0; }
- int type;
- int displayId;
- sp<IGraphicBufferProducer> surface;
- uint32_t layerStack;
- Rect viewport;
- Rect frame;
- uint8_t orientation;
- uint32_t width, height;
- String8 displayName;
- bool isSecure;
- };
-
- // access must be protected by mStateLock
- mutable Mutex mStateLock;
- DefaultKeyedVector<wp<IBinder>, DisplayDeviceState> mDisplays;
-
- friend class DestroyDisplayRunnable;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // NATIVEWINDOW_FAKE_SURFACE_COMPOSER_H
diff --git a/widget/gonk/nativewindow/GonkBufferQueue.h b/widget/gonk/nativewindow/GonkBufferQueue.h
deleted file mode 100644
index defdb0ae2..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueue.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright 2013 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
-# include "GonkBufferQueueLL.h"
-#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
-# include "GonkBufferQueueKK.h"
-#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
-# include "GonkBufferQueueJB.h"
-#endif
diff --git a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp b/widget/gonk/nativewindow/GonkBufferQueueJB.cpp
deleted file mode 100644
index 81502f81e..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp
+++ /dev/null
@@ -1,1036 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "GonkBufferQueue"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#define LOG_NDEBUG 0
-
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <utils/Log.h>
-
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-
-#include "GonkBufferQueueJB.h"
-
-// Macros for including the GonkBufferQueue name in log messages
-#define ST_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#define ST_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-#define ST_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-#define ST_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
-#define ST_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-
-#define ATRACE_BUFFER_INDEX(index)
-
-using namespace mozilla;
-using namespace mozilla::gfx;
-using namespace mozilla::layers;
-
-namespace android {
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-static const char* scalingModeName(int scalingMode) {
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
- default: return "Unknown";
- }
-}
-
-GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode,
- const sp<IGraphicBufferAlloc>& allocator) :
- mDefaultWidth(1),
- mDefaultHeight(1),
- mMaxAcquiredBufferCount(1),
- mDefaultMaxBufferCount(2),
- mOverrideMaxBufferCount(0),
- mSynchronousMode(true),
- mAllowSynchronousMode(allowSynchronousMode),
- mConnectedApi(NO_CONNECTED_API),
- mAbandoned(false),
- mFrameCounter(0),
- mBufferHasBeenQueued(false),
- mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
- mConsumerUsageBits(0),
- mTransformHint(0)
-{
- // Choose a name using the PID and a process-unique ID.
- mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
- ST_LOGV("GonkBufferQueue");
-}
-
-GonkBufferQueue::~GonkBufferQueue() {
- ST_LOGV("~GonkBufferQueue");
-}
-
-status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) {
- if (count < 2 || count > NUM_BUFFER_SLOTS)
- return BAD_VALUE;
-
- mDefaultMaxBufferCount = count;
- mDequeueCondition.broadcast();
-
- return NO_ERROR;
-}
-
-bool GonkBufferQueue::isSynchronousMode() const {
- Mutex::Autolock lock(mMutex);
- return mSynchronousMode;
-}
-
-void GonkBufferQueue::setConsumerName(const String8& name) {
- Mutex::Autolock lock(mMutex);
- mConsumerName = name;
-}
-
-status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock lock(mMutex);
- mDefaultBufferFormat = defaultFormat;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) {
- Mutex::Autolock lock(mMutex);
- mConsumerUsageBits = usage;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::setTransformHint(uint32_t hint) {
- ST_LOGV("setTransformHint: %02x", hint);
- Mutex::Autolock lock(mMutex);
- mTransformHint = hint;
- return NO_ERROR;
-}
-
-already_AddRefed<TextureClient>
-GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
-{
- Mutex::Autolock _l(mMutex);
- if (buffer == NULL) {
- ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
- return nullptr;
- }
-
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
- RefPtr<TextureClient> client(mSlots[i].mTextureClient);
- return client.forget();
- }
- }
- ST_LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
- return nullptr;
-}
-
-int GonkBufferQueue::getSlotFromTextureClientLocked(
- TextureClient* client) const
-{
- if (client == NULL) {
- ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
- return BAD_VALUE;
- }
-
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].mTextureClient == client) {
- return i;
- }
- }
- ST_LOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client);
- return BAD_VALUE;
-}
-
-
-status_t GonkBufferQueue::setBufferCount(int bufferCount) {
- ST_LOGV("setBufferCount: count=%d", bufferCount);
-
- sp<ConsumerListener> listener;
- {
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setBufferCount: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
- if (bufferCount > NUM_BUFFER_SLOTS) {
- ST_LOGE("setBufferCount: bufferCount too large (max %d)",
- NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- }
-
- // Error out if the user has dequeued buffers
- int maxBufferCount = getMaxBufferCountLocked();
- for (int i=0 ; i<maxBufferCount; i++) {
- if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
- ST_LOGE("setBufferCount: client owns some buffers");
- return -EINVAL;
- }
- }
-
- const int minBufferSlots = getMinMaxBufferCountLocked();
- if (bufferCount == 0) {
- mOverrideMaxBufferCount = 0;
- mDequeueCondition.broadcast();
- return NO_ERROR;
- }
-
- if (bufferCount < minBufferSlots) {
- ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
- "minimum (%d)", bufferCount, minBufferSlots);
- return BAD_VALUE;
- }
-
- // here we're guaranteed that the client doesn't have dequeued buffers
- // and will release all of its buffer references.
- //
- // XXX: Should this use drainQueueAndFreeBuffersLocked instead?
- freeAllBuffersLocked();
- mOverrideMaxBufferCount = bufferCount;
- mBufferHasBeenQueued = false;
- mDequeueCondition.broadcast();
- listener = mConsumerListener;
- } // scope for lock
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return NO_ERROR;
-}
-
-int GonkBufferQueue::query(int what, int* outValue)
-{
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("query: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- int value;
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- value = mDefaultWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- value = mDefaultHeight;
- break;
- case NATIVE_WINDOW_FORMAT:
- value = mDefaultBufferFormat;
- break;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- value = getMinUndequeuedBufferCountLocked();
- break;
- case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
- value = (mQueue.size() >= 2);
- break;
- default:
- return BAD_VALUE;
- }
- outValue[0] = value;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- ST_LOGV("requestBuffer: slot=%d", slot);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("requestBuffer: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
- int maxBufferCount = getMaxBufferCountLocked();
- if (slot < 0 || maxBufferCount <= slot) {
- ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
- maxBufferCount, slot);
- return BAD_VALUE;
- } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
- // XXX: I vaguely recall there was some reason this can be valid, but
- // for the life of me I can't recall under what circumstances that's
- // the case.
- ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
- slot, mSlots[slot].mBufferState);
- return BAD_VALUE;
- }
- mSlots[slot].mRequestBufferCalled = true;
- *buf = mSlots[slot].mGraphicBuffer;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
- ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
-
- if ((w && !h) || (!w && h)) {
- ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
- return BAD_VALUE;
- }
-
- status_t returnFlags(OK);
- int buf = INVALID_BUFFER_SLOT;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (format == 0) {
- format = mDefaultBufferFormat;
- }
- // turn on usage bits the consumer requested
- usage |= mConsumerUsageBits;
-
- int found = -1;
- int dequeuedCount = 0;
- bool tryAgain = true;
- while (tryAgain) {
- if (mAbandoned) {
- ST_LOGE("dequeueBuffer: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- const int maxBufferCount = getMaxBufferCountLocked();
-
- // Free up any buffers that are in slots beyond the max buffer
- // count.
- //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
- // assert(mSlots[i].mBufferState == BufferSlot::FREE);
- // if (mSlots[i].mGraphicBuffer != NULL) {
- // freeBufferLocked(i);
- // returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
- // }
- //}
-
- // look for a free buffer to give to the client
- found = INVALID_BUFFER_SLOT;
- dequeuedCount = 0;
- for (int i = 0; i < maxBufferCount; i++) {
- const int state = mSlots[i].mBufferState;
- if (state == BufferSlot::DEQUEUED) {
- dequeuedCount++;
- }
-
- if (state == BufferSlot::FREE) {
- /* We return the oldest of the free buffers to avoid
- * stalling the producer if possible. This is because
- * the consumer may still have pending reads of the
- * buffers in flight.
- */
- if ((found < 0) ||
- mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
- found = i;
- }
- }
- }
-
- // clients are not allowed to dequeue more than one buffer
- // if they didn't set a buffer count.
- if (!mOverrideMaxBufferCount && dequeuedCount) {
- ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
- "setting the buffer count");
- return -EINVAL;
- }
-
- // See whether a buffer has been queued since the last
- // setBufferCount so we know whether to perform the min undequeued
- // buffers check below.
- if (mBufferHasBeenQueued) {
- // make sure the client is not trying to dequeue more buffers
- // than allowed.
- const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
- const int minUndequeuedCount = getMinUndequeuedBufferCountLocked();
- if (newUndequeuedCount < minUndequeuedCount) {
- ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
- "exceeded (dequeued=%d undequeudCount=%d)",
- minUndequeuedCount, dequeuedCount,
- newUndequeuedCount);
- return -EBUSY;
- }
- }
-
- // If no buffer is found, wait for a buffer to be released or for
- // the max buffer count to change.
- tryAgain = found == INVALID_BUFFER_SLOT;
- if (tryAgain) {
- mDequeueCondition.wait(mMutex);
- }
- }
-
-
- if (found == INVALID_BUFFER_SLOT) {
- // This should not happen.
- ST_LOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
- }
-
- buf = found;
- *outBuf = found;
-
- const bool useDefaultSize = !w && !h;
- if (useDefaultSize) {
- // use the default size
- w = mDefaultWidth;
- h = mDefaultHeight;
- }
-
- mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
-
- const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
- if ((buffer == NULL) ||
- (uint32_t(buffer->width) != w) ||
- (uint32_t(buffer->height) != h) ||
- (uint32_t(buffer->format) != format) ||
- ((uint32_t(buffer->usage) & usage) != usage))
- {
- mSlots[buf].mAcquireCalled = false;
- mSlots[buf].mGraphicBuffer = NULL;
- mSlots[buf].mRequestBufferCalled = false;
- mSlots[buf].mFence = Fence::NO_FENCE;
- if (mSlots[buf].mTextureClient) {
- mSlots[buf].mTextureClient->ClearRecycleCallback();
- // release TextureClient in ImageBridge thread
- RefPtr<TextureClientReleaseTask> task =
- MakeAndAddRef<TextureClientReleaseTask>(mSlots[buf].mTextureClient);
- mSlots[buf].mTextureClient = NULL;
- ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
- }
- returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
- }
-
- *outFence = mSlots[buf].mFence;
- mSlots[buf].mFence = Fence::NO_FENCE;
- } // end lock scope
-
- sp<GraphicBuffer> graphicBuffer;
- if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
-
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- RefPtr<LayersIPCChannel> allocator = ImageBridgeChild::GetSingleton();
- GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w,h), format,
- gfx::BackendType::NONE, usage,
- allocator);
- if (!texData) {
- ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
- return -ENOMEM;
- }
- RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator);
- sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- mSlots[buf].mGraphicBuffer = graphicBuffer;
- mSlots[buf].mTextureClient = textureClient;
- ST_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
- mSlots[buf].mGraphicBuffer->handle);
- //mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
- }
- }
-
- ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
- mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
-
- return returnFlags;
-}
-
-status_t GonkBufferQueue::setSynchronousMode(bool enabled) {
- ST_LOGV("setSynchronousMode: enabled=%d", enabled);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setSynchronousMode: BufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- if (mSynchronousMode != enabled) {
- mSynchronousMode = enabled;
- mDequeueCondition.broadcast();
- }
- return OK;
-}
-
-status_t GonkBufferQueue::queueBuffer(int buf,
- const QueueBufferInput& input, QueueBufferOutput* output) {
-
- Rect crop;
- uint32_t transform;
- int scalingMode;
- int64_t timestamp;
- sp<Fence> fence;
-
- input.deflate(&timestamp, &crop, &scalingMode, &transform, &fence);
-
-#if ANDROID_VERSION >= 18
- if (fence == NULL) {
- ST_LOGE("queueBuffer: fence is NULL");
- return BAD_VALUE;
- }
-#endif
-
- ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
- "scale=%s",
- buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
- transform, scalingModeName(scalingMode));
-
- sp<ConsumerListener> listener;
-
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("queueBuffer: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
- int maxBufferCount = getMaxBufferCountLocked();
- if (buf < 0 || buf >= maxBufferCount) {
- ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
- maxBufferCount, buf);
- return -EINVAL;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("queueBuffer: slot %d is not owned by the client "
- "(state=%d)", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- } else if (!mSlots[buf].mRequestBufferCalled) {
- ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
- "buffer", buf);
- return -EINVAL;
- }
-
- const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
- Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
- Rect croppedCrop;
- crop.intersect(bufferRect, &croppedCrop);
- if (croppedCrop != crop) {
- ST_LOGE("queueBuffer: crop rect is not contained within the "
- "buffer in slot %d", buf);
- return -EINVAL;
- }
-
- if (mSynchronousMode) {
- // In synchronous mode we queue all buffers in a FIFO.
- mQueue.push_back(buf);
- } else {
- // In asynchronous mode we only keep the most recent buffer.
- if (mQueue.empty()) {
- mQueue.push_back(buf);
- } else {
- Fifo::iterator front(mQueue.begin());
- // buffer currently queued is freed
- mSlots[*front].mBufferState = BufferSlot::FREE;
- // and we record the new buffer index in the queued list
- *front = buf;
- }
- }
- // always signals that an additional frame should be consumed
- // to handle max acquired buffer count reached case.
- listener = mConsumerListener;
-
- mSlots[buf].mTimestamp = timestamp;
- mSlots[buf].mCrop = crop;
- mSlots[buf].mTransform = transform;
- mSlots[buf].mFence = fence;
-
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
- break;
- default:
- ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
- scalingMode = mSlots[buf].mScalingMode;
- break;
- }
-
- mSlots[buf].mBufferState = BufferSlot::QUEUED;
- mSlots[buf].mScalingMode = scalingMode;
- mFrameCounter++;
- mSlots[buf].mFrameNumber = mFrameCounter;
-
- mBufferHasBeenQueued = true;
- mDequeueCondition.broadcast();
-
- output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
- mQueue.size());
- } // scope for the lock
-
- // call back without lock held
- if (listener != 0) {
- listener->onFrameAvailable();
- }
- return NO_ERROR;
-}
-
-#if ANDROID_VERSION == 17
-void GonkBufferQueue::cancelBuffer(int buf, sp<Fence> fence) {
-#else
-void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
-#endif
-
- ST_LOGV("cancelBuffer: slot=%d", buf);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGW("cancelBuffer: GonkBufferQueue has been abandoned!");
- return;
- }
-
- int maxBufferCount = getMaxBufferCountLocked();
- if (buf < 0 || buf >= maxBufferCount) {
- ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
- maxBufferCount, buf);
- return;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
- buf, mSlots[buf].mBufferState);
- return;
-#if ANDROID_VERSION >= 18
- } else if (fence == NULL) {
- ST_LOGE("cancelBuffer: fence is NULL");
- return;
-#endif
- }
- mSlots[buf].mBufferState = BufferSlot::FREE;
- mSlots[buf].mFrameNumber = 0;
- mSlots[buf].mFence = fence;
- mDequeueCondition.broadcast();
-}
-
-status_t GonkBufferQueue::connect(int api, QueueBufferOutput* output) {
- ST_LOGV("connect: api=%d", api);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("connect: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- if (mConsumerListener == NULL) {
- ST_LOGE("connect: GonkBufferQueue has no consumer!");
- return NO_INIT;
- }
-
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi != NO_CONNECTED_API) {
- ST_LOGE("connect: already connected (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- } else {
- mConnectedApi = api;
- output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
- mQueue.size());
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
-
- mBufferHasBeenQueued = false;
-
- return err;
-}
-
-status_t GonkBufferQueue::disconnect(int api) {
- ST_LOGV("disconnect: api=%d", api);
-
- int err = NO_ERROR;
- sp<ConsumerListener> listener;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- // it is not really an error to disconnect after the surface
- // has been abandoned, it should just be a no-op.
- return NO_ERROR;
- }
-
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi == api) {
- freeAllBuffersLocked();
- mConnectedApi = NO_CONNECTED_API;
- mDequeueCondition.broadcast();
- listener = mConsumerListener;
- } else {
- ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- }
- break;
- default:
- ST_LOGE("disconnect: unknown API %d", api);
- err = -EINVAL;
- break;
- }
- }
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return err;
-}
-
-void GonkBufferQueue::dumpToString(String8& result) const
-{
- char buffer[1024];
- GonkBufferQueue::dumpToString(result, "", buffer, 1024);
-}
-
-void GonkBufferQueue::dumpToString(String8& result, const char* prefix,
- char* buffer, size_t SIZE) const
-{
- Mutex::Autolock _l(mMutex);
-
- String8 fifo;
- int fifoSize = 0;
- Fifo::const_iterator i(mQueue.begin());
- while (i != mQueue.end()) {
- snprintf(buffer, SIZE, "%02d ", *i++);
- fifoSize++;
- fifo.append(buffer);
- }
-
- int maxBufferCount = getMaxBufferCountLocked();
-
- snprintf(buffer, SIZE,
- "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
- "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
- prefix, maxBufferCount, mSynchronousMode, mDefaultWidth,
- mDefaultHeight, mDefaultBufferFormat, mTransformHint,
- fifoSize, fifo.string());
- result.append(buffer);
-
-
- struct {
- const char * operator()(int state) const {
- switch (state) {
- case BufferSlot::DEQUEUED: return "DEQUEUED";
- case BufferSlot::QUEUED: return "QUEUED";
- case BufferSlot::FREE: return "FREE";
- case BufferSlot::ACQUIRED: return "ACQUIRED";
- default: return "Unknown";
- }
- }
- } stateName;
-
- for (int i=0 ; i<maxBufferCount ; i++) {
- const BufferSlot& slot(mSlots[i]);
- snprintf(buffer, SIZE,
- "%s%s[%02d] "
- "state=%-8s, crop=[%d,%d,%d,%d], "
- "xform=0x%02x, time=%#llx, scale=%s",
- prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
- stateName(slot.mBufferState),
- slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
- slot.mCrop.bottom, slot.mTransform, slot.mTimestamp,
- scalingModeName(slot.mScalingMode)
- );
- result.append(buffer);
-
- const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
- if (buf != NULL) {
- snprintf(buffer, SIZE,
- ", %p [%4ux%4u:%4u,%3X]",
- buf->handle, buf->width, buf->height, buf->stride,
- buf->format);
- result.append(buffer);
- }
- result.append("\n");
- }
-}
-
-void GonkBufferQueue::freeAllBuffersLocked()
-{
- ALOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersLocked called but mQueue is not empty");
- mQueue.clear();
- mBufferHasBeenQueued = false;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- mSlots[i].mGraphicBuffer = 0;
- if (mSlots[i].mTextureClient) {
- mSlots[i].mTextureClient->ClearRecycleCallback();
- // release TextureClient in ImageBridge thread
- RefPtr<TextureClientReleaseTask> task =
- MakeAndAddRef<TextureClientReleaseTask>(mSlots[i].mTextureClient);
- mSlots[i].mTextureClient = NULL;
- ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
- }
- if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
- mSlots[i].mNeedsCleanupOnRelease = true;
- }
- mSlots[i].mBufferState = BufferSlot::FREE;
- mSlots[i].mFrameNumber = 0;
- mSlots[i].mAcquireCalled = false;
- // destroy fence as GonkBufferQueue now takes ownership
- mSlots[i].mFence = Fence::NO_FENCE;
- }
-}
-
-status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer) {
- Mutex::Autolock _l(mMutex);
-
- // Check that the consumer doesn't currently have the maximum number of
- // buffers acquired. We allow the max buffer count to be exceeded by one
- // buffer, so that the consumer can successfully set up the newly acquired
- // buffer before releasing the old one.
- int numAcquiredBuffers = 0;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
- numAcquiredBuffers++;
- }
- }
- if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) {
- ST_LOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)",
- numAcquiredBuffers, mMaxAcquiredBufferCount);
- return INVALID_OPERATION;
- }
-
- // check if queue is empty
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- if (!mQueue.empty()) {
- Fifo::iterator front(mQueue.begin());
- int buf = *front;
-
- // In android, when the buffer is aquired by BufferConsumer,
- // BufferQueue releases a reference to the buffer and
- // it's ownership moves to the BufferConsumer.
- // In b2g, GonkBufferQueue continues to have a buffer ownership.
- // It is necessary to free buffer via ImageBridgeChild.
-
- //if (mSlots[buf].mAcquireCalled) {
- // buffer->mGraphicBuffer = NULL;
- //} else {
- // buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
- //}
- buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
- buffer->mCrop = mSlots[buf].mCrop;
- buffer->mTransform = mSlots[buf].mTransform;
- buffer->mScalingMode = mSlots[buf].mScalingMode;
- buffer->mFrameNumber = mSlots[buf].mFrameNumber;
- buffer->mTimestamp = mSlots[buf].mTimestamp;
- buffer->mBuf = buf;
- buffer->mFence = mSlots[buf].mFence;
-
- mSlots[buf].mAcquireCalled = true;
- mSlots[buf].mNeedsCleanupOnRelease = false;
- mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
- mSlots[buf].mFence = Fence::NO_FENCE;
-
- mQueue.erase(front);
- mDequeueCondition.broadcast();
- } else {
- return NO_BUFFER_AVAILABLE;
- }
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::releaseBuffer(int buf, const sp<Fence>& fence) {
- Mutex::Autolock _l(mMutex);
-
-#if ANDROID_VERSION == 17
- if (buf == INVALID_BUFFER_SLOT) {
-#else
- if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
-#endif
- return BAD_VALUE;
- }
-
- mSlots[buf].mFence = fence;
-
- // The buffer can now only be released if its in the acquired state
- if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
- mSlots[buf].mBufferState = BufferSlot::FREE;
- } else if (mSlots[buf].mNeedsCleanupOnRelease) {
- ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
- mSlots[buf].mNeedsCleanupOnRelease = false;
- return STALE_BUFFER_SLOT;
- } else {
- ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- }
-
- mDequeueCondition.broadcast();
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
- ST_LOGV("consumerConnect");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("consumerConnect: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
- if (consumerListener == NULL) {
- ST_LOGE("consumerConnect: consumerListener may not be NULL");
- return BAD_VALUE;
- }
-
- mConsumerListener = consumerListener;
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::consumerDisconnect() {
- ST_LOGV("consumerDisconnect");
- Mutex::Autolock lock(mMutex);
-
- if (mConsumerListener == NULL) {
- ST_LOGE("consumerDisconnect: No consumer is connected!");
- return -EINVAL;
- }
-
- mAbandoned = true;
- mConsumerListener = NULL;
- mQueue.clear();
- freeAllBuffersLocked();
- mDequeueCondition.broadcast();
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) {
- ST_LOGV("getReleasedBuffers");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- uint32_t mask = 0;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (!mSlots[i].mAcquireCalled) {
- mask |= 1 << i;
- }
- }
- *slotMask = mask;
-
- ST_LOGV("getReleasedBuffers: returning mask %#x", mask);
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
-{
- ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
- if (!w || !h) {
- ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
- w, h);
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mMutex);
- mDefaultWidth = w;
- mDefaultHeight = h;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) {
- Mutex::Autolock lock(mMutex);
- return setDefaultMaxBufferCountLocked(bufferCount);
-}
-
-status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
- Mutex::Autolock lock(mMutex);
- if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) {
- ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d",
- maxAcquiredBuffers);
- return BAD_VALUE;
- }
- if (mConnectedApi != NO_CONNECTED_API) {
- return INVALID_OPERATION;
- }
- mMaxAcquiredBufferCount = maxAcquiredBuffers;
- return NO_ERROR;
-}
-
-int GonkBufferQueue::getMinMaxBufferCountLocked() const {
- return getMinUndequeuedBufferCountLocked() + 1;
-}
-
-int GonkBufferQueue::getMinUndequeuedBufferCountLocked() const {
- return mSynchronousMode ? mMaxAcquiredBufferCount :
- mMaxAcquiredBufferCount + 1;
-}
-
-int GonkBufferQueue::getMaxBufferCountLocked() const {
- int minMaxBufferCount = getMinMaxBufferCountLocked();
-
- int maxBufferCount = mDefaultMaxBufferCount;
- if (maxBufferCount < minMaxBufferCount) {
- maxBufferCount = minMaxBufferCount;
- }
- if (mOverrideMaxBufferCount != 0) {
- assert(mOverrideMaxBufferCount >= minMaxBufferCount);
- maxBufferCount = mOverrideMaxBufferCount;
- }
-
- // Any buffers that are dequeued by the producer or sitting in the queue
- // waiting to be consumed need to have their slots preserved. Such
- // buffers will temporarily keep the max buffer count up until the slots
- // no longer need to be preserved.
- for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
- BufferSlot::BufferState state = mSlots[i].mBufferState;
- if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
- maxBufferCount = i + 1;
- }
- }
-
- return maxBufferCount;
-}
-
-GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener(
- const wp<GonkBufferQueue::ConsumerListener>& consumerListener):
- mConsumerListener(consumerListener) {}
-
-GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
-
-void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() {
- sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameAvailable();
- }
-}
-
-void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() {
- sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-}
-
-}; // namespace android
diff --git a/widget/gonk/nativewindow/GonkBufferQueueJB.h b/widget/gonk/nativewindow/GonkBufferQueueJB.h
deleted file mode 100644
index df0c4599f..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueJB.h
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKBUFFERQUEUE_JB_H
-#define NATIVEWINDOW_GONKBUFFERQUEUE_JB_H
-
-#include <gui/IGraphicBufferAlloc.h>
-#if ANDROID_VERSION == 17
-#include <gui/ISurfaceTexture.h>
-#else
-#include <gui/IGraphicBufferProducer.h>
-#endif
-
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#include "mozilla/layers/LayersSurfaces.h"
-#include "mozilla/layers/TextureClient.h"
-
-#if ANDROID_VERSION == 17
-#define IGraphicBufferProducer ISurfaceTexture
-#endif
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-#if ANDROID_VERSION == 17
-class GonkBufferQueue : public BnSurfaceTexture {
-#else
-class GonkBufferQueue : public BnGraphicBufferProducer {
-#endif
- typedef mozilla::layers::TextureClient TextureClient;
-
-public:
- enum { MIN_UNDEQUEUED_BUFFERS = 2 };
- enum { NUM_BUFFER_SLOTS = 32 };
- enum { NO_CONNECTED_API = 0 };
- enum { INVALID_BUFFER_SLOT = -1 };
- enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE };
-
- // When in async mode we reserve two slots in order to guarantee that the
- // producer and consumer can run asynchronously.
- enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 };
-
- // ConsumerListener is the interface through which the GonkBufferQueue notifies
- // the consumer of events that the consumer may wish to react to. Because
- // the consumer will generally have a mutex that is locked during calls from
- // the consumer to the GonkBufferQueue, these calls from the GonkBufferQueue to the
- // consumer *MUST* be called only when the GonkBufferQueue mutex is NOT locked.
- struct ConsumerListener : public virtual RefBase {
- // onFrameAvailable is called from queueBuffer each time an additional
- // frame becomes available for consumption. This means that frames that
- // are queued while in asynchronous mode only trigger the callback if no
- // previous frames are pending. Frames queued while in synchronous mode
- // always trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
-
- // onBuffersReleased is called to notify the buffer consumer that the
- // GonkBufferQueue has released its references to one or more GraphicBuffers
- // contained in its slots. The buffer consumer should then call
- // GonkBufferQueue::getReleasedBuffers to retrieve the list of buffers
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onBuffersReleased() = 0;
- };
-
- // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
- // reference to the actual consumer object. It forwards all calls to that
- // consumer object so long as it exists.
- //
- // This class exists to avoid having a circular reference between the
- // GonkBufferQueue object and the consumer object. The reason this can't be a weak
- // reference in the GonkBufferQueue class is because we're planning to expose the
- // consumer side of a GonkBufferQueue as a binder interface, which doesn't support
- // weak references.
- class ProxyConsumerListener : public GonkBufferQueue::ConsumerListener {
- public:
-
- ProxyConsumerListener(const wp<GonkBufferQueue::ConsumerListener>& consumerListener);
- virtual ~ProxyConsumerListener();
- virtual void onFrameAvailable();
- virtual void onBuffersReleased();
-
- private:
-
- // mConsumerListener is a weak reference to the ConsumerListener. This is
- // the raison d'etre of ProxyConsumerListener.
- wp<GonkBufferQueue::ConsumerListener> mConsumerListener;
- };
-
-
- // GonkBufferQueue manages a pool of gralloc memory slots to be used by
- // producers and consumers. allowSynchronousMode specifies whether or not
- // synchronous mode can be enabled by the producer. allocator is used to
- // allocate all the needed gralloc buffers.
- GonkBufferQueue(bool allowSynchronousMode = true,
- const sp<IGraphicBufferAlloc>& allocator = NULL);
- virtual ~GonkBufferQueue();
-
- // Query native window attributes. The "what" values are enumerated in
- // window.h (e.g. NATIVE_WINDOW_FORMAT).
- virtual int query(int what, int* value);
-
- // setBufferCount updates the number of available buffer slots. If this
- // method succeeds, buffer slots will be both unallocated and owned by
- // the GonkBufferQueue object (i.e. they are not owned by the producer or
- // consumer).
- //
- // This will fail if the producer has dequeued any buffers, or if
- // bufferCount is invalid. bufferCount must generally be a value
- // between the minimum undequeued buffer count and NUM_BUFFER_SLOTS
- // (inclusive). It may also be set to zero (the default) to indicate
- // that the producer does not wish to set a value. The minimum value
- // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
- // ...).
- //
- // This may only be called by the producer. The consumer will be told
- // to discard buffers through the onBuffersReleased callback.
- virtual status_t setBufferCount(int bufferCount);
-
- // requestBuffer returns the GraphicBuffer for slot N.
- //
- // In normal operation, this is called the first time slot N is returned
- // by dequeueBuffer. It must be called again if dequeueBuffer returns
- // flags indicating that previously-returned buffers are no longer valid.
- virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
-
- // dequeueBuffer gets the next buffer slot index for the producer to use.
- // If a buffer slot is available then that slot index is written to the
- // location pointed to by the buf argument and a status of OK is returned.
- // If no slot is available then a status of -EBUSY is returned and buf is
- // unmodified.
- //
- // The fence parameter will be updated to hold the fence associated with
- // the buffer. The contents of the buffer must not be overwritten until the
- // fence signals. If the fence is Fence::NO_FENCE, the buffer may be
- // written immediately.
- //
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called. If width and height are both zero, the
- // default values specified by setDefaultBufferSize() are used instead.
- //
- // The pixel formats are enumerated in graphics.h, e.g.
- // HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format
- // will be used.
- //
- // The usage argument specifies gralloc buffer usage flags. The values
- // are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER. These
- // will be merged with the usage flags specified by setConsumerUsageBits.
- //
- // The return value may be a negative error value or a non-negative
- // collection of flags. If the flags are set, the return values are
- // valid, but additional actions must be performed.
- //
- // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the
- // producer must discard cached GraphicBuffer references for the slot
- // returned in buf.
- // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer
- // must discard cached GraphicBuffer references for all slots.
- //
- // In both cases, the producer will need to call requestBuffer to get a
- // GraphicBuffer handle for the returned slot.
-#if ANDROID_VERSION == 17
- virtual status_t dequeueBuffer(int *buf, sp<Fence>& fence,
- uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
- return dequeueBuffer(buf, &fence, width, height, format, usage);
- }
-#endif
-
- virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
- uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
-
- // queueBuffer returns a filled buffer to the GonkBufferQueue.
- //
- // Additional data is provided in the QueueBufferInput struct. Notably,
- // a timestamp must be provided for the buffer. The timestamp is in
- // nanoseconds, and must be monotonically increasing. Its other semantics
- // (zero point, etc) are producer-specific and should be documented by the
- // producer.
- //
- // The caller may provide a fence that signals when all rendering
- // operations have completed. Alternatively, NO_FENCE may be used,
- // indicating that the buffer is ready immediately.
- //
- // Some values are returned in the output struct: the current settings
- // for default width and height, the current transform hint, and the
- // number of queued buffers.
- virtual status_t queueBuffer(int buf,
- const QueueBufferInput& input, QueueBufferOutput* output);
-
- // cancelBuffer returns a dequeued buffer to the GonkBufferQueue, but doesn't
- // queue it for use by the consumer.
- //
- // The buffer will not be overwritten until the fence signals. The fence
- // will usually be the one obtained from dequeueBuffer.
-#if ANDROID_VERSION == 17
- virtual void cancelBuffer(int buf, sp<Fence> fence);
-#else
- virtual void cancelBuffer(int buf, const sp<Fence>& fence);
-#endif
-
- // setSynchronousMode sets whether dequeueBuffer is synchronous or
- // asynchronous. In synchronous mode, dequeueBuffer blocks until
- // a buffer is available, the currently bound buffer can be dequeued and
- // queued buffers will be acquired in order. In asynchronous mode,
- // a queued buffer may be replaced by a subsequently queued buffer.
- //
- // The default mode is synchronous.
- // This should be called only during initialization.
- virtual status_t setSynchronousMode(bool enabled);
-
- // connect attempts to connect a producer API to the GonkBufferQueue. This
- // must be called before any other IGraphicBufferProducer methods are
- // called except for getAllocator. A consumer must already be connected.
- //
- // This method will fail if connect was previously called on the
- // GonkBufferQueue and no corresponding disconnect call was made (i.e. if
- // it's still connected to a producer).
- //
- // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU).
- virtual status_t connect(int api, QueueBufferOutput* output);
-
- // disconnect attempts to disconnect a producer API from the GonkBufferQueue.
- // Calling this method will cause any subsequent calls to other
- // IGraphicBufferProducer methods to fail except for getAllocator and connect.
- // Successfully calling connect after this will allow the other methods to
- // succeed again.
- //
- // This method will fail if the the GonkBufferQueue is not currently
- // connected to the specified producer API.
- virtual status_t disconnect(int api);
-
- // dump our state in a String
- virtual void dumpToString(String8& result) const;
- virtual void dumpToString(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
-
- // public facing structure for BufferSlot
- struct BufferItem {
-
- BufferItem()
- :
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mFrameNumber(0),
- mBuf(INVALID_BUFFER_SLOT) {
- mCrop.makeInvalid();
- }
- // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
- // if the buffer in this slot has been acquired in the past (see
- // BufferSlot.mAcquireCalled).
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued.
- int64_t mTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mBuf is the slot index of this buffer
- int mBuf;
-
- // mFence is a fence that will signal when the buffer is idle.
- sp<Fence> mFence;
- };
-
- // The following public functions are the consumer-facing interface
-
- // acquireBuffer attempts to acquire ownership of the next pending buffer in
- // the GonkBufferQueue. If no buffer is pending then it returns -EINVAL. If a
- // buffer is successfully acquired, the information about the buffer is
- // returned in BufferItem. If the buffer returned had previously been
- // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
- // NULL and it is assumed that the consumer still holds a reference to the
- // buffer.
- status_t acquireBuffer(BufferItem *buffer);
-
- // releaseBuffer releases a buffer slot from the consumer back to the
- // GonkBufferQueue. This may be done while the buffer's contents are still
- // being accessed. The fence will signal when the buffer is no longer
- // in use.
- //
- // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
- // any references to the just-released buffer that it might have, as if it
- // had received a onBuffersReleased() call with a mask set for the released
- // buffer.
- //
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
- status_t releaseBuffer(int buf, const sp<Fence>& releaseFence);
-
- // consumerConnect connects a consumer to the GonkBufferQueue. Only one
- // consumer may be connected, and when that consumer disconnects the
- // GonkBufferQueue is placed into the "abandoned" state, causing most
- // interactions with the GonkBufferQueue by the producer to fail.
- //
- // consumer may not be NULL.
- status_t consumerConnect(const sp<ConsumerListener>& consumer);
-
- // consumerDisconnect disconnects a consumer from the GonkBufferQueue. All
- // buffers will be freed and the GonkBufferQueue is placed in the "abandoned"
- // state, causing most interactions with the GonkBufferQueue by the producer to
- // fail.
- status_t consumerDisconnect();
-
- // getReleasedBuffers sets the value pointed to by slotMask to a bit mask
- // indicating which buffer slots have been released by the GonkBufferQueue
- // but have not yet been released by the consumer.
- //
- // This should be called from the onBuffersReleased() callback.
- status_t getReleasedBuffers(uint32_t* slotMask);
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // dequeueBuffer when a width and height of zero is requested. Default
- // is 1x1.
- status_t setDefaultBufferSize(uint32_t w, uint32_t h);
-
- // setDefaultMaxBufferCount sets the default value for the maximum buffer
- // count (the initial default is 2). If the producer has requested a
- // buffer count using setBufferCount, the default buffer count will only
- // take effect if the producer sets the count back to zero.
- //
- // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
- status_t setDefaultMaxBufferCount(int bufferCount);
-
- // setMaxAcquiredBufferCount sets the maximum number of buffers that can
- // be acquired by the consumer at one time (default 1). This call will
- // fail if a producer is connected to the GonkBufferQueue.
- status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
-
- // isSynchronousMode returns whether the GonkBufferQueue is currently in
- // synchronous mode.
- bool isSynchronousMode() const;
-
- // setConsumerName sets the name used in logging
- void setConsumerName(const String8& name);
-
- // setDefaultBufferFormat allows the GonkBufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer. Formats are enumerated in graphics.h; the
- // initial default is HAL_PIXEL_FORMAT_RGBA_8888.
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
-
- // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
- // These are merged with the bits passed to dequeueBuffer. The values are
- // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
- status_t setConsumerUsageBits(uint32_t usage);
-
- // setTransformHint bakes in rotation to buffers so overlays can be used.
- // The values are enumerated in window.h, e.g.
- // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform).
- status_t setTransformHint(uint32_t hint);
-
- already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer);
-
- int getSlotFromTextureClientLocked(TextureClient* client) const;
-
-private:
- // freeBufferLocked frees the GraphicBuffer and sync resources for the
- // given slot.
- //void freeBufferLocked(int index);
-
- // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
- // all slots.
- //void freeAllBuffersLocked();
- void freeAllBuffersLocked();
-
- // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
- // that will be used if the producer does not override the buffer slot
- // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
- // The initial default is 2.
- status_t setDefaultMaxBufferCountLocked(int count);
-
- // getMinBufferCountLocked returns the minimum number of buffers allowed
- // given the current GonkBufferQueue state.
- int getMinMaxBufferCountLocked() const;
-
- // getMinUndequeuedBufferCountLocked returns the minimum number of buffers
- // that must remain in a state other than DEQUEUED.
- int getMinUndequeuedBufferCountLocked() const;
-
- // getMaxBufferCountLocked returns the maximum number of buffers that can
- // be allocated at once. This value depends upon the following member
- // variables:
- //
- // mSynchronousMode
- // mMaxAcquiredBufferCount
- // mDefaultMaxBufferCount
- // mOverrideMaxBufferCount
- //
- // Any time one of these member variables is changed while a producer is
- // connected, mDequeueCondition must be broadcast.
- int getMaxBufferCountLocked() const;
-
- struct BufferSlot {
-
- BufferSlot()
- : mBufferState(BufferSlot::FREE),
- mRequestBufferCalled(false),
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mFrameNumber(0),
- mAcquireCalled(false),
- mNeedsCleanupOnRelease(false) {
- mCrop.makeInvalid();
- }
-
- // mGraphicBuffer points to the buffer allocated for this slot or is NULL
- // if no buffer has been allocated.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mTextureClient is a thin abstraction over remotely allocated GraphicBuffer.
- RefPtr<TextureClient> mTextureClient;
-
- // BufferState represents the different states in which a buffer slot
- // can be. All slots are initially FREE.
- enum BufferState {
- // FREE indicates that the buffer is available to be dequeued
- // by the producer. The buffer may be in use by the consumer for
- // a finite time, so the buffer must not be modified until the
- // associated fence is signaled.
- //
- // The slot is "owned" by GonkBufferQueue. It transitions to DEQUEUED
- // when dequeueBuffer is called.
- FREE = 0,
-
- // DEQUEUED indicates that the buffer has been dequeued by the
- // producer, but has not yet been queued or canceled. The
- // producer may modify the buffer's contents as soon as the
- // associated ready fence is signaled.
- //
- // The slot is "owned" by the producer. It can transition to
- // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
- DEQUEUED = 1,
-
- // QUEUED indicates that the buffer has been filled by the
- // producer and queued for use by the consumer. The buffer
- // contents may continue to be modified for a finite time, so
- // the contents must not be accessed until the associated fence
- // is signaled.
- //
- // The slot is "owned" by GonkBufferQueue. It can transition to
- // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
- // queued in asynchronous mode).
- QUEUED = 2,
-
- // ACQUIRED indicates that the buffer has been acquired by the
- // consumer. As with QUEUED, the contents must not be accessed
- // by the consumer until the fence is signaled.
- //
- // The slot is "owned" by the consumer. It transitions to FREE
- // when releaseBuffer is called.
- ACQUIRED = 3
- };
-
- // mBufferState is the current state of this buffer slot.
- BufferState mBufferState;
-
- // mRequestBufferCalled is used for validating that the producer did
- // call requestBuffer() when told to do so. Technically this is not
- // needed but useful for debugging and catching producer bugs.
- bool mRequestBufferCalled;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- // (example: NATIVE_WINDOW_TRANSFORM_ROT_90)
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- // (example: NATIVE_WINDOW_SCALING_MODE_FREEZE)
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued.
- int64_t mTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot. This
- // is used to dequeue buffers in LRU order (useful because buffers
- // may be released before their release fence is signaled).
- uint64_t mFrameNumber;
-
- // mEglFence is the EGL sync object that must signal before the buffer
- // associated with this buffer slot may be dequeued. It is initialized
- // to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
- // new sync object in releaseBuffer. (This is deprecated in favor of
- // mFence, below.)
- //EGLSyncKHR mEglFence;
-
- // mFence is a fence which will signal when work initiated by the
- // previous owner of the buffer is finished. When the buffer is FREE,
- // the fence indicates when the consumer has finished reading
- // from the buffer, or when the producer has finished writing if it
- // called cancelBuffer after queueing some writes. When the buffer is
- // QUEUED, it indicates when the producer has finished filling the
- // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
- // passed to the consumer or producer along with ownership of the
- // buffer, and mFence is set to NO_FENCE.
- sp<Fence> mFence;
-
- // Indicates whether this buffer has been seen by a consumer yet
- bool mAcquireCalled;
-
- // Indicates whether this buffer needs to be cleaned up by the
- // consumer. This is set when a buffer in ACQUIRED state is freed.
- // It causes releaseBuffer to return STALE_BUFFER_SLOT.
- bool mNeedsCleanupOnRelease;
- };
-
- // mSlots is the array of buffer slots that must be mirrored on the
- // producer side. This allows buffer ownership to be transferred between
- // the producer and consumer without sending a GraphicBuffer over binder.
- // The entire array is initialized to NULL at construction time, and
- // buffers are allocated for a slot when requestBuffer is called with
- // that slot's index.
- BufferSlot mSlots[NUM_BUFFER_SLOTS];
-
- // mDefaultWidth holds the default width of allocated buffers. It is used
- // in dequeueBuffer() if a width and height of zero is specified.
- uint32_t mDefaultWidth;
-
- // mDefaultHeight holds the default height of allocated buffers. It is used
- // in dequeueBuffer() if a width and height of zero is specified.
- uint32_t mDefaultHeight;
-
- // mMaxAcquiredBufferCount is the number of buffers that the consumer may
- // acquire at one time. It defaults to 1 and can be changed by the
- // consumer via the setMaxAcquiredBufferCount method, but this may only be
- // done when no producer is connected to the GonkBufferQueue.
- //
- // This value is used to derive the value returned for the
- // MIN_UNDEQUEUED_BUFFERS query by the producer.
- int mMaxAcquiredBufferCount;
-
- // mDefaultMaxBufferCount is the default limit on the number of buffers
- // that will be allocated at one time. This default limit is set by the
- // consumer. The limit (as opposed to the default limit) may be
- // overridden by the producer.
- int mDefaultMaxBufferCount;
-
- // mOverrideMaxBufferCount is the limit on the number of buffers that will
- // be allocated at one time. This value is set by the image producer by
- // calling setBufferCount. The default is zero, which means the producer
- // doesn't care about the number of buffers in the pool. In that case
- // mDefaultMaxBufferCount is used as the limit.
- int mOverrideMaxBufferCount;
-
- // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
- // allocate new GraphicBuffer objects.
- sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
-
- // mConsumerListener is used to notify the connected consumer of
- // asynchronous events that it may wish to react to. It is initially set
- // to NULL and is written by consumerConnect and consumerDisconnect.
- sp<ConsumerListener> mConsumerListener;
-
- // mSynchronousMode whether we're in synchronous mode or not
- bool mSynchronousMode;
-
- // mAllowSynchronousMode whether we allow synchronous mode or not. Set
- // when the GonkBufferQueue is created (by the consumer).
- const bool mAllowSynchronousMode;
-
- // mConnectedApi indicates the producer API that is currently connected
- // to this GonkBufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets
- // updated by the connect and disconnect methods.
- int mConnectedApi;
-
- // mDequeueCondition condition used for dequeueBuffer in synchronous mode
- mutable Condition mDequeueCondition;
-
- // mQueue is a FIFO of queued buffers used in synchronous mode
- typedef Vector<int> Fifo;
- Fifo mQueue;
-
- // mAbandoned indicates that the GonkBufferQueue will no longer be used to
- // consume image buffers pushed to it using the IGraphicBufferProducer
- // interface. It is initialized to false, and set to true in the
- // consumerDisconnect method. A GonkBufferQueue that has been abandoned will
- // return the NO_INIT error from all IGraphicBufferProducer methods
- // capable of returning an error.
- bool mAbandoned;
-
- // mConsumerName is a string used to identify the GonkBufferQueue in log
- // messages. It is set by the setConsumerName method.
- String8 mConsumerName;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of GonkBufferQueue objects. It must be locked whenever the
- // member variables are accessed.
- mutable Mutex mMutex;
-
- // mFrameCounter is the free running counter, incremented on every
- // successful queueBuffer call.
- uint64_t mFrameCounter;
-
- // mBufferHasBeenQueued is true once a buffer has been queued. It is
- // reset when something causes all buffers to be freed (e.g. changing the
- // buffer count).
- bool mBufferHasBeenQueued;
-
- // mDefaultBufferFormat can be set so it will override
- // the buffer format when it isn't specified in dequeueBuffer
- uint32_t mDefaultBufferFormat;
-
- // mConsumerUsageBits contains flags the consumer wants for GraphicBuffers
- uint32_t mConsumerUsageBits;
-
- // mTransformHint is used to optimize for screen rotations
- uint32_t mTransformHint;
-
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_BUFFERQUEUE_H
diff --git a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp b/widget/gonk/nativewindow/GonkBufferQueueKK.cpp
deleted file mode 100644
index 0c5cdfeb9..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp
+++ /dev/null
@@ -1,1265 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "GonkBufferQueue"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <utils/Log.h>
-#include <utils/Trace.h>
-#include <utils/CallStack.h>
-#include <cutils/compiler.h>
-
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "GonkBufferQueueKK.h"
-
-#define ATRACE_BUFFER_INDEX(index)
-
-using namespace mozilla;
-using namespace mozilla::gfx;
-using namespace mozilla::layers;
-
-namespace android {
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-static const char* scalingModeName(int scalingMode) {
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
- default: return "Unknown";
- }
-}
-
-GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode,
- const sp<IGraphicBufferAlloc>& allocator) :
- mDefaultWidth(1),
- mDefaultHeight(1),
- mMaxAcquiredBufferCount(1),
- mDefaultMaxBufferCount(2),
- mOverrideMaxBufferCount(0),
- mSynchronousMode(true),
- mConsumerControlledByApp(false),
- mDequeueBufferCannotBlock(false),
- mUseAsyncBuffer(true),
- mConnectedApi(NO_CONNECTED_API),
- mAbandoned(false),
- mFrameCounter(0),
- mBufferHasBeenQueued(false),
- mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
- mConsumerUsageBits(0),
- mTransformHint(0)
-{
- // Choose a name using the PID and a process-unique ID.
- mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
- ALOGV("GonkBufferQueue");
-}
-
-GonkBufferQueue::~GonkBufferQueue() {
- ALOGV("~GonkBufferQueue");
-}
-
-status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) {
- if (count < 2 || count > NUM_BUFFER_SLOTS)
- return BAD_VALUE;
-
- mDefaultMaxBufferCount = count;
- mDequeueCondition.broadcast();
-
- return NO_ERROR;
-}
-
-void GonkBufferQueue::setConsumerName(const String8& name) {
- Mutex::Autolock lock(mMutex);
- mConsumerName = name;
-}
-
-status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock lock(mMutex);
- mDefaultBufferFormat = defaultFormat;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) {
- Mutex::Autolock lock(mMutex);
- mConsumerUsageBits = usage;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::setTransformHint(uint32_t hint) {
- ALOGV("setTransformHint: %02x", hint);
- Mutex::Autolock lock(mMutex);
- mTransformHint = hint;
- return NO_ERROR;
-}
-
-already_AddRefed<TextureClient>
-GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
-{
- Mutex::Autolock _l(mMutex);
- if (buffer == NULL) {
- ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
- return nullptr;
- }
-
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
- RefPtr<TextureClient> client(mSlots[i].mTextureClient);
- return client.forget();
- }
- }
- ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
- return nullptr;
-}
-
-int GonkBufferQueue::getSlotFromTextureClientLocked(
- TextureClient* client) const
-{
- if (client == NULL) {
- ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
- return BAD_VALUE;
- }
-
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].mTextureClient == client) {
- return i;
- }
- }
- ALOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client);
- return BAD_VALUE;
-}
-
-status_t GonkBufferQueue::setBufferCount(int bufferCount) {
- ALOGV("setBufferCount: count=%d", bufferCount);
-
- sp<IConsumerListener> listener;
- {
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ALOGE("setBufferCount: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
- if (bufferCount > NUM_BUFFER_SLOTS) {
- ALOGE("setBufferCount: bufferCount too large (max %d)",
- NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- }
-
- // Error out if the user has dequeued buffers
- for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
- ALOGE("setBufferCount: client owns some buffers");
- return -EINVAL;
- }
- }
-
- if (bufferCount == 0) {
- mOverrideMaxBufferCount = 0;
- mDequeueCondition.broadcast();
- return NO_ERROR;
- }
-
- // fine to assume async to false before we're setting the buffer count
- const int minBufferSlots = getMinMaxBufferCountLocked(false);
- if (bufferCount < minBufferSlots) {
- ALOGE("setBufferCount: requested buffer count (%d) is less than "
- "minimum (%d)", bufferCount, minBufferSlots);
- return BAD_VALUE;
- }
-
- // here we're guaranteed that the client doesn't have dequeued buffers
- // and will release all of its buffer references. We don't clear the
- // queue, however, so currently queued buffers still get displayed.
- // XXX: Should this use drainQueueAndFreeBuffersLocked instead?
- freeAllBuffersLocked();
- mOverrideMaxBufferCount = bufferCount;
- mDequeueCondition.broadcast();
- listener = mConsumerListener;
- } // scope for lock
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return NO_ERROR;
-}
-
-int GonkBufferQueue::query(int what, int* outValue)
-{
- ATRACE_CALL();
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ALOGE("query: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- int value;
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- value = mDefaultWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- value = mDefaultHeight;
- break;
- case NATIVE_WINDOW_FORMAT:
- value = mDefaultBufferFormat;
- break;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- value = getMinUndequeuedBufferCount(false);
- break;
- case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
- value = (mQueue.size() >= 2);
- break;
- case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
- value = mConsumerUsageBits;
- break;
- default:
- return BAD_VALUE;
- }
- outValue[0] = value;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- ATRACE_CALL();
- ALOGV("requestBuffer: slot=%d", slot);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ALOGE("requestBuffer: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
- if (slot < 0 || slot >= NUM_BUFFER_SLOTS) {
- ALOGE("requestBuffer: slot index out of range [0, %d]: %d",
- NUM_BUFFER_SLOTS, slot);
- return BAD_VALUE;
- } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
- ALOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
- slot, mSlots[slot].mBufferState);
- return BAD_VALUE;
- }
- mSlots[slot].mRequestBufferCalled = true;
- *buf = mSlots[slot].mGraphicBuffer;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
- ATRACE_CALL();
- ALOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
-
- if ((w && !h) || (!w && h)) {
- ALOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
- return BAD_VALUE;
- }
-
- status_t returnFlags(OK);
- int buf = INVALID_BUFFER_SLOT;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (format == 0) {
- format = mDefaultBufferFormat;
- }
- // turn on usage bits the consumer requested
- usage |= mConsumerUsageBits;
-
- int found = -1;
- bool tryAgain = true;
- while (tryAgain) {
- if (mAbandoned) {
- ALOGE("dequeueBuffer: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- const int maxBufferCount = getMaxBufferCountLocked(async);
- if (async && mOverrideMaxBufferCount) {
- // FIXME: some drivers are manually setting the buffer-count (which they
- // shouldn't), so we do this extra test here to handle that case.
- // This is TEMPORARY, until we get this fixed.
- if (mOverrideMaxBufferCount < maxBufferCount) {
- ALOGE("dequeueBuffer: async mode is invalid with buffercount override");
- return BAD_VALUE;
- }
- }
-
- // Free up any buffers that are in slots beyond the max buffer
- // count.
- //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
- // assert(mSlots[i].mBufferState == BufferSlot::FREE);
- // if (mSlots[i].mGraphicBuffer != NULL) {
- // freeBufferLocked(i);
- // returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
- // }
- //}
-
- // look for a free buffer to give to the client
- found = INVALID_BUFFER_SLOT;
- int dequeuedCount = 0;
- int acquiredCount = 0;
- for (int i = 0; i < maxBufferCount; i++) {
- const int state = mSlots[i].mBufferState;
- switch (state) {
- case BufferSlot::DEQUEUED:
- dequeuedCount++;
- break;
- case BufferSlot::ACQUIRED:
- acquiredCount++;
- break;
- case BufferSlot::FREE:
- /* We return the oldest of the free buffers to avoid
- * stalling the producer if possible. This is because
- * the consumer may still have pending reads of the
- * buffers in flight.
- */
- if ((found < 0) ||
- mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
- found = i;
- }
- break;
- }
- }
-
- // clients are not allowed to dequeue more than one buffer
- // if they didn't set a buffer count.
- if (!mOverrideMaxBufferCount && dequeuedCount) {
- ALOGE("dequeueBuffer: can't dequeue multiple buffers without "
- "setting the buffer count");
- return -EINVAL;
- }
-
- // See whether a buffer has been queued since the last
- // setBufferCount so we know whether to perform the min undequeued
- // buffers check below.
- if (mBufferHasBeenQueued) {
- // make sure the client is not trying to dequeue more buffers
- // than allowed.
- const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
- const int minUndequeuedCount = getMinUndequeuedBufferCount(async);
- if (newUndequeuedCount < minUndequeuedCount) {
- ALOGE("dequeueBuffer: min undequeued buffer count (%d) "
- "exceeded (dequeued=%d undequeudCount=%d)",
- minUndequeuedCount, dequeuedCount,
- newUndequeuedCount);
- return -EBUSY;
- }
- }
-
- // If no buffer is found, wait for a buffer to be released or for
- // the max buffer count to change.
- tryAgain = found == INVALID_BUFFER_SLOT;
- if (tryAgain) {
- // return an error if we're in "cannot block" mode (producer and consumer
- // are controlled by the application) -- however, the consumer is allowed
- // to acquire briefly an extra buffer (which could cause us to have to wait here)
- // and that's okay because we know the wait will be brief (it happens
- // if we dequeue a buffer while the consumer has acquired one but not released
- // the old one yet -- for e.g.: see GLConsumer::updateTexImage()).
- if (mDequeueBufferCannotBlock && (acquiredCount <= mMaxAcquiredBufferCount)) {
- ALOGE("dequeueBuffer: would block! returning an error instead.");
- return WOULD_BLOCK;
- }
- mDequeueCondition.wait(mMutex);
- }
- }
-
-
- if (found == INVALID_BUFFER_SLOT) {
- // This should not happen.
- ALOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
- }
-
- buf = found;
- *outBuf = found;
-
- const bool useDefaultSize = !w && !h;
- if (useDefaultSize) {
- // use the default size
- w = mDefaultWidth;
- h = mDefaultHeight;
- }
-
- mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
-
- const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
- if ((buffer == NULL) ||
- (uint32_t(buffer->width) != w) ||
- (uint32_t(buffer->height) != h) ||
- (uint32_t(buffer->format) != format) ||
- ((uint32_t(buffer->usage) & usage) != usage))
- {
- mSlots[buf].mAcquireCalled = false;
- mSlots[buf].mGraphicBuffer = NULL;
- mSlots[buf].mRequestBufferCalled = false;
- mSlots[buf].mFence = Fence::NO_FENCE;
- if (mSlots[buf].mTextureClient) {
- mSlots[buf].mTextureClient->ClearRecycleCallback();
- // release TextureClient in ImageBridge thread
- RefPtr<TextureClientReleaseTask> task =
- MakeAndAddRef<TextureClientReleaseTask>(mSlots[buf].mTextureClient);
- mSlots[buf].mTextureClient = NULL;
- ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
- }
- returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
- }
-
-
- if (CC_UNLIKELY(mSlots[buf].mFence == NULL)) {
- ALOGE("dequeueBuffer: about to return a NULL fence from mSlot. "
- "buf=%d, w=%d, h=%d, format=%d",
- buf, buffer->width, buffer->height, buffer->format);
- }
- *outFence = mSlots[buf].mFence;
- mSlots[buf].mFence = Fence::NO_FENCE;
- } // end lock scope
-
- if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
-
- RefPtr<LayersIPCChannel> allocator = ImageBridgeChild::GetSingleton();
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format,
- gfx::BackendType::NONE, usage,
- allocator);
- if (!texData) {
- return -ENOMEM;
- }
-
- RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator);
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ALOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- mSlots[buf].mGraphicBuffer = texData->GetGraphicBuffer();
- mSlots[buf].mTextureClient = textureClient;
- ALOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
- mSlots[buf].mGraphicBuffer->handle);
-
- }
-
- }
-
- ALOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outBuf,
- mSlots[*outBuf].mFrameNumber,
- mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
-
- return returnFlags;
-}
-
-status_t GonkBufferQueue::setSynchronousMode(bool enabled) {
- ALOGV("setSynchronousMode: enabled=%d", enabled);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ALOGE("setSynchronousMode: BufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- if (mSynchronousMode != enabled) {
- mSynchronousMode = enabled;
- mDequeueCondition.broadcast();
- }
- return OK;
-}
-
-status_t GonkBufferQueue::queueBuffer(int buf,
- const QueueBufferInput& input, QueueBufferOutput* output) {
- ATRACE_CALL();
-
- Rect crop;
- uint32_t transform;
- int scalingMode;
- int64_t timestamp;
- bool isAutoTimestamp;
- bool async;
- sp<Fence> fence;
-
- input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
- &async, &fence);
-
- if (fence == NULL) {
- ALOGE("queueBuffer: fence is NULL");
- return BAD_VALUE;
- }
-
- ALOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
- "scale=%s",
- buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
- transform, scalingModeName(scalingMode));
-
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
- case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
- break;
- default:
- ALOGE("unknown scaling mode: %d", scalingMode);
- return -EINVAL;
- }
-
- sp<IConsumerListener> listener;
-
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ALOGE("queueBuffer: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- const int maxBufferCount = getMaxBufferCountLocked(async);
- if (async && mOverrideMaxBufferCount) {
- // FIXME: some drivers are manually setting the buffer-count (which they
- // shouldn't), so we do this extra test here to handle that case.
- // This is TEMPORARY, until we get this fixed.
- if (mOverrideMaxBufferCount < maxBufferCount) {
- ALOGE("queueBuffer: async mode is invalid with buffercount override");
- return BAD_VALUE;
- }
- }
- if (buf < 0 || buf >= maxBufferCount) {
- ALOGE("queueBuffer: slot index out of range [0, %d]: %d",
- maxBufferCount, buf);
- return -EINVAL;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ALOGE("queueBuffer: slot %d is not owned by the client "
- "(state=%d)", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- } else if (!mSlots[buf].mRequestBufferCalled) {
- ALOGE("queueBuffer: slot %d was enqueued without requesting a "
- "buffer", buf);
- return -EINVAL;
- }
-
- ALOGV("queueBuffer: slot=%d/%llu time=%#llx crop=[%d,%d,%d,%d] "
- "tr=%#x scale=%s",
- buf, mFrameCounter + 1, timestamp,
- crop.left, crop.top, crop.right, crop.bottom,
- transform, scalingModeName(scalingMode));
-
- const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
- Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
- Rect croppedCrop;
- crop.intersect(bufferRect, &croppedCrop);
- if (croppedCrop != crop) {
- ALOGE("queueBuffer: crop rect is not contained within the "
- "buffer in slot %d", buf);
- return -EINVAL;
- }
-
- mSlots[buf].mFence = fence;
- mSlots[buf].mBufferState = BufferSlot::QUEUED;
- mFrameCounter++;
- mSlots[buf].mFrameNumber = mFrameCounter;
-
- BufferItem item;
- item.mAcquireCalled = mSlots[buf].mAcquireCalled;
- item.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
- item.mCrop = crop;
- item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
- item.mTransformToDisplayInverse = bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
- item.mScalingMode = scalingMode;
- item.mTimestamp = timestamp;
- item.mIsAutoTimestamp = isAutoTimestamp;
- item.mFrameNumber = mFrameCounter;
- item.mBuf = buf;
- item.mFence = fence;
- item.mIsDroppable = mDequeueBufferCannotBlock || async;
-
- if (mQueue.empty()) {
- // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and
- // simply queue this buffer.
- mQueue.push_back(item);
- } else {
- // when the queue is not empty, we need to look at the front buffer
- // state and see if we need to replace it.
- Fifo::iterator front(mQueue.begin());
- if (front->mIsDroppable || !mSynchronousMode) {
- // buffer slot currently queued is marked free if still tracked
- if (stillTracking(front)) {
- mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
- // reset the frame number of the freed buffer so that it is the first in
- // line to be dequeued again.
- mSlots[front->mBuf].mFrameNumber = 0;
- }
- // and we record the new buffer in the queued list
- *front = item;
- } else {
- mQueue.push_back(item);
- }
- }
- // always signals that an additional frame should be consumed
- // to handle max acquired buffer count reached case.
- listener = mConsumerListener;
-
- mBufferHasBeenQueued = true;
- mDequeueCondition.broadcast();
-
- output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
- mQueue.size());
-
- } // scope for the lock
-
- // call back without lock held
- if (listener != 0) {
- listener->onFrameAvailable();
- }
- return NO_ERROR;
-}
-
-void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
- ATRACE_CALL();
- ALOGV("cancelBuffer: slot=%d", buf);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ALOGW("cancelBuffer: GonkBufferQueue has been abandoned!");
- return;
- }
-
- if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
- ALOGE("cancelBuffer: slot index out of range [0, %d]: %d",
- NUM_BUFFER_SLOTS, buf);
- return;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ALOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
- buf, mSlots[buf].mBufferState);
- return;
- } else if (fence == NULL) {
- ALOGE("cancelBuffer: fence is NULL");
- return;
- }
- mSlots[buf].mBufferState = BufferSlot::FREE;
- mSlots[buf].mFrameNumber = 0;
- mSlots[buf].mFence = fence;
- mDequeueCondition.broadcast();
-}
-
-
-status_t GonkBufferQueue::connect(const sp<IBinder>& token,
- int api, bool producerControlledByApp, QueueBufferOutput* output) {
- ATRACE_CALL();
- ALOGV("connect: api=%d producerControlledByApp=%s", api,
- producerControlledByApp ? "true" : "false");
- Mutex::Autolock lock(mMutex);
-
-retry:
- if (mAbandoned) {
- ALOGE("connect: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- if (mConsumerListener == NULL) {
- ALOGE("connect: GonkBufferQueue has no consumer!");
- return NO_INIT;
- }
-
- if (mConnectedApi != NO_CONNECTED_API) {
- ALOGE("connect: already connected (cur=%d, req=%d)",
- mConnectedApi, api);
- return -EINVAL;
- }
-
- // If we disconnect and reconnect quickly, we can be in a state where our slots are
- // empty but we have many buffers in the queue. This can cause us to run out of
- // memory if we outrun the consumer. Wait here if it looks like we have too many
- // buffers queued up.
- int maxBufferCount = getMaxBufferCountLocked(false); // worst-case, i.e. largest value
- if (mQueue.size() > (size_t) maxBufferCount) {
- // TODO: make this bound tighter?
- ALOGV("queue size is %d, waiting", mQueue.size());
- mDequeueCondition.wait(mMutex);
- goto retry;
- }
-
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- mConnectedApi = api;
- output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
-
- // set-up a death notification so that we can disconnect
- // automatically when/if the remote producer dies.
- if (token != NULL && token->remoteBinder() != NULL) {
- status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
- if (err == NO_ERROR) {
- mConnectedProducerToken = token;
- } else {
- ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
- }
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
-
- mBufferHasBeenQueued = false;
- mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp;
-
- return err;
-}
-
-void GonkBufferQueue::binderDied(const wp<IBinder>& who) {
- // If we're here, it means that a producer we were connected to died.
- // We're GUARANTEED that we still are connected to it because it has no other way
- // to get disconnected -- or -- we wouldn't be here because we're removing this
- // callback upon disconnect. Therefore, it's okay to read mConnectedApi without
- // synchronization here.
- int api = mConnectedApi;
- this->disconnect(api);
-}
-
-status_t GonkBufferQueue::disconnect(int api) {
- ATRACE_CALL();
- ALOGV("disconnect: api=%d", api);
-
- int err = NO_ERROR;
- sp<IConsumerListener> listener;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- // it is not really an error to disconnect after the surface
- // has been abandoned, it should just be a no-op.
- return NO_ERROR;
- }
-
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi == api) {
- freeAllBuffersLocked();
- mConnectedApi = NO_CONNECTED_API;
- mDequeueCondition.broadcast();
- listener = mConsumerListener;
- } else {
- ALOGE("disconnect: connected to another api (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- }
- break;
- default:
- ALOGE("disconnect: unknown API %d", api);
- err = -EINVAL;
- break;
- }
- }
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return err;
-}
-
-void GonkBufferQueue::dumpToString(String8& result, const char* prefix) const {
- Mutex::Autolock _l(mMutex);
-
- String8 fifo;
- int fifoSize = 0;
- Fifo::const_iterator i(mQueue.begin());
- while (i != mQueue.end()) {
- fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
- "xform=0x%02x, time=%#llx, scale=%s\n",
- i->mBuf, i->mGraphicBuffer.get(),
- i->mCrop.left, i->mCrop.top, i->mCrop.right,
- i->mCrop.bottom, i->mTransform, i->mTimestamp,
- scalingModeName(i->mScalingMode)
- );
- i++;
- fifoSize++;
- }
-
-
- result.appendFormat(
- "%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
- "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
- prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth,
- mDefaultHeight, mDefaultBufferFormat, mTransformHint,
- fifoSize, fifo.string());
-
- struct {
- const char * operator()(int state) const {
- switch (state) {
- case BufferSlot::DEQUEUED: return "DEQUEUED";
- case BufferSlot::QUEUED: return "QUEUED";
- case BufferSlot::FREE: return "FREE";
- case BufferSlot::ACQUIRED: return "ACQUIRED";
- default: return "Unknown";
- }
- }
- } stateName;
-
- // just trim the free buffers to not spam the dump
- int maxBufferCount = 0;
- for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) {
- const BufferSlot& slot(mSlots[i]);
- if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) {
- maxBufferCount = i+1;
- break;
- }
- }
-
- for (int i=0 ; i<maxBufferCount ; i++) {
- const BufferSlot& slot(mSlots[i]);
- const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
- result.appendFormat(
- "%s%s[%02d:%p] state=%-8s",
- prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(),
- stateName(slot.mBufferState)
- );
-
- if (buf != NULL) {
- result.appendFormat(
- ", %p [%4ux%4u:%4u,%3X]",
- buf->handle, buf->width, buf->height, buf->stride,
- buf->format);
- }
- result.append("\n");
- }
-}
-
-void GonkBufferQueue::freeAllBuffersLocked()
-{
- ALOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersLocked called but mQueue is not empty");
- mQueue.clear();
- mBufferHasBeenQueued = false;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- mSlots[i].mGraphicBuffer = 0;
- if (mSlots[i].mTextureClient) {
- mSlots[i].mTextureClient->ClearRecycleCallback();
- // release TextureClient in ImageBridge thread
- RefPtr<TextureClientReleaseTask> task =
- MakeAndAddRef<TextureClientReleaseTask>(mSlots[i].mTextureClient);
- mSlots[i].mTextureClient = NULL;
- ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
- }
- if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
- mSlots[i].mNeedsCleanupOnRelease = true;
- }
- mSlots[i].mBufferState = BufferSlot::FREE;
- mSlots[i].mFrameNumber = 0;
- mSlots[i].mAcquireCalled = false;
- // destroy fence as GonkBufferQueue now takes ownership
- mSlots[i].mFence = Fence::NO_FENCE;
- }
-}
-
-status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t expectedPresent) {
- ATRACE_CALL();
- Mutex::Autolock _l(mMutex);
-
- // Check that the consumer doesn't currently have the maximum number of
- // buffers acquired. We allow the max buffer count to be exceeded by one
- // buffer, so that the consumer can successfully set up the newly acquired
- // buffer before releasing the old one.
- int numAcquiredBuffers = 0;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
- numAcquiredBuffers++;
- }
- }
- if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) {
- ALOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)",
- numAcquiredBuffers, mMaxAcquiredBufferCount);
- return INVALID_OPERATION;
- }
-
- // check if queue is empty
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- if (mQueue.empty()) {
- return NO_BUFFER_AVAILABLE;
- }
-
- Fifo::iterator front(mQueue.begin());
-
- // If expectedPresent is specified, we may not want to return a buffer yet.
- // If it's specified and there's more than one buffer queued, we may
- // want to drop a buffer.
- if (expectedPresent != 0) {
- const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
-
- // The "expectedPresent" argument indicates when the buffer is expected
- // to be presented on-screen. If the buffer's desired-present time
- // is earlier (less) than expectedPresent, meaning it'll be displayed
- // on time or possibly late if we show it ASAP, we acquire and return
- // it. If we don't want to display it until after the expectedPresent
- // time, we return PRESENT_LATER without acquiring it.
- //
- // To be safe, we don't defer acquisition if expectedPresent is
- // more than one second in the future beyond the desired present time
- // (i.e. we'd be holding the buffer for a long time).
- //
- // NOTE: code assumes monotonic time values from the system clock are
- // positive.
-
- // Start by checking to see if we can drop frames. We skip this check
- // if the timestamps are being auto-generated by Surface -- if the
- // app isn't generating timestamps explicitly, they probably don't
- // want frames to be discarded based on them.
- while (mQueue.size() > 1 && !mQueue[0].mIsAutoTimestamp) {
- // If entry[1] is timely, drop entry[0] (and repeat). We apply
- // an additional criteria here: we only drop the earlier buffer if
- // our desiredPresent falls within +/- 1 second of the expected
- // present. Otherwise, bogus desiredPresent times (e.g. 0 or
- // a small relative timestamp), which normally mean "ignore the
- // timestamp and acquire immediately", would cause us to drop
- // frames.
- //
- // We may want to add an additional criteria: don't drop the
- // earlier buffer if entry[1]'s fence hasn't signaled yet.
- //
- // (Vector front is [0], back is [size()-1])
- const BufferItem& bi(mQueue[1]);
- nsecs_t desiredPresent = bi.mTimestamp;
- if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
- desiredPresent > expectedPresent) {
- // This buffer is set to display in the near future, or
- // desiredPresent is garbage. Either way we don't want to
- // drop the previous buffer just to get this on screen sooner.
- ALOGV("pts nodrop: des=%lld expect=%lld (%lld) now=%lld",
- desiredPresent, expectedPresent, desiredPresent - expectedPresent,
- systemTime(CLOCK_MONOTONIC));
- break;
- }
- ALOGV("pts drop: queue1des=%lld expect=%lld size=%d",
- desiredPresent, expectedPresent, mQueue.size());
- if (stillTracking(front)) {
- // front buffer is still in mSlots, so mark the slot as free
- mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
- }
- mQueue.erase(front);
- front = mQueue.begin();
- }
-
- // See if the front buffer is due.
- nsecs_t desiredPresent = front->mTimestamp;
- if (desiredPresent > expectedPresent &&
- desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
- ALOGV("pts defer: des=%lld expect=%lld (%lld) now=%lld",
- desiredPresent, expectedPresent, desiredPresent - expectedPresent,
- systemTime(CLOCK_MONOTONIC));
- return PRESENT_LATER;
- }
-
- ALOGV("pts accept: des=%lld expect=%lld (%lld) now=%lld",
- desiredPresent, expectedPresent, desiredPresent - expectedPresent,
- systemTime(CLOCK_MONOTONIC));
- }
-
- int buf = front->mBuf;
- buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
- buffer->mFrameNumber = mSlots[buf].mFrameNumber;
- buffer->mBuf = buf;
- buffer->mFence = mSlots[buf].mFence;
- ATRACE_BUFFER_INDEX(buf);
-
- ALOGV("acquireBuffer: acquiring { slot=%d/%llu, buffer=%p }",
- front->mBuf, front->mFrameNumber,
- front->mGraphicBuffer->handle);
- // if front buffer still being tracked update slot state
- if (stillTracking(front)) {
- mSlots[buf].mAcquireCalled = true;
- mSlots[buf].mNeedsCleanupOnRelease = false;
- mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
- mSlots[buf].mFence = Fence::NO_FENCE;
- }
-
- // If the buffer has previously been acquired by the consumer, set
- // mGraphicBuffer to NULL to avoid unnecessarily remapping this
- // buffer on the consumer side.
- //if (buffer->mAcquireCalled) {
- // buffer->mGraphicBuffer = NULL;
- //}
-
- mQueue.erase(front);
- mDequeueCondition.broadcast();
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& fence) {
- ATRACE_CALL();
-
- if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
- return BAD_VALUE;
- }
-
- Mutex::Autolock _l(mMutex);
-
- // If the frame number has changed because buffer has been reallocated,
- // we can ignore this releaseBuffer for the old buffer.
- //if (frameNumber != mSlots[buf].mFrameNumber) {
- // return STALE_BUFFER_SLOT;
- //}
-
-
- // Internal state consistency checks:
- // Make sure this buffers hasn't been queued while we were owning it (acquired)
- Fifo::iterator front(mQueue.begin());
- Fifo::const_iterator const end(mQueue.end());
- while (front != end) {
- if (front->mBuf == buf) {
- LOG_ALWAYS_FATAL("[%s] received new buffer(#%lld) on slot #%d that has not yet been "
- "acquired", mConsumerName.string(), frameNumber, buf);
- break; // never reached
- }
- front++;
- }
-
- // The buffer can now only be released if its in the acquired state
- if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
- mSlots[buf].mFence = fence;
- mSlots[buf].mBufferState = BufferSlot::FREE;
- } else if (mSlots[buf].mNeedsCleanupOnRelease) {
- ALOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
- mSlots[buf].mNeedsCleanupOnRelease = false;
- return STALE_BUFFER_SLOT;
- } else {
- ALOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- }
-
- mDequeueCondition.broadcast();
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::consumerConnect(const sp<IConsumerListener>& consumerListener,
- bool controlledByApp) {
- ALOGV("consumerConnect controlledByApp=%s",
- controlledByApp ? "true" : "false");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ALOGE("consumerConnect: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
- if (consumerListener == NULL) {
- ALOGE("consumerConnect: consumerListener may not be NULL");
- return BAD_VALUE;
- }
-
- mConsumerListener = consumerListener;
- mConsumerControlledByApp = controlledByApp;
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::consumerDisconnect() {
- ALOGV("consumerDisconnect");
- Mutex::Autolock lock(mMutex);
-
- if (mConsumerListener == NULL) {
- ALOGE("consumerDisconnect: No consumer is connected!");
- return -EINVAL;
- }
-
- mAbandoned = true;
- mConsumerListener = NULL;
- mQueue.clear();
- freeAllBuffersLocked();
- mDequeueCondition.broadcast();
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) {
- ALOGV("getReleasedBuffers");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ALOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- uint32_t mask = 0;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (!mSlots[i].mAcquireCalled) {
- mask |= 1 << i;
- }
- }
-
- // Remove buffers in flight (on the queue) from the mask where acquire has
- // been called, as the consumer will not receive the buffer address, so
- // it should not free these slots.
- Fifo::iterator front(mQueue.begin());
- while (front != mQueue.end()) {
- if (front->mAcquireCalled)
- mask &= ~(1 << front->mBuf);
- front++;
- }
-
- *slotMask = mask;
-
- ALOGV("getReleasedBuffers: returning mask %#x", mask);
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) {
- ALOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
- if (!w || !h) {
- ALOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
- w, h);
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mMutex);
- mDefaultWidth = w;
- mDefaultHeight = h;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) {
- ATRACE_CALL();
- Mutex::Autolock lock(mMutex);
- return setDefaultMaxBufferCountLocked(bufferCount);
-}
-
-status_t GonkBufferQueue::disableAsyncBuffer() {
- ATRACE_CALL();
- Mutex::Autolock lock(mMutex);
- if (mConsumerListener != NULL) {
- ALOGE("disableAsyncBuffer: consumer already connected!");
- return INVALID_OPERATION;
- }
- mUseAsyncBuffer = false;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
- ATRACE_CALL();
- Mutex::Autolock lock(mMutex);
- if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) {
- ALOGE("setMaxAcquiredBufferCount: invalid count specified: %d",
- maxAcquiredBuffers);
- return BAD_VALUE;
- }
- if (mConnectedApi != NO_CONNECTED_API) {
- return INVALID_OPERATION;
- }
- mMaxAcquiredBufferCount = maxAcquiredBuffers;
- return NO_ERROR;
-}
-
-int GonkBufferQueue::getMinUndequeuedBufferCount(bool async) const {
- // if dequeueBuffer is allowed to error out, we don't have to
- // add an extra buffer.
- if (!mUseAsyncBuffer)
- return mMaxAcquiredBufferCount;
-
- // we're in async mode, or we want to prevent the app to
- // deadlock itself, we throw-in an extra buffer to guarantee it.
- if (mDequeueBufferCannotBlock || async || !mSynchronousMode)
- return mMaxAcquiredBufferCount + 1;
-
- return mMaxAcquiredBufferCount;
-}
-
-int GonkBufferQueue::getMinMaxBufferCountLocked(bool async) const {
- return getMinUndequeuedBufferCount(async) + 1;
-}
-
-int GonkBufferQueue::getMaxBufferCountLocked(bool async) const {
- int minMaxBufferCount = getMinMaxBufferCountLocked(async);
-
- int maxBufferCount = mDefaultMaxBufferCount;
- if (maxBufferCount < minMaxBufferCount) {
- maxBufferCount = minMaxBufferCount;
- }
- if (mOverrideMaxBufferCount != 0) {
- assert(mOverrideMaxBufferCount >= minMaxBufferCount);
- maxBufferCount = mOverrideMaxBufferCount;
- }
-
- // Any buffers that are dequeued by the producer or sitting in the queue
- // waiting to be consumed need to have their slots preserved. Such
- // buffers will temporarily keep the max buffer count up until the slots
- // no longer need to be preserved.
- for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
- BufferSlot::BufferState state = mSlots[i].mBufferState;
- if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
- maxBufferCount = i + 1;
- }
- }
-
- return maxBufferCount;
-}
-
-bool GonkBufferQueue::stillTracking(const BufferItem *item) const {
- const BufferSlot &slot = mSlots[item->mBuf];
-
- ALOGV("stillTracking?: item: { slot=%d/%llu, buffer=%p }, "
- "slot: { slot=%d/%llu, buffer=%p }",
- item->mBuf, item->mFrameNumber,
- (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0),
- item->mBuf, slot.mFrameNumber,
- (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0));
-
- // Compare item with its original buffer slot. We can check the slot
- // as the buffer would not be moved to a different slot by the producer.
- return (slot.mGraphicBuffer != NULL &&
- item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle);
-}
-
-GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener(
- const wp<ConsumerListener>& consumerListener):
- mConsumerListener(consumerListener) {}
-
-GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
-
-void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameAvailable();
- }
-}
-
-void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-}
-
-}; // namespace android
diff --git a/widget/gonk/nativewindow/GonkBufferQueueKK.h b/widget/gonk/nativewindow/GonkBufferQueueKK.h
deleted file mode 100644
index 01905427d..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueKK.h
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKBUFFERQUEUE_KK_H
-#define NATIVEWINDOW_GONKBUFFERQUEUE_KK_H
-
-#include <gui/IConsumerListener.h>
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/IGraphicBufferProducer.h>
-#include "IGonkGraphicBufferConsumer.h"
-
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#include "mozilla/layers/LayersSurfaces.h"
-#include "mozilla/layers/TextureClient.h"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class GonkBufferQueue : public BnGraphicBufferProducer,
- public BnGonkGraphicBufferConsumer,
- private IBinder::DeathRecipient
-{
- typedef mozilla::layers::TextureClient TextureClient;
-
-public:
- enum { MIN_UNDEQUEUED_BUFFERS = 2 };
- enum { NUM_BUFFER_SLOTS = 32 };
- enum { NO_CONNECTED_API = 0 };
- enum { INVALID_BUFFER_SLOT = -1 };
- enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE, PRESENT_LATER };
-
- // When in async mode we reserve two slots in order to guarantee that the
- // producer and consumer can run asynchronously.
- enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 };
-
- // for backward source compatibility
- typedef ::android::ConsumerListener ConsumerListener;
-
- // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
- // reference to the actual consumer object. It forwards all calls to that
- // consumer object so long as it exists.
- //
- // This class exists to avoid having a circular reference between the
- // GonkBufferQueue object and the consumer object. The reason this can't be a weak
- // reference in the GonkBufferQueue class is because we're planning to expose the
- // consumer side of a GonkBufferQueue as a binder interface, which doesn't support
- // weak references.
- class ProxyConsumerListener : public BnConsumerListener {
- public:
- ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
- virtual ~ProxyConsumerListener();
- virtual void onFrameAvailable();
- virtual void onBuffersReleased();
- private:
- // mConsumerListener is a weak reference to the IConsumerListener. This is
- // the raison d'etre of ProxyConsumerListener.
- wp<ConsumerListener> mConsumerListener;
- };
-
-
- // BufferQueue manages a pool of gralloc memory slots to be used by
- // producers and consumers. allocator is used to allocate all the
- // needed gralloc buffers.
- GonkBufferQueue(bool allowSynchronousMode = true,
- const sp<IGraphicBufferAlloc>& allocator = NULL);
- virtual ~GonkBufferQueue();
-
- /*
- * IBinder::DeathRecipient interface
- */
-
- virtual void binderDied(const wp<IBinder>& who);
-
- /*
- * IGraphicBufferProducer interface
- */
-
- // Query native window attributes. The "what" values are enumerated in
- // window.h (e.g. NATIVE_WINDOW_FORMAT).
- virtual int query(int what, int* value);
-
- // setBufferCount updates the number of available buffer slots. If this
- // method succeeds, buffer slots will be both unallocated and owned by
- // the GonkBufferQueue object (i.e. they are not owned by the producer or
- // consumer).
- //
- // This will fail if the producer has dequeued any buffers, or if
- // bufferCount is invalid. bufferCount must generally be a value
- // between the minimum undequeued buffer count and NUM_BUFFER_SLOTS
- // (inclusive). It may also be set to zero (the default) to indicate
- // that the producer does not wish to set a value. The minimum value
- // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
- // ...).
- //
- // This may only be called by the producer. The consumer will be told
- // to discard buffers through the onBuffersReleased callback.
- virtual status_t setBufferCount(int bufferCount);
-
- // requestBuffer returns the GraphicBuffer for slot N.
- //
- // In normal operation, this is called the first time slot N is returned
- // by dequeueBuffer. It must be called again if dequeueBuffer returns
- // flags indicating that previously-returned buffers are no longer valid.
- virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
-
- // dequeueBuffer gets the next buffer slot index for the producer to use.
- // If a buffer slot is available then that slot index is written to the
- // location pointed to by the buf argument and a status of OK is returned.
- // If no slot is available then a status of -EBUSY is returned and buf is
- // unmodified.
- //
- // The fence parameter will be updated to hold the fence associated with
- // the buffer. The contents of the buffer must not be overwritten until the
- // fence signals. If the fence is Fence::NO_FENCE, the buffer may be
- // written immediately.
- //
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called. If width and height are both zero, the
- // default values specified by setDefaultBufferSize() are used instead.
- //
- // The pixel formats are enumerated in graphics.h, e.g.
- // HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format
- // will be used.
- //
- // The usage argument specifies gralloc buffer usage flags. The values
- // are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER. These
- // will be merged with the usage flags specified by setConsumerUsageBits.
- //
- // The return value may be a negative error value or a non-negative
- // collection of flags. If the flags are set, the return values are
- // valid, but additional actions must be performed.
- //
- // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the
- // producer must discard cached GraphicBuffer references for the slot
- // returned in buf.
- // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer
- // must discard cached GraphicBuffer references for all slots.
- //
- // In both cases, the producer will need to call requestBuffer to get a
- // GraphicBuffer handle for the returned slot.
- virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
- uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
-
- // queueBuffer returns a filled buffer to the GonkBufferQueue.
- //
- // Additional data is provided in the QueueBufferInput struct. Notably,
- // a timestamp must be provided for the buffer. The timestamp is in
- // nanoseconds, and must be monotonically increasing. Its other semantics
- // (zero point, etc) are producer-specific and should be documented by the
- // producer.
- //
- // The caller may provide a fence that signals when all rendering
- // operations have completed. Alternatively, NO_FENCE may be used,
- // indicating that the buffer is ready immediately.
- //
- // Some values are returned in the output struct: the current settings
- // for default width and height, the current transform hint, and the
- // number of queued buffers.
- virtual status_t queueBuffer(int buf,
- const QueueBufferInput& input, QueueBufferOutput* output);
-
- // cancelBuffer returns a dequeued buffer to the GonkBufferQueue, but doesn't
- // queue it for use by the consumer.
- //
- // The buffer will not be overwritten until the fence signals. The fence
- // will usually be the one obtained from dequeueBuffer.
- virtual void cancelBuffer(int buf, const sp<Fence>& fence);
-
- // setSynchronousMode sets whether dequeueBuffer is synchronous or
- // asynchronous. In synchronous mode, dequeueBuffer blocks until
- // a buffer is available, the currently bound buffer can be dequeued and
- // queued buffers will be acquired in order. In asynchronous mode,
- // a queued buffer may be replaced by a subsequently queued buffer.
- //
- // The default mode is synchronous.
- // This should be called only during initialization.
- virtual status_t setSynchronousMode(bool enabled);
-
- // connect attempts to connect a producer API to the GonkBufferQueue. This
- // must be called before any other IGraphicBufferProducer methods are
- // called except for getAllocator. A consumer must already be connected.
- //
- // This method will fail if connect was previously called on the
- // GonkBufferQueue and no corresponding disconnect call was made (i.e. if
- // it's still connected to a producer).
- //
- // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU).
- virtual status_t connect(const sp<IBinder>& token,
- int api, bool producerControlledByApp, QueueBufferOutput* output);
-
- // disconnect attempts to disconnect a producer API from the GonkBufferQueue.
- // Calling this method will cause any subsequent calls to other
- // IGraphicBufferProducer methods to fail except for getAllocator and connect.
- // Successfully calling connect after this will allow the other methods to
- // succeed again.
- //
- // This method will fail if the the GonkBufferQueue is not currently
- // connected to the specified producer API.
- virtual status_t disconnect(int api);
-
- /*
- * IGraphicBufferConsumer interface
- */
-
- // acquireBuffer attempts to acquire ownership of the next pending buffer in
- // the GonkBufferQueue. If no buffer is pending then it returns -EINVAL. If a
- // buffer is successfully acquired, the information about the buffer is
- // returned in BufferItem. If the buffer returned had previously been
- // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
- // NULL and it is assumed that the consumer still holds a reference to the
- // buffer.
- //
- // If presentWhen is nonzero, it indicates the time when the buffer will
- // be displayed on screen. If the buffer's timestamp is farther in the
- // future, the buffer won't be acquired, and PRESENT_LATER will be
- // returned. The presentation time is in nanoseconds, and the time base
- // is CLOCK_MONOTONIC.
- virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen);
-
- // releaseBuffer releases a buffer slot from the consumer back to the
- // GonkBufferQueue. This may be done while the buffer's contents are still
- // being accessed. The fence will signal when the buffer is no longer
- // in use. frameNumber is used to indentify the exact buffer returned.
- //
- // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
- // any references to the just-released buffer that it might have, as if it
- // had received a onBuffersReleased() call with a mask set for the released
- // buffer.
- //
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
- virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
- const sp<Fence>& releaseFence);
-
- // consumerConnect connects a consumer to the GonkBufferQueue. Only one
- // consumer may be connected, and when that consumer disconnects the
- // GonkBufferQueue is placed into the "abandoned" state, causing most
- // interactions with the GonkBufferQueue by the producer to fail.
- // controlledByApp indicates whether the consumer is controlled by
- // the application.
- //
- // consumer may not be NULL.
- virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp);
-
- // consumerDisconnect disconnects a consumer from the GonkBufferQueue. All
- // buffers will be freed and the GonkBufferQueue is placed in the "abandoned"
- // state, causing most interactions with the GonkBufferQueue by the producer to
- // fail.
- virtual status_t consumerDisconnect();
-
- // getReleasedBuffers sets the value pointed to by slotMask to a bit mask
- // indicating which buffer slots have been released by the GonkBufferQueue
- // but have not yet been released by the consumer.
- //
- // This should be called from the onBuffersReleased() callback.
- virtual status_t getReleasedBuffers(uint32_t* slotMask);
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // dequeueBuffer when a width and height of zero is requested. Default
- // is 1x1.
- virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h);
-
- // setDefaultMaxBufferCount sets the default value for the maximum buffer
- // count (the initial default is 2). If the producer has requested a
- // buffer count using setBufferCount, the default buffer count will only
- // take effect if the producer sets the count back to zero.
- //
- // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
- virtual status_t setDefaultMaxBufferCount(int bufferCount);
-
- // disableAsyncBuffer disables the extra buffer used in async mode
- // (when both producer and consumer have set their "isControlledByApp"
- // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
- //
- // This can only be called before consumerConnect().
- virtual status_t disableAsyncBuffer();
-
- // setMaxAcquiredBufferCount sets the maximum number of buffers that can
- // be acquired by the consumer at one time (default 1). This call will
- // fail if a producer is connected to the GonkBufferQueue.
- virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
-
- // setConsumerName sets the name used in logging
- virtual void setConsumerName(const String8& name);
-
- // setDefaultBufferFormat allows the GonkBufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer. Formats are enumerated in graphics.h; the
- // initial default is HAL_PIXEL_FORMAT_RGBA_8888.
- virtual status_t setDefaultBufferFormat(uint32_t defaultFormat);
-
- // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
- // These are merged with the bits passed to dequeueBuffer. The values are
- // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
- virtual status_t setConsumerUsageBits(uint32_t usage);
-
- // setTransformHint bakes in rotation to buffers so overlays can be used.
- // The values are enumerated in window.h, e.g.
- // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform).
- virtual status_t setTransformHint(uint32_t hint);
-
- // dump our state in a String
- virtual void dumpToString(String8& result, const char* prefix) const;
-
- already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer);
-
- int getSlotFromTextureClientLocked(TextureClient* client) const;
-
-private:
- // freeBufferLocked frees the GraphicBuffer and sync resources for the
- // given slot.
- //void freeBufferLocked(int index);
-
- // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
- // all slots.
- void freeAllBuffersLocked();
-
- // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
- // that will be used if the producer does not override the buffer slot
- // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
- // The initial default is 2.
- status_t setDefaultMaxBufferCountLocked(int count);
-
- // getMinUndequeuedBufferCount returns the minimum number of buffers
- // that must remain in a state other than DEQUEUED.
- // The async parameter tells whether we're in asynchronous mode.
- int getMinUndequeuedBufferCount(bool async) const;
-
- // getMinBufferCountLocked returns the minimum number of buffers allowed
- // given the current GonkBufferQueue state.
- // The async parameter tells whether we're in asynchronous mode.
- int getMinMaxBufferCountLocked(bool async) const;
-
- // getMaxBufferCountLocked returns the maximum number of buffers that can
- // be allocated at once. This value depends upon the following member
- // variables:
- //
- // mDequeueBufferCannotBlock
- // mMaxAcquiredBufferCount
- // mDefaultMaxBufferCount
- // mOverrideMaxBufferCount
- // async parameter
- //
- // Any time one of these member variables is changed while a producer is
- // connected, mDequeueCondition must be broadcast.
- int getMaxBufferCountLocked(bool async) const;
-
- // stillTracking returns true iff the buffer item is still being tracked
- // in one of the slots.
- bool stillTracking(const BufferItem *item) const;
-
- struct BufferSlot {
-
- BufferSlot()
- : mBufferState(BufferSlot::FREE),
- mRequestBufferCalled(false),
- mFrameNumber(0),
- mAcquireCalled(false),
- mNeedsCleanupOnRelease(false) {
- }
-
- // mGraphicBuffer points to the buffer allocated for this slot or is NULL
- // if no buffer has been allocated.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mTextureClient is a thin abstraction over remotely allocated GraphicBuffer.
- RefPtr<TextureClient> mTextureClient;
-
- // BufferState represents the different states in which a buffer slot
- // can be. All slots are initially FREE.
- enum BufferState {
- // FREE indicates that the buffer is available to be dequeued
- // by the producer. The buffer may be in use by the consumer for
- // a finite time, so the buffer must not be modified until the
- // associated fence is signaled.
- //
- // The slot is "owned" by GonkBufferQueue. It transitions to DEQUEUED
- // when dequeueBuffer is called.
- FREE = 0,
-
- // DEQUEUED indicates that the buffer has been dequeued by the
- // producer, but has not yet been queued or canceled. The
- // producer may modify the buffer's contents as soon as the
- // associated ready fence is signaled.
- //
- // The slot is "owned" by the producer. It can transition to
- // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
- DEQUEUED = 1,
-
- // QUEUED indicates that the buffer has been filled by the
- // producer and queued for use by the consumer. The buffer
- // contents may continue to be modified for a finite time, so
- // the contents must not be accessed until the associated fence
- // is signaled.
- //
- // The slot is "owned" by GonkBufferQueue. It can transition to
- // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
- // queued in asynchronous mode).
- QUEUED = 2,
-
- // ACQUIRED indicates that the buffer has been acquired by the
- // consumer. As with QUEUED, the contents must not be accessed
- // by the consumer until the fence is signaled.
- //
- // The slot is "owned" by the consumer. It transitions to FREE
- // when releaseBuffer is called.
- ACQUIRED = 3
- };
-
- // mBufferState is the current state of this buffer slot.
- BufferState mBufferState;
-
- // mRequestBufferCalled is used for validating that the producer did
- // call requestBuffer() when told to do so. Technically this is not
- // needed but useful for debugging and catching producer bugs.
- bool mRequestBufferCalled;
-
- // mFrameNumber is the number of the queued frame for this slot. This
- // is used to dequeue buffers in LRU order (useful because buffers
- // may be released before their release fence is signaled).
- uint64_t mFrameNumber;
-
- // mFence is a fence which will signal when work initiated by the
- // previous owner of the buffer is finished. When the buffer is FREE,
- // the fence indicates when the consumer has finished reading
- // from the buffer, or when the producer has finished writing if it
- // called cancelBuffer after queueing some writes. When the buffer is
- // QUEUED, it indicates when the producer has finished filling the
- // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
- // passed to the consumer or producer along with ownership of the
- // buffer, and mFence is set to NO_FENCE.
- sp<Fence> mFence;
-
- // Indicates whether this buffer has been seen by a consumer yet
- bool mAcquireCalled;
-
- // Indicates whether this buffer needs to be cleaned up by the
- // consumer. This is set when a buffer in ACQUIRED state is freed.
- // It causes releaseBuffer to return STALE_BUFFER_SLOT.
- bool mNeedsCleanupOnRelease;
- };
-
- // mSlots is the array of buffer slots that must be mirrored on the
- // producer side. This allows buffer ownership to be transferred between
- // the producer and consumer without sending a GraphicBuffer over binder.
- // The entire array is initialized to NULL at construction time, and
- // buffers are allocated for a slot when requestBuffer is called with
- // that slot's index.
- BufferSlot mSlots[NUM_BUFFER_SLOTS];
-
- // mDefaultWidth holds the default width of allocated buffers. It is used
- // in dequeueBuffer() if a width and height of zero is specified.
- uint32_t mDefaultWidth;
-
- // mDefaultHeight holds the default height of allocated buffers. It is used
- // in dequeueBuffer() if a width and height of zero is specified.
- uint32_t mDefaultHeight;
-
- // mMaxAcquiredBufferCount is the number of buffers that the consumer may
- // acquire at one time. It defaults to 1 and can be changed by the
- // consumer via the setMaxAcquiredBufferCount method, but this may only be
- // done when no producer is connected to the GonkBufferQueue.
- //
- // This value is used to derive the value returned for the
- // MIN_UNDEQUEUED_BUFFERS query by the producer.
- int mMaxAcquiredBufferCount;
-
- // mDefaultMaxBufferCount is the default limit on the number of buffers
- // that will be allocated at one time. This default limit is set by the
- // consumer. The limit (as opposed to the default limit) may be
- // overridden by the producer.
- int mDefaultMaxBufferCount;
-
- // mOverrideMaxBufferCount is the limit on the number of buffers that will
- // be allocated at one time. This value is set by the image producer by
- // calling setBufferCount. The default is zero, which means the producer
- // doesn't care about the number of buffers in the pool. In that case
- // mDefaultMaxBufferCount is used as the limit.
- int mOverrideMaxBufferCount;
-
- // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
- // allocate new GraphicBuffer objects.
- sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
-
- // mConsumerListener is used to notify the connected consumer of
- // asynchronous events that it may wish to react to. It is initially set
- // to NULL and is written by consumerConnect and consumerDisconnect.
- sp<IConsumerListener> mConsumerListener;
-
- // mSynchronousMode whether we're in synchronous mode or not
- bool mSynchronousMode;
-
- // mConsumerControlledByApp whether the connected consumer is controlled by the
- // application.
- bool mConsumerControlledByApp;
-
- // mDequeueBufferCannotBlock whether dequeueBuffer() isn't allowed to block.
- // this flag is set during connect() when both consumer and producer are controlled
- // by the application.
- bool mDequeueBufferCannotBlock;
-
- // mUseAsyncBuffer whether an extra buffer is used in async mode to prevent
- // dequeueBuffer() from ever blocking.
- bool mUseAsyncBuffer;
-
- // mConnectedApi indicates the producer API that is currently connected
- // to this GonkBufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets
- // updated by the connect and disconnect methods.
- int mConnectedApi;
-
- // mDequeueCondition condition used for dequeueBuffer in synchronous mode
- mutable Condition mDequeueCondition;
-
- // mQueue is a FIFO of queued buffers used in synchronous mode
- typedef Vector<BufferItem> Fifo;
- Fifo mQueue;
-
- // mAbandoned indicates that the GonkBufferQueue will no longer be used to
- // consume image buffers pushed to it using the IGraphicBufferProducer
- // interface. It is initialized to false, and set to true in the
- // consumerDisconnect method. A GonkBufferQueue that has been abandoned will
- // return the NO_INIT error from all IGraphicBufferProducer methods
- // capable of returning an error.
- bool mAbandoned;
-
- // mConsumerName is a string used to identify the GonkBufferQueue in log
- // messages. It is set by the setConsumerName method.
- String8 mConsumerName;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of GonkBufferQueue objects. It must be locked whenever the
- // member variables are accessed.
- mutable Mutex mMutex;
-
- // mFrameCounter is the free running counter, incremented on every
- // successful queueBuffer call, and buffer allocation.
- uint64_t mFrameCounter;
-
- // mBufferHasBeenQueued is true once a buffer has been queued. It is
- // reset when something causes all buffers to be freed (e.g. changing the
- // buffer count).
- bool mBufferHasBeenQueued;
-
- // mDefaultBufferFormat can be set so it will override
- // the buffer format when it isn't specified in dequeueBuffer
- uint32_t mDefaultBufferFormat;
-
- // mConsumerUsageBits contains flags the consumer wants for GraphicBuffers
- uint32_t mConsumerUsageBits;
-
- // mTransformHint is used to optimize for screen rotations
- uint32_t mTransformHint;
-
- // mConnectedProducerToken is used to set a binder death notification on the producer
- sp<IBinder> mConnectedProducerToken;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_BUFFERQUEUE_H
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp
deleted file mode 100644
index 7df72bf68..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "GonkBufferItem.h"
-
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-
-#include <system/window.h>
-
-namespace android {
-
-GonkBufferItem::GonkBufferItem() :
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mIsAutoTimestamp(false),
- mFrameNumber(0),
- mSlot(INVALID_BUFFER_SLOT),
- mIsDroppable(false),
- mAcquireCalled(false),
- mTransformToDisplayInverse(false) {
- mCrop.makeInvalid();
-}
-
-GonkBufferItem::operator IGonkGraphicBufferConsumer::BufferItem() const {
- IGonkGraphicBufferConsumer::BufferItem bufferItem;
- bufferItem.mGraphicBuffer = mGraphicBuffer;
- bufferItem.mFence = mFence;
- bufferItem.mCrop = mCrop;
- bufferItem.mTransform = mTransform;
- bufferItem.mScalingMode = mScalingMode;
- bufferItem.mTimestamp = mTimestamp;
- bufferItem.mIsAutoTimestamp = mIsAutoTimestamp;
- bufferItem.mFrameNumber = mFrameNumber;
- bufferItem.mBuf = mSlot;
- bufferItem.mIsDroppable = mIsDroppable;
- bufferItem.mAcquireCalled = mAcquireCalled;
- bufferItem.mTransformToDisplayInverse = mTransformToDisplayInverse;
- return bufferItem;
-}
-
-size_t GonkBufferItem::getPodSize() const {
- size_t c = sizeof(mCrop) +
- sizeof(mTransform) +
- sizeof(mScalingMode) +
- sizeof(mTimestamp) +
- sizeof(mIsAutoTimestamp) +
- sizeof(mFrameNumber) +
- sizeof(mSlot) +
- sizeof(mIsDroppable) +
- sizeof(mAcquireCalled) +
- sizeof(mTransformToDisplayInverse);
- return c;
-}
-
-size_t GonkBufferItem::getFlattenedSize() const {
- size_t c = 0;
- if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFlattenedSize();
- FlattenableUtils::align<4>(c);
- }
- if (mFence != 0) {
- c += mFence->getFlattenedSize();
- FlattenableUtils::align<4>(c);
- }
- return sizeof(int32_t) + c + getPodSize();
-}
-
-size_t GonkBufferItem::getFdCount() const {
- size_t c = 0;
- if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFdCount();
- }
- if (mFence != 0) {
- c += mFence->getFdCount();
- }
- return c;
-}
-
-status_t GonkBufferItem::flatten(
- void*& buffer, size_t& size, int*& fds, size_t& count) const {
-
- // make sure we have enough space
- if (count < GonkBufferItem::getFlattenedSize()) {
- return NO_MEMORY;
- }
-
- // content flags are stored first
- uint32_t& flags = *static_cast<uint32_t*>(buffer);
-
- // advance the pointer
- FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
-
- flags = 0;
- if (mGraphicBuffer != 0) {
- status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- flags |= 1;
- }
- if (mFence != 0) {
- status_t err = mFence->flatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- flags |= 2;
- }
-
- // check we have enough space (in case flattening the fence/graphicbuffer lied to us)
- if (size < getPodSize()) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, mCrop);
- FlattenableUtils::write(buffer, size, mTransform);
- FlattenableUtils::write(buffer, size, mScalingMode);
- FlattenableUtils::write(buffer, size, mTimestamp);
- FlattenableUtils::write(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::write(buffer, size, mFrameNumber);
- FlattenableUtils::write(buffer, size, mSlot);
- FlattenableUtils::write(buffer, size, mIsDroppable);
- FlattenableUtils::write(buffer, size, mAcquireCalled);
- FlattenableUtils::write(buffer, size, mTransformToDisplayInverse);
-
- return NO_ERROR;
-}
-
-status_t GonkBufferItem::unflatten(
- void const*& buffer, size_t& size, int const*& fds, size_t& count) {
-
- if (size < sizeof(uint32_t))
- return NO_MEMORY;
-
- uint32_t flags = 0;
- FlattenableUtils::read(buffer, size, flags);
-
- if (flags & 1) {
- mGraphicBuffer = new GraphicBuffer();
- status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- }
-
- if (flags & 2) {
- mFence = new Fence();
- status_t err = mFence->unflatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- }
-
- // check we have enough space
- if (size < getPodSize()) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::read(buffer, size, mCrop);
- FlattenableUtils::read(buffer, size, mTransform);
- FlattenableUtils::read(buffer, size, mScalingMode);
- FlattenableUtils::read(buffer, size, mTimestamp);
- FlattenableUtils::read(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::read(buffer, size, mFrameNumber);
- FlattenableUtils::read(buffer, size, mSlot);
- FlattenableUtils::read(buffer, size, mIsDroppable);
- FlattenableUtils::read(buffer, size, mAcquireCalled);
- FlattenableUtils::read(buffer, size, mTransformToDisplayInverse);
-
- return NO_ERROR;
-}
-
-const char* GonkBufferItem::scalingModeName(uint32_t scalingMode) {
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
- default: return "Unknown";
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h
deleted file mode 100644
index b2d6d3068..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKBUFFERITEM_LL_H
-#define NATIVEWINDOW_GONKBUFFERITEM_LL_H
-
-#include "IGonkGraphicBufferConsumerLL.h"
-
-#include <ui/Rect.h>
-
-#include <utils/Flattenable.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-class Fence;
-class GraphicBuffer;
-
-class GonkBufferItem : public Flattenable<GonkBufferItem> {
- friend class Flattenable<GonkBufferItem>;
- size_t getPodSize() const;
- size_t getFlattenedSize() const;
- size_t getFdCount() const;
- status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
- status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
-
- public:
- // The default value of mBuf, used to indicate this doesn't correspond to a slot.
- enum { INVALID_BUFFER_SLOT = -1 };
- GonkBufferItem();
- operator IGonkGraphicBufferConsumer::BufferItem() const;
-
- static const char* scalingModeName(uint32_t scalingMode);
-
- // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
- // if the buffer in this slot has been acquired in the past (see
- // BufferSlot.mAcquireCalled).
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mFence is a fence that will signal when the buffer is idle.
- sp<Fence> mFence;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- // refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- // refer to NATIVE_WINDOW_SCALING_* in <window.h>
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued. This value
- // is guaranteed to be monotonically increasing for each newly
- // acquired buffer.
- int64_t mTimestamp;
-
- // mIsAutoTimestamp indicates whether mTimestamp was generated
- // automatically when the buffer was queued.
- bool mIsAutoTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
- int mSlot;
-
- // mIsDroppable whether this buffer was queued with the
- // property that it can be replaced by a new buffer for the purpose of
- // making sure dequeueBuffer() won't block.
- // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
- // was queued.
- bool mIsDroppable;
-
- // Indicates whether this buffer has been seen by a consumer yet
- bool mAcquireCalled;
-
- // Indicates this buffer must be transformed by the inverse transform of the screen
- // it is displayed onto. This is applied after mTransform.
- bool mTransformToDisplayInverse;
-};
-
-} // namespace android
-
-#endif
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp
deleted file mode 100644
index 1d7eb2702..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <inttypes.h>
-
-#define LOG_TAG "GonkBufferQueueConsumer"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#include "GonkBufferItem.h"
-#include "GonkBufferQueueConsumer.h"
-#include "GonkBufferQueueCore.h"
-#include <gui/IConsumerListener.h>
-#include <gui/IProducerListener.h>
-
-namespace android {
-
-GonkBufferQueueConsumer::GonkBufferQueueConsumer(const sp<GonkBufferQueueCore>& core) :
- mCore(core),
- mSlots(core->mSlots),
- mConsumerName() {}
-
-GonkBufferQueueConsumer::~GonkBufferQueueConsumer() {}
-
-status_t GonkBufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
- nsecs_t expectedPresent) {
- ATRACE_CALL();
- Mutex::Autolock lock(mCore->mMutex);
-
- // Check that the consumer doesn't currently have the maximum number of
- // buffers acquired. We allow the max buffer count to be exceeded by one
- // buffer so that the consumer can successfully set up the newly acquired
- // buffer before releasing the old one.
- int numAcquiredBuffers = 0;
- for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- if (mSlots[s].mBufferState == GonkBufferSlot::ACQUIRED) {
- ++numAcquiredBuffers;
- }
- }
- if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
- ALOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
- numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
- return INVALID_OPERATION;
- }
-
- // Check if the queue is empty.
- // In asynchronous mode the list is guaranteed to be one buffer deep,
- // while in synchronous mode we use the oldest buffer.
- if (mCore->mQueue.empty()) {
- return NO_BUFFER_AVAILABLE;
- }
-
- GonkBufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
-
- // If expectedPresent is specified, we may not want to return a buffer yet.
- // If it's specified and there's more than one buffer queued, we may want
- // to drop a buffer.
- if (expectedPresent != 0) {
- const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
-
- // The 'expectedPresent' argument indicates when the buffer is expected
- // to be presented on-screen. If the buffer's desired present time is
- // earlier (less) than expectedPresent -- meaning it will be displayed
- // on time or possibly late if we show it as soon as possible -- we
- // acquire and return it. If we don't want to display it until after the
- // expectedPresent time, we return PRESENT_LATER without acquiring it.
- //
- // To be safe, we don't defer acquisition if expectedPresent is more
- // than one second in the future beyond the desired present time
- // (i.e., we'd be holding the buffer for a long time).
- //
- // NOTE: Code assumes monotonic time values from the system clock
- // are positive.
-
- // Start by checking to see if we can drop frames. We skip this check if
- // the timestamps are being auto-generated by Surface. If the app isn't
- // generating timestamps explicitly, it probably doesn't want frames to
- // be discarded based on them.
- while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
- // If entry[1] is timely, drop entry[0] (and repeat). We apply an
- // additional criterion here: we only drop the earlier buffer if our
- // desiredPresent falls within +/- 1 second of the expected present.
- // Otherwise, bogus desiredPresent times (e.g., 0 or a small
- // relative timestamp), which normally mean "ignore the timestamp
- // and acquire immediately", would cause us to drop frames.
- //
- // We may want to add an additional criterion: don't drop the
- // earlier buffer if entry[1]'s fence hasn't signaled yet.
- const BufferItem& bufferItem(mCore->mQueue[1]);
- nsecs_t desiredPresent = bufferItem.mTimestamp;
- if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
- desiredPresent > expectedPresent) {
- // This buffer is set to display in the near future, or
- // desiredPresent is garbage. Either way we don't want to drop
- // the previous buffer just to get this on the screen sooner.
- ALOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
- PRId64 " (%" PRId64 ") now=%" PRId64,
- desiredPresent, expectedPresent,
- desiredPresent - expectedPresent,
- systemTime(CLOCK_MONOTONIC));
- break;
- }
-
- ALOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
- " size=%zu",
- desiredPresent, expectedPresent, mCore->mQueue.size());
- if (mCore->stillTracking(front)) {
- // Front buffer is still in mSlots, so mark the slot as free
- mSlots[front->mSlot].mBufferState = GonkBufferSlot::FREE;
- }
- mCore->mQueue.erase(front);
- front = mCore->mQueue.begin();
- }
-
- // See if the front buffer is due
- nsecs_t desiredPresent = front->mTimestamp;
- if (desiredPresent > expectedPresent &&
- desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
- ALOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
- " (%" PRId64 ") now=%" PRId64,
- desiredPresent, expectedPresent,
- desiredPresent - expectedPresent,
- systemTime(CLOCK_MONOTONIC));
- return PRESENT_LATER;
- }
-
- ALOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
- "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
- desiredPresent - expectedPresent,
- systemTime(CLOCK_MONOTONIC));
- }
-
- int slot = front->mSlot;
- //*outBuffer = *front;
- outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
- outBuffer->mFrameNumber = mSlots[slot].mFrameNumber;
- outBuffer->mBuf = slot;
- outBuffer->mFence = mSlots[slot].mFence;
-
- ATRACE_BUFFER_INDEX(slot);
-
- ALOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
- slot, front->mFrameNumber, front->mGraphicBuffer->handle);
- // If the front buffer is still being tracked, update its slot state
- if (mCore->stillTracking(front)) {
- mSlots[slot].mAcquireCalled = true;
- mSlots[slot].mNeedsCleanupOnRelease = false;
- mSlots[slot].mBufferState = GonkBufferSlot::ACQUIRED;
- mSlots[slot].mFence = Fence::NO_FENCE;
- }
-
- // If the buffer has previously been acquired by the consumer, set
- // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
- // on the consumer side
- //if (outBuffer->mAcquireCalled) {
- // outBuffer->mGraphicBuffer = NULL;
- //}
-
- mCore->mQueue.erase(front);
-
- // We might have freed a slot while dropping old buffers, or the producer
- // may be blocked waiting for the number of buffers in the queue to
- // decrease.
- mCore->mDequeueCondition.broadcast();
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::detachBuffer(int slot) {
- ATRACE_CALL();
- ATRACE_BUFFER_INDEX(slot);
- ALOGV("detachBuffer(C): slot %d", slot);
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mIsAbandoned) {
- ALOGE("detachBuffer(C): GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
- ALOGE("detachBuffer(C): slot index %d out of range [0, %d)",
- slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- } else if (mSlots[slot].mBufferState != GonkBufferSlot::ACQUIRED) {
- ALOGE("detachBuffer(C): slot %d is not owned by the consumer "
- "(state = %d)", slot, mSlots[slot].mBufferState);
- return BAD_VALUE;
- }
-
- mCore->freeBufferLocked(slot);
- mCore->mDequeueCondition.broadcast();
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::attachBuffer(int* outSlot,
- const sp<android::GraphicBuffer>& buffer) {
- ATRACE_CALL();
-
- if (outSlot == NULL) {
- ALOGE("attachBuffer(P): outSlot must not be NULL");
- return BAD_VALUE;
- } else if (buffer == NULL) {
- ALOGE("attachBuffer(P): cannot attach NULL buffer");
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mCore->mMutex);
-
- // Make sure we don't have too many acquired buffers and find a free slot
- // to put the buffer into (the oldest if there are multiple).
- int numAcquiredBuffers = 0;
- int found = GonkBufferQueueCore::INVALID_BUFFER_SLOT;
- for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- if (mSlots[s].mBufferState == GonkBufferSlot::ACQUIRED) {
- ++numAcquiredBuffers;
- } else if (mSlots[s].mBufferState == GonkBufferSlot::FREE) {
- if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT ||
- mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
- found = s;
- }
- }
- }
-
- if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
- ALOGE("attachBuffer(P): max acquired buffer count reached: %d "
- "(max %d)", numAcquiredBuffers,
- mCore->mMaxAcquiredBufferCount);
- return INVALID_OPERATION;
- }
- if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) {
- ALOGE("attachBuffer(P): could not find free buffer slot");
- return NO_MEMORY;
- }
-
- *outSlot = found;
- ATRACE_BUFFER_INDEX(*outSlot);
- ALOGV("attachBuffer(C): returning slot %d", *outSlot);
-
- mSlots[*outSlot].mGraphicBuffer = buffer;
- mSlots[*outSlot].mBufferState = GonkBufferSlot::ACQUIRED;
- mSlots[*outSlot].mAttachedByConsumer = true;
- mSlots[*outSlot].mNeedsCleanupOnRelease = false;
- mSlots[*outSlot].mFence = Fence::NO_FENCE;
- mSlots[*outSlot].mFrameNumber = 0;
-
- // mAcquireCalled tells GonkBufferQueue that it doesn't need to send a valid
- // GraphicBuffer pointer on the next acquireBuffer call, which decreases
- // Binder traffic by not un/flattening the GraphicBuffer. However, it
- // requires that the consumer maintain a cached copy of the slot <--> buffer
- // mappings, which is why the consumer doesn't need the valid pointer on
- // acquire.
- //
- // The StreamSplitter is one of the primary users of the attach/detach
- // logic, and while it is running, all buffers it acquires are immediately
- // detached, and all buffers it eventually releases are ones that were
- // attached (as opposed to having been obtained from acquireBuffer), so it
- // doesn't make sense to maintain the slot/buffer mappings, which would
- // become invalid for every buffer during detach/attach. By setting this to
- // false, the valid GraphicBuffer pointer will always be sent with acquire
- // for attached buffers.
- mSlots[*outSlot].mAcquireCalled = false;
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
- const sp<Fence>& releaseFence) {
- ATRACE_CALL();
-
- if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS ||
- releaseFence == NULL) {
- return BAD_VALUE;
- }
-
- sp<IProducerListener> listener;
- { // Autolock scope
- Mutex::Autolock lock(mCore->mMutex);
-
- // If the frame number has changed because the buffer has been reallocated,
- // we can ignore this releaseBuffer for the old buffer
- //if (frameNumber != mSlots[slot].mFrameNumber) {
- // return STALE_BUFFER_SLOT;
- //}
-
- // Make sure this buffer hasn't been queued while acquired by the consumer
- GonkBufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
- while (current != mCore->mQueue.end()) {
- if (current->mSlot == slot) {
- ALOGE("releaseBuffer: buffer slot %d pending release is "
- "currently queued", slot);
- return BAD_VALUE;
- }
- ++current;
- }
-
- if (mSlots[slot].mBufferState == GonkBufferSlot::ACQUIRED) {
- mSlots[slot].mFence = releaseFence;
- mSlots[slot].mBufferState = GonkBufferSlot::FREE;
- listener = mCore->mConnectedProducerListener;
- ALOGV("releaseBuffer: releasing slot %d", slot);
- } else if (mSlots[slot].mNeedsCleanupOnRelease) {
- ALOGV("releaseBuffer: releasing a stale buffer slot %d "
- "(state = %d)", slot, mSlots[slot].mBufferState);
- mSlots[slot].mNeedsCleanupOnRelease = false;
- return STALE_BUFFER_SLOT;
- } else {
- ALOGV("releaseBuffer: attempted to release buffer slot %d "
- "but its state was %d", slot, mSlots[slot].mBufferState);
- return BAD_VALUE;
- }
-
- mCore->mDequeueCondition.broadcast();
- } // Autolock scope
-
- // Call back without lock held
- if (listener != NULL) {
- listener->onBufferReleased();
- }
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::connect(
- const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
- ATRACE_CALL();
-
- if (consumerListener == NULL) {
- ALOGE("connect(C): consumerListener may not be NULL");
- return BAD_VALUE;
- }
-
- ALOGV("connect(C): controlledByApp=%s",
- controlledByApp ? "true" : "false");
-
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mIsAbandoned) {
- ALOGE("connect(C): GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- mCore->mConsumerListener = consumerListener;
- mCore->mConsumerControlledByApp = controlledByApp;
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::disconnect() {
- ATRACE_CALL();
-
- ALOGV("disconnect(C)");
-
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mConsumerListener == NULL) {
- ALOGE("disconnect(C): no consumer is connected");
- return BAD_VALUE;
- }
-
- mCore->mIsAbandoned = true;
- mCore->mConsumerListener = NULL;
- mCore->mQueue.clear();
- mCore->freeAllBuffersLocked();
- mCore->mDequeueCondition.broadcast();
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
- ATRACE_CALL();
-
- if (outSlotMask == NULL) {
- ALOGE("getReleasedBuffers: outSlotMask may not be NULL");
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mIsAbandoned) {
- ALOGE("getReleasedBuffers: GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- uint64_t mask = 0;
- for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- if (!mSlots[s].mAcquireCalled) {
- mask |= (1ULL << s);
- }
- }
-
- // Remove from the mask queued buffers for which acquire has been called,
- // since the consumer will not receive their buffer addresses and so must
- // retain their cached information
- GonkBufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
- while (current != mCore->mQueue.end()) {
- if (current->mAcquireCalled) {
- mask &= ~(1ULL << current->mSlot);
- }
- ++current;
- }
-
- ALOGV("getReleasedBuffers: returning mask %#" PRIx64, mask);
- *outSlotMask = mask;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::setDefaultBufferSize(uint32_t width,
- uint32_t height) {
- ATRACE_CALL();
-
- if (width == 0 || height == 0) {
- ALOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u "
- "height=%u)", width, height);
- return BAD_VALUE;
- }
-
- ALOGV("setDefaultBufferSize: width=%u height=%u", width, height);
-
- Mutex::Autolock lock(mCore->mMutex);
- mCore->mDefaultWidth = width;
- mCore->mDefaultHeight = height;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) {
- ATRACE_CALL();
- Mutex::Autolock lock(mCore->mMutex);
- return mCore->setDefaultMaxBufferCountLocked(bufferCount);
-}
-
-status_t GonkBufferQueueConsumer::disableAsyncBuffer() {
- ATRACE_CALL();
-
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mConsumerListener != NULL) {
- ALOGE("disableAsyncBuffer: consumer already connected");
- return INVALID_OPERATION;
- }
-
- ALOGV("disableAsyncBuffer");
- mCore->mUseAsyncBuffer = false;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::setMaxAcquiredBufferCount(
- int maxAcquiredBuffers) {
- ATRACE_CALL();
-
- if (maxAcquiredBuffers < 1 ||
- maxAcquiredBuffers > GonkBufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) {
- ALOGE("setMaxAcquiredBufferCount: invalid count %d",
- maxAcquiredBuffers);
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mConnectedApi != GonkBufferQueueCore::NO_CONNECTED_API) {
- ALOGE("setMaxAcquiredBufferCount: producer is already connected");
- return INVALID_OPERATION;
- }
-
- ALOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
- mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
- return NO_ERROR;
-}
-
-void GonkBufferQueueConsumer::setConsumerName(const String8& name) {
- ATRACE_CALL();
- ALOGV("setConsumerName: '%s'", name.string());
- Mutex::Autolock lock(mCore->mMutex);
- mCore->mConsumerName = name;
- mConsumerName = name;
-}
-
-status_t GonkBufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
- ATRACE_CALL();
- ALOGV("setDefaultBufferFormat: %u", defaultFormat);
- Mutex::Autolock lock(mCore->mMutex);
- mCore->mDefaultBufferFormat = defaultFormat;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
- ATRACE_CALL();
- ALOGV("setConsumerUsageBits: %#x", usage);
- Mutex::Autolock lock(mCore->mMutex);
- mCore->mConsumerUsageBits = usage;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueConsumer::setTransformHint(uint32_t hint) {
- ATRACE_CALL();
- ALOGV("setTransformHint: %#x", hint);
- Mutex::Autolock lock(mCore->mMutex);
- mCore->mTransformHint = hint;
- return NO_ERROR;
-}
-
-sp<NativeHandle> GonkBufferQueueConsumer::getSidebandStream() const {
- return mCore->mSidebandStream;
-}
-
-void GonkBufferQueueConsumer::dumpToString(String8& result, const char* prefix) const {
- mCore->dump(result, prefix);
-}
-
-already_AddRefed<GonkBufferSlot::TextureClient>
-GonkBufferQueueConsumer::getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
-{
- Mutex::Autolock _l(mCore->mMutex);
- if (buffer == NULL) {
- ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
- return nullptr;
- }
-
- for (int i = 0; i < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
- RefPtr<TextureClient> client(mSlots[i].mTextureClient);
- return client.forget();
- }
- }
- ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
- return nullptr;
-}
-
-int
-GonkBufferQueueConsumer::getSlotFromTextureClientLocked(GonkBufferSlot::TextureClient* client) const
-{
- if (client == NULL) {
- ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
- return BAD_VALUE;
- }
-
- for (int i = 0; i < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].mTextureClient == client) {
- return i;
- }
- }
- ALOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client);
- return BAD_VALUE;
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h
deleted file mode 100644
index a97cfab42..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKBUFFERQUEUECONSUMER_LL_H
-#define NATIVEWINDOW_GONKBUFFERQUEUECONSUMER_LL_H
-
-#include "GonkBufferQueueDefs.h"
-#include "IGonkGraphicBufferConsumerLL.h"
-
-namespace android {
-
-class GonkBufferQueueCore;
-
-class GonkBufferQueueConsumer : public BnGonkGraphicBufferConsumer {
-
-public:
- GonkBufferQueueConsumer(const sp<GonkBufferQueueCore>& core);
- virtual ~GonkBufferQueueConsumer();
-
- // acquireBuffer attempts to acquire ownership of the next pending buffer in
- // the GonkBufferQueue. If no buffer is pending then it returns
- // NO_BUFFER_AVAILABLE. If a buffer is successfully acquired, the
- // information about the buffer is returned in BufferItem. If the buffer
- // returned had previously been acquired then the BufferItem::mGraphicBuffer
- // field of buffer is set to NULL and it is assumed that the consumer still
- // holds a reference to the buffer.
- //
- // If expectedPresent is nonzero, it indicates the time when the buffer
- // will be displayed on screen. If the buffer's timestamp is farther in the
- // future, the buffer won't be acquired, and PRESENT_LATER will be
- // returned. The presentation time is in nanoseconds, and the time base
- // is CLOCK_MONOTONIC.
- virtual status_t acquireBuffer(BufferItem* outBuffer,
- nsecs_t expectedPresent);
-
- // See IGonkGraphicBufferConsumer::detachBuffer
- virtual status_t detachBuffer(int slot);
-
- // See IGonkGraphicBufferConsumer::attachBuffer
- virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer);
-
- // releaseBuffer releases a buffer slot from the consumer back to the
- // GonkBufferQueue. This may be done while the buffer's contents are still
- // being accessed. The fence will signal when the buffer is no longer
- // in use. frameNumber is used to indentify the exact buffer returned.
- //
- // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
- // any references to the just-released buffer that it might have, as if it
- // had received a onBuffersReleased() call with a mask set for the released
- // buffer.
- virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
- const sp<Fence>& releaseFence);
-
- // connect connects a consumer to the GonkBufferQueue. Only one
- // consumer may be connected, and when that consumer disconnects the
- // GonkBufferQueue is placed into the "abandoned" state, causing most
- // interactions with the GonkBufferQueue by the producer to fail.
- // controlledByApp indicates whether the consumer is controlled by
- // the application.
- //
- // consumerListener may not be NULL.
- virtual status_t connect(const sp<IConsumerListener>& consumerListener,
- bool controlledByApp);
-
- // disconnect disconnects a consumer from the GonkBufferQueue. All
- // buffers will be freed and the GonkBufferQueue is placed in the "abandoned"
- // state, causing most interactions with the GonkBufferQueue by the producer to
- // fail.
- virtual status_t disconnect();
-
- // getReleasedBuffers sets the value pointed to by outSlotMask to a bit mask
- // indicating which buffer slots have been released by the GonkBufferQueue
- // but have not yet been released by the consumer.
- //
- // This should be called from the onBuffersReleased() callback.
- virtual status_t getReleasedBuffers(uint64_t* outSlotMask);
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // dequeueBuffer when a width and height of zero is requested. Default
- // is 1x1.
- virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height);
-
- // setDefaultMaxBufferCount sets the default value for the maximum buffer
- // count (the initial default is 2). If the producer has requested a
- // buffer count using setBufferCount, the default buffer count will only
- // take effect if the producer sets the count back to zero.
- //
- // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
- virtual status_t setDefaultMaxBufferCount(int bufferCount);
-
- // disableAsyncBuffer disables the extra buffer used in async mode
- // (when both producer and consumer have set their "isControlledByApp"
- // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
- //
- // This can only be called before connect().
- virtual status_t disableAsyncBuffer();
-
- // setMaxAcquiredBufferCount sets the maximum number of buffers that can
- // be acquired by the consumer at one time (default 1). This call will
- // fail if a producer is connected to the GonkBufferQueue.
- virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
-
- // setConsumerName sets the name used in logging
- virtual void setConsumerName(const String8& name);
-
- // setDefaultBufferFormat allows the GonkBufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer. Formats are enumerated in graphics.h; the
- // initial default is HAL_PIXEL_FORMAT_RGBA_8888.
- virtual status_t setDefaultBufferFormat(uint32_t defaultFormat);
-
- // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
- // These are merged with the bits passed to dequeueBuffer. The values are
- // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
- virtual status_t setConsumerUsageBits(uint32_t usage);
-
- // setTransformHint bakes in rotation to buffers so overlays can be used.
- // The values are enumerated in window.h, e.g.
- // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform).
- virtual status_t setTransformHint(uint32_t hint);
-
- // Retrieve the sideband buffer stream, if any.
- virtual sp<NativeHandle> getSidebandStream() const;
-
- // dump our state in a String
- virtual void dumpToString(String8& result, const char* prefix) const;
-
- // Added by mozilla
- virtual already_AddRefed<GonkBufferSlot::TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer);
-
- virtual int getSlotFromTextureClientLocked(GonkBufferSlot::TextureClient* client) const;
-
- // Functions required for backwards compatibility.
- // These will be modified/renamed in IGonkGraphicBufferConsumer and will be
- // removed from this class at that time. See b/13306289.
- virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
- bool controlledByApp) {
- return connect(consumer, controlledByApp);
- }
-
- virtual status_t consumerDisconnect() { return disconnect(); }
-
- // End functions required for backwards compatibility
-
-private:
- sp<GonkBufferQueueCore> mCore;
-
- // This references mCore->mSlots. Lock mCore->mMutex while accessing.
- GonkBufferQueueDefs::SlotsType& mSlots;
-
- // This is a cached copy of the name stored in the GonkBufferQueueCore.
- // It's updated during setConsumerName.
- String8 mConsumerName;
-
-}; // class GonkBufferQueueConsumer
-
-} // namespace android
-
-#endif
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp
deleted file mode 100644
index 9e8e337f6..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "GonkBufferQueueCore"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#include <inttypes.h>
-
-#include "GonkBufferItem.h"
-#include "GonkBufferQueueCore.h"
-#include <gui/IConsumerListener.h>
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/IProducerListener.h>
-#include <gui/ISurfaceComposer.h>
-#include <private/gui/ComposerService.h>
-
-#include <cutils/compiler.h>
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-
-template <typename T>
-static inline T max(T a, T b) { return a > b ? a : b; }
-
-namespace android {
-
-static String8 getUniqueName() {
- static volatile int32_t counter = 0;
- return String8::format("unnamed-%d-%d", getpid(),
- android_atomic_inc(&counter));
-}
-
-GonkBufferQueueCore::GonkBufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
- mAllocator(allocator),
- mMutex(),
- mIsAbandoned(false),
- mConsumerControlledByApp(false),
- mConsumerName(getUniqueName()),
- mConsumerListener(),
- mConsumerUsageBits(0),
- mConnectedApi(NO_CONNECTED_API),
- mConnectedProducerListener(),
- mSlots(),
- mQueue(),
- mOverrideMaxBufferCount(0),
- mDequeueCondition(),
- mUseAsyncBuffer(true),
- mDequeueBufferCannotBlock(false),
- mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
- mDefaultWidth(1),
- mDefaultHeight(1),
- mDefaultMaxBufferCount(2),
- mMaxAcquiredBufferCount(1),
- mBufferHasBeenQueued(false),
- mFrameCounter(0),
- mTransformHint(0),
- mIsAllocating(false),
- mIsAllocatingCondition()
-{
- ALOGV("GonkBufferQueueCore");
-}
-
-GonkBufferQueueCore::~GonkBufferQueueCore() {}
-
-void GonkBufferQueueCore::dump(String8& result, const char* prefix) const {
- Mutex::Autolock lock(mMutex);
-
- String8 fifo;
- Fifo::const_iterator current(mQueue.begin());
- while (current != mQueue.end()) {
- fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
- "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
- current->mSlot, current->mGraphicBuffer.get(),
- current->mCrop.left, current->mCrop.top, current->mCrop.right,
- current->mCrop.bottom, current->mTransform, current->mTimestamp,
- GonkBufferItem::scalingModeName(current->mScalingMode));
- ++current;
- }
-
- result.appendFormat("%s-GonkBufferQueue mMaxAcquiredBufferCount=%d, "
- "mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
- "default-format=%d, transform-hint=%02x, FIFO(%zu)={%s}\n",
- prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock,
- mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint,
- mQueue.size(), fifo.string());
-
- // Trim the free buffers so as to not spam the dump
- int maxBufferCount = 0;
- for (int s = GonkBufferQueueDefs::NUM_BUFFER_SLOTS - 1; s >= 0; --s) {
- const GonkBufferSlot& slot(mSlots[s]);
- if (slot.mBufferState != GonkBufferSlot::FREE ||
- slot.mGraphicBuffer != NULL) {
- maxBufferCount = s + 1;
- break;
- }
- }
-
- for (int s = 0; s < maxBufferCount; ++s) {
- const GonkBufferSlot& slot(mSlots[s]);
- const sp<GraphicBuffer>& buffer(slot.mGraphicBuffer);
- result.appendFormat("%s%s[%02d:%p] state=%-8s", prefix,
- (slot.mBufferState == GonkBufferSlot::ACQUIRED) ? ">" : " ",
- s, buffer.get(),
- GonkBufferSlot::bufferStateName(slot.mBufferState));
-
- if (buffer != NULL) {
- result.appendFormat(", %p [%4ux%4u:%4u,%3X]", buffer->handle,
- buffer->width, buffer->height, buffer->stride,
- buffer->format);
- }
-
- result.append("\n");
- }
-}
-
-int GonkBufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const {
- // If dequeueBuffer is allowed to error out, we don't have to add an
- // extra buffer.
- if (!mUseAsyncBuffer) {
- return mMaxAcquiredBufferCount;
- }
-
- if (mDequeueBufferCannotBlock || async) {
- return mMaxAcquiredBufferCount + 1;
- }
-
- return mMaxAcquiredBufferCount;
-}
-
-int GonkBufferQueueCore::getMinMaxBufferCountLocked(bool async) const {
- return getMinUndequeuedBufferCountLocked(async) + 1;
-}
-
-int GonkBufferQueueCore::getMaxBufferCountLocked(bool async) const {
- int minMaxBufferCount = getMinMaxBufferCountLocked(async);
-
- int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount);
- if (mOverrideMaxBufferCount != 0) {
- assert(mOverrideMaxBufferCount >= minMaxBufferCount);
- maxBufferCount = mOverrideMaxBufferCount;
- }
-
- // Any buffers that are dequeued by the producer or sitting in the queue
- // waiting to be consumed need to have their slots preserved. Such buffers
- // will temporarily keep the max buffer count up until the slots no longer
- // need to be preserved.
- for (int s = maxBufferCount; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- GonkBufferSlot::BufferState state = mSlots[s].mBufferState;
- if (state == GonkBufferSlot::QUEUED || state == GonkBufferSlot::DEQUEUED) {
- maxBufferCount = s + 1;
- }
- }
-
- return maxBufferCount;
-}
-
-status_t GonkBufferQueueCore::setDefaultMaxBufferCountLocked(int count) {
- const int minBufferCount = 2;
- if (count < minBufferCount || count > GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
- ALOGV("setDefaultMaxBufferCount: invalid count %d, should be in "
- "[%d, %d]",
- count, minBufferCount, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- }
-
- ALOGV("setDefaultMaxBufferCount: setting count to %d", count);
- mDefaultMaxBufferCount = count;
- mDequeueCondition.broadcast();
-
- return NO_ERROR;
-}
-
-void GonkBufferQueueCore::freeBufferLocked(int slot) {
- ALOGV("freeBufferLocked: slot %d", slot);
-
- if (mSlots[slot].mTextureClient) {
- mSlots[slot].mTextureClient->ClearRecycleCallback();
- // release TextureClient in ImageBridge thread
- RefPtr<TextureClientReleaseTask> task =
- MakeAndAddRef<TextureClientReleaseTask>(mSlots[slot].mTextureClient);
- mSlots[slot].mTextureClient = NULL;
- ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
- }
- mSlots[slot].mGraphicBuffer.clear();
- if (mSlots[slot].mBufferState == GonkBufferSlot::ACQUIRED) {
- mSlots[slot].mNeedsCleanupOnRelease = true;
- }
- mSlots[slot].mBufferState = GonkBufferSlot::FREE;
- mSlots[slot].mFrameNumber = UINT32_MAX;
- mSlots[slot].mAcquireCalled = false;
-
- // Destroy fence as GonkBufferQueue now takes ownership
- mSlots[slot].mFence = Fence::NO_FENCE;
-}
-
-void GonkBufferQueueCore::freeAllBuffersLocked() {
- ALOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersLocked called but mQueue is not empty");
- mQueue.clear();
- mBufferHasBeenQueued = false;
- for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- freeBufferLocked(s);
- }
-}
-
-bool GonkBufferQueueCore::stillTracking(const GonkBufferItem* item) const {
- const GonkBufferSlot& slot = mSlots[item->mSlot];
-
- ALOGV("stillTracking: item { slot=%d/%" PRIu64 " buffer=%p } "
- "slot { slot=%d/%" PRIu64 " buffer=%p }",
- item->mSlot, item->mFrameNumber,
- (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0),
- item->mSlot, slot.mFrameNumber,
- (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0));
-
- // Compare item with its original buffer slot. We can check the slot as
- // the buffer would not be moved to a different slot by the producer.
- return (slot.mGraphicBuffer != NULL) &&
- (item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle);
-}
-
-void GonkBufferQueueCore::waitWhileAllocatingLocked() const {
- ATRACE_CALL();
- while (mIsAllocating) {
- mIsAllocatingCondition.wait(mMutex);
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h
deleted file mode 100644
index 936e11686..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKBUFFERQUEUECORE_LL_H
-#define NATIVEWINDOW_GONKBUFFERQUEUECORE_LL_H
-
-#include "GonkBufferQueueDefs.h"
-#include "GonkBufferSlot.h"
-
-#include <utils/Condition.h>
-#include <utils/Mutex.h>
-#include <utils/NativeHandle.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/StrongPointer.h>
-#include <utils/Trace.h>
-#include <utils/Vector.h>
-
-#include "mozilla/layers/TextureClient.h"
-
-#define ATRACE_BUFFER_INDEX(index)
-
-using namespace mozilla;
-using namespace mozilla::gfx;
-using namespace mozilla::layers;
-
-namespace android {
-
-class GonkBufferItem;
-class IConsumerListener;
-class IGraphicBufferAlloc;
-class IProducerListener;
-
-class GonkBufferQueueCore : public virtual RefBase {
-
- friend class GonkBufferQueueProducer;
- friend class GonkBufferQueueConsumer;
-
-public:
- // Used as a placeholder slot number when the value isn't pointing to an
- // existing buffer.
- enum { INVALID_BUFFER_SLOT = -1 }; // TODO: Extract from IGBC::BufferItem
-
- // We reserve two slots in order to guarantee that the producer and
- // consumer can run asynchronously.
- enum { MAX_MAX_ACQUIRED_BUFFERS = GonkBufferQueueDefs::NUM_BUFFER_SLOTS - 2 };
-
- // The default API number used to indicate that no producer is connected
- enum { NO_CONNECTED_API = 0 };
-
- typedef Vector<GonkBufferItem> Fifo;
- typedef mozilla::layers::TextureClient TextureClient;
-
- // GonkBufferQueueCore manages a pool of gralloc memory slots to be used by
- // producers and consumers. allocator is used to allocate all the needed
- // gralloc buffers.
- GonkBufferQueueCore(const sp<IGraphicBufferAlloc>& allocator = NULL);
- virtual ~GonkBufferQueueCore();
-
-private:
- // Dump our state in a string
- void dump(String8& result, const char* prefix) const;
-
- int getSlotFromTextureClientLocked(TextureClient* client) const;
-
- // getMinUndequeuedBufferCountLocked returns the minimum number of buffers
- // that must remain in a state other than DEQUEUED. The async parameter
- // tells whether we're in asynchronous mode.
- int getMinUndequeuedBufferCountLocked(bool async) const;
-
- // getMinMaxBufferCountLocked returns the minimum number of buffers allowed
- // given the current GonkBufferQueue state. The async parameter tells whether
- // we're in asynchonous mode.
- int getMinMaxBufferCountLocked(bool async) const;
-
- // getMaxBufferCountLocked returns the maximum number of buffers that can be
- // allocated at once. This value depends on the following member variables:
- //
- // mDequeueBufferCannotBlock
- // mMaxAcquiredBufferCount
- // mDefaultMaxBufferCount
- // mOverrideMaxBufferCount
- // async parameter
- //
- // Any time one of these member variables is changed while a producer is
- // connected, mDequeueCondition must be broadcast.
- int getMaxBufferCountLocked(bool async) const;
-
- // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
- // that will be used if the producer does not override the buffer slot
- // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The
- // initial default is 2.
- status_t setDefaultMaxBufferCountLocked(int count);
-
- // freeBufferLocked frees the GraphicBuffer and sync resources for the
- // given slot.
- void freeBufferLocked(int slot);
-
- // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
- // all slots.
- void freeAllBuffersLocked();
-
- // stillTracking returns true iff the buffer item is still being tracked
- // in one of the slots.
- bool stillTracking(const GonkBufferItem* item) const;
-
- // waitWhileAllocatingLocked blocks until mIsAllocating is false.
- void waitWhileAllocatingLocked() const;
-
- // mAllocator is the connection to SurfaceFlinger that is used to allocate
- // new GraphicBuffer objects.
- sp<IGraphicBufferAlloc> mAllocator;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of GonkBufferQueueCore objects. It must be locked whenever any
- // member variable is accessed.
- mutable Mutex mMutex;
-
- // mIsAbandoned indicates that the GonkBufferQueue will no longer be used to
- // consume image buffers pushed to it using the IGraphicBufferProducer
- // interface. It is initialized to false, and set to true in the
- // consumerDisconnect method. A GonkBufferQueue that is abandoned will return
- // the NO_INIT error from all IGraphicBufferProducer methods capable of
- // returning an error.
- bool mIsAbandoned;
-
- // mConsumerControlledByApp indicates whether the connected consumer is
- // controlled by the application.
- bool mConsumerControlledByApp;
-
- // mConsumerName is a string used to identify the GonkBufferQueue in log
- // messages. It is set by the IGraphicBufferConsumer::setConsumerName
- // method.
- String8 mConsumerName;
-
- // mConsumerListener is used to notify the connected consumer of
- // asynchronous events that it may wish to react to. It is initially
- // set to NULL and is written by consumerConnect and consumerDisconnect.
- sp<IConsumerListener> mConsumerListener;
-
- // mConsumerUsageBits contains flags that the consumer wants for
- // GraphicBuffers.
- uint32_t mConsumerUsageBits;
-
- // mConnectedApi indicates the producer API that is currently connected
- // to this GonkBufferQueue. It defaults to NO_CONNECTED_API, and gets updated
- // by the connect and disconnect methods.
- int mConnectedApi;
-
- // mConnectedProducerToken is used to set a binder death notification on
- // the producer.
- sp<IProducerListener> mConnectedProducerListener;
-
- // 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
- // and consumer without sending a GraphicBuffer over Binder. The entire
- // array is initialized to NULL at construction time, and buffers are
- // allocated for a slot when requestBuffer is called with that slot's index.
- GonkBufferQueueDefs::SlotsType mSlots;
-
- // mQueue is a FIFO of queued buffers used in synchronous mode.
- Fifo mQueue;
-
- // mOverrideMaxBufferCount is the limit on the number of buffers that will
- // be allocated at one time. This value is set by the producer by calling
- // setBufferCount. The default is 0, which means that the producer doesn't
- // care about the number of buffers in the pool. In that case,
- // mDefaultMaxBufferCount is used as the limit.
- int mOverrideMaxBufferCount;
-
- // mDequeueCondition is a condition variable used for dequeueBuffer in
- // synchronous mode.
- mutable Condition mDequeueCondition;
-
- // mUseAsyncBuffer indicates whether an extra buffer is used in async mode
- // to prevent dequeueBuffer from blocking.
- bool mUseAsyncBuffer;
-
- // mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
- // block. This flag is set during connect when both the producer and
- // consumer are controlled by the application.
- bool mDequeueBufferCannotBlock;
-
- // mDefaultBufferFormat can be set so it will override the buffer format
- // when it isn't specified in dequeueBuffer.
- uint32_t mDefaultBufferFormat;
-
- // mDefaultWidth holds the default width of allocated buffers. It is used
- // in dequeueBuffer if a width and height of 0 are specified.
- int mDefaultWidth;
-
- // mDefaultHeight holds the default height of allocated buffers. It is used
- // in dequeueBuffer if a width and height of 0 are specified.
- int mDefaultHeight;
-
- // mDefaultMaxBufferCount is the default limit on the number of buffers that
- // will be allocated at one time. This default limit is set by the consumer.
- // The limit (as opposed to the default limit) may be overriden by the
- // producer.
- int mDefaultMaxBufferCount;
-
- // mMaxAcquiredBufferCount is the number of buffers that the consumer may
- // acquire at one time. It defaults to 1, and can be changed by the consumer
- // via setMaxAcquiredBufferCount, but this may only be done while no
- // producer is connected to the GonkBufferQueue. This value is used to derive
- // the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer.
- int mMaxAcquiredBufferCount;
-
- // mBufferHasBeenQueued is true once a buffer has been queued. It is reset
- // when something causes all buffers to be freed (e.g., changing the buffer
- // count).
- bool mBufferHasBeenQueued;
-
- // mFrameCounter is the free running counter, incremented on every
- // successful queueBuffer call and buffer allocation.
- uint64_t mFrameCounter;
-
- // mTransformHint is used to optimize for screen rotations.
- uint32_t mTransformHint;
-
- // mSidebandStream is a handle to the sideband buffer stream, if any
- sp<NativeHandle> mSidebandStream;
-
- // mIsAllocating indicates whether a producer is currently trying to allocate buffers (which
- // releases mMutex while doing the allocation proper). Producers should not modify any of the
- // FREE slots while this is true. mIsAllocatingCondition is signaled when this value changes to
- // false.
- bool mIsAllocating;
-
- // mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating
- // becomes false.
- mutable Condition mIsAllocatingCondition;
-}; // class GonkBufferQueueCore
-
-} // namespace android
-
-#endif
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h
deleted file mode 100644
index 60085706f..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_BUFFERQUEUECOREDEFS_H
-#define NATIVEWINDOW_BUFFERQUEUECOREDEFS_H
-
-#include "GonkBufferSlot.h"
-
-namespace android {
- class GonkBufferQueueCore;
-
- namespace GonkBufferQueueDefs {
- // GonkBufferQueue will keep track of at most this value of buffers.
- // Attempts at runtime to increase the number of buffers past this
- // will fail.
- enum { NUM_BUFFER_SLOTS = 64 };
-
- typedef GonkBufferSlot SlotsType[NUM_BUFFER_SLOTS];
- } // namespace GonkBufferQueueDefs
-} // namespace android
-
-#endif
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp
deleted file mode 100644
index 649d06bee..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "GonkBufferQueue"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#define LOG_NDEBUG 0
-
-#include "GonkBufferQueue.h"
-#include "GonkBufferQueueConsumer.h"
-#include "GonkBufferQueueCore.h"
-#include "GonkBufferQueueProducer.h"
-
-namespace android {
-
-GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener(
- const wp<ConsumerListener>& consumerListener):
- mConsumerListener(consumerListener) {}
-
-GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
-
-#if ANDROID_VERSION == 21
-void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameAvailable();
- }
-}
-#else
-void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable(const ::android::BufferItem& item) {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameAvailable(item);
- }
-}
-
-void GonkBufferQueue::ProxyConsumerListener::onFrameReplaced(const ::android::BufferItem& item) {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameReplaced(item);
- }
-}
-#endif
-
-void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-}
-
-void GonkBufferQueue::ProxyConsumerListener::onSidebandStreamChanged() {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onSidebandStreamChanged();
- }
-}
-
-void GonkBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
- sp<IGonkGraphicBufferConsumer>* outConsumer,
- const sp<IGraphicBufferAlloc>& allocator) {
- LOG_ALWAYS_FATAL_IF(outProducer == NULL,
- "GonkBufferQueue: outProducer must not be NULL");
- LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
- "GonkBufferQueue: outConsumer must not be NULL");
-
- sp<GonkBufferQueueCore> core(new GonkBufferQueueCore(allocator));
- LOG_ALWAYS_FATAL_IF(core == NULL,
- "GonkBufferQueue: failed to create GonkBufferQueueCore");
-
- sp<IGraphicBufferProducer> producer(new GonkBufferQueueProducer(core));
- LOG_ALWAYS_FATAL_IF(producer == NULL,
- "GonkBufferQueue: failed to create GonkBufferQueueProducer");
-
- sp<IGonkGraphicBufferConsumer> consumer(new GonkBufferQueueConsumer(core));
- LOG_ALWAYS_FATAL_IF(consumer == NULL,
- "GonkBufferQueue: failed to create GonkBufferQueueConsumer");
-
- *outProducer = producer;
- *outConsumer = consumer;
-}
-
-}; // namespace android
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h
deleted file mode 100644
index b1b4e06b5..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKBUFFERQUEUE_LL_H
-#define NATIVEWINDOW_GONKBUFFERQUEUE_LL_H
-
-#include "GonkBufferQueueDefs.h"
-#include "IGonkGraphicBufferConsumerLL.h"
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/IConsumerListener.h>
-
-// These are only required to keep other parts of the framework with incomplete
-// dependencies building successfully
-#include <gui/IGraphicBufferAlloc.h>
-
-namespace android {
-
-class GonkBufferQueue {
-public:
- // GonkBufferQueue will keep track of at most this value of buffers.
- // Attempts at runtime to increase the number of buffers past this will fail.
- enum { NUM_BUFFER_SLOTS = GonkBufferQueueDefs::NUM_BUFFER_SLOTS };
- // Used as a placeholder slot# when the value isn't pointing to an existing buffer.
- enum { INVALID_BUFFER_SLOT = IGonkGraphicBufferConsumer::BufferItem::INVALID_BUFFER_SLOT };
- // Alias to <IGonkGraphicBufferConsumer.h> -- please scope from there in future code!
- enum {
- NO_BUFFER_AVAILABLE = IGonkGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
- PRESENT_LATER = IGonkGraphicBufferConsumer::PRESENT_LATER,
- };
-
- // When in async mode we reserve two slots in order to guarantee that the
- // producer and consumer can run asynchronously.
- enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 };
-
- // for backward source compatibility
- typedef ::android::ConsumerListener ConsumerListener;
- typedef IGonkGraphicBufferConsumer::BufferItem BufferItem;
-
- // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
- // reference to the actual consumer object. It forwards all calls to that
- // consumer object so long as it exists.
- //
- // This class exists to avoid having a circular reference between the
- // GonkBufferQueue object and the consumer object. The reason this can't be a weak
- // reference in the GonkBufferQueue class is because we're planning to expose the
- // consumer side of a GonkBufferQueue as a binder interface, which doesn't support
- // weak references.
- class ProxyConsumerListener : public BnConsumerListener {
- public:
- ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
- virtual ~ProxyConsumerListener();
-#if ANDROID_VERSION == 21
- virtual void onFrameAvailable();
-#else
- virtual void onFrameAvailable(const ::android::BufferItem& item);
- virtual void onFrameReplaced(const ::android::BufferItem& item);
-#endif
- virtual void onBuffersReleased();
- virtual void onSidebandStreamChanged();
- private:
- // mConsumerListener is a weak reference to the IConsumerListener. This is
- // the raison d'etre of ProxyConsumerListener.
- wp<ConsumerListener> mConsumerListener;
- };
-
- // GonkBufferQueue manages a pool of gralloc memory slots to be used by
- // producers and consumers. allocator is used to allocate all the
- // needed gralloc buffers.
- static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
- sp<IGonkGraphicBufferConsumer>* outConsumer,
- const sp<IGraphicBufferAlloc>& allocator = NULL);
-
-private:
- GonkBufferQueue(); // Create through createBufferQueue
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // NATIVEWINDOW_GONKBUFFERQUEUE_LL_H
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp
deleted file mode 100644
index d3436756f..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp
+++ /dev/null
@@ -1,886 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <inttypes.h>
-
-#define LOG_TAG "GonkBufferQueueProducer"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#include "GonkBufferItem.h"
-#include "GonkBufferQueueCore.h"
-#include "GonkBufferQueueProducer.h"
-#include <gui/IConsumerListener.h>
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/IProducerListener.h>
-
-#include <cutils/compiler.h>
-#include <utils/Log.h>
-#include <utils/Trace.h>
-
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/TextureClient.h"
-
-namespace android {
-
-GonkBufferQueueProducer::GonkBufferQueueProducer(const sp<GonkBufferQueueCore>& core) :
- mCore(core),
- mSlots(core->mSlots),
- mConsumerName(),
- mSynchronousMode(true),
- mStickyTransform(0) {}
-
-GonkBufferQueueProducer::~GonkBufferQueueProducer() {}
-
-status_t GonkBufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- ATRACE_CALL();
- ALOGV("requestBuffer: slot %d", slot);
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mIsAbandoned) {
- ALOGE("requestBuffer: GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
- ALOGE("requestBuffer: slot index %d out of range [0, %d)",
- slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) {
- ALOGE("requestBuffer: slot %d is not owned by the producer "
- "(state = %d)", slot, mSlots[slot].mBufferState);
- return BAD_VALUE;
- }
-
- mSlots[slot].mRequestBufferCalled = true;
- *buf = mSlots[slot].mGraphicBuffer;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueProducer::setBufferCount(int bufferCount) {
- ATRACE_CALL();
- ALOGV("setBufferCount: count = %d", bufferCount);
-
- sp<IConsumerListener> listener;
- { // Autolock scope
- Mutex::Autolock lock(mCore->mMutex);
- mCore->waitWhileAllocatingLocked();
-
- if (mCore->mIsAbandoned) {
- ALOGE("setBufferCount: GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- if (bufferCount > GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
- ALOGE("setBufferCount: bufferCount %d too large (max %d)",
- bufferCount, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- }
-
- // There must be no dequeued buffers when changing the buffer count.
- for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- if (mSlots[s].mBufferState == GonkBufferSlot::DEQUEUED) {
- ALOGE("setBufferCount: buffer owned by producer");
- return BAD_VALUE;
- }
- }
-
- if (bufferCount == 0) {
- mCore->mOverrideMaxBufferCount = 0;
- mCore->mDequeueCondition.broadcast();
- return NO_ERROR;
- }
-
- const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
- if (bufferCount < minBufferSlots) {
- ALOGE("setBufferCount: requested buffer count %d is less than "
- "minimum %d", bufferCount, minBufferSlots);
- return BAD_VALUE;
- }
-
- // Here we are guaranteed that the producer doesn't have any dequeued
- // buffers and will release all of its buffer references. We don't
- // clear the queue, however, so that currently queued buffers still
- // get displayed.
- mCore->freeAllBuffersLocked();
- mCore->mOverrideMaxBufferCount = bufferCount;
- mCore->mDequeueCondition.broadcast();
- listener = mCore->mConsumerListener;
- } // Autolock scope
-
- // Call back without lock held
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
- bool async, int* found, status_t* returnFlags) const {
- bool tryAgain = true;
- while (tryAgain) {
- if (mCore->mIsAbandoned) {
- ALOGE("%s: GonkBufferQueue has been abandoned", caller);
- return NO_INIT;
- }
-
- const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
- if (async && mCore->mOverrideMaxBufferCount) {
- // FIXME: Some drivers are manually setting the buffer count
- // (which they shouldn't), so we do this extra test here to
- // handle that case. This is TEMPORARY until we get this fixed.
- if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
- ALOGE("%s: async mode is invalid with buffer count override",
- caller);
- return BAD_VALUE;
- }
- }
-
- // Free up any buffers that are in slots beyond the max buffer count
- //for (int s = maxBufferCount; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- // assert(mSlots[s].mBufferState == GonkBufferSlot::FREE);
- // if (mSlots[s].mGraphicBuffer != NULL) {
- // mCore->freeBufferLocked(s);
- // *returnFlags |= RELEASE_ALL_BUFFERS;
- // }
- //}
-
- // Look for a free buffer to give to the client
- *found = GonkBufferQueueCore::INVALID_BUFFER_SLOT;
- int dequeuedCount = 0;
- int acquiredCount = 0;
- for (int s = 0; s < maxBufferCount; ++s) {
- switch (mSlots[s].mBufferState) {
- case GonkBufferSlot::DEQUEUED:
- ++dequeuedCount;
- break;
- case GonkBufferSlot::ACQUIRED:
- ++acquiredCount;
- break;
- case GonkBufferSlot::FREE:
- // We return the oldest of the free buffers to avoid
- // stalling the producer if possible, since the consumer
- // may still have pending reads of in-flight buffers
- if (*found == GonkBufferQueueCore::INVALID_BUFFER_SLOT ||
- mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
- *found = s;
- }
- break;
- default:
- break;
- }
- }
-
- // Producers are not allowed to dequeue more than one buffer if they
- // did not set a buffer count
- if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
- ALOGE("%s: can't dequeue multiple buffers without setting the "
- "buffer count", caller);
- return INVALID_OPERATION;
- }
-
- // See whether a buffer has been queued since the last
- // setBufferCount so we know whether to perform the min undequeued
- // buffers check below
- if (mCore->mBufferHasBeenQueued) {
- // Make sure the producer is not trying to dequeue more buffers
- // than allowed
- const int newUndequeuedCount =
- maxBufferCount - (dequeuedCount + 1);
- const int minUndequeuedCount =
- mCore->getMinUndequeuedBufferCountLocked(async);
- if (newUndequeuedCount < minUndequeuedCount) {
- ALOGE("%s: min undequeued buffer count (%d) exceeded "
- "(dequeued=%d undequeued=%d)",
- caller, minUndequeuedCount,
- dequeuedCount, newUndequeuedCount);
- return INVALID_OPERATION;
- }
- }
-
- // If we disconnect and reconnect quickly, we can be in a state where
- // our slots are empty but we have many buffers in the queue. This can
- // cause us to run out of memory if we outrun the consumer. Wait here if
- // it looks like we have too many buffers queued up.
- bool tooManyBuffers = mCore->mQueue.size()
- > static_cast<size_t>(maxBufferCount);
- if (tooManyBuffers) {
- ALOGV("%s: queue size is %zu, waiting", caller,
- mCore->mQueue.size());
- }
-
- // If no buffer is found, or if the queue has too many buffers
- // outstanding, wait for a buffer to be acquired or released, or for the
- // max buffer count to change.
- tryAgain = (*found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) ||
- tooManyBuffers;
- if (tryAgain) {
- // Return an error if we're in non-blocking mode (producer and
- // consumer are controlled by the application).
- // However, the consumer is allowed to briefly acquire an extra
- // buffer (which could cause us to have to wait here), which is
- // okay, since it is only used to implement an atomic acquire +
- // release (e.g., in GLConsumer::updateTexImage())
- if (mCore->mDequeueBufferCannotBlock &&
- (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
- return WOULD_BLOCK;
- }
- mCore->mDequeueCondition.wait(mCore->mMutex);
- }
- } // while (tryAgain)
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueProducer::dequeueBuffer(int *outSlot,
- sp<android::Fence> *outFence, bool async,
- uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
- ATRACE_CALL();
- { // Autolock scope
- Mutex::Autolock lock(mCore->mMutex);
- mConsumerName = mCore->mConsumerName;
- } // Autolock scope
-
- ALOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
- async ? "true" : "false", width, height, format, usage);
-
- if ((width && !height) || (!width && height)) {
- ALOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
- return BAD_VALUE;
- }
-
- status_t returnFlags = NO_ERROR;
- // Reset slot
- *outSlot = GonkBufferQueueCore::INVALID_BUFFER_SLOT;
-
- bool attachedByConsumer = false;
-
- { // Autolock scope
- Mutex::Autolock lock(mCore->mMutex);
- mCore->waitWhileAllocatingLocked();
-
- if (format == 0) {
- format = mCore->mDefaultBufferFormat;
- }
-
- // Enable the usage bits the consumer requested
- usage |= mCore->mConsumerUsageBits;
-
- int found;
- status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
- &found, &returnFlags);
- if (status != NO_ERROR) {
- return status;
- }
-
- // This should not happen
- if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) {
- ALOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
- }
-
- *outSlot = found;
-
- attachedByConsumer = mSlots[found].mAttachedByConsumer;
-
- const bool useDefaultSize = !width && !height;
- if (useDefaultSize) {
- width = mCore->mDefaultWidth;
- height = mCore->mDefaultHeight;
- }
-
- mSlots[found].mBufferState = GonkBufferSlot::DEQUEUED;
-
- const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
- if ((buffer == NULL) ||
- (static_cast<uint32_t>(buffer->width) != width) ||
- (static_cast<uint32_t>(buffer->height) != height) ||
- (static_cast<uint32_t>(buffer->format) != format) ||
- ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
- {
- mSlots[found].mAcquireCalled = false;
- mSlots[found].mGraphicBuffer = NULL;
- mSlots[found].mRequestBufferCalled = false;
- mSlots[found].mFence = Fence::NO_FENCE;
-
- if (mSlots[found].mTextureClient) {
- mSlots[found].mTextureClient->ClearRecycleCallback();
- // release TextureClient in ImageBridge thread
- RefPtr<TextureClientReleaseTask> task =
- MakeAndAddRef<TextureClientReleaseTask>(mSlots[found].mTextureClient);
- mSlots[found].mTextureClient = NULL;
- ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
- }
-
- returnFlags |= BUFFER_NEEDS_REALLOCATION;
- }
-
- if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
- ALOGE("dequeueBuffer: about to return a NULL fence - "
- "slot=%d w=%d h=%d format=%u",
- found, buffer->width, buffer->height, buffer->format);
- }
-
- *outFence = mSlots[found].mFence;
- mSlots[found].mFence = Fence::NO_FENCE;
- } // Autolock scope
-
- if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
- RefPtr<LayersIPCChannel> allocator = ImageBridgeChild::GetSingleton();
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- GrallocTextureData* texData = GrallocTextureData::Create(IntSize(width,height), format,
- gfx::BackendType::NONE,
- usage, allocator);
- if (!texData) {
- ALOGE("dequeueBuffer: failed to alloc gralloc buffer");
- return -ENOMEM;
- }
- RefPtr<TextureClient> textureClient = TextureClient::CreateWithData(
- texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator);
-
- sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
-
- { // Autolock scope
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mIsAbandoned) {
- ALOGE("dequeueBuffer: GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- mSlots[*outSlot].mFrameNumber = UINT32_MAX;
- mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
- mSlots[*outSlot].mTextureClient = textureClient;
- } // Autolock scope
- }
-
- if (attachedByConsumer) {
- returnFlags |= BUFFER_NEEDS_REALLOCATION;
- }
-
- ALOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
- *outSlot,
- mSlots[*outSlot].mFrameNumber,
- mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
-
- return returnFlags;
-}
-
-status_t GonkBufferQueueProducer::detachBuffer(int slot) {
- ATRACE_CALL();
- ATRACE_BUFFER_INDEX(slot);
- ALOGV("detachBuffer(P): slot %d", slot);
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mIsAbandoned) {
- ALOGE("detachBuffer(P): GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
- ALOGE("detachBuffer(P): slot index %d out of range [0, %d)",
- slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) {
- ALOGE("detachBuffer(P): slot %d is not owned by the producer "
- "(state = %d)", slot, mSlots[slot].mBufferState);
- return BAD_VALUE;
- } else if (!mSlots[slot].mRequestBufferCalled) {
- ALOGE("detachBuffer(P): buffer in slot %d has not been requested",
- slot);
- return BAD_VALUE;
- }
-
- mCore->freeBufferLocked(slot);
- mCore->mDequeueCondition.broadcast();
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) {
- ATRACE_CALL();
-
- if (outBuffer == NULL) {
- ALOGE("detachNextBuffer: outBuffer must not be NULL");
- return BAD_VALUE;
- } else if (outFence == NULL) {
- ALOGE("detachNextBuffer: outFence must not be NULL");
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mCore->mMutex);
- mCore->waitWhileAllocatingLocked();
-
- if (mCore->mIsAbandoned) {
- ALOGE("detachNextBuffer: GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- // Find the oldest valid slot
- int found = GonkBufferQueueCore::INVALID_BUFFER_SLOT;
- for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- if (mSlots[s].mBufferState == GonkBufferSlot::FREE &&
- mSlots[s].mGraphicBuffer != NULL) {
- if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT ||
- mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
- found = s;
- }
- }
- }
-
- if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) {
- return NO_MEMORY;
- }
-
- ALOGV("detachNextBuffer detached slot %d", found);
-
- *outBuffer = mSlots[found].mGraphicBuffer;
- *outFence = mSlots[found].mFence;
- mCore->freeBufferLocked(found);
-
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueProducer::attachBuffer(int* outSlot,
- const sp<android::GraphicBuffer>& buffer) {
- ATRACE_CALL();
-
- if (outSlot == NULL) {
- ALOGE("attachBuffer(P): outSlot must not be NULL");
- return BAD_VALUE;
- } else if (buffer == NULL) {
- ALOGE("attachBuffer(P): cannot attach NULL buffer");
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mCore->mMutex);
- mCore->waitWhileAllocatingLocked();
-
- status_t returnFlags = NO_ERROR;
- int found;
- // TODO: Should we provide an async flag to attachBuffer? It seems
- // unlikely that buffers which we are attaching to a GonkBufferQueue will
- // be asynchronous (droppable), but it may not be impossible.
- status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false,
- &found, &returnFlags);
- if (status != NO_ERROR) {
- return status;
- }
-
- // This should not happen
- if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) {
- ALOGE("attachBuffer(P): no available buffer slots");
- return -EBUSY;
- }
-
- *outSlot = found;
- ATRACE_BUFFER_INDEX(*outSlot);
- ALOGV("attachBuffer(P): returning slot %d flags=%#x",
- *outSlot, returnFlags);
-
- mSlots[*outSlot].mGraphicBuffer = buffer;
- mSlots[*outSlot].mBufferState = GonkBufferSlot::DEQUEUED;
- mSlots[*outSlot].mFence = Fence::NO_FENCE;
- mSlots[*outSlot].mRequestBufferCalled = true;
-
- return returnFlags;
-}
-
-status_t GonkBufferQueueProducer::setSynchronousMode(bool enabled) {
- ALOGV("setSynchronousMode: enabled=%d", enabled);
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mIsAbandoned) {
- ALOGE("setSynchronousMode: BufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- if (mSynchronousMode != enabled) {
- mSynchronousMode = enabled;
- mCore->mDequeueCondition.broadcast();
- }
- return OK;
-}
-
-status_t GonkBufferQueueProducer::queueBuffer(int slot,
- const QueueBufferInput &input, QueueBufferOutput *output) {
- ATRACE_CALL();
-
- int64_t timestamp;
- bool isAutoTimestamp;
- Rect crop;
- int scalingMode;
- uint32_t transform;
- uint32_t stickyTransform;
- bool async;
- sp<Fence> fence;
- input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
- &async, &fence, &stickyTransform);
-
- if (fence == NULL) {
- ALOGE("queueBuffer: fence is NULL");
- // Temporary workaround for b/17946343: soldier-on instead of returning an error. This
- // prevents the client from dying, at the risk of visible corruption due to hwcomposer
- // reading the buffer before the producer is done rendering it. Unless the buffer is the
- // last frame of an animation, the corruption will be transient.
- fence = Fence::NO_FENCE;
- // return BAD_VALUE;
- }
-
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
- case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
- break;
- default:
- ALOGE("queueBuffer: unknown scaling mode %d", scalingMode);
- return BAD_VALUE;
- }
-
- GonkBufferItem item;
- sp<IConsumerListener> listener;
- { // Autolock scope
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mIsAbandoned) {
- ALOGE("queueBuffer: GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
- if (async && mCore->mOverrideMaxBufferCount) {
- // FIXME: Some drivers are manually setting the buffer count
- // (which they shouldn't), so we do this extra test here to
- // handle that case. This is TEMPORARY until we get this fixed.
- if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
- ALOGE("queueBuffer: async mode is invalid with "
- "buffer count override");
- return BAD_VALUE;
- }
- }
-
- if (slot < 0 || slot >= maxBufferCount) {
- ALOGE("queueBuffer: slot index %d out of range [0, %d)",
- slot, maxBufferCount);
- return BAD_VALUE;
- } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) {
- ALOGE("queueBuffer: slot %d is not owned by the producer "
- "(state = %d)", slot, mSlots[slot].mBufferState);
- return BAD_VALUE;
- } else if (!mSlots[slot].mRequestBufferCalled) {
- ALOGE("queueBuffer: slot %d was queued without requesting "
- "a buffer", slot);
- return BAD_VALUE;
- }
-
- ALOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
- " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
- slot, mCore->mFrameCounter + 1, timestamp,
- crop.left, crop.top, crop.right, crop.bottom,
- transform, GonkBufferItem::scalingModeName(scalingMode));
-
- const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
- Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
- Rect croppedRect;
- crop.intersect(bufferRect, &croppedRect);
- if (croppedRect != crop) {
- ALOGE("queueBuffer: crop rect is not contained within the "
- "buffer in slot %d", slot);
- return BAD_VALUE;
- }
-
- mSlots[slot].mFence = fence;
- mSlots[slot].mBufferState = GonkBufferSlot::QUEUED;
- ++mCore->mFrameCounter;
- mSlots[slot].mFrameNumber = mCore->mFrameCounter;
-
- item.mAcquireCalled = mSlots[slot].mAcquireCalled;
- item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
- item.mCrop = crop;
- item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
- item.mTransformToDisplayInverse =
- bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
- item.mScalingMode = scalingMode;
- item.mTimestamp = timestamp;
- item.mIsAutoTimestamp = isAutoTimestamp;
- item.mFrameNumber = mCore->mFrameCounter;
- item.mSlot = slot;
- item.mFence = fence;
- item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
-
- mStickyTransform = stickyTransform;
-
- if (mCore->mQueue.empty()) {
- // When the queue is empty, we can ignore mDequeueBufferCannotBlock
- // and simply queue this buffer
- mCore->mQueue.push_back(item);
- listener = mCore->mConsumerListener;
- } else {
- // When the queue is not empty, we need to look at the front buffer
- // state to see if we need to replace it
- GonkBufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
- if (front->mIsDroppable || !mSynchronousMode) {
- // If the front queued buffer is still being tracked, we first
- // mark it as freed
- if (mCore->stillTracking(front)) {
- mSlots[front->mSlot].mBufferState = GonkBufferSlot::FREE;
- // Reset the frame number of the freed buffer so that it is
- // the first in line to be dequeued again
- mSlots[front->mSlot].mFrameNumber = 0;
- }
- // Overwrite the droppable buffer with the incoming one
- *front = item;
- listener = mCore->mConsumerListener;
- } else {
- mCore->mQueue.push_back(item);
- listener = mCore->mConsumerListener;
- }
- }
-
- mCore->mBufferHasBeenQueued = true;
- mCore->mDequeueCondition.broadcast();
-
- output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
- mCore->mTransformHint, mCore->mQueue.size());
-
- item.mGraphicBuffer.clear();
- item.mSlot = GonkBufferItem::INVALID_BUFFER_SLOT;
- } // Autolock scope
-
- // Call back without lock held
- if (listener != NULL) {
-#if ANDROID_VERSION == 21
- listener->onFrameAvailable();
-#else
- listener->onFrameAvailable(reinterpret_cast<::android::BufferItem&>(item));
-#endif
- }
-
- return NO_ERROR;
-}
-
-void GonkBufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
- ATRACE_CALL();
- ALOGV("cancelBuffer: slot %d", slot);
- Mutex::Autolock lock(mCore->mMutex);
-
- if (mCore->mIsAbandoned) {
- ALOGE("cancelBuffer: GonkBufferQueue has been abandoned");
- return;
- }
-
- if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
- ALOGE("cancelBuffer: slot index %d out of range [0, %d)",
- slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
- return;
- } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) {
- ALOGE("cancelBuffer: slot %d is not owned by the producer "
- "(state = %d)", slot, mSlots[slot].mBufferState);
- return;
- } else if (fence == NULL) {
- ALOGE("cancelBuffer: fence is NULL");
- return;
- }
-
- mSlots[slot].mBufferState = GonkBufferSlot::FREE;
- mSlots[slot].mFrameNumber = 0;
- mSlots[slot].mFence = fence;
- mCore->mDequeueCondition.broadcast();
-}
-
-int GonkBufferQueueProducer::query(int what, int *outValue) {
- ATRACE_CALL();
- Mutex::Autolock lock(mCore->mMutex);
-
- if (outValue == NULL) {
- ALOGE("query: outValue was NULL");
- return BAD_VALUE;
- }
-
- if (mCore->mIsAbandoned) {
- ALOGE("query: GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- int value;
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- value = mCore->mDefaultWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- value = mCore->mDefaultHeight;
- break;
- case NATIVE_WINDOW_FORMAT:
- value = mCore->mDefaultBufferFormat;
- break;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- value = mCore->getMinUndequeuedBufferCountLocked(false);
- break;
- case NATIVE_WINDOW_STICKY_TRANSFORM:
- value = static_cast<int>(mStickyTransform);
- break;
- case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
- value = (mCore->mQueue.size() > 1);
- break;
- case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
- value = mCore->mConsumerUsageBits;
- break;
- default:
- return BAD_VALUE;
- }
-
- ALOGV("query: %d? %d", what, value);
- *outValue = value;
- return NO_ERROR;
-}
-
-status_t GonkBufferQueueProducer::connect(const sp<IProducerListener>& listener,
- int api, bool producerControlledByApp, QueueBufferOutput *output) {
- ATRACE_CALL();
- Mutex::Autolock lock(mCore->mMutex);
- mConsumerName = mCore->mConsumerName;
- ALOGV("connect(P): api=%d producerControlledByApp=%s", api,
- producerControlledByApp ? "true" : "false");
-
- if (mCore->mIsAbandoned) {
- ALOGE("connect(P): GonkBufferQueue has been abandoned");
- return NO_INIT;
- }
-
- if (mCore->mConsumerListener == NULL) {
- ALOGE("connect(P): GonkBufferQueue has no consumer");
- return NO_INIT;
- }
-
- if (output == NULL) {
- ALOGE("connect(P): output was NULL");
- return BAD_VALUE;
- }
-
- if (mCore->mConnectedApi != GonkBufferQueueCore::NO_CONNECTED_API) {
- ALOGE("connect(P): already connected (cur=%d req=%d)", mCore->mConnectedApi,
- api);
- return BAD_VALUE;
- }
-
- int status = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- mCore->mConnectedApi = api;
- output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
- mCore->mTransformHint, mCore->mQueue.size());
-
- // Set up a death notification so that we can disconnect
- // automatically if the remote producer dies
- if (listener != NULL &&
- listener->asBinder()->remoteBinder() != NULL) {
- status = listener->asBinder()->linkToDeath(
- static_cast<IBinder::DeathRecipient*>(this));
- if (status != NO_ERROR) {
- ALOGE("connect(P): linkToDeath failed: %s (%d)",
- strerror(-status), status);
- }
- }
- mCore->mConnectedProducerListener = listener;
- break;
- default:
- ALOGE("connect(P): unknown API %d", api);
- status = BAD_VALUE;
- break;
- }
-
- mCore->mBufferHasBeenQueued = false;
- mCore->mDequeueBufferCannotBlock =
- mCore->mConsumerControlledByApp && producerControlledByApp;
-
- return status;
-}
-
-status_t GonkBufferQueueProducer::disconnect(int api) {
- ATRACE_CALL();
- ALOGV("disconnect(P): api %d", api);
-
- int status = NO_ERROR;
- sp<IConsumerListener> listener;
- { // Autolock scope
- Mutex::Autolock lock(mCore->mMutex);
- mCore->waitWhileAllocatingLocked();
-
- if (mCore->mIsAbandoned) {
- // It's not really an error to disconnect after the surface has
- // been abandoned; it should just be a no-op.
- return NO_ERROR;
- }
-
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mCore->mConnectedApi == api) {
- mCore->freeAllBuffersLocked();
- mCore->mConnectedApi = GonkBufferQueueCore::NO_CONNECTED_API;
- mCore->mSidebandStream.clear();
- mCore->mDequeueCondition.broadcast();
- listener = mCore->mConsumerListener;
- } else {
- ALOGE("disconnect(P): connected to another API "
- "(cur=%d req=%d)", mCore->mConnectedApi, api);
- status = BAD_VALUE;
- }
- break;
- default:
- ALOGE("disconnect(P): unknown API %d", api);
- status = BAD_VALUE;
- break;
- }
- } // Autolock scope
-
- // Call back without lock held
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return status;
-}
-
-status_t GonkBufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
- return INVALID_OPERATION;
-}
-
-void GonkBufferQueueProducer::allocateBuffers(bool async, uint32_t width,
- uint32_t height, uint32_t format, uint32_t usage) {
- ALOGE("allocateBuffers: no op");
-}
-
-void GonkBufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
- // If we're here, it means that a producer we were connected to died.
- // We're guaranteed that we are still connected to it because we remove
- // this callback upon disconnect. It's therefore safe to read mConnectedApi
- // without synchronization here.
- int api = mCore->mConnectedApi;
- disconnect(api);
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h
deleted file mode 100644
index a1a22416a..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKBUFFERQUEUEPRODUCER_LL_H
-#define NATIVEWINDOW_GONKBUFFERQUEUEPRODUCER_LL_H
-
-#include "GonkBufferQueueDefs.h"
-#include <gui/IGraphicBufferProducer.h>
-
-namespace android {
-
-class GonkBufferQueueProducer : public BnGraphicBufferProducer,
- private IBinder::DeathRecipient {
-public:
- friend class GonkBufferQueue; // Needed to access binderDied
-
- GonkBufferQueueProducer(const sp<GonkBufferQueueCore>& core);
- virtual ~GonkBufferQueueProducer();
-
- // requestBuffer returns the GraphicBuffer for slot N.
- //
- // In normal operation, this is called the first time slot N is returned
- // by dequeueBuffer. It must be called again if dequeueBuffer returns
- // flags indicating that previously-returned buffers are no longer valid.
- virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
-
- // setBufferCount updates the number of available buffer slots. If this
- // method succeeds, buffer slots will be both unallocated and owned by
- // the GonkBufferQueue object (i.e. they are not owned by the producer or
- // consumer).
- //
- // This will fail if the producer has dequeued any buffers, or if
- // bufferCount is invalid. bufferCount must generally be a value
- // between the minimum undequeued buffer count (exclusive) and NUM_BUFFER_SLOTS
- // (inclusive). It may also be set to zero (the default) to indicate
- // that the producer does not wish to set a value. The minimum value
- // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
- // ...).
- //
- // This may only be called by the producer. The consumer will be told
- // to discard buffers through the onBuffersReleased callback.
- virtual status_t setBufferCount(int bufferCount);
-
- // dequeueBuffer gets the next buffer slot index for the producer to use.
- // If a buffer slot is available then that slot index is written to the
- // location pointed to by the buf argument and a status of OK is returned.
- // If no slot is available then a status of -EBUSY is returned and buf is
- // unmodified.
- //
- // The outFence parameter will be updated to hold the fence associated with
- // the buffer. The contents of the buffer must not be overwritten until the
- // fence signals. If the fence is Fence::NO_FENCE, the buffer may be
- // written immediately.
- //
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called. If width and height are both zero, the
- // default values specified by setDefaultBufferSize() are used instead.
- //
- // The pixel formats are enumerated in graphics.h, e.g.
- // HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format
- // will be used.
- //
- // The usage argument specifies gralloc buffer usage flags. The values
- // are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER. These
- // will be merged with the usage flags specified by setConsumerUsageBits.
- //
- // The return value may be a negative error value or a non-negative
- // collection of flags. If the flags are set, the return values are
- // valid, but additional actions must be performed.
- //
- // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the
- // producer must discard cached GraphicBuffer references for the slot
- // returned in buf.
- // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer
- // must discard cached GraphicBuffer references for all slots.
- //
- // In both cases, the producer will need to call requestBuffer to get a
- // GraphicBuffer handle for the returned slot.
- virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence, bool async,
- uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
-
- // See IGraphicBufferProducer::detachBuffer
- virtual status_t detachBuffer(int slot);
-
- // See IGraphicBufferProducer::detachNextBuffer
- virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence);
-
- // See IGraphicBufferProducer::attachBuffer
- virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer);
-
- // queueBuffer returns a filled buffer to the GonkBufferQueue.
- //
- // Additional data is provided in the QueueBufferInput struct. Notably,
- // a timestamp must be provided for the buffer. The timestamp is in
- // nanoseconds, and must be monotonically increasing. Its other semantics
- // (zero point, etc) are producer-specific and should be documented by the
- // producer.
- //
- // The caller may provide a fence that signals when all rendering
- // operations have completed. Alternatively, NO_FENCE may be used,
- // indicating that the buffer is ready immediately.
- //
- // Some values are returned in the output struct: the current settings
- // for default width and height, the current transform hint, and the
- // number of queued buffers.
- virtual status_t queueBuffer(int slot,
- const QueueBufferInput& input, QueueBufferOutput* output);
-
- // cancelBuffer returns a dequeued buffer to the GonkBufferQueue, but doesn't
- // queue it for use by the consumer.
- //
- // The buffer will not be overwritten until the fence signals. The fence
- // will usually be the one obtained from dequeueBuffer.
- virtual void cancelBuffer(int slot, const sp<Fence>& fence);
-
- // Query native window attributes. The "what" values are enumerated in
- // window.h (e.g. NATIVE_WINDOW_FORMAT).
- virtual int query(int what, int* outValue);
-
- // connect attempts to connect a producer API to the GonkBufferQueue. This
- // must be called before any other IGraphicBufferProducer methods are
- // called except for getAllocator. A consumer must already be connected.
- //
- // This method will fail if connect was previously called on the
- // GonkBufferQueue and no corresponding disconnect call was made (i.e. if
- // it's still connected to a producer).
- //
- // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU).
- virtual status_t connect(const sp<IProducerListener>& listener,
- int api, bool producerControlledByApp, QueueBufferOutput* output);
-
- // disconnect attempts to disconnect a producer API from the GonkBufferQueue.
- // Calling this method will cause any subsequent calls to other
- // IGraphicBufferProducer methods to fail except for getAllocator and connect.
- // Successfully calling connect after this will allow the other methods to
- // succeed again.
- //
- // This method will fail if the the GonkBufferQueue is not currently
- // connected to the specified producer API.
- virtual status_t disconnect(int api);
-
- // Attaches a sideband buffer stream to the IGraphicBufferProducer.
- //
- // A sideband stream is a device-specific mechanism for passing buffers
- // from the producer to the consumer without using dequeueBuffer/
- // queueBuffer. If a sideband stream is present, the consumer can choose
- // whether to acquire buffers from the sideband stream or from the queued
- // buffers.
- //
- // Passing NULL or a different stream handle will detach the previous
- // handle if any.
- virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
-
- // See IGraphicBufferProducer::allocateBuffers
- virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage);
-
- // setSynchronousMode sets whether dequeueBuffer is synchronous or
- // asynchronous. In synchronous mode, dequeueBuffer blocks until
- // a buffer is available, the currently bound buffer can be dequeued and
- // queued buffers will be acquired in order. In asynchronous mode,
- // a queued buffer may be replaced by a subsequently queued buffer.
- //
- // The default mode is synchronous.
- // This should be called only during initialization.
- virtual status_t setSynchronousMode(bool enabled);
-
-private:
- // This is required by the IBinder::DeathRecipient interface
- virtual void binderDied(const wp<IBinder>& who);
-
- // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may
- // block if there are no available slots and we are not in non-blocking
- // mode (producer and consumer controlled by the application). If it blocks,
- // it will release mCore->mMutex while blocked so that other operations on
- // the GonkBufferQueue may succeed.
- status_t waitForFreeSlotThenRelock(const char* caller, bool async,
- int* found, status_t* returnFlags) const;
-
- sp<GonkBufferQueueCore> mCore;
-
- // This references mCore->mSlots. Lock mCore->mMutex while accessing.
- GonkBufferQueueDefs::SlotsType& mSlots;
-
- // This is a cached copy of the name stored in the GonkBufferQueueCore.
- // It's updated during connect and dequeueBuffer (which should catch
- // most updates).
- String8 mConsumerName;
-
- // mSynchronousMode whether we're in synchronous mode or not
- bool mSynchronousMode;
-
- uint32_t mStickyTransform;
-
-}; // class GonkBufferQueueProducer
-
-} // namespace android
-
-#endif
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp
deleted file mode 100644
index 9e4a424a9..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "GonkBufferSlot.h"
-
-namespace android {
-
-const char* GonkBufferSlot::bufferStateName(BufferState state) {
- switch (state) {
- case GonkBufferSlot::DEQUEUED: return "DEQUEUED";
- case GonkBufferSlot::QUEUED: return "QUEUED";
- case GonkBufferSlot::FREE: return "FREE";
- case GonkBufferSlot::ACQUIRED: return "ACQUIRED";
- default: return "Unknown";
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h
deleted file mode 100644
index 759bb7b23..000000000
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferSlot.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKBUFFERSLOT_LL_H
-#define NATIVEWINDOW_GONKBUFFERSLOT_LL_H
-
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-
-#include <utils/StrongPointer.h>
-
-#include "mozilla/layers/TextureClient.h"
-
-namespace android {
-
-struct GonkBufferSlot {
- typedef mozilla::layers::TextureClient TextureClient;
-
- GonkBufferSlot()
- : mBufferState(GonkBufferSlot::FREE),
- mRequestBufferCalled(false),
- mFrameNumber(0),
- mAcquireCalled(false),
- mNeedsCleanupOnRelease(false),
- mAttachedByConsumer(false) {
- }
-
- // mGraphicBuffer points to the buffer allocated for this slot or is NULL
- // if no buffer has been allocated.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // BufferState represents the different states in which a buffer slot
- // can be. All slots are initially FREE.
- enum BufferState {
- // FREE indicates that the buffer is available to be dequeued
- // by the producer. The buffer may be in use by the consumer for
- // a finite time, so the buffer must not be modified until the
- // associated fence is signaled.
- //
- // The slot is "owned" by BufferQueue. It transitions to DEQUEUED
- // when dequeueBuffer is called.
- FREE = 0,
-
- // DEQUEUED indicates that the buffer has been dequeued by the
- // producer, but has not yet been queued or canceled. The
- // producer may modify the buffer's contents as soon as the
- // associated ready fence is signaled.
- //
- // The slot is "owned" by the producer. It can transition to
- // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
- DEQUEUED = 1,
-
- // QUEUED indicates that the buffer has been filled by the
- // producer and queued for use by the consumer. The buffer
- // contents may continue to be modified for a finite time, so
- // the contents must not be accessed until the associated fence
- // is signaled.
- //
- // The slot is "owned" by BufferQueue. It can transition to
- // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
- // queued in asynchronous mode).
- QUEUED = 2,
-
- // ACQUIRED indicates that the buffer has been acquired by the
- // consumer. As with QUEUED, the contents must not be accessed
- // by the consumer until the fence is signaled.
- //
- // The slot is "owned" by the consumer. It transitions to FREE
- // when releaseBuffer is called.
- ACQUIRED = 3
- };
-
- static const char* bufferStateName(BufferState state);
-
- // mBufferState is the current state of this buffer slot.
- BufferState mBufferState;
-
- // mRequestBufferCalled is used for validating that the producer did
- // call requestBuffer() when told to do so. Technically this is not
- // needed but useful for debugging and catching producer bugs.
- bool mRequestBufferCalled;
-
- // mFrameNumber is the number of the queued frame for this slot. This
- // is used to dequeue buffers in LRU order (useful because buffers
- // may be released before their release fence is signaled).
- uint64_t mFrameNumber;
-
- // mFence is a fence which will signal when work initiated by the
- // previous owner of the buffer is finished. When the buffer is FREE,
- // the fence indicates when the consumer has finished reading
- // from the buffer, or when the producer has finished writing if it
- // called cancelBuffer after queueing some writes. When the buffer is
- // QUEUED, it indicates when the producer has finished filling the
- // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
- // passed to the consumer or producer along with ownership of the
- // buffer, and mFence is set to NO_FENCE.
- sp<Fence> mFence;
-
- // Indicates whether this buffer has been seen by a consumer yet
- bool mAcquireCalled;
-
- // Indicates whether this buffer needs to be cleaned up by the
- // consumer. This is set when a buffer in ACQUIRED state is freed.
- // It causes releaseBuffer to return STALE_BUFFER_SLOT.
- bool mNeedsCleanupOnRelease;
-
- // Indicates whether the buffer was attached on the consumer side.
- // If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when dequeued
- // to prevent the producer from using a stale cached buffer.
- bool mAttachedByConsumer;
-
- // mTextureClient is a thin abstraction over remotely allocated GraphicBuffer.
- RefPtr<TextureClient> mTextureClient;
-};
-
-} // namespace android
-
-#endif
diff --git a/widget/gonk/nativewindow/GonkConsumerBaseJB.cpp b/widget/gonk/nativewindow/GonkConsumerBaseJB.cpp
deleted file mode 100644
index 1ee37e4e2..000000000
--- a/widget/gonk/nativewindow/GonkConsumerBaseJB.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "GonkConsumerBase"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <hardware/hardware.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "GonkConsumerBaseJB.h"
-
-// Macros for including the GonkConsumerBase name in log messages
-#define CB_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#define CB_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-#define CB_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-#define CB_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
-#define CB_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-
-namespace android {
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-GonkConsumerBase::GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue) :
- mAbandoned(false),
- mBufferQueue(bufferQueue) {
- // Choose a name using the PID and a process-unique ID.
- mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
- // Note that we can't create an sp<...>(this) in a ctor that will not keep a
- // reference once the ctor ends, as that would cause the refcount of 'this'
- // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
- // that's what we create.
- wp<GonkBufferQueue::ConsumerListener> listener;
- sp<GonkBufferQueue::ConsumerListener> proxy;
- listener = static_cast<GonkBufferQueue::ConsumerListener*>(this);
- proxy = new GonkBufferQueue::ProxyConsumerListener(listener);
-
- status_t err = mBufferQueue->consumerConnect(proxy);
- if (err != NO_ERROR) {
- CB_LOGE("GonkConsumerBase: error connecting to GonkBufferQueue: %s (%d)",
- strerror(-err), err);
- } else {
- mBufferQueue->setConsumerName(mName);
- }
-}
-
-GonkConsumerBase::~GonkConsumerBase() {
- CB_LOGV("~GonkConsumerBase");
- Mutex::Autolock lock(mMutex);
-
- // Verify that abandon() has been called before we get here. This should
- // be done by GonkConsumerBase::onLastStrongRef(), but it's possible for a
- // derived class to override that method and not call
- // GonkConsumerBase::onLastStrongRef().
- LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~GonkConsumerBase was called, but the "
- "consumer is not abandoned!", mName.string());
-}
-
-void GonkConsumerBase::onLastStrongRef(const void* id) {
- abandon();
-}
-
-void GonkConsumerBase::freeBufferLocked(int slotIndex) {
- CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
- mSlots[slotIndex].mGraphicBuffer = 0;
- mSlots[slotIndex].mFence = Fence::NO_FENCE;
-}
-
-// Used for refactoring, should not be in final interface
-sp<GonkBufferQueue> GonkConsumerBase::getBufferQueue() const {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue;
-}
-
-void GonkConsumerBase::onFrameAvailable() {
- CB_LOGV("onFrameAvailable");
-
- sp<FrameAvailableListener> listener;
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
-#if ANDROID_VERSION == 17
- listener = mFrameAvailableListener;
-#else
- listener = mFrameAvailableListener.promote();
-#endif
- }
-
- if (listener != NULL) {
- CB_LOGV("actually calling onFrameAvailable");
- listener->onFrameAvailable();
- }
-}
-
-void GonkConsumerBase::onBuffersReleased() {
- Mutex::Autolock lock(mMutex);
-
- CB_LOGV("onBuffersReleased");
-
- if (mAbandoned) {
- // Nothing to do if we're already abandoned.
- return;
- }
-
- uint32_t mask = 0;
- mBufferQueue->getReleasedBuffers(&mask);
- for (int i = 0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
- if (mask & (1 << i)) {
- freeBufferLocked(i);
- }
- }
-}
-
-void GonkConsumerBase::abandon() {
- CB_LOGV("abandon");
- Mutex::Autolock lock(mMutex);
-
- if (!mAbandoned) {
- abandonLocked();
- mAbandoned = true;
- }
-}
-
-void GonkConsumerBase::abandonLocked() {
- CB_LOGV("abandonLocked");
- for (int i =0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
- // disconnect from the GonkBufferQueue
- mBufferQueue->consumerDisconnect();
- mBufferQueue.clear();
-}
-
-void GonkConsumerBase::setFrameAvailableListener(
-#if ANDROID_VERSION == 17
- const sp<FrameAvailableListener>& listener) {
-#else
- const wp<FrameAvailableListener>& listener) {
-#endif
- CB_LOGV("setFrameAvailableListener");
- Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = listener;
-}
-
-void GonkConsumerBase::dump(String8& result) const {
- char buffer[1024];
- dump(result, "", buffer, 1024);
-}
-
-void GonkConsumerBase::dump(String8& result, const char* prefix,
- char* buffer, size_t size) const {
- Mutex::Autolock _l(mMutex);
- dumpLocked(result, prefix, buffer, size);
-}
-
-void GonkConsumerBase::dumpLocked(String8& result, const char* prefix,
- char* buffer, size_t SIZE) const {
- snprintf(buffer, SIZE, "%smAbandoned=%d\n", prefix, int(mAbandoned));
- result.append(buffer);
-
- if (!mAbandoned) {
- mBufferQueue->dumpToString(result, prefix, buffer, SIZE);
- }
-}
-
-status_t GonkConsumerBase::acquireBufferLocked(GonkBufferQueue::BufferItem *item) {
- status_t err = mBufferQueue->acquireBuffer(item);
- if (err != NO_ERROR) {
- return err;
- }
-
- if (item->mGraphicBuffer != NULL) {
- mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
- }
-
- mSlots[item->mBuf].mFence = item->mFence;
-
- CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf);
-
- return OK;
-}
-
-status_t GonkConsumerBase::addReleaseFence(int slot, const sp<Fence>& fence) {
- Mutex::Autolock lock(mMutex);
- return addReleaseFenceLocked(slot, fence);
-}
-
-status_t GonkConsumerBase::addReleaseFenceLocked(int slot, const sp<Fence>& fence) {
- CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
-
- if (!mSlots[slot].mFence.get()) {
- mSlots[slot].mFence = fence;
- } else {
- sp<Fence> mergedFence = Fence::merge(
- String8::format("%.28s:%d", mName.string(), slot),
- mSlots[slot].mFence, fence);
- if (!mergedFence.get()) {
- CB_LOGE("failed to merge release fences");
- // synchronization is broken, the best we can do is hope fences
- // signal in order so the new fence will act like a union
- mSlots[slot].mFence = fence;
- return BAD_VALUE;
- }
- mSlots[slot].mFence = mergedFence;
- }
-
- return OK;
-}
-
-status_t GonkConsumerBase::releaseBufferLocked(int slot) {
- CB_LOGV("releaseBufferLocked: slot=%d", slot);
- status_t err = mBufferQueue->releaseBuffer(slot, mSlots[slot].mFence);
- if (err == GonkBufferQueue::STALE_BUFFER_SLOT) {
- freeBufferLocked(slot);
- }
-
- mSlots[slot].mFence = Fence::NO_FENCE;
-
- return err;
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkConsumerBaseJB.h b/widget/gonk/nativewindow/GonkConsumerBaseJB.h
deleted file mode 100644
index 8f523af37..000000000
--- a/widget/gonk/nativewindow/GonkConsumerBaseJB.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKCONSUMERBASE_JB_H
-#define NATIVEWINDOW_GONKCONSUMERBASE_JB_H
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#include "GonkBufferQueueJB.h"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class String8;
-
-// GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It
-// handles common tasks like management of the connection to the GonkBufferQueue
-// and the buffer pool.
-class GonkConsumerBase : public virtual RefBase,
- protected GonkBufferQueue::ConsumerListener {
-public:
- struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called each time an additional frame becomes
- // available for consumption. This means that frames that are queued
- // while in asynchronous mode only trigger the callback if no previous
- // frames are pending. Frames queued while in synchronous mode always
- // trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
- };
-
- virtual ~GonkConsumerBase();
-
- // abandon frees all the buffers and puts the GonkConsumerBase into the
- // 'abandoned' state. Once put in this state the GonkConsumerBase can never
- // leave it. When in the 'abandoned' state, all methods of the
- // IGraphicBufferProducer interface will fail with the NO_INIT error.
- //
- // Note that while calling this method causes all the buffers to be freed
- // from the perspective of the the GonkConsumerBase, if there are additional
- // references on the buffers (e.g. if a buffer is referenced by a client
- // or by OpenGL ES as a texture) then those buffer will remain allocated.
- void abandon();
-
- // set the name of the GonkConsumerBase that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // getBufferQueue returns the GonkBufferQueue object to which this
- // GonkConsumerBase is connected.
- sp<GonkBufferQueue> getBufferQueue() const;
-
- // dump writes the current state to a string. Child classes should add
- // their state to the dump by overriding the dumpLocked method, which is
- // called by these methods after locking the mutex.
- void dump(String8& result) const;
- void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
-
- // setFrameAvailableListener sets the listener object that will be notified
- // when a new frame becomes available.
-#if ANDROID_VERSION == 17
- void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
-#else
- void setFrameAvailableListener(const wp<FrameAvailableListener>& listener);
-#endif
-
-private:
- GonkConsumerBase(const GonkConsumerBase&);
- void operator=(const GonkConsumerBase&);
-
-protected:
-
- // GonkConsumerBase constructs a new GonkConsumerBase object to consume image
- // buffers from the given GonkBufferQueue.
- GonkConsumerBase(const sp<GonkBufferQueue> &bufferQueue);
-
- // onLastStrongRef gets called by RefBase just before the dtor of the most
- // derived class. It is used to clean up the buffers so that GonkConsumerBase
- // can coordinate the clean-up by calling into virtual methods implemented
- // by the derived classes. This would not be possible from the
- // ConsuemrBase dtor because by the time that gets called the derived
- // classes have already been destructed.
- //
- // This methods should not need to be overridden by derived classes, but
- // if they are overridden the GonkConsumerBase implementation must be called
- // from the derived class.
- virtual void onLastStrongRef(const void* id);
-
- // Implementation of the GonkBufferQueue::ConsumerListener interface. These
- // calls are used to notify the GonkConsumerBase of asynchronous events in the
- // GonkBufferQueue. These methods should not need to be overridden by derived
- // classes, but if they are overridden the GonkConsumerBase implementation
- // must be called from the derived class.
- virtual void onFrameAvailable();
- virtual void onBuffersReleased();
-
- // freeBufferLocked frees up the given buffer slot. If the slot has been
- // initialized this will release the reference to the GraphicBuffer in that
- // slot. Otherwise it has no effect.
- //
- // Derived classes should override this method to clean up any state they
- // keep per slot. If it is overridden, the derived class's implementation
- // must call GonkConsumerBase::freeBufferLocked.
- //
- // This method must be called with mMutex locked.
- virtual void freeBufferLocked(int slotIndex);
-
- // abandonLocked puts the GonkBufferQueue into the abandoned state, causing
- // all future operations on it to fail. This method rather than the public
- // abandon method should be overridden by child classes to add abandon-
- // time behavior.
- //
- // Derived classes should override this method to clean up any object
- // state they keep (as opposed to per-slot state). If it is overridden,
- // the derived class's implementation must call GonkConsumerBase::abandonLocked.
- //
- // This method must be called with mMutex locked.
- virtual void abandonLocked();
-
- // dumpLocked dumps the current state of the GonkConsumerBase object to the
- // result string. Each line is prefixed with the string pointed to by the
- // prefix argument. The buffer argument points to a buffer that may be
- // used for intermediate formatting data, and the size of that buffer is
- // indicated by the size argument.
- //
- // Derived classes should override this method to dump their internal
- // state. If this method is overridden the derived class's implementation
- // should call GonkConsumerBase::dumpLocked.
- //
- // This method must be called with mMutex locked.
- virtual void dumpLocked(String8& result, const char* prefix, char* buffer,
- size_t size) const;
-
- // acquireBufferLocked fetches the next buffer from the GonkBufferQueue and
- // updates the buffer slot for the buffer returned.
- //
- // Derived classes should override this method to perform any
- // initialization that must take place the first time a buffer is assigned
- // to a slot. If it is overridden the derived class's implementation must
- // call GonkConsumerBase::acquireBufferLocked.
- virtual status_t acquireBufferLocked(GonkBufferQueue::BufferItem *item);
-
- // releaseBufferLocked relinquishes control over a buffer, returning that
- // control to the GonkBufferQueue.
- //
- // Derived classes should override this method to perform any cleanup that
- // must take place when a buffer is released back to the GonkBufferQueue. If
- // it is overridden the derived class's implementation must call
- // GonkConsumerBase::releaseBufferLocked.
- virtual status_t releaseBufferLocked(int buf);
-
- // addReleaseFence* adds the sync points associated with a fence to the set
- // of sync points that must be reached before the buffer in the given slot
- // may be used after the slot has been released. This should be called by
- // derived classes each time some asynchronous work is kicked off that
- // references the buffer.
- status_t addReleaseFence(int slot, const sp<Fence>& fence);
- status_t addReleaseFenceLocked(int slot, const sp<Fence>& fence);
-
- // Slot contains the information and object references that
- // GonkConsumerBase maintains about a GonkBufferQueue buffer slot.
- struct Slot {
- // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if
- // no Gralloc buffer is in the slot.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mFence is a fence which will signal when the buffer associated with
- // this buffer slot is no longer being used by the consumer and can be
- // overwritten. The buffer can be dequeued before the fence signals;
- // the producer is responsible for delaying writes until it signals.
- sp<Fence> mFence;
- };
-
- // mSlots stores the buffers that have been allocated by the GonkBufferQueue
- // for each buffer slot. It is initialized to null pointers, and gets
- // filled in with the result of GonkBufferQueue::acquire when the
- // client dequeues a buffer from a
- // slot that has not yet been used. The buffer allocated to a slot will also
- // be replaced if the requested buffer usage or geometry differs from that
- // of the buffer allocated to a slot.
- Slot mSlots[GonkBufferQueue::NUM_BUFFER_SLOTS];
-
- // mAbandoned indicates that the GonkBufferQueue will no longer be used to
- // consume images buffers pushed to it using the IGraphicBufferProducer
- // interface. It is initialized to false, and set to true in the abandon
- // method. A GonkBufferQueue that has been abandoned will return the NO_INIT
- // error from all IGonkConsumerBase methods capable of returning an error.
- bool mAbandoned;
-
- // mName is a string used to identify the GonkConsumerBase in log messages.
- // It can be set by the setName method.
- String8 mName;
-
- // mFrameAvailableListener is the listener object that will be called when a
- // new frame becomes available. If it is not NULL it will be called from
- // queueBuffer.
-#if ANDROID_VERSION == 17
- sp<FrameAvailableListener> mFrameAvailableListener;
-#else
- wp<FrameAvailableListener> mFrameAvailableListener;
-#endif
-
- // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object
- // if none is supplied
- sp<GonkBufferQueue> mBufferQueue;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of GonkConsumerBase objects. It must be locked whenever the
- // member variables are accessed or when any of the *Locked methods are
- // called.
- //
- // This mutex is intended to be locked by derived classes.
- mutable Mutex mMutex;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // NATIVEWINDOW_GONKCONSUMERBASE_H
diff --git a/widget/gonk/nativewindow/GonkConsumerBaseKK.cpp b/widget/gonk/nativewindow/GonkConsumerBaseKK.cpp
deleted file mode 100644
index 3fc9fc16c..000000000
--- a/widget/gonk/nativewindow/GonkConsumerBaseKK.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "GonkConsumerBase"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <hardware/hardware.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "GonkConsumerBaseKK.h"
-
-namespace android {
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-GonkConsumerBase::GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue, bool controlledByApp) :
- mAbandoned(false),
- mConsumer(bufferQueue) {
- // Choose a name using the PID and a process-unique ID.
- mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
- // Note that we can't create an sp<...>(this) in a ctor that will not keep a
- // reference once the ctor ends, as that would cause the refcount of 'this'
- // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
- // that's what we create.
- wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
- sp<IConsumerListener> proxy = new GonkBufferQueue::ProxyConsumerListener(listener);
-
- status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
- if (err != NO_ERROR) {
- ALOGE("GonkConsumerBase: error connecting to GonkBufferQueue: %s (%d)",
- strerror(-err), err);
- } else {
- mConsumer->setConsumerName(mName);
- }
-}
-
-GonkConsumerBase::~GonkConsumerBase() {
- ALOGV("~GonkConsumerBase");
- Mutex::Autolock lock(mMutex);
-
- // Verify that abandon() has been called before we get here. This should
- // be done by GonkConsumerBase::onLastStrongRef(), but it's possible for a
- // derived class to override that method and not call
- // GonkConsumerBase::onLastStrongRef().
- LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~GonkConsumerBase was called, but the "
- "consumer is not abandoned!", mName.string());
-}
-
-void GonkConsumerBase::onLastStrongRef(const void* id) {
- abandon();
-}
-
-void GonkConsumerBase::freeBufferLocked(int slotIndex) {
- ALOGV("freeBufferLocked: slotIndex=%d", slotIndex);
- mSlots[slotIndex].mGraphicBuffer = 0;
- mSlots[slotIndex].mFence = Fence::NO_FENCE;
- mSlots[slotIndex].mFrameNumber = 0;
-}
-
-// Used for refactoring, should not be in final interface
-sp<GonkBufferQueue> GonkConsumerBase::getBufferQueue() const {
- Mutex::Autolock lock(mMutex);
- return mConsumer;
-}
-
-void GonkConsumerBase::onFrameAvailable() {
- ALOGV("onFrameAvailable");
-
- sp<FrameAvailableListener> listener;
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- listener = mFrameAvailableListener.promote();
- }
-
- if (listener != NULL) {
- ALOGV("actually calling onFrameAvailable");
- listener->onFrameAvailable();
- }
-}
-
-void GonkConsumerBase::onBuffersReleased() {
- Mutex::Autolock lock(mMutex);
-
- ALOGV("onBuffersReleased");
-
- if (mAbandoned) {
- // Nothing to do if we're already abandoned.
- return;
- }
-
- uint32_t mask = 0;
- mConsumer->getReleasedBuffers(&mask);
- for (int i = 0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
- if (mask & (1 << i)) {
- freeBufferLocked(i);
- }
- }
-}
-
-void GonkConsumerBase::abandon() {
- ALOGV("abandon");
- Mutex::Autolock lock(mMutex);
-
- if (!mAbandoned) {
- abandonLocked();
- mAbandoned = true;
- }
-}
-
-void GonkConsumerBase::abandonLocked() {
- ALOGV("abandonLocked");
- for (int i =0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
- // disconnect from the BufferQueue
- mConsumer->consumerDisconnect();
- mConsumer.clear();
-}
-
-void GonkConsumerBase::setFrameAvailableListener(
- const wp<FrameAvailableListener>& listener) {
- ALOGV("setFrameAvailableListener");
- Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = listener;
-}
-
-void GonkConsumerBase::dump(String8& result) const {
- dump(result, "");
-}
-
-void GonkConsumerBase::dump(String8& result, const char* prefix) const {
- Mutex::Autolock _l(mMutex);
- dumpLocked(result, prefix);
-}
-
-void GonkConsumerBase::dumpLocked(String8& result, const char* prefix) const {
- result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
-
- if (!mAbandoned) {
- mConsumer->dumpToString(result, prefix);
- }
-}
-
-status_t GonkConsumerBase::acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item,
- nsecs_t presentWhen) {
- status_t err = mConsumer->acquireBuffer(item, presentWhen);
- if (err != NO_ERROR) {
- return err;
- }
-
- if (item->mGraphicBuffer != NULL) {
- mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
- }
-
- mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
- mSlots[item->mBuf].mFence = item->mFence;
-
- ALOGV("acquireBufferLocked: -> slot=%d", item->mBuf);
-
- return OK;
-}
-
-status_t GonkConsumerBase::addReleaseFence(int slot,
- const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
- Mutex::Autolock lock(mMutex);
- return addReleaseFenceLocked(slot, graphicBuffer, fence);
-}
-
-status_t GonkConsumerBase::addReleaseFenceLocked(int slot,
- const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
- ALOGV("addReleaseFenceLocked: slot=%d", slot);
-
- // If consumer no longer tracks this graphicBuffer, we can safely
- // drop this fence, as it will never be received by the producer.
- if (!stillTracking(slot, graphicBuffer)) {
- return OK;
- }
-
- if (!mSlots[slot].mFence.get()) {
- mSlots[slot].mFence = fence;
- } else {
- sp<Fence> mergedFence = Fence::merge(
- String8::format("%.28s:%d", mName.string(), slot),
- mSlots[slot].mFence, fence);
- if (!mergedFence.get()) {
- ALOGE("failed to merge release fences");
- // synchronization is broken, the best we can do is hope fences
- // signal in order so the new fence will act like a union
- mSlots[slot].mFence = fence;
- return BAD_VALUE;
- }
- mSlots[slot].mFence = mergedFence;
- }
-
- return OK;
-}
-
-status_t GonkConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) {
- // If consumer no longer tracks this graphicBuffer (we received a new
- // buffer on the same slot), the buffer producer is definitely no longer
- // tracking it.
- if (!stillTracking(slot, graphicBuffer)) {
- return OK;
- }
-
- ALOGV("releaseBufferLocked: slot=%d/%llu",
- slot, mSlots[slot].mFrameNumber);
- status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence);
- if (err == GonkBufferQueue::STALE_BUFFER_SLOT) {
- freeBufferLocked(slot);
- }
-
- mSlots[slot].mFence = Fence::NO_FENCE;
-
- return err;
-}
-
-bool GonkConsumerBase::stillTracking(int slot,
- const sp<GraphicBuffer> graphicBuffer) {
- if (slot < 0 || slot >= GonkBufferQueue::NUM_BUFFER_SLOTS) {
- return false;
- }
- return (mSlots[slot].mGraphicBuffer != NULL &&
- mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkConsumerBaseKK.h b/widget/gonk/nativewindow/GonkConsumerBaseKK.h
deleted file mode 100644
index e198ad843..000000000
--- a/widget/gonk/nativewindow/GonkConsumerBaseKK.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKCONSUMERBASE_KK_H
-#define NATIVEWINDOW_GONKCONSUMERBASE_KK_H
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-#include <gui/IConsumerListener.h>
-
-#include "GonkBufferQueueKK.h"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class String8;
-
-// GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It
-// handles common tasks like management of the connection to the GonkBufferQueue
-// and the buffer pool.
-class GonkConsumerBase : public virtual RefBase,
- protected ConsumerListener {
-public:
- struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called each time an additional frame becomes
- // available for consumption. This means that frames that are queued
- // while in asynchronous mode only trigger the callback if no previous
- // frames are pending. Frames queued while in synchronous mode always
- // trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
- };
-
- virtual ~GonkConsumerBase();
-
- // abandon frees all the buffers and puts the GonkConsumerBase into the
- // 'abandoned' state. Once put in this state the GonkConsumerBase can never
- // leave it. When in the 'abandoned' state, all methods of the
- // IGraphicBufferProducer interface will fail with the NO_INIT error.
- //
- // Note that while calling this method causes all the buffers to be freed
- // from the perspective of the the GonkConsumerBase, if there are additional
- // references on the buffers (e.g. if a buffer is referenced by a client
- // or by OpenGL ES as a texture) then those buffer will remain allocated.
- void abandon();
-
- // set the name of the GonkConsumerBase that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // getBufferQueue returns the GonkBufferQueue object to which this
- // GonkConsumerBase is connected.
- sp<GonkBufferQueue> getBufferQueue() const;
-
- // dump writes the current state to a string. Child classes should add
- // their state to the dump by overriding the dumpLocked method, which is
- // called by these methods after locking the mutex.
- void dump(String8& result) const;
- void dump(String8& result, const char* prefix) const;
-
- // setFrameAvailableListener sets the listener object that will be notified
- // when a new frame becomes available.
- void setFrameAvailableListener(const wp<FrameAvailableListener>& listener);
-
-private:
- GonkConsumerBase(const GonkConsumerBase&);
- void operator=(const GonkConsumerBase&);
-
-protected:
-
- // GonkConsumerBase constructs a new GonkConsumerBase object to consume image
- // buffers from the given GonkBufferQueue.
- GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue, bool controlledByApp = false);
-
- // onLastStrongRef gets called by RefBase just before the dtor of the most
- // derived class. It is used to clean up the buffers so that GonkConsumerBase
- // can coordinate the clean-up by calling into virtual methods implemented
- // by the derived classes. This would not be possible from the
- // ConsuemrBase dtor because by the time that gets called the derived
- // classes have already been destructed.
- //
- // This methods should not need to be overridden by derived classes, but
- // if they are overridden the GonkConsumerBase implementation must be called
- // from the derived class.
- virtual void onLastStrongRef(const void* id);
-
- // Implementation of the GonkBufferQueue::ConsumerListener interface. These
- // calls are used to notify the GonkConsumerBase of asynchronous events in the
- // GonkBufferQueue. These methods should not need to be overridden by derived
- // classes, but if they are overridden the GonkConsumerBase implementation
- // must be called from the derived class.
- virtual void onFrameAvailable();
- virtual void onBuffersReleased();
-
- // freeBufferLocked frees up the given buffer slot. If the slot has been
- // initialized this will release the reference to the GraphicBuffer in that
- // slot. Otherwise it has no effect.
- //
- // Derived classes should override this method to clean up any state they
- // keep per slot. If it is overridden, the derived class's implementation
- // must call GonkConsumerBase::freeBufferLocked.
- //
- // This method must be called with mMutex locked.
- virtual void freeBufferLocked(int slotIndex);
-
- // abandonLocked puts the GonkBufferQueue into the abandoned state, causing
- // all future operations on it to fail. This method rather than the public
- // abandon method should be overridden by child classes to add abandon-
- // time behavior.
- //
- // Derived classes should override this method to clean up any object
- // state they keep (as opposed to per-slot state). If it is overridden,
- // the derived class's implementation must call GonkConsumerBase::abandonLocked.
- //
- // This method must be called with mMutex locked.
- virtual void abandonLocked();
-
- // dumpLocked dumps the current state of the GonkConsumerBase object to the
- // result string. Each line is prefixed with the string pointed to by the
- // prefix argument. The buffer argument points to a buffer that may be
- // used for intermediate formatting data, and the size of that buffer is
- // indicated by the size argument.
- //
- // Derived classes should override this method to dump their internal
- // state. If this method is overridden the derived class's implementation
- // should call GonkConsumerBase::dumpLocked.
- //
- // This method must be called with mMutex locked.
- virtual void dumpLocked(String8& result, const char* prefix) const;
-
- // acquireBufferLocked fetches the next buffer from the GonkBufferQueue and
- // updates the buffer slot for the buffer returned.
- //
- // Derived classes should override this method to perform any
- // initialization that must take place the first time a buffer is assigned
- // to a slot. If it is overridden the derived class's implementation must
- // call GonkConsumerBase::acquireBufferLocked.
- virtual status_t acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item,
- nsecs_t presentWhen);
-
- // releaseBufferLocked relinquishes control over a buffer, returning that
- // control to the GonkBufferQueue.
- //
- // Derived classes should override this method to perform any cleanup that
- // must take place when a buffer is released back to the GonkBufferQueue. If
- // it is overridden the derived class's implementation must call
- // GonkConsumerBase::releaseBufferLocked.
- virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer);
-
- // returns true iff the slot still has the graphicBuffer in it.
- bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
-
- // addReleaseFence* adds the sync points associated with a fence to the set
- // of sync points that must be reached before the buffer in the given slot
- // may be used after the slot has been released. This should be called by
- // derived classes each time some asynchronous work is kicked off that
- // references the buffer.
- status_t addReleaseFence(int slot,
- const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence);
- status_t addReleaseFenceLocked(int slot,
- const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence);
-
- // Slot contains the information and object references that
- // GonkConsumerBase maintains about a GonkBufferQueue buffer slot.
- struct Slot {
- // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if
- // no Gralloc buffer is in the slot.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mFence is a fence which will signal when the buffer associated with
- // this buffer slot is no longer being used by the consumer and can be
- // overwritten. The buffer can be dequeued before the fence signals;
- // the producer is responsible for delaying writes until it signals.
- sp<Fence> mFence;
-
- // the frame number of the last acquired frame for this slot
- uint64_t mFrameNumber;
- };
-
- // mSlots stores the buffers that have been allocated by the GonkBufferQueue
- // for each buffer slot. It is initialized to null pointers, and gets
- // filled in with the result of GonkBufferQueue::acquire when the
- // client dequeues a buffer from a
- // slot that has not yet been used. The buffer allocated to a slot will also
- // be replaced if the requested buffer usage or geometry differs from that
- // of the buffer allocated to a slot.
- Slot mSlots[GonkBufferQueue::NUM_BUFFER_SLOTS];
-
- // mAbandoned indicates that the GonkBufferQueue will no longer be used to
- // consume images buffers pushed to it using the IGraphicBufferProducer
- // interface. It is initialized to false, and set to true in the abandon
- // method. A GonkBufferQueue that has been abandoned will return the NO_INIT
- // error from all IGonkConsumerBase methods capable of returning an error.
- bool mAbandoned;
-
- // mName is a string used to identify the GonkConsumerBase in log messages.
- // It can be set by the setName method.
- String8 mName;
-
- // mFrameAvailableListener is the listener object that will be called when a
- // new frame becomes available. If it is not NULL it will be called from
- // queueBuffer.
- wp<FrameAvailableListener> mFrameAvailableListener;
-
- // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object
- // if none is supplied
- sp<GonkBufferQueue> mConsumer;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of GonkConsumerBase objects. It must be locked whenever the
- // member variables are accessed or when any of the *Locked methods are
- // called.
- //
- // This mutex is intended to be locked by derived classes.
- mutable Mutex mMutex;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // NATIVEWINDOW_GONKCONSUMERBASE_H
diff --git a/widget/gonk/nativewindow/GonkConsumerBaseLL.cpp b/widget/gonk/nativewindow/GonkConsumerBaseLL.cpp
deleted file mode 100644
index 5b1166b57..000000000
--- a/widget/gonk/nativewindow/GonkConsumerBaseLL.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <inttypes.h>
-
-#define LOG_TAG "GonkConsumerBase"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <hardware/hardware.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "GonkConsumerBaseLL.h"
-
-namespace android {
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-GonkConsumerBase::GonkConsumerBase(const sp<IGonkGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
- mAbandoned(false),
- mConsumer(bufferQueue) {
- // Choose a name using the PID and a process-unique ID.
- mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
- // Note that we can't create an sp<...>(this) in a ctor that will not keep a
- // reference once the ctor ends, as that would cause the refcount of 'this'
- // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
- // that's what we create.
- wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
- sp<IConsumerListener> proxy = new GonkBufferQueue::ProxyConsumerListener(listener);
-
- status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
- if (err != NO_ERROR) {
- ALOGE("GonkConsumerBase: error connecting to GonkBufferQueue: %s (%d)",
- strerror(-err), err);
- } else {
- mConsumer->setConsumerName(mName);
- }
-}
-
-GonkConsumerBase::~GonkConsumerBase() {
- ALOGV("~GonkConsumerBase");
- Mutex::Autolock lock(mMutex);
-
- // Verify that abandon() has been called before we get here. This should
- // be done by GonkConsumerBase::onLastStrongRef(), but it's possible for a
- // derived class to override that method and not call
- // GonkConsumerBase::onLastStrongRef().
- LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~GonkConsumerBase was called, but the "
- "consumer is not abandoned!", mName.string());
-}
-
-void GonkConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) {
- abandon();
-}
-
-void GonkConsumerBase::freeBufferLocked(int slotIndex) {
- ALOGV("freeBufferLocked: slotIndex=%d", slotIndex);
- mSlots[slotIndex].mGraphicBuffer = 0;
- mSlots[slotIndex].mFence = Fence::NO_FENCE;
- mSlots[slotIndex].mFrameNumber = 0;
-}
-
-#if ANDROID_VERSION == 21
-void GonkConsumerBase::onFrameAvailable() {
-#else
-void GonkConsumerBase::onFrameAvailable(const ::android::BufferItem& item) {
-#endif
- ALOGV("onFrameAvailable");
-
- sp<FrameAvailableListener> listener;
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- listener = mFrameAvailableListener.promote();
- }
-
- if (listener != NULL) {
- ALOGV("actually calling onFrameAvailable");
- listener->onFrameAvailable();
- }
-}
-
-void GonkConsumerBase::onBuffersReleased() {
- Mutex::Autolock lock(mMutex);
-
- ALOGV("onBuffersReleased");
-
- if (mAbandoned) {
- // Nothing to do if we're already abandoned.
- return;
- }
-
- uint64_t mask = 0;
- mConsumer->getReleasedBuffers(&mask);
- for (int i = 0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
- if (mask & (1ULL << i)) {
- freeBufferLocked(i);
- }
- }
-}
-
-void GonkConsumerBase::onSidebandStreamChanged() {
-}
-
-void GonkConsumerBase::abandon() {
- ALOGV("abandon");
- Mutex::Autolock lock(mMutex);
-
- if (!mAbandoned) {
- abandonLocked();
- mAbandoned = true;
- }
-}
-
-void GonkConsumerBase::abandonLocked() {
- ALOGV("abandonLocked");
- for (int i =0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
- // disconnect from the BufferQueue
- mConsumer->consumerDisconnect();
- mConsumer.clear();
-}
-
-void GonkConsumerBase::setFrameAvailableListener(
- const wp<FrameAvailableListener>& listener) {
- ALOGV("setFrameAvailableListener");
- Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = listener;
-}
-
-void GonkConsumerBase::dump(String8& result) const {
- dump(result, "");
-}
-
-void GonkConsumerBase::dump(String8& result, const char* prefix) const {
- Mutex::Autolock _l(mMutex);
- dumpLocked(result, prefix);
-}
-
-void GonkConsumerBase::dumpLocked(String8& result, const char* prefix) const {
- result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
-
- if (!mAbandoned) {
- mConsumer->dumpToString(result, prefix);
- }
-}
-
-status_t GonkConsumerBase::acquireBufferLocked(GonkBufferQueue::BufferItem *item,
- nsecs_t presentWhen) {
- status_t err = mConsumer->acquireBuffer(item, presentWhen);
- if (err != NO_ERROR) {
- return err;
- }
-
- if (item->mGraphicBuffer != NULL) {
- mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
- }
-
- mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
- mSlots[item->mBuf].mFence = item->mFence;
-
- ALOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
- item->mBuf, item->mFrameNumber);
-
- return OK;
-}
-
-status_t GonkConsumerBase::addReleaseFence(int slot,
- const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
- Mutex::Autolock lock(mMutex);
- return addReleaseFenceLocked(slot, graphicBuffer, fence);
-}
-
-status_t GonkConsumerBase::addReleaseFenceLocked(int slot,
- const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
- ALOGV("addReleaseFenceLocked: slot=%d", slot);
-
- // If consumer no longer tracks this graphicBuffer, we can safely
- // drop this fence, as it will never be received by the producer.
- if (!stillTracking(slot, graphicBuffer)) {
- return OK;
- }
-
- if (!mSlots[slot].mFence.get()) {
- mSlots[slot].mFence = fence;
- } else {
- sp<Fence> mergedFence = Fence::merge(
- String8::format("%.28s:%d", mName.string(), slot),
- mSlots[slot].mFence, fence);
- if (!mergedFence.get()) {
- ALOGE("failed to merge release fences");
- // synchronization is broken, the best we can do is hope fences
- // signal in order so the new fence will act like a union
- mSlots[slot].mFence = fence;
- return BAD_VALUE;
- }
- mSlots[slot].mFence = mergedFence;
- }
-
- return OK;
-}
-
-status_t GonkConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) {
- // If consumer no longer tracks this graphicBuffer (we received a new
- // buffer on the same slot), the buffer producer is definitely no longer
- // tracking it.
- if (!stillTracking(slot, graphicBuffer)) {
- return OK;
- }
-
- ALOGV("releaseBufferLocked: slot=%d/%" PRIu64,
- slot, mSlots[slot].mFrameNumber);
- status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence);
- if (err == IGonkGraphicBufferConsumer::STALE_BUFFER_SLOT) {
- freeBufferLocked(slot);
- }
-
- mSlots[slot].mFence = Fence::NO_FENCE;
-
- return err;
-}
-
-bool GonkConsumerBase::stillTracking(int slot,
- const sp<GraphicBuffer> graphicBuffer) {
- if (slot < 0 || slot >= GonkBufferQueue::NUM_BUFFER_SLOTS) {
- return false;
- }
- return (mSlots[slot].mGraphicBuffer != NULL &&
- mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkConsumerBaseLL.h b/widget/gonk/nativewindow/GonkConsumerBaseLL.h
deleted file mode 100644
index 0b2c2d166..000000000
--- a/widget/gonk/nativewindow/GonkConsumerBaseLL.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKCONSUMERBASE_LL_H
-#define NATIVEWINDOW_GONKCONSUMERBASE_LL_H
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-#include <gui/IConsumerListener.h>
-
-#include "GonkBufferQueueLL.h"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class String8;
-
-// GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It
-// handles common tasks like management of the connection to the GonkBufferQueue
-// and the buffer pool.
-class GonkConsumerBase : public virtual RefBase,
- protected ConsumerListener {
-public:
- struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called each time an additional frame becomes
- // available for consumption. This means that frames that are queued
- // while in asynchronous mode only trigger the callback if no previous
- // frames are pending. Frames queued while in synchronous mode always
- // trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
- };
-
- virtual ~GonkConsumerBase();
-
- // abandon frees all the buffers and puts the GonkConsumerBase into the
- // 'abandoned' state. Once put in this state the GonkConsumerBase can never
- // leave it. When in the 'abandoned' state, all methods of the
- // IGraphicBufferProducer interface will fail with the NO_INIT error.
- //
- // Note that while calling this method causes all the buffers to be freed
- // from the perspective of the the GonkConsumerBase, if there are additional
- // references on the buffers (e.g. if a buffer is referenced by a client
- // or by OpenGL ES as a texture) then those buffer will remain allocated.
- void abandon();
-
- // set the name of the GonkConsumerBase that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // dump writes the current state to a string. Child classes should add
- // their state to the dump by overriding the dumpLocked method, which is
- // called by these methods after locking the mutex.
- void dump(String8& result) const;
- void dump(String8& result, const char* prefix) const;
-
- // setFrameAvailableListener sets the listener object that will be notified
- // when a new frame becomes available.
- void setFrameAvailableListener(const wp<FrameAvailableListener>& listener);
-
-private:
- GonkConsumerBase(const GonkConsumerBase&);
- void operator=(const GonkConsumerBase&);
-
-protected:
- // GonkConsumerBase constructs a new GonkConsumerBase object to consume image
- // buffers from the given IGonkGraphicBufferConsumer.
- // The controlledByApp flag indicates that this consumer is under the application's
- // control.
- GonkConsumerBase(const sp<IGonkGraphicBufferConsumer>& consumer, bool controlledByApp = false);
-
- // onLastStrongRef gets called by RefBase just before the dtor of the most
- // derived class. It is used to clean up the buffers so that GonkConsumerBase
- // can coordinate the clean-up by calling into virtual methods implemented
- // by the derived classes. This would not be possible from the
- // ConsuemrBase dtor because by the time that gets called the derived
- // classes have already been destructed.
- //
- // This methods should not need to be overridden by derived classes, but
- // if they are overridden the GonkConsumerBase implementation must be called
- // from the derived class.
- virtual void onLastStrongRef(const void* id);
-
- // Implementation of the IConsumerListener interface. These
- // calls are used to notify the GonkConsumerBase of asynchronous events in the
- // GonkBufferQueue. The onFrameAvailable and onBuffersReleased methods should
- // not need to be overridden by derived classes, but if they are overridden
- // the GonkConsumerBase implementation must be called from the derived class.
- // The GonkConsumerBase version of onSidebandStreamChanged does nothing and can
- // be overriden by derived classes if they want the notification.
-#if ANDROID_VERSION == 21
- virtual void onFrameAvailable();
-#else
- virtual void onFrameAvailable(const ::android::BufferItem& item);
- virtual void onFrameReplaced(const ::android::BufferItem& item) {};
-#endif
- virtual void onBuffersReleased();
- virtual void onSidebandStreamChanged();
-
- // freeBufferLocked frees up the given buffer slot. If the slot has been
- // initialized this will release the reference to the GraphicBuffer in that
- // slot. Otherwise it has no effect.
- //
- // Derived classes should override this method to clean up any state they
- // keep per slot. If it is overridden, the derived class's implementation
- // must call GonkConsumerBase::freeBufferLocked.
- //
- // This method must be called with mMutex locked.
- virtual void freeBufferLocked(int slotIndex);
-
- // abandonLocked puts the GonkBufferQueue into the abandoned state, causing
- // all future operations on it to fail. This method rather than the public
- // abandon method should be overridden by child classes to add abandon-
- // time behavior.
- //
- // Derived classes should override this method to clean up any object
- // state they keep (as opposed to per-slot state). If it is overridden,
- // the derived class's implementation must call GonkConsumerBase::abandonLocked.
- //
- // This method must be called with mMutex locked.
- virtual void abandonLocked();
-
- // dumpLocked dumps the current state of the GonkConsumerBase object to the
- // result string. Each line is prefixed with the string pointed to by the
- // prefix argument. The buffer argument points to a buffer that may be
- // used for intermediate formatting data, and the size of that buffer is
- // indicated by the size argument.
- //
- // Derived classes should override this method to dump their internal
- // state. If this method is overridden the derived class's implementation
- // should call GonkConsumerBase::dumpLocked.
- //
- // This method must be called with mMutex locked.
- virtual void dumpLocked(String8& result, const char* prefix) const;
-
- // acquireBufferLocked fetches the next buffer from the GonkBufferQueue and
- // updates the buffer slot for the buffer returned.
- //
- // Derived classes should override this method to perform any
- // initialization that must take place the first time a buffer is assigned
- // to a slot. If it is overridden the derived class's implementation must
- // call GonkConsumerBase::acquireBufferLocked.
- virtual status_t acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item,
- nsecs_t presentWhen);
-
- // releaseBufferLocked relinquishes control over a buffer, returning that
- // control to the GonkBufferQueue.
- //
- // Derived classes should override this method to perform any cleanup that
- // must take place when a buffer is released back to the GonkBufferQueue. If
- // it is overridden the derived class's implementation must call
- // GonkConsumerBase::releaseBufferLocked.
- virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer);
-
- // returns true iff the slot still has the graphicBuffer in it.
- bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
-
- // addReleaseFence* adds the sync points associated with a fence to the set
- // of sync points that must be reached before the buffer in the given slot
- // may be used after the slot has been released. This should be called by
- // derived classes each time some asynchronous work is kicked off that
- // references the buffer.
- status_t addReleaseFence(int slot,
- const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence);
- status_t addReleaseFenceLocked(int slot,
- const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence);
-
- // Slot contains the information and object references that
- // GonkConsumerBase maintains about a GonkBufferQueue buffer slot.
- struct Slot {
- // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if
- // no Gralloc buffer is in the slot.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mFence is a fence which will signal when the buffer associated with
- // this buffer slot is no longer being used by the consumer and can be
- // overwritten. The buffer can be dequeued before the fence signals;
- // the producer is responsible for delaying writes until it signals.
- sp<Fence> mFence;
-
- // the frame number of the last acquired frame for this slot
- uint64_t mFrameNumber;
- };
-
- // mSlots stores the buffers that have been allocated by the GonkBufferQueue
- // for each buffer slot. It is initialized to null pointers, and gets
- // filled in with the result of GonkBufferQueue::acquire when the
- // client dequeues a buffer from a
- // slot that has not yet been used. The buffer allocated to a slot will also
- // be replaced if the requested buffer usage or geometry differs from that
- // of the buffer allocated to a slot.
- Slot mSlots[GonkBufferQueue::NUM_BUFFER_SLOTS];
-
- // mAbandoned indicates that the GonkBufferQueue will no longer be used to
- // consume images buffers pushed to it using the IGraphicBufferProducer
- // interface. It is initialized to false, and set to true in the abandon
- // method. A GonkBufferQueue that has been abandoned will return the NO_INIT
- // error from all IConsumerBase methods capable of returning an error.
- bool mAbandoned;
-
- // mName is a string used to identify the GonkConsumerBase in log messages.
- // It can be set by the setName method.
- String8 mName;
-
- // mFrameAvailableListener is the listener object that will be called when a
- // new frame becomes available. If it is not NULL it will be called from
- // queueBuffer.
- wp<FrameAvailableListener> mFrameAvailableListener;
-
- // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object
- // if none is supplied
- sp<IGonkGraphicBufferConsumer> mConsumer;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of GonkConsumerBase objects. It must be locked whenever the
- // member variables are accessed or when any of the *Locked methods are
- // called.
- //
- // This mutex is intended to be locked by derived classes.
- mutable Mutex mMutex;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // NATIVEWINDOW_GONKCONSUMERBASE_LL_H
diff --git a/widget/gonk/nativewindow/GonkNativeWindow.h b/widget/gonk/nativewindow/GonkNativeWindow.h
deleted file mode 100644
index 61b6780b8..000000000
--- a/widget/gonk/nativewindow/GonkNativeWindow.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright 2013 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
-# include "GonkNativeWindowLL.h"
-#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
-# include "GonkNativeWindowKK.h"
-#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
-# include "GonkNativeWindowJB.h"
-#endif
diff --git a/widget/gonk/nativewindow/GonkNativeWindowJB.cpp b/widget/gonk/nativewindow/GonkNativeWindowJB.cpp
deleted file mode 100644
index e38642009..000000000
--- a/widget/gonk/nativewindow/GonkNativeWindowJB.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "GonkNativeWindow"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Log.h>
-
-#include "GonkNativeWindowJB.h"
-#include "GrallocImages.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/RefPtr.h"
-
-#define BI_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#define BI_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-#define BI_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-#define BI_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
-#define BI_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-
-using namespace mozilla;
-using namespace mozilla::layers;
-
-namespace android {
-
-GonkNativeWindow::GonkNativeWindow(int bufferCount) :
- GonkConsumerBase(new GonkBufferQueue(true) ),
- mNewFrameCallback(nullptr)
-{
- mBufferQueue->setMaxAcquiredBufferCount(bufferCount);
-}
-
-GonkNativeWindow::~GonkNativeWindow() {
-}
-
-void GonkNativeWindow::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- mName = name;
- mBufferQueue->setConsumerName(name);
-}
-#if ANDROID_VERSION >= 18
-status_t GonkNativeWindow::acquireBuffer(BufferItem *item, bool waitForFence) {
- status_t err;
-
- if (!item) return BAD_VALUE;
-
- Mutex::Autolock _l(mMutex);
-
- err = acquireBufferLocked(item);
- if (err != OK) {
- if (err != NO_BUFFER_AVAILABLE) {
- BI_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
- }
- return err;
- }
-
- if (waitForFence) {
- err = item->mFence->waitForever("GonkNativeWindow::acquireBuffer");
- if (err != OK) {
- BI_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
- strerror(-err), err);
- return err;
- }
- }
-
- item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer;
-
- return OK;
-}
-
-status_t GonkNativeWindow::releaseBuffer(const BufferItem &item,
- const sp<Fence>& releaseFence) {
- status_t err;
-
- Mutex::Autolock _l(mMutex);
-
- err = addReleaseFenceLocked(item.mBuf, releaseFence);
-
- err = releaseBufferLocked(item.mBuf);
- if (err != OK) {
- BI_LOGE("Failed to release buffer: %s (%d)",
- strerror(-err), err);
- }
- return err;
-}
-#endif
-
-status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) {
- Mutex::Autolock _l(mMutex);
- return mBufferQueue->setDefaultBufferSize(w, h);
-}
-
-status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock _l(mMutex);
- return mBufferQueue->setDefaultBufferFormat(defaultFormat);
-}
-
-already_AddRefed<TextureClient>
-GonkNativeWindow::getCurrentBuffer() {
- Mutex::Autolock _l(mMutex);
- GonkBufferQueue::BufferItem item;
-
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- status_t err = acquireBufferLocked(&item);
- if (err != NO_ERROR) {
- return NULL;
- }
-
- RefPtr<TextureClient> textureClient =
- mBufferQueue->getTextureClientFromBuffer(item.mGraphicBuffer.get());
- if (!textureClient) {
- return NULL;
- }
- textureClient->SetRecycleCallback(GonkNativeWindow::RecycleCallback, this);
- return textureClient.forget();
-}
-
-/* static */ void
-GonkNativeWindow::RecycleCallback(TextureClient* client, void* closure) {
- GonkNativeWindow* nativeWindow =
- static_cast<GonkNativeWindow*>(closure);
-
- MOZ_ASSERT(client && !client->IsDead());
- client->ClearRecycleCallback();
- nativeWindow->returnBuffer(client);
-}
-
-void GonkNativeWindow::returnBuffer(TextureClient* client) {
- BI_LOGD("GonkNativeWindow::returnBuffer");
- Mutex::Autolock lock(mMutex);
-
- int index = mBufferQueue->getSlotFromTextureClientLocked(client);
- if (index < 0) {
- }
-
- FenceHandle handle = client->GetAndResetReleaseFenceHandle();
- RefPtr<FenceHandle::FdObj> fdObj = handle.GetAndResetFdObj();
- sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
-
- addReleaseFenceLocked(index, fence);
-
- releaseBufferLocked(index);
-}
-
-already_AddRefed<TextureClient>
-GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->getTextureClientFromBuffer(buffer);
-}
-
-void GonkNativeWindow::setNewFrameCallback(
- GonkNativeWindowNewFrameCallback* callback) {
- BI_LOGD("setNewFrameCallback");
- Mutex::Autolock lock(mMutex);
- mNewFrameCallback = callback;
-}
-
-void GonkNativeWindow::onFrameAvailable() {
- GonkConsumerBase::onFrameAvailable();
-
- if (mNewFrameCallback) {
- mNewFrameCallback->OnNewFrame();
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkNativeWindowJB.h b/widget/gonk/nativewindow/GonkNativeWindowJB.h
deleted file mode 100644
index e63a7527d..000000000
--- a/widget/gonk/nativewindow/GonkNativeWindowJB.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKNATIVEWINDOW_JB_H
-#define NATIVEWINDOW_GONKNATIVEWINDOW_JB_H
-
-#include <ui/GraphicBuffer.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#include "GonkConsumerBaseJB.h"
-#include "GrallocImages.h"
-#include "mozilla/layers/LayersSurfaces.h"
-
-namespace mozilla {
-namespace layers {
- class PGrallocBufferChild;
-}
-}
-
-namespace android {
-
-// The user of GonkNativeWindow who wants to receive notification of
-// new frames should implement this interface.
-class GonkNativeWindowNewFrameCallback {
-public:
- virtual void OnNewFrame() = 0;
-};
-
-/**
- * GonkNativeWindow is a GonkBufferQueue consumer endpoint that allows clients
- * access to the whole BufferItem entry from GonkBufferQueue. Multiple buffers may
- * be acquired at once, to be used concurrently by the client. This consumer can
- * operate either in synchronous or asynchronous mode.
- */
-class GonkNativeWindow: public GonkConsumerBase
-{
- typedef mozilla::layers::TextureClient TextureClient;
- public:
- typedef GonkConsumerBase::FrameAvailableListener FrameAvailableListener;
-
- typedef GonkBufferQueue::BufferItem BufferItem;
-
- enum { INVALID_BUFFER_SLOT = GonkBufferQueue::INVALID_BUFFER_SLOT };
- enum { NO_BUFFER_AVAILABLE = GonkBufferQueue::NO_BUFFER_AVAILABLE };
-
- // Create a new buffer item consumer. The consumerUsage parameter determines
- // the consumer usage flags passed to the graphics allocator. The
- // bufferCount parameter specifies how many buffers can be locked for user
- // access at the same time.
- GonkNativeWindow(int bufferCount = GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS);
-
- virtual ~GonkNativeWindow();
-
- // set the name of the GonkNativeWindow that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // Gets the next graphics buffer from the producer, filling out the
- // passed-in BufferItem structure. Returns NO_BUFFER_AVAILABLE if the queue
- // of buffers is empty, and INVALID_OPERATION if the maximum number of
- // buffers is already acquired.
- //
- // Only a fixed number of buffers can be acquired at a time, determined by
- // the construction-time bufferCount parameter. If INVALID_OPERATION is
- // returned by acquireBuffer, then old buffers must be returned to the
- // queue by calling releaseBuffer before more buffers can be acquired.
- //
- // If waitForFence is true, and the acquired BufferItem has a valid fence object,
- // acquireBuffer will wait on the fence with no timeout before returning.
-#if ANDROID_VERSION >= 18
- status_t acquireBuffer(BufferItem *item, bool waitForFence = true);
-#endif
- // Returns an acquired buffer to the queue, allowing it to be reused. Since
- // only a fixed number of buffers may be acquired at a time, old buffers
- // must be released by calling releaseBuffer to ensure new buffers can be
- // acquired by acquireBuffer. Once a BufferItem is released, the caller must
- // not access any members of the BufferItem, and should immediately remove
- // all of its references to the BufferItem itself.
-#if ANDROID_VERSION >= 18
- status_t releaseBuffer(const BufferItem &item,
- const sp<Fence>& releaseFence = Fence::NO_FENCE);
-#endif
-
- sp<IGraphicBufferProducer> getProducerInterface() const { return getBufferQueue(); }
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- status_t setDefaultBufferSize(uint32_t w, uint32_t h);
-
- // setDefaultBufferFormat allows the BufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
-
- // Get next frame from the queue, caller owns the returned buffer.
- already_AddRefed<TextureClient> getCurrentBuffer();
-
- // Return the buffer to the queue and mark it as FREE. After that
- // the buffer is useable again for the decoder.
- void returnBuffer(TextureClient* client);
-
- already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer);
-
- void setNewFrameCallback(GonkNativeWindowNewFrameCallback* callback);
-
- static void RecycleCallback(TextureClient* client, void* closure);
-
-protected:
- virtual void onFrameAvailable();
-
-private:
- GonkNativeWindowNewFrameCallback* mNewFrameCallback;
-};
-
-} // namespace android
-
-#endif // NATIVEWINDOW_GONKNATIVEWINDOW_JB_H
diff --git a/widget/gonk/nativewindow/GonkNativeWindowKK.cpp b/widget/gonk/nativewindow/GonkNativeWindowKK.cpp
deleted file mode 100644
index cf34d6539..000000000
--- a/widget/gonk/nativewindow/GonkNativeWindowKK.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "GonkNativeWindow"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Log.h>
-
-#include "GonkNativeWindowKK.h"
-#include "GrallocImages.h"
-
-using namespace mozilla;
-using namespace mozilla::layers;
-
-namespace android {
-
-GonkNativeWindow::GonkNativeWindow(int bufferCount) :
- GonkConsumerBase(new GonkBufferQueue(true), false),
- mNewFrameCallback(nullptr)
-{
- mConsumer->setMaxAcquiredBufferCount(bufferCount);
-}
-
-GonkNativeWindow::GonkNativeWindow(const sp<GonkBufferQueue>& bq,
- uint32_t consumerUsage, int bufferCount, bool controlledByApp) :
- GonkConsumerBase(bq, controlledByApp)
-{
- mConsumer->setConsumerUsageBits(consumerUsage);
- mConsumer->setMaxAcquiredBufferCount(bufferCount);
-}
-
-GonkNativeWindow::~GonkNativeWindow() {
-}
-
-void GonkNativeWindow::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- mName = name;
- mConsumer->setConsumerName(name);
-}
-
-status_t GonkNativeWindow::acquireBuffer(BufferItem *item,
- nsecs_t presentWhen, bool waitForFence) {
- status_t err;
-
- if (!item) return BAD_VALUE;
-
- Mutex::Autolock _l(mMutex);
-
- err = acquireBufferLocked(item, presentWhen);
- if (err != OK) {
- if (err != NO_BUFFER_AVAILABLE) {
- ALOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
- }
- return err;
- }
-
- if (waitForFence) {
- err = item->mFence->waitForever("GonkNativeWindow::acquireBuffer");
- if (err != OK) {
- ALOGE("Failed to wait for fence of acquired buffer: %s (%d)",
- strerror(-err), err);
- return err;
- }
- }
-
- item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer;
-
- return OK;
-}
-
-status_t GonkNativeWindow::releaseBuffer(const BufferItem &item,
- const sp<Fence>& releaseFence) {
- status_t err;
-
- Mutex::Autolock _l(mMutex);
-
- err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence);
-
- err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer);
- if (err != OK) {
- ALOGE("Failed to release buffer: %s (%d)",
- strerror(-err), err);
- }
- return err;
-}
-
-status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) {
- Mutex::Autolock _l(mMutex);
- return mConsumer->setDefaultBufferSize(w, h);
-}
-
-status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock _l(mMutex);
- return mConsumer->setDefaultBufferFormat(defaultFormat);
-}
-
-already_AddRefed<TextureClient>
-GonkNativeWindow::getCurrentBuffer() {
- Mutex::Autolock _l(mMutex);
- BufferItem item;
-
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- status_t err = acquireBufferLocked(&item, 0); //???
- if (err != NO_ERROR) {
- return NULL;
- }
-
- RefPtr<TextureClient> textureClient =
- mConsumer->getTextureClientFromBuffer(item.mGraphicBuffer.get());
- if (!textureClient) {
- return NULL;
- }
- textureClient->SetRecycleCallback(GonkNativeWindow::RecycleCallback, this);
- return textureClient.forget();
-}
-
-/* static */ void
-GonkNativeWindow::RecycleCallback(TextureClient* client, void* closure) {
- GonkNativeWindow* nativeWindow =
- static_cast<GonkNativeWindow*>(closure);
-
- MOZ_ASSERT(client && !client->IsDead());
- client->ClearRecycleCallback();
- nativeWindow->returnBuffer(client);
-}
-
-void GonkNativeWindow::returnBuffer(TextureClient* client) {
- ALOGD("GonkNativeWindow::returnBuffer");
- Mutex::Autolock lock(mMutex);
-
- int index = mConsumer->getSlotFromTextureClientLocked(client);
- if (index < 0) {
- }
-
- FenceHandle handle = client->GetAndResetReleaseFenceHandle();
- RefPtr<FenceHandle::FdObj> fdObj = handle.GetAndResetFdObj();
- sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
-
- addReleaseFenceLocked(index,
- mSlots[index].mGraphicBuffer,
- fence);
-
- releaseBufferLocked(index, mSlots[index].mGraphicBuffer);
-}
-
-already_AddRefed<TextureClient>
-GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) {
- Mutex::Autolock lock(mMutex);
- return mConsumer->getTextureClientFromBuffer(buffer);
-}
-
-void GonkNativeWindow::setNewFrameCallback(
- GonkNativeWindowNewFrameCallback* callback) {
- ALOGD("setNewFrameCallback");
- Mutex::Autolock lock(mMutex);
- mNewFrameCallback = callback;
-}
-
-void GonkNativeWindow::onFrameAvailable() {
- GonkConsumerBase::onFrameAvailable();
-
- if (mNewFrameCallback) {
- mNewFrameCallback->OnNewFrame();
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkNativeWindowKK.h b/widget/gonk/nativewindow/GonkNativeWindowKK.h
deleted file mode 100644
index e36788b41..000000000
--- a/widget/gonk/nativewindow/GonkNativeWindowKK.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKNATIVEWINDOW_KK_H
-#define NATIVEWINDOW_GONKNATIVEWINDOW_KK_H
-
-#include <ui/GraphicBuffer.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#include "GonkConsumerBaseKK.h"
-#include "GrallocImages.h"
-#include "IGonkGraphicBufferConsumer.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/LayersSurfaces.h"
-
-namespace mozilla {
-namespace layers {
- class PGrallocBufferChild;
-}
-}
-
-namespace android {
-
-// The user of GonkNativeWindow who wants to receive notification of
-// new frames should implement this interface.
-class GonkNativeWindowNewFrameCallback {
-public:
- virtual void OnNewFrame() = 0;
-};
-
-/**
- * GonkNativeWindow is a GonkBufferQueue consumer endpoint that allows clients
- * access to the whole BufferItem entry from GonkBufferQueue. Multiple buffers may
- * be acquired at once, to be used concurrently by the client. This consumer can
- * operate either in synchronous or asynchronous mode.
- */
-class GonkNativeWindow: public GonkConsumerBase
-{
- typedef mozilla::layers::TextureClient TextureClient;
- public:
- typedef GonkConsumerBase::FrameAvailableListener FrameAvailableListener;
- typedef IGonkGraphicBufferConsumer::BufferItem BufferItem;
-
- enum { INVALID_BUFFER_SLOT = GonkBufferQueue::INVALID_BUFFER_SLOT };
- enum { NO_BUFFER_AVAILABLE = GonkBufferQueue::NO_BUFFER_AVAILABLE };
-
- // Create a new buffer item consumer. The consumerUsage parameter determines
- // the consumer usage flags passed to the graphics allocator. The
- // bufferCount parameter specifies how many buffers can be locked for user
- // access at the same time.
- // controlledByApp tells whether this consumer is controlled by the
- // application.
- GonkNativeWindow(int bufferCount = GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS);
- GonkNativeWindow(const sp<GonkBufferQueue>& bq, uint32_t consumerUsage,
- int bufferCount = GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS,
- bool controlledByApp = false);
-
- virtual ~GonkNativeWindow();
-
- // set the name of the GonkNativeWindow that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // Gets the next graphics buffer from the producer, filling out the
- // passed-in BufferItem structure. Returns NO_BUFFER_AVAILABLE if the queue
- // of buffers is empty, and INVALID_OPERATION if the maximum number of
- // buffers is already acquired.
- //
- // Only a fixed number of buffers can be acquired at a time, determined by
- // the construction-time bufferCount parameter. If INVALID_OPERATION is
- // returned by acquireBuffer, then old buffers must be returned to the
- // queue by calling releaseBuffer before more buffers can be acquired.
- //
- // If waitForFence is true, and the acquired BufferItem has a valid fence object,
- // acquireBuffer will wait on the fence with no timeout before returning.
- status_t acquireBuffer(BufferItem *item, nsecs_t presentWhen,
- bool waitForFence = true);
-
- // Returns an acquired buffer to the queue, allowing it to be reused. Since
- // only a fixed number of buffers may be acquired at a time, old buffers
- // must be released by calling releaseBuffer to ensure new buffers can be
- // acquired by acquireBuffer. Once a BufferItem is released, the caller must
- // not access any members of the BufferItem, and should immediately remove
- // all of its references to the BufferItem itself.
- status_t releaseBuffer(const BufferItem &item,
- const sp<Fence>& releaseFence = Fence::NO_FENCE);
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- status_t setDefaultBufferSize(uint32_t w, uint32_t h);
-
- // setDefaultBufferFormat allows the BufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
-
- // Get next frame from the queue, caller owns the returned buffer.
- already_AddRefed<TextureClient> getCurrentBuffer();
-
- // Return the buffer to the queue and mark it as FREE. After that
- // the buffer is useable again for the decoder.
- void returnBuffer(TextureClient* client);
-
- already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer);
-
- void setNewFrameCallback(GonkNativeWindowNewFrameCallback* callback);
-
- static void RecycleCallback(TextureClient* client, void* closure);
-
-protected:
- virtual void onFrameAvailable();
-
-private:
- GonkNativeWindowNewFrameCallback* mNewFrameCallback;
-};
-
-} // namespace android
-
-#endif // NATIVEWINDOW_GONKNATIVEWINDOW_JB_H
diff --git a/widget/gonk/nativewindow/GonkNativeWindowLL.cpp b/widget/gonk/nativewindow/GonkNativeWindowLL.cpp
deleted file mode 100644
index 48644a22f..000000000
--- a/widget/gonk/nativewindow/GonkNativeWindowLL.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "GonkNativeWindow"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Log.h>
-
-#include "GonkNativeWindowLL.h"
-
-using namespace mozilla;
-using namespace mozilla::layers;
-
-namespace android {
-
-GonkNativeWindow::GonkNativeWindow(
- const sp<IGonkGraphicBufferConsumer>& consumer, int bufferCount) :
- GonkConsumerBase(consumer, false),
- mNewFrameCallback(nullptr)
-{
- if (bufferCount != DEFAULT_MAX_BUFFERS) {
- status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
- LOG_ALWAYS_FATAL_IF(err != OK,
- "Failed to set max acquired buffer count to %d", bufferCount);
- }
-}
-
-GonkNativeWindow::GonkNativeWindow(
- const sp<IGonkGraphicBufferConsumer>& consumer, uint32_t consumerUsage,
- int bufferCount, bool controlledByApp) :
- GonkConsumerBase(consumer, controlledByApp)
-{
- status_t err = mConsumer->setConsumerUsageBits(consumerUsage);
- LOG_ALWAYS_FATAL_IF(err != OK,
- "Failed to set consumer usage bits to %#x", consumerUsage);
- if (bufferCount != DEFAULT_MAX_BUFFERS) {
- err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
- LOG_ALWAYS_FATAL_IF(err != OK,
- "Failed to set max acquired buffer count to %d", bufferCount);
- }
-}
-
-GonkNativeWindow::~GonkNativeWindow() {
-}
-
-void GonkNativeWindow::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- mName = name;
- mConsumer->setConsumerName(name);
-}
-
-status_t GonkNativeWindow::acquireBuffer(BufferItem *item,
- nsecs_t presentWhen, bool waitForFence) {
- status_t err;
-
- if (!item) return BAD_VALUE;
-
- Mutex::Autolock _l(mMutex);
-
- err = acquireBufferLocked(item, presentWhen);
- if (err != OK) {
- if (err != NO_BUFFER_AVAILABLE) {
- ALOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
- }
- return err;
- }
-
- if (waitForFence) {
- err = item->mFence->waitForever("GonkNativeWindow::acquireBuffer");
- if (err != OK) {
- ALOGE("Failed to wait for fence of acquired buffer: %s (%d)",
- strerror(-err), err);
- return err;
- }
- }
-
- item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer;
-
- return OK;
-}
-
-status_t GonkNativeWindow::releaseBuffer(const BufferItem &item,
- const sp<Fence>& releaseFence) {
- status_t err;
-
- Mutex::Autolock _l(mMutex);
-
- err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence);
-
- err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer);
- if (err != OK) {
- ALOGE("Failed to release buffer: %s (%d)",
- strerror(-err), err);
- }
- return err;
-}
-
-status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) {
- Mutex::Autolock _l(mMutex);
- return mConsumer->setDefaultBufferSize(w, h);
-}
-
-status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock _l(mMutex);
- return mConsumer->setDefaultBufferFormat(defaultFormat);
-}
-
-already_AddRefed<TextureClient>
-GonkNativeWindow::getCurrentBuffer() {
- Mutex::Autolock _l(mMutex);
- BufferItem item;
-
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- status_t err = acquireBufferLocked(&item, 0); //???
- if (err != NO_ERROR) {
- return NULL;
- }
-
- RefPtr<TextureClient> textureClient =
- mConsumer->getTextureClientFromBuffer(item.mGraphicBuffer.get());
- if (!textureClient) {
- return NULL;
- }
- textureClient->SetRecycleCallback(GonkNativeWindow::RecycleCallback, this);
- return textureClient.forget();
-}
-
-/* static */ void
-GonkNativeWindow::RecycleCallback(TextureClient* client, void* closure) {
- GonkNativeWindow* nativeWindow =
- static_cast<GonkNativeWindow*>(closure);
-
- MOZ_ASSERT(client && !client->IsDead());
- client->ClearRecycleCallback();
- nativeWindow->returnBuffer(client);
-}
-
-void GonkNativeWindow::returnBuffer(TextureClient* client) {
- ALOGD("GonkNativeWindow::returnBuffer");
- Mutex::Autolock lock(mMutex);
-
- int index = mConsumer->getSlotFromTextureClientLocked(client);
- if (index < 0) {
- return;
- }
-
- FenceHandle handle = client->GetAndResetReleaseFenceHandle();
- RefPtr<FenceHandle::FdObj> fdObj = handle.GetAndResetFdObj();
- sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
-
- status_t err;
- err = addReleaseFenceLocked(index,
- mSlots[index].mGraphicBuffer,
- fence);
-
- err = releaseBufferLocked(index, mSlots[index].mGraphicBuffer);
-
- if (err != OK) {
- ALOGE("Failed to return buffer: %s (%d)", strerror(-err), err);
- }
-}
-
-already_AddRefed<TextureClient>
-GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) {
- Mutex::Autolock lock(mMutex);
- return mConsumer->getTextureClientFromBuffer(buffer);
-}
-
-void GonkNativeWindow::setNewFrameCallback(
- GonkNativeWindowNewFrameCallback* callback) {
- ALOGD("setNewFrameCallback");
- Mutex::Autolock lock(mMutex);
- mNewFrameCallback = callback;
-}
-
-#if ANDROID_VERSION == 21
-void GonkNativeWindow::onFrameAvailable() {
- GonkConsumerBase::onFrameAvailable();
-#else
-void GonkNativeWindow::onFrameAvailable(const ::android::BufferItem &item) {
- GonkConsumerBase::onFrameAvailable(item);
-#endif
-
- if (mNewFrameCallback) {
- mNewFrameCallback->OnNewFrame();
- }
-}
-
-} // namespace android
diff --git a/widget/gonk/nativewindow/GonkNativeWindowLL.h b/widget/gonk/nativewindow/GonkNativeWindowLL.h
deleted file mode 100644
index 64cd6482d..000000000
--- a/widget/gonk/nativewindow/GonkNativeWindowLL.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- * Copyright (C) 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 NATIVEWINDOW_GONKNATIVEWINDOW_LL_H
-#define NATIVEWINDOW_GONKNATIVEWINDOW_LL_H
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#include "GonkConsumerBaseLL.h"
-#include "IGonkGraphicBufferConsumerLL.h"
-
-namespace android {
-
-// The user of GonkNativeWindow who wants to receive notification of
-// new frames should implement this interface.
-class GonkNativeWindowNewFrameCallback {
-public:
- virtual void OnNewFrame() = 0;
-};
-
-/**
- * GonkNativeWindow is a GonkBufferQueue consumer endpoint that allows clients
- * access to the whole BufferItem entry from GonkBufferQueue. Multiple buffers may
- * be acquired at once, to be used concurrently by the client. This consumer can
- * operate either in synchronous or asynchronous mode.
- */
-class GonkNativeWindow: public GonkConsumerBase
-{
- typedef mozilla::layers::TextureClient TextureClient;
- public:
- typedef GonkConsumerBase::FrameAvailableListener FrameAvailableListener;
- typedef GonkBufferQueue::BufferItem BufferItem;
-
- enum { DEFAULT_MAX_BUFFERS = -1 };
- enum { INVALID_BUFFER_SLOT = GonkBufferQueue::INVALID_BUFFER_SLOT };
- enum { NO_BUFFER_AVAILABLE = GonkBufferQueue::NO_BUFFER_AVAILABLE };
-
- // Create a new buffer item consumer. The consumerUsage parameter determines
- // the consumer usage flags passed to the graphics allocator. The
- // bufferCount parameter specifies how many buffers can be locked for user
- // access at the same time.
- // controlledByApp tells whether this consumer is controlled by the
- // application.
- GonkNativeWindow(const sp<IGonkGraphicBufferConsumer>& consumer,
- int bufferCount = DEFAULT_MAX_BUFFERS);
- GonkNativeWindow(const sp<IGonkGraphicBufferConsumer>& consumer,
- uint32_t consumerUsage, int bufferCount = DEFAULT_MAX_BUFFERS,
- bool controlledByApp = false);
-
- virtual ~GonkNativeWindow();
-
- // set the name of the GonkNativeWindow that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // Gets the next graphics buffer from the producer, filling out the
- // passed-in BufferItem structure. Returns NO_BUFFER_AVAILABLE if the queue
- // of buffers is empty, and INVALID_OPERATION if the maximum number of
- // buffers is already acquired.
- //
- // Only a fixed number of buffers can be acquired at a time, determined by
- // the construction-time bufferCount parameter. If INVALID_OPERATION is
- // returned by acquireBuffer, then old buffers must be returned to the
- // queue by calling releaseBuffer before more buffers can be acquired.
- //
- // If waitForFence is true, and the acquired BufferItem has a valid fence object,
- // acquireBuffer will wait on the fence with no timeout before returning.
- status_t acquireBuffer(BufferItem *item, nsecs_t presentWhen,
- bool waitForFence = true);
-
- // Returns an acquired buffer to the queue, allowing it to be reused. Since
- // only a fixed number of buffers may be acquired at a time, old buffers
- // must be released by calling releaseBuffer to ensure new buffers can be
- // acquired by acquireBuffer. Once a BufferItem is released, the caller must
- // not access any members of the BufferItem, and should immediately remove
- // all of its references to the BufferItem itself.
- status_t releaseBuffer(const BufferItem &item,
- const sp<Fence>& releaseFence = Fence::NO_FENCE);
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- status_t setDefaultBufferSize(uint32_t w, uint32_t h);
-
- // setDefaultBufferFormat allows the GonkBufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
-
- // Get next frame from the queue, caller owns the returned buffer.
- already_AddRefed<TextureClient> getCurrentBuffer();
-
- // Return the buffer to the queue and mark it as FREE. After that
- // the buffer is useable again for the decoder.
- void returnBuffer(TextureClient* client);
-
- already_AddRefed<TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer);
-
- void setNewFrameCallback(GonkNativeWindowNewFrameCallback* callback);
-
- static void RecycleCallback(TextureClient* client, void* closure);
-
-protected:
-#if ANDROID_VERSION == 21
- virtual void onFrameAvailable();
-#else
- virtual void onFrameAvailable(const ::android::BufferItem &item);
-#endif
-
-private:
- GonkNativeWindowNewFrameCallback* mNewFrameCallback;
-};
-
-} // namespace android
-
-#endif // NATIVEWINDOW_GONKNATIVEWINDOW_LL_H
diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumer.h b/widget/gonk/nativewindow/IGonkGraphicBufferConsumer.h
deleted file mode 100644
index 14541c9b4..000000000
--- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumer.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright 2013 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
-# include "IGonkGraphicBufferConsumerLL.h"
-#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
-# include "IGonkGraphicBufferConsumerKK.h"
-#endif
diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.cpp b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.cpp
deleted file mode 100644
index c4c9f6578..000000000
--- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.cpp
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <binder/Parcel.h>
-#include <binder/IInterface.h>
-
-#include <gui/IConsumerListener.h>
-#include "IGonkGraphicBufferConsumerKK.h"
-
-#include <ui/GraphicBuffer.h>
-#include <ui/Fence.h>
-
-#include <system/window.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-IGonkGraphicBufferConsumer::BufferItem::BufferItem() :
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mIsAutoTimestamp(false),
- mFrameNumber(0),
- mBuf(INVALID_BUFFER_SLOT),
- mIsDroppable(false),
- mAcquireCalled(false),
- mTransformToDisplayInverse(false) {
- mCrop.makeInvalid();
-}
-
-size_t IGonkGraphicBufferConsumer::BufferItem::getPodSize() const {
- size_t c = sizeof(mCrop) +
- sizeof(mTransform) +
- sizeof(mScalingMode) +
- sizeof(mTimestamp) +
- sizeof(mIsAutoTimestamp) +
- sizeof(mFrameNumber) +
- sizeof(mBuf) +
- sizeof(mIsDroppable) +
- sizeof(mAcquireCalled) +
- sizeof(mTransformToDisplayInverse);
- return c;
-}
-
-size_t IGonkGraphicBufferConsumer::BufferItem::getFlattenedSize() const {
- size_t c = 0;
- if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFlattenedSize();
- FlattenableUtils::align<4>(c);
- }
- if (mFence != 0) {
- c += mFence->getFlattenedSize();
- FlattenableUtils::align<4>(c);
- }
- return sizeof(int32_t) + c + getPodSize();
-}
-
-size_t IGonkGraphicBufferConsumer::BufferItem::getFdCount() const {
- size_t c = 0;
- if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFdCount();
- }
- if (mFence != 0) {
- c += mFence->getFdCount();
- }
- return c;
-}
-
-status_t IGonkGraphicBufferConsumer::BufferItem::flatten(
- void*& buffer, size_t& size, int*& fds, size_t& count) const {
-
- // make sure we have enough space
- if (count < BufferItem::getFlattenedSize()) {
- return NO_MEMORY;
- }
-
- // content flags are stored first
- uint32_t& flags = *static_cast<uint32_t*>(buffer);
-
- // advance the pointer
- FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
-
- flags = 0;
- if (mGraphicBuffer != 0) {
- status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- flags |= 1;
- }
- if (mFence != 0) {
- status_t err = mFence->flatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- flags |= 2;
- }
-
- // check we have enough space (in case flattening the fence/graphicbuffer lied to us)
- if (size < getPodSize()) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, mCrop);
- FlattenableUtils::write(buffer, size, mTransform);
- FlattenableUtils::write(buffer, size, mScalingMode);
- FlattenableUtils::write(buffer, size, mTimestamp);
- FlattenableUtils::write(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::write(buffer, size, mFrameNumber);
- FlattenableUtils::write(buffer, size, mBuf);
- FlattenableUtils::write(buffer, size, mIsDroppable);
- FlattenableUtils::write(buffer, size, mAcquireCalled);
- FlattenableUtils::write(buffer, size, mTransformToDisplayInverse);
-
- return NO_ERROR;
-}
-
-status_t IGonkGraphicBufferConsumer::BufferItem::unflatten(
- void const*& buffer, size_t& size, int const*& fds, size_t& count) {
-
- if (size < sizeof(uint32_t))
- return NO_MEMORY;
-
- uint32_t flags = 0;
- FlattenableUtils::read(buffer, size, flags);
-
- if (flags & 1) {
- mGraphicBuffer = new GraphicBuffer();
- status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- }
-
- if (flags & 2) {
- mFence = new Fence();
- status_t err = mFence->unflatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- }
-
- // check we have enough space
- if (size < getPodSize()) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::read(buffer, size, mCrop);
- FlattenableUtils::read(buffer, size, mTransform);
- FlattenableUtils::read(buffer, size, mScalingMode);
- FlattenableUtils::read(buffer, size, mTimestamp);
- FlattenableUtils::read(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::read(buffer, size, mFrameNumber);
- FlattenableUtils::read(buffer, size, mBuf);
- FlattenableUtils::read(buffer, size, mIsDroppable);
- FlattenableUtils::read(buffer, size, mAcquireCalled);
- FlattenableUtils::read(buffer, size, mTransformToDisplayInverse);
-
- return NO_ERROR;
-}
-
-// ---------------------------------------------------------------------------
-
-enum {
- ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
- RELEASE_BUFFER,
- CONSUMER_CONNECT,
- CONSUMER_DISCONNECT,
- GET_RELEASED_BUFFERS,
- SET_DEFAULT_BUFFER_SIZE,
- SET_DEFAULT_MAX_BUFFER_COUNT,
- DISABLE_ASYNC_BUFFER,
- SET_MAX_ACQUIRED_BUFFER_COUNT,
- SET_CONSUMER_NAME,
- SET_DEFAULT_BUFFER_FORMAT,
- SET_CONSUMER_USAGE_BITS,
- SET_TRANSFORM_HINT,
- DUMP,
-};
-
-class BpGonkGraphicBufferConsumer : public BpInterface<IGonkGraphicBufferConsumer>
-{
-public:
- BpGonkGraphicBufferConsumer(const sp<IBinder>& impl)
- : BpInterface<IGonkGraphicBufferConsumer>(impl)
- {
- }
-
- virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt64(presentWhen);
- status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.read(*buffer);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
- const sp<Fence>& releaseFence) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(buf);
- data.writeInt64(frameNumber);
- data.write(*releaseFence);
- status_t result = remote()->transact(RELEASE_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeStrongBinder(consumer->asBinder());
- data.writeInt32(controlledByApp);
- status_t result = remote()->transact(CONSUMER_CONNECT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t consumerDisconnect() {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(CONSUMER_DISCONNECT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t getReleasedBuffers(uint32_t* slotMask) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(GET_RELEASED_BUFFERS, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- *slotMask = reply.readInt32();
- return reply.readInt32();
- }
-
- virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(w);
- data.writeInt32(h);
- status_t result = remote()->transact(SET_DEFAULT_BUFFER_SIZE, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t setDefaultMaxBufferCount(int bufferCount) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(bufferCount);
- status_t result = remote()->transact(SET_DEFAULT_MAX_BUFFER_COUNT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t disableAsyncBuffer() {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(DISABLE_ASYNC_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(maxAcquiredBuffers);
- status_t result = remote()->transact(SET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual void setConsumerName(const String8& name) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeString8(name);
- remote()->transact(SET_CONSUMER_NAME, data, &reply);
- }
-
- virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(defaultFormat);
- status_t result = remote()->transact(SET_DEFAULT_BUFFER_FORMAT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t setConsumerUsageBits(uint32_t usage) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(usage);
- status_t result = remote()->transact(SET_CONSUMER_USAGE_BITS, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t setTransformHint(uint32_t hint) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(hint);
- status_t result = remote()->transact(SET_TRANSFORM_HINT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual void dumpToString(String8& result, const char* prefix) const {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeString8(result);
- data.writeString8(String8(prefix ? prefix : ""));
- remote()->transact(DUMP, data, &reply);
- reply.readString8();
- }
-};
-
-IMPLEMENT_META_INTERFACE(GonkGraphicBufferConsumer, "android.gui.IGonkGraphicBufferConsumer");
-// ----------------------------------------------------------------------
-
-status_t BnGonkGraphicBufferConsumer::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case ACQUIRE_BUFFER: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- BufferItem item;
- int64_t presentWhen = data.readInt64();
- status_t result = acquireBuffer(&item, presentWhen);
- status_t err = reply->write(item);
- if (err) return err;
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case RELEASE_BUFFER: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- int buf = data.readInt32();
- uint64_t frameNumber = data.readInt64();
- sp<Fence> releaseFence = new Fence();
- status_t err = data.read(*releaseFence);
- if (err) return err;
- status_t result = releaseBuffer(buf, frameNumber, releaseFence);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
-
- case CONSUMER_CONNECT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- sp<IConsumerListener> consumer = IConsumerListener::asInterface( data.readStrongBinder() );
- bool controlledByApp = data.readInt32();
- status_t result = consumerConnect(consumer, controlledByApp);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
-
- case CONSUMER_DISCONNECT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- status_t result = consumerDisconnect();
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case GET_RELEASED_BUFFERS: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t slotMask;
- status_t result = getReleasedBuffers(&slotMask);
- reply->writeInt32(slotMask);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_DEFAULT_BUFFER_SIZE: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t w = data.readInt32();
- uint32_t h = data.readInt32();
- status_t result = setDefaultBufferSize(w, h);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_DEFAULT_MAX_BUFFER_COUNT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t bufferCount = data.readInt32();
- status_t result = setDefaultMaxBufferCount(bufferCount);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case DISABLE_ASYNC_BUFFER: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- status_t result = disableAsyncBuffer();
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_MAX_ACQUIRED_BUFFER_COUNT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t maxAcquiredBuffers = data.readInt32();
- status_t result = setMaxAcquiredBufferCount(maxAcquiredBuffers);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_CONSUMER_NAME: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- setConsumerName( data.readString8() );
- return NO_ERROR;
- } break;
- case SET_DEFAULT_BUFFER_FORMAT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t defaultFormat = data.readInt32();
- status_t result = setDefaultBufferFormat(defaultFormat);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_CONSUMER_USAGE_BITS: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t usage = data.readInt32();
- status_t result = setConsumerUsageBits(usage);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_TRANSFORM_HINT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t hint = data.readInt32();
- status_t result = setTransformHint(hint);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
-
- case DUMP: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- String8 result = data.readString8();
- String8 prefix = data.readString8();
- static_cast<IGonkGraphicBufferConsumer*>(this)->dumpToString(result, prefix);
- reply->writeString8(result);
- return NO_ERROR;
- }
- }
- return BBinder::onTransact(code, data, reply, flags);
-}
-
-}; // namespace android
diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.h b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.h
deleted file mode 100644
index ce51e1ef2..000000000
--- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerKK.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef NATIVEWINDOW_IGONKGRAPHICBUFFERCONSUMER_KK_H
-#define NATIVEWINDOW_IGONKGRAPHICBUFFERCONSUMER_KK_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-
-#include <binder/IInterface.h>
-#include <ui/Rect.h>
-
-#include "mozilla/Types.h"
-#include "mozilla/layers/LayersSurfaces.h"
-
-namespace mozilla {
-
-namespace layers {
-class TextureClient;
-}
-}
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class MOZ_EXPORT IConsumerListener;
-class MOZ_EXPORT GraphicBuffer;
-class MOZ_EXPORT Fence;
-
-class IGonkGraphicBufferConsumer : public IInterface {
- typedef mozilla::layers::TextureClient TextureClient;
-public:
-
- // public facing structure for BufferSlot
- class BufferItem : public Flattenable<BufferItem> {
- friend class Flattenable<BufferItem>;
- size_t getPodSize() const;
- size_t getFlattenedSize() const;
- size_t getFdCount() const;
- status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
- status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
-
- public:
- enum { INVALID_BUFFER_SLOT = -1 };
- BufferItem();
-
- // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
- // if the buffer in this slot has been acquired in the past (see
- // BufferSlot.mAcquireCalled).
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mFence is a fence that will signal when the buffer is idle.
- sp<Fence> mFence;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued.
- int64_t mTimestamp;
-
- // mIsAutoTimestamp indicates whether mTimestamp was generated
- // automatically when the buffer was queued.
- bool mIsAutoTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mBuf is the slot index of this buffer
- int mBuf;
-
- // mIsDroppable whether this buffer was queued with the
- // property that it can be replaced by a new buffer for the purpose of
- // making sure dequeueBuffer() won't block.
- // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
- // was queued.
- bool mIsDroppable;
-
- // Indicates whether this buffer has been seen by a consumer yet
- bool mAcquireCalled;
-
- // Indicates this buffer must be transformed by the inverse transform of the screen
- // it is displayed onto. This is applied after mTransform.
- bool mTransformToDisplayInverse;
- };
-
-
- // acquireBuffer attempts to acquire ownership of the next pending buffer in
- // the BufferQueue. If no buffer is pending then it returns -EINVAL. If a
- // buffer is successfully acquired, the information about the buffer is
- // returned in BufferItem. If the buffer returned had previously been
- // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
- // NULL and it is assumed that the consumer still holds a reference to the
- // buffer.
- //
- // If presentWhen is nonzero, it indicates the time when the buffer will
- // be displayed on screen. If the buffer's timestamp is farther in the
- // future, the buffer won't be acquired, and PRESENT_LATER will be
- // returned. The presentation time is in nanoseconds, and the time base
- // is CLOCK_MONOTONIC.
- virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) = 0;
-
- // releaseBuffer releases a buffer slot from the consumer back to the
- // BufferQueue. This may be done while the buffer's contents are still
- // being accessed. The fence will signal when the buffer is no longer
- // in use. frameNumber is used to indentify the exact buffer returned.
- //
- // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
- // any references to the just-released buffer that it might have, as if it
- // had received a onBuffersReleased() call with a mask set for the released
- // buffer.
- //
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
- virtual status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) = 0;
-
- // consumerConnect connects a consumer to the BufferQueue. Only one
- // consumer may be connected, and when that consumer disconnects the
- // BufferQueue is placed into the "abandoned" state, causing most
- // interactions with the BufferQueue by the producer to fail.
- // controlledByApp indicates whether the consumer is controlled by
- // the application.
- //
- // consumer may not be NULL.
- virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) = 0;
-
- // consumerDisconnect disconnects a consumer from the BufferQueue. All
- // buffers will be freed and the BufferQueue is placed in the "abandoned"
- // state, causing most interactions with the BufferQueue by the producer to
- // fail.
- virtual status_t consumerDisconnect() = 0;
-
- // getReleasedBuffers sets the value pointed to by slotMask to a bit mask
- // indicating which buffer slots have been released by the BufferQueue
- // but have not yet been released by the consumer.
- //
- // This should be called from the onBuffersReleased() callback.
- virtual status_t getReleasedBuffers(uint32_t* slotMask) = 0;
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // dequeueBuffer when a width and height of zero is requested. Default
- // is 1x1.
- virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
-
- // setDefaultMaxBufferCount sets the default value for the maximum buffer
- // count (the initial default is 2). If the producer has requested a
- // buffer count using setBufferCount, the default buffer count will only
- // take effect if the producer sets the count back to zero.
- //
- // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
- virtual status_t setDefaultMaxBufferCount(int bufferCount) = 0;
-
- // disableAsyncBuffer disables the extra buffer used in async mode
- // (when both producer and consumer have set their "isControlledByApp"
- // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
- //
- // This can only be called before consumerConnect().
- virtual status_t disableAsyncBuffer() = 0;
-
- // setMaxAcquiredBufferCount sets the maximum number of buffers that can
- // be acquired by the consumer at one time (default 1). This call will
- // fail if a producer is connected to the BufferQueue.
- virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) = 0;
-
- // setConsumerName sets the name used in logging
- virtual void setConsumerName(const String8& name) = 0;
-
- // setDefaultBufferFormat allows the BufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer. Formats are enumerated in graphics.h; the
- // initial default is HAL_PIXEL_FORMAT_RGBA_8888.
- virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) = 0;
-
- // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
- // These are merged with the bits passed to dequeueBuffer. The values are
- // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
- virtual status_t setConsumerUsageBits(uint32_t usage) = 0;
-
- // setTransformHint bakes in rotation to buffers so overlays can be used.
- // The values are enumerated in window.h, e.g.
- // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform).
- virtual status_t setTransformHint(uint32_t hint) = 0;
-
- // dump state into a string
- virtual void dumpToString(String8& result, const char* prefix) const = 0;
-
-public:
- DECLARE_META_INTERFACE(GonkGraphicBufferConsumer);
-};
-
-// ----------------------------------------------------------------------------
-
-class BnGonkGraphicBufferConsumer : public BnInterface<IGonkGraphicBufferConsumer>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_IGRAPHICBUFFERCONSUMER_H
diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp
deleted file mode 100644
index 729ed6736..000000000
--- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/NativeHandle.h>
-
-#include <binder/Parcel.h>
-#include <binder/IInterface.h>
-
-#include <gui/IConsumerListener.h>
-#include "IGonkGraphicBufferConsumerLL.h"
-
-#include <ui/GraphicBuffer.h>
-#include <ui/Fence.h>
-
-#include <system/window.h>
-
-#include "mozilla/layers/TextureClient.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-IGonkGraphicBufferConsumer::BufferItem::BufferItem() :
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mIsAutoTimestamp(false),
- mFrameNumber(0),
- mBuf(INVALID_BUFFER_SLOT),
- mIsDroppable(false),
- mAcquireCalled(false),
- mTransformToDisplayInverse(false) {
- mCrop.makeInvalid();
-}
-
-size_t IGonkGraphicBufferConsumer::BufferItem::getPodSize() const {
- size_t c = sizeof(mCrop) +
- sizeof(mTransform) +
- sizeof(mScalingMode) +
- sizeof(mTimestamp) +
- sizeof(mIsAutoTimestamp) +
- sizeof(mFrameNumber) +
- sizeof(mBuf) +
- sizeof(mIsDroppable) +
- sizeof(mAcquireCalled) +
- sizeof(mTransformToDisplayInverse);
- return c;
-}
-
-size_t IGonkGraphicBufferConsumer::BufferItem::getFlattenedSize() const {
- size_t c = 0;
- if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFlattenedSize();
- c = FlattenableUtils::align<4>(c);
- }
- if (mFence != 0) {
- c += mFence->getFlattenedSize();
- c = FlattenableUtils::align<4>(c);
- }
- return sizeof(int32_t) + c + getPodSize();
-}
-
-size_t IGonkGraphicBufferConsumer::BufferItem::getFdCount() const {
- size_t c = 0;
- if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFdCount();
- }
- if (mFence != 0) {
- c += mFence->getFdCount();
- }
- return c;
-}
-
-static void writeBoolAsInt(void*& buffer, size_t& size, bool b) {
- FlattenableUtils::write(buffer, size, static_cast<int32_t>(b));
-}
-
-static bool readBoolFromInt(void const*& buffer, size_t& size) {
- int32_t i;
- FlattenableUtils::read(buffer, size, i);
- return static_cast<bool>(i);
-}
-
-status_t IGonkGraphicBufferConsumer::BufferItem::flatten(
- void*& buffer, size_t& size, int*& fds, size_t& count) const {
-
- // make sure we have enough space
- if (size < BufferItem::getFlattenedSize()) {
- return NO_MEMORY;
- }
-
- // content flags are stored first
- uint32_t& flags = *static_cast<uint32_t*>(buffer);
-
- // advance the pointer
- FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
-
- flags = 0;
- if (mGraphicBuffer != 0) {
- status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- flags |= 1;
- }
- if (mFence != 0) {
- status_t err = mFence->flatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- flags |= 2;
- }
-
- // check we have enough space (in case flattening the fence/graphicbuffer lied to us)
- if (size < getPodSize()) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, mCrop);
- FlattenableUtils::write(buffer, size, mTransform);
- FlattenableUtils::write(buffer, size, mScalingMode);
- FlattenableUtils::write(buffer, size, mTimestamp);
- writeBoolAsInt(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::write(buffer, size, mFrameNumber);
- FlattenableUtils::write(buffer, size, mBuf);
- writeBoolAsInt(buffer, size, mIsDroppable);
- writeBoolAsInt(buffer, size, mAcquireCalled);
- writeBoolAsInt(buffer, size, mTransformToDisplayInverse);
-
- return NO_ERROR;
-}
-
-status_t IGonkGraphicBufferConsumer::BufferItem::unflatten(
- void const*& buffer, size_t& size, int const*& fds, size_t& count) {
-
- if (size < sizeof(uint32_t))
- return NO_MEMORY;
-
- uint32_t flags = 0;
- FlattenableUtils::read(buffer, size, flags);
-
- if (flags & 1) {
- mGraphicBuffer = new GraphicBuffer();
- status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- }
-
- if (flags & 2) {
- mFence = new Fence();
- status_t err = mFence->unflatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- }
-
- // check we have enough space
- if (size < getPodSize()) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::read(buffer, size, mCrop);
- FlattenableUtils::read(buffer, size, mTransform);
- FlattenableUtils::read(buffer, size, mScalingMode);
- FlattenableUtils::read(buffer, size, mTimestamp);
- mIsAutoTimestamp = readBoolFromInt(buffer, size);
- FlattenableUtils::read(buffer, size, mFrameNumber);
- FlattenableUtils::read(buffer, size, mBuf);
- mIsDroppable = readBoolFromInt(buffer, size);
- mAcquireCalled = readBoolFromInt(buffer, size);
- mTransformToDisplayInverse = readBoolFromInt(buffer, size);
-
- return NO_ERROR;
-}
-
-// ---------------------------------------------------------------------------
-
-enum {
- ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
- DETACH_BUFFER,
- ATTACH_BUFFER,
- RELEASE_BUFFER,
- CONSUMER_CONNECT,
- CONSUMER_DISCONNECT,
- GET_RELEASED_BUFFERS,
- SET_DEFAULT_BUFFER_SIZE,
- SET_DEFAULT_MAX_BUFFER_COUNT,
- DISABLE_ASYNC_BUFFER,
- SET_MAX_ACQUIRED_BUFFER_COUNT,
- SET_CONSUMER_NAME,
- SET_DEFAULT_BUFFER_FORMAT,
- SET_CONSUMER_USAGE_BITS,
- SET_TRANSFORM_HINT,
- GET_SIDEBAND_STREAM,
- DUMP,
-};
-
-
-class BpGonkGraphicBufferConsumer : public BpInterface<IGonkGraphicBufferConsumer>
-{
-public:
- BpGonkGraphicBufferConsumer(const sp<IBinder>& impl)
- : BpInterface<IGonkGraphicBufferConsumer>(impl)
- {
- }
-
- virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt64(presentWhen);
- status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.read(*buffer);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t detachBuffer(int slot) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(slot);
- status_t result = remote()->transact(DETACH_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readInt32();
- return result;
- }
-
- virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.write(*buffer.get());
- status_t result = remote()->transact(ATTACH_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- *slot = reply.readInt32();
- result = reply.readInt32();
- return result;
- }
-
- virtual status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(buf);
- data.writeInt64(frameNumber);
- data.write(*releaseFence);
- status_t result = remote()->transact(RELEASE_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeStrongBinder(consumer->asBinder());
- data.writeInt32(controlledByApp);
- status_t result = remote()->transact(CONSUMER_CONNECT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t consumerDisconnect() {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(CONSUMER_DISCONNECT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t getReleasedBuffers(uint64_t* slotMask) {
- Parcel data, reply;
- if (slotMask == NULL) {
- ALOGE("getReleasedBuffers: slotMask must not be NULL");
- return BAD_VALUE;
- }
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(GET_RELEASED_BUFFERS, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- *slotMask = reply.readInt64();
- return reply.readInt32();
- }
-
- virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(w);
- data.writeInt32(h);
- status_t result = remote()->transact(SET_DEFAULT_BUFFER_SIZE, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t setDefaultMaxBufferCount(int bufferCount) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(bufferCount);
- status_t result = remote()->transact(SET_DEFAULT_MAX_BUFFER_COUNT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t disableAsyncBuffer() {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(DISABLE_ASYNC_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(maxAcquiredBuffers);
- status_t result = remote()->transact(SET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual void setConsumerName(const String8& name) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeString8(name);
- remote()->transact(SET_CONSUMER_NAME, data, &reply);
- }
-
- virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(defaultFormat);
- status_t result = remote()->transact(SET_DEFAULT_BUFFER_FORMAT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t setConsumerUsageBits(uint32_t usage) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(usage);
- status_t result = remote()->transact(SET_CONSUMER_USAGE_BITS, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t setTransformHint(uint32_t hint) {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(hint);
- status_t result = remote()->transact(SET_TRANSFORM_HINT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual sp<NativeHandle> getSidebandStream() const {
- Parcel data, reply;
- status_t err;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- if ((err = remote()->transact(GET_SIDEBAND_STREAM, data, &reply)) != NO_ERROR) {
- return NULL;
- }
- sp<NativeHandle> stream;
- if (reply.readInt32()) {
- stream = NativeHandle::create(reply.readNativeHandle(), true);
- }
- return stream;
- }
-
- virtual void dumpToString(String8& result, const char* prefix) const {
- Parcel data, reply;
- data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeString8(result);
- data.writeString8(String8(prefix ? prefix : ""));
- remote()->transact(DUMP, data, &reply);
- reply.readString8();
- }
-
- // Added by mozilla
- virtual already_AddRefed<mozilla::layers::TextureClient>
- getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
- {
- return nullptr;
- }
-
- virtual int
- getSlotFromTextureClientLocked(mozilla::layers::TextureClient* client) const
- {
- return BAD_VALUE;
- }
-};
-
-IMPLEMENT_META_INTERFACE(GonkGraphicBufferConsumer, "android.gui.IGonkGraphicBufferConsumer");
-
-// ----------------------------------------------------------------------
-
-status_t BnGonkGraphicBufferConsumer::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case ACQUIRE_BUFFER: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- BufferItem item;
- int64_t presentWhen = data.readInt64();
- status_t result = acquireBuffer(&item, presentWhen);
- status_t err = reply->write(item);
- if (err) return err;
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case DETACH_BUFFER: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- int slot = data.readInt32();
- int result = detachBuffer(slot);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case ATTACH_BUFFER: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- sp<GraphicBuffer> buffer = new GraphicBuffer();
- data.read(*buffer.get());
- int slot;
- int result = attachBuffer(&slot, buffer);
- reply->writeInt32(slot);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case RELEASE_BUFFER: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- int buf = data.readInt32();
- uint64_t frameNumber = data.readInt64();
- sp<Fence> releaseFence = new Fence();
- status_t err = data.read(*releaseFence);
- if (err) return err;
- status_t result = releaseBuffer(buf, frameNumber, releaseFence);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case CONSUMER_CONNECT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- sp<IConsumerListener> consumer = IConsumerListener::asInterface( data.readStrongBinder() );
- bool controlledByApp = data.readInt32();
- status_t result = consumerConnect(consumer, controlledByApp);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case CONSUMER_DISCONNECT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- status_t result = consumerDisconnect();
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case GET_RELEASED_BUFFERS: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint64_t slotMask;
- status_t result = getReleasedBuffers(&slotMask);
- reply->writeInt64(slotMask);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_DEFAULT_BUFFER_SIZE: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t w = data.readInt32();
- uint32_t h = data.readInt32();
- status_t result = setDefaultBufferSize(w, h);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_DEFAULT_MAX_BUFFER_COUNT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t bufferCount = data.readInt32();
- status_t result = setDefaultMaxBufferCount(bufferCount);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case DISABLE_ASYNC_BUFFER: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- status_t result = disableAsyncBuffer();
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_MAX_ACQUIRED_BUFFER_COUNT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t maxAcquiredBuffers = data.readInt32();
- status_t result = setMaxAcquiredBufferCount(maxAcquiredBuffers);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_CONSUMER_NAME: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- setConsumerName( data.readString8() );
- return NO_ERROR;
- } break;
- case SET_DEFAULT_BUFFER_FORMAT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t defaultFormat = data.readInt32();
- status_t result = setDefaultBufferFormat(defaultFormat);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_CONSUMER_USAGE_BITS: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t usage = data.readInt32();
- status_t result = setConsumerUsageBits(usage);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case SET_TRANSFORM_HINT: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- uint32_t hint = data.readInt32();
- status_t result = setTransformHint(hint);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case DUMP: {
- CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply);
- String8 result = data.readString8();
- String8 prefix = data.readString8();
- static_cast<IGonkGraphicBufferConsumer*>(this)->dumpToString(result, prefix);
- reply->writeString8(result);
- return NO_ERROR;
- }
- }
- return BBinder::onTransact(code, data, reply, flags);
-}
-
-}; // namespace android
diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h
deleted file mode 100644
index 8a93a0849..000000000
--- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef NATIVEWINDOW_IGONKGRAPHICBUFFERCONSUMER_LL_H
-#define NATIVEWINDOW_IGONKGRAPHICBUFFERCONSUMER_LL_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-
-#include <binder/IInterface.h>
-#include <ui/Rect.h>
-
-#include "mozilla/RefPtr.h"
-
-class ANativeWindowBuffer;
-
-namespace mozilla {
-namespace layers {
-class TextureClient;
-}
-}
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class Fence;
-class GraphicBuffer;
-class IConsumerListener;
-class NativeHandle;
-
-class IGonkGraphicBufferConsumer : public IInterface {
-public:
-
- // public facing structure for BufferSlot
- class BufferItem : public Flattenable<BufferItem> {
- friend class Flattenable<BufferItem>;
- size_t getPodSize() const;
- size_t getFlattenedSize() const;
- size_t getFdCount() const;
- status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
- status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
-
- public:
- // The default value of mBuf, used to indicate this doesn't correspond to a slot.
- enum { INVALID_BUFFER_SLOT = -1 };
- BufferItem();
-
- // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
- // if the buffer in this slot has been acquired in the past (see
- // BufferSlot.mAcquireCalled).
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mFence is a fence that will signal when the buffer is idle.
- sp<Fence> mFence;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- // refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- // refer to NATIVE_WINDOW_SCALING_* in <window.h>
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued. This value
- // is guaranteed to be monotonically increasing for each newly
- // acquired buffer.
- int64_t mTimestamp;
-
- // mIsAutoTimestamp indicates whether mTimestamp was generated
- // automatically when the buffer was queued.
- bool mIsAutoTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mBuf is the slot index of this buffer (default INVALID_BUFFER_SLOT).
- int mBuf;
-
- // mIsDroppable whether this buffer was queued with the
- // property that it can be replaced by a new buffer for the purpose of
- // making sure dequeueBuffer() won't block.
- // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
- // was queued.
- bool mIsDroppable;
-
- // Indicates whether this buffer has been seen by a consumer yet
- bool mAcquireCalled;
-
- // Indicates this buffer must be transformed by the inverse transform of the screen
- // it is displayed onto. This is applied after mTransform.
- bool mTransformToDisplayInverse;
- };
-
- enum {
- // Returned by releaseBuffer, after which the consumer must
- // free any references to the just-released buffer that it might have.
- STALE_BUFFER_SLOT = 1,
- // Returned by dequeueBuffer if there are no pending buffers available.
- NO_BUFFER_AVAILABLE,
- // Returned by dequeueBuffer if it's too early for the buffer to be acquired.
- PRESENT_LATER,
- };
-
- // acquireBuffer attempts to acquire ownership of the next pending buffer in
- // the BufferQueue. If no buffer is pending then it returns
- // NO_BUFFER_AVAILABLE. If a buffer is successfully acquired, the
- // information about the buffer is returned in BufferItem.
- //
- // If the buffer returned had previously been
- // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
- // NULL and it is assumed that the consumer still holds a reference to the
- // buffer.
- //
- // If presentWhen is non-zero, it indicates the time when the buffer will
- // be displayed on screen. If the buffer's timestamp is farther in the
- // future, the buffer won't be acquired, and PRESENT_LATER will be
- // returned. The presentation time is in nanoseconds, and the time base
- // is CLOCK_MONOTONIC.
- //
- // Return of NO_ERROR means the operation completed as normal.
- //
- // Return of a positive value means the operation could not be completed
- // at this time, but the user should try again later:
- // * NO_BUFFER_AVAILABLE - no buffer is pending (nothing queued by producer)
- // * PRESENT_LATER - the buffer's timestamp is farther in the future
- //
- // Return of a negative value means an error has occurred:
- // * INVALID_OPERATION - too many buffers have been acquired
- virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen) = 0;
-
- // detachBuffer attempts to remove all ownership of the buffer in the given
- // slot from the buffer queue. If this call succeeds, the slot will be
- // freed, and there will be no way to obtain the buffer from this interface.
- // The freed slot will remain unallocated until either it is selected to
- // hold a freshly allocated buffer in dequeueBuffer or a buffer is attached
- // to the slot. The buffer must have already been acquired.
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * BAD_VALUE - the given slot number is invalid, either because it is
- // out of the range [0, NUM_BUFFER_SLOTS) or because the slot
- // it refers to is not currently acquired.
- virtual status_t detachBuffer(int slot) = 0;
-
- // attachBuffer attempts to transfer ownership of a buffer to the buffer
- // queue. If this call succeeds, it will be as if this buffer was acquired
- // from the returned slot number. As such, this call will fail if attaching
- // this buffer would cause too many buffers to be simultaneously acquired.
- //
- // If the buffer is successfully attached, its frameNumber is initialized
- // to 0. This must be passed into the releaseBuffer call or else the buffer
- // will be deallocated as stale.
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * BAD_VALUE - outSlot or buffer were NULL
- // * INVALID_OPERATION - cannot attach the buffer because it would cause too
- // many buffers to be acquired.
- // * NO_MEMORY - no free slots available
- virtual status_t attachBuffer(int *outSlot,
- const sp<GraphicBuffer>& buffer) = 0;
-
- // releaseBuffer releases a buffer slot from the consumer back to the
- // BufferQueue. This may be done while the buffer's contents are still
- // being accessed. The fence will signal when the buffer is no longer
- // in use. frameNumber is used to indentify the exact buffer returned.
- //
- // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
- // any references to the just-released buffer that it might have, as if it
- // had received a onBuffersReleased() call with a mask set for the released
- // buffer.
- //
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
- //
- // Return of NO_ERROR means the operation completed as normal.
- //
- // Return of a positive value means the operation could not be completed
- // at this time, but the user should try again later:
- // * STALE_BUFFER_SLOT - see above (second paragraph)
- //
- // Return of a negative value means an error has occurred:
- // * BAD_VALUE - one of the following could've happened:
- // * the buffer slot was invalid
- // * the fence was NULL
- // * the buffer slot specified is not in the acquired state
- virtual status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) = 0;
-
- // consumerConnect connects a consumer to the BufferQueue. Only one
- // consumer may be connected, and when that consumer disconnects the
- // BufferQueue is placed into the "abandoned" state, causing most
- // interactions with the BufferQueue by the producer to fail.
- // controlledByApp indicates whether the consumer is controlled by
- // the application.
- //
- // consumer may not be NULL.
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned
- // * BAD_VALUE - a NULL consumer was provided
- virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) = 0;
-
- // consumerDisconnect disconnects a consumer from the BufferQueue. All
- // buffers will be freed and the BufferQueue is placed in the "abandoned"
- // state, causing most interactions with the BufferQueue by the producer to
- // fail.
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * BAD_VALUE - no consumer is currently connected
- virtual status_t consumerDisconnect() = 0;
-
- // getReleasedBuffers sets the value pointed to by slotMask to a bit set.
- // Each bit index with a 1 corresponds to a released buffer slot with that
- // index value. In particular, a released buffer is one that has
- // been released by the BufferQueue but have not yet been released by the consumer.
- //
- // This should be called from the onBuffersReleased() callback.
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned.
- virtual status_t getReleasedBuffers(uint64_t* slotMask) = 0;
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // dequeueBuffer when a width and height of zero is requested. Default
- // is 1x1.
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * BAD_VALUE - either w or h was zero
- virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
-
- // setDefaultMaxBufferCount sets the default value for the maximum buffer
- // count (the initial default is 2). If the producer has requested a
- // buffer count using setBufferCount, the default buffer count will only
- // take effect if the producer sets the count back to zero.
- //
- // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * BAD_VALUE - bufferCount was out of range (see above).
- virtual status_t setDefaultMaxBufferCount(int bufferCount) = 0;
-
- // disableAsyncBuffer disables the extra buffer used in async mode
- // (when both producer and consumer have set their "isControlledByApp"
- // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
- //
- // This can only be called before consumerConnect().
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * INVALID_OPERATION - attempting to call this after consumerConnect.
- virtual status_t disableAsyncBuffer() = 0;
-
- // setMaxAcquiredBufferCount sets the maximum number of buffers that can
- // be acquired by the consumer at one time (default 1). This call will
- // fail if a producer is connected to the BufferQueue.
- //
- // maxAcquiredBuffers must be (inclusive) between 1 and MAX_MAX_ACQUIRED_BUFFERS.
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * BAD_VALUE - maxAcquiredBuffers was out of range (see above).
- // * INVALID_OPERATION - attempting to call this after a producer connected.
- virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) = 0;
-
- // setConsumerName sets the name used in logging
- virtual void setConsumerName(const String8& name) = 0;
-
- // setDefaultBufferFormat allows the BufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer. Formats are enumerated in graphics.h; the
- // initial default is HAL_PIXEL_FORMAT_RGBA_8888.
- //
- // Return of a value other than NO_ERROR means an unknown error has occurred.
- virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) = 0;
-
- // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
- // These are merged with the bits passed to dequeueBuffer. The values are
- // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
- //
- // Return of a value other than NO_ERROR means an unknown error has occurred.
- virtual status_t setConsumerUsageBits(uint32_t usage) = 0;
-
- // setTransformHint bakes in rotation to buffers so overlays can be used.
- // The values are enumerated in window.h, e.g.
- // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform).
- //
- // Return of a value other than NO_ERROR means an unknown error has occurred.
- virtual status_t setTransformHint(uint32_t hint) = 0;
-
- // Retrieve the sideband buffer stream, if any.
- virtual sp<NativeHandle> getSidebandStream() const = 0;
-
- // dump state into a string
- virtual void dumpToString(String8& result, const char* prefix) const = 0;
-
- // Added by mozilla
- virtual already_AddRefed<mozilla::layers::TextureClient>
- getTextureClientFromBuffer(ANativeWindowBuffer* buffer) = 0;
-
- virtual int getSlotFromTextureClientLocked(mozilla::layers::TextureClient* client) const = 0;
-
-public:
- DECLARE_META_INTERFACE(GonkGraphicBufferConsumer);
-};
-
-// ----------------------------------------------------------------------------
-
-class BnGonkGraphicBufferConsumer : public BnInterface<IGonkGraphicBufferConsumer>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_IGONKGRAPHICBUFFERCONSUMER_H
diff --git a/widget/gonk/nativewindow/moz.build b/widget/gonk/nativewindow/moz.build
deleted file mode 100644
index fbcee601c..000000000
--- a/widget/gonk/nativewindow/moz.build
+++ /dev/null
@@ -1,104 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# Copyright 2013 Mozilla Foundation and Mozilla contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-EXPORTS += [
- 'GonkBufferQueue.h',
- 'GonkNativeWindow.h',
-]
-
-if CONFIG['ANDROID_VERSION'] >= '19':
- EXPORTS += [
- 'IGonkGraphicBufferConsumer.h',
- ]
-
-if CONFIG['ANDROID_VERSION'] >= '21':
- EXPORTS += [
- 'GonkBufferQueueLL/GonkBufferQueueDefs.h',
- 'GonkBufferQueueLL/GonkBufferQueueLL.h',
- 'GonkBufferQueueLL/GonkBufferQueueProducer.h',
- 'GonkBufferQueueLL/GonkBufferSlot.h',
- 'GonkConsumerBaseLL.h',
- 'GonkNativeWindowLL.h',
- 'IGonkGraphicBufferConsumerLL.h',
- ]
-elif CONFIG['ANDROID_VERSION'] >= '19':
- EXPORTS += [
- 'GonkBufferQueueKK.h',
- 'GonkConsumerBaseKK.h',
- 'GonkNativeWindowKK.h',
- 'IGonkGraphicBufferConsumerKK.h',
- ]
-elif CONFIG['ANDROID_VERSION'] in ('17', '18'):
- EXPORTS += [
- 'GonkBufferQueueJB.h',
- 'GonkConsumerBaseJB.h',
- 'GonkNativeWindowJB.h',
- ]
-
-if CONFIG['MOZ_WEBRTC']:
- if CONFIG['ANDROID_VERSION'] >= '21':
- SOURCES += [
- 'GonkBufferQueueLL/GonkBufferItem.cpp',
- 'GonkBufferQueueLL/GonkBufferQueueConsumer.cpp',
- 'GonkBufferQueueLL/GonkBufferQueueCore.cpp',
- 'GonkBufferQueueLL/GonkBufferQueueLL.cpp',
- 'GonkBufferQueueLL/GonkBufferQueueProducer.cpp',
- 'GonkBufferQueueLL/GonkBufferSlot.cpp',
- 'GonkConsumerBaseLL.cpp',
- 'GonkNativeWindowLL.cpp',
- 'IGonkGraphicBufferConsumerLL.cpp',
- ]
- elif CONFIG['ANDROID_VERSION'] >= '19':
- SOURCES += [
- 'GonkBufferQueueKK.cpp',
- 'GonkConsumerBaseKK.cpp',
- 'GonkNativeWindowKK.cpp',
- 'IGonkGraphicBufferConsumerKK.cpp',
- ]
- elif CONFIG['ANDROID_VERSION'] in ('17', '18'):
- SOURCES += [
- 'GonkBufferQueueJB.cpp',
- 'GonkConsumerBaseJB.cpp',
- 'GonkNativeWindowJB.cpp',
- ]
-
-if CONFIG['ANDROID_VERSION'] >= '18':
- SOURCES += [
- 'FakeSurfaceComposer.cpp',
- ]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-if CONFIG['ANDROID_VERSION'] >= '18':
- LOCAL_INCLUDES += [
- '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/native/opengl/include',
- ]
- ]
-
-DEFINES['HAVE_ANDROID_OS'] = True
-
-# Suppress some GCC warnings being treated as errors:
-# - about attributes on forward declarations for types that are already
-# defined, which complains about an important MOZ_EXPORT for android::AString
-if CONFIG['GNU_CC']:
- CXXFLAGS += ['-Wno-error=attributes', '-Wno-overloaded-virtual']
-
-FINAL_LIBRARY = 'xul'
-
-DISABLE_STL_WRAPPING = True
-
-NO_VISIBILITY_FLAGS = True
diff --git a/widget/gonk/nsAppShell.cpp b/widget/gonk/nsAppShell.cpp
deleted file mode 100644
index 24e791b4b..000000000
--- a/widget/gonk/nsAppShell.cpp
+++ /dev/null
@@ -1,1087 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim: set ts=4 sw=4 sts=4 tw=80 et: */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <hardware_legacy/power.h>
-#include <signal.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <utils/BitSet.h>
-
-#include "base/basictypes.h"
-#include "GonkPermission.h"
-#include "libdisplay/BootAnimation.h"
-#include "nscore.h"
-#include "mozilla/TouchEvents.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/Hal.h"
-#include "mozilla/MouseEvents.h"
-#include "mozilla/Mutex.h"
-#include "mozilla/Services.h"
-#include "mozilla/TextEvents.h"
-#if ANDROID_VERSION >= 18
-#include "nativewindow/FakeSurfaceComposer.h"
-#endif
-#include "nsAppShell.h"
-#include "mozilla/DebugOnly.h"
-#include "mozilla/dom/Touch.h"
-#include "nsGkAtoms.h"
-#include "nsIObserverService.h"
-#include "nsIScreen.h"
-#include "nsScreenManagerGonk.h"
-#include "nsThreadUtils.h"
-#include "nsWindow.h"
-#include "OrientationObserver.h"
-#include "GonkMemoryPressureMonitoring.h"
-
-#include "android/log.h"
-#include "libui/EventHub.h"
-#include "libui/InputReader.h"
-#include "libui/InputDispatcher.h"
-
-#include "mozilla/Preferences.h"
-#include "GeckoProfiler.h"
-
-// Defines kKeyMapping and GetKeyNameIndex()
-#include "GonkKeyMapping.h"
-#include "mozilla/layers/CompositorBridgeParent.h"
-#include "GeckoTouchDispatcher.h"
-
-#undef LOG
-#define LOG(args...) \
- __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
-#ifdef VERBOSE_LOG_ENABLED
-# define VERBOSE_LOG(args...) \
- __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
-#else
-# define VERBOSE_LOG(args...) \
- (void)0
-#endif
-
-using namespace android;
-using namespace mozilla;
-using namespace mozilla::dom;
-using namespace mozilla::services;
-using namespace mozilla::widget;
-
-bool gDrawRequest = false;
-static nsAppShell *gAppShell = nullptr;
-static int epollfd = 0;
-static int signalfds[2] = {0};
-static bool sDevInputAudioJack;
-static int32_t sHeadphoneState;
-static int32_t sMicrophoneState;
-
-// Amount of time in MS before an input is considered expired.
-static const uint64_t kInputExpirationThresholdMs = 1000;
-static const char kKey_WAKE_LOCK_ID[] = "GeckoKeyEvent";
-
-NS_IMPL_ISUPPORTS_INHERITED(nsAppShell, nsBaseAppShell, nsIObserver)
-
-static uint64_t
-nanosecsToMillisecs(nsecs_t nsecs)
-{
- return nsecs / 1000000;
-}
-
-namespace mozilla {
-
-bool ProcessNextEvent()
-{
- return gAppShell->ProcessNextNativeEvent(true);
-}
-
-void NotifyEvent()
-{
- gAppShell->NotifyNativeEvent();
-}
-
-} // namespace mozilla
-
-static void
-pipeHandler(int fd, FdHandler *data)
-{
- ssize_t len;
- do {
- char tmp[32];
- len = read(fd, tmp, sizeof(tmp));
- } while (len > 0);
-}
-
-struct Touch {
- int32_t id;
- PointerCoords coords;
-};
-
-struct UserInputData {
- uint64_t timeMs;
- enum {
- MOTION_DATA,
- KEY_DATA
- } type;
- int32_t action;
- int32_t flags;
- int32_t metaState;
- int32_t deviceId;
- union {
- struct {
- int32_t keyCode;
- int32_t scanCode;
- } key;
- struct {
- int32_t touchCount;
- ::Touch touches[MAX_POINTERS];
- } motion;
- };
-};
-
-static mozilla::Modifiers
-getDOMModifiers(int32_t metaState)
-{
- mozilla::Modifiers result = 0;
- if (metaState & (AMETA_ALT_ON | AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
- result |= MODIFIER_ALT;
- }
- if (metaState & (AMETA_SHIFT_ON |
- AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
- result |= MODIFIER_SHIFT;
- }
- if (metaState & AMETA_FUNCTION_ON) {
- result |= MODIFIER_FN;
- }
- if (metaState & (AMETA_CTRL_ON |
- AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
- result |= MODIFIER_CONTROL;
- }
- if (metaState & (AMETA_META_ON |
- AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) {
- result |= MODIFIER_META;
- }
- if (metaState & AMETA_CAPS_LOCK_ON) {
- result |= MODIFIER_CAPSLOCK;
- }
- if (metaState & AMETA_NUM_LOCK_ON) {
- result |= MODIFIER_NUMLOCK;
- }
- if (metaState & AMETA_SCROLL_LOCK_ON) {
- result |= MODIFIER_SCROLLLOCK;
- }
- return result;
-}
-
-class MOZ_STACK_CLASS KeyEventDispatcher
-{
-public:
- KeyEventDispatcher(const UserInputData& aData,
- KeyCharacterMap* aKeyCharMap);
- void Dispatch();
-
-private:
- const UserInputData& mData;
- sp<KeyCharacterMap> mKeyCharMap;
-
- char16_t mChar;
- char16_t mUnmodifiedChar;
-
- uint32_t mDOMKeyCode;
- uint32_t mDOMKeyLocation;
- KeyNameIndex mDOMKeyNameIndex;
- CodeNameIndex mDOMCodeNameIndex;
- char16_t mDOMPrintableKeyValue;
-
- bool IsKeyPress() const
- {
- return mData.action == AKEY_EVENT_ACTION_DOWN;
- }
- bool IsRepeat() const
- {
- return IsKeyPress() && (mData.flags & AKEY_EVENT_FLAG_LONG_PRESS);
- }
-
- char16_t PrintableKeyValue() const;
-
- int32_t UnmodifiedMetaState() const
- {
- return mData.metaState &
- ~(AMETA_ALT_ON | AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON |
- AMETA_CTRL_ON | AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON |
- AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
- }
-
- static bool IsControlChar(char16_t aChar)
- {
- return (aChar < ' ' || aChar == 0x7F);
- }
-
- void DispatchKeyDownEvent();
- void DispatchKeyUpEvent();
- nsEventStatus DispatchKeyEventInternal(EventMessage aEventMessage);
-};
-
-KeyEventDispatcher::KeyEventDispatcher(const UserInputData& aData,
- KeyCharacterMap* aKeyCharMap)
- : mData(aData)
- , mKeyCharMap(aKeyCharMap)
- , mChar(0)
- , mUnmodifiedChar(0)
- , mDOMPrintableKeyValue(0)
-{
- // XXX Printable key's keyCode value should be computed with actual
- // input character.
- mDOMKeyCode = (mData.key.keyCode < (ssize_t)ArrayLength(kKeyMapping)) ?
- kKeyMapping[mData.key.keyCode] : 0;
- mDOMKeyNameIndex = GetKeyNameIndex(mData.key.keyCode);
- mDOMCodeNameIndex = GetCodeNameIndex(mData.key.scanCode);
- mDOMKeyLocation =
- WidgetKeyboardEvent::ComputeLocationFromCodeValue(mDOMCodeNameIndex);
-
- if (!mKeyCharMap.get()) {
- return;
- }
-
- mChar = mKeyCharMap->getCharacter(mData.key.keyCode, mData.metaState);
- if (IsControlChar(mChar)) {
- mChar = 0;
- }
- int32_t unmodifiedMetaState = UnmodifiedMetaState();
- if (mData.metaState == unmodifiedMetaState) {
- mUnmodifiedChar = mChar;
- } else {
- mUnmodifiedChar = mKeyCharMap->getCharacter(mData.key.keyCode,
- unmodifiedMetaState);
- if (IsControlChar(mUnmodifiedChar)) {
- mUnmodifiedChar = 0;
- }
- }
-
- mDOMPrintableKeyValue = PrintableKeyValue();
-}
-
-char16_t
-KeyEventDispatcher::PrintableKeyValue() const
-{
- if (mDOMKeyNameIndex != KEY_NAME_INDEX_USE_STRING) {
- return 0;
- }
- return mChar ? mChar : mUnmodifiedChar;
-}
-
-nsEventStatus
-KeyEventDispatcher::DispatchKeyEventInternal(EventMessage aEventMessage)
-{
- WidgetKeyboardEvent event(true, aEventMessage, nullptr);
- if (aEventMessage == eKeyPress) {
- // XXX If the charCode is not a printable character, the charCode
- // should be computed without Ctrl/Alt/Meta modifiers.
- event.mCharCode = static_cast<uint32_t>(mChar);
- }
- if (!event.mCharCode) {
- event.mKeyCode = mDOMKeyCode;
- }
- event.mIsChar = !!event.mCharCode;
- event.mIsRepeat = IsRepeat();
- event.mKeyNameIndex = mDOMKeyNameIndex;
- if (mDOMPrintableKeyValue) {
- event.mKeyValue = mDOMPrintableKeyValue;
- }
- event.mCodeNameIndex = mDOMCodeNameIndex;
- event.mModifiers = getDOMModifiers(mData.metaState);
- event.mLocation = mDOMKeyLocation;
- event.mTime = mData.timeMs;
- return nsWindow::DispatchKeyInput(event);
-}
-
-void
-KeyEventDispatcher::Dispatch()
-{
- // XXX Even if unknown key is pressed, DOM key event should be
- // dispatched since Gecko for the other platforms are implemented
- // as so.
- if (!mDOMKeyCode && mDOMKeyNameIndex == KEY_NAME_INDEX_Unidentified) {
- VERBOSE_LOG("Got unknown key event code. "
- "type 0x%04x code 0x%04x value %d",
- mData.action, mData.key.keyCode, IsKeyPress());
- return;
- }
-
- if (IsKeyPress()) {
- DispatchKeyDownEvent();
- } else {
- DispatchKeyUpEvent();
- }
-}
-
-void
-KeyEventDispatcher::DispatchKeyDownEvent()
-{
- nsEventStatus status = DispatchKeyEventInternal(eKeyDown);
- if (status != nsEventStatus_eConsumeNoDefault) {
- DispatchKeyEventInternal(eKeyPress);
- }
-}
-
-void
-KeyEventDispatcher::DispatchKeyUpEvent()
-{
- DispatchKeyEventInternal(eKeyUp);
-}
-
-class SwitchEventRunnable : public mozilla::Runnable {
-public:
- SwitchEventRunnable(hal::SwitchEvent& aEvent) : mEvent(aEvent)
- {}
-
- NS_IMETHOD Run() override
- {
- hal::NotifySwitchStateFromInputDevice(mEvent.device(),
- mEvent.status());
- return NS_OK;
- }
-private:
- hal::SwitchEvent mEvent;
-};
-
-static void
-updateHeadphoneSwitch()
-{
- hal::SwitchEvent event;
-
- switch (sHeadphoneState) {
- case AKEY_STATE_UP:
- event.status() = hal::SWITCH_STATE_OFF;
- break;
- case AKEY_STATE_DOWN:
- event.status() = sMicrophoneState == AKEY_STATE_DOWN ?
- hal::SWITCH_STATE_HEADSET : hal::SWITCH_STATE_HEADPHONE;
- break;
- default:
- return;
- }
-
- event.device() = hal::SWITCH_HEADPHONES;
- NS_DispatchToMainThread(new SwitchEventRunnable(event));
-}
-
-class GeckoPointerController : public PointerControllerInterface {
- float mX;
- float mY;
- int32_t mButtonState;
- InputReaderConfiguration* mConfig;
-public:
- GeckoPointerController(InputReaderConfiguration* config)
- : mX(0)
- , mY(0)
- , mButtonState(0)
- , mConfig(config)
- {}
-
- virtual bool getBounds(float* outMinX, float* outMinY,
- float* outMaxX, float* outMaxY) const;
- virtual void move(float deltaX, float deltaY);
- virtual void setButtonState(int32_t buttonState);
- virtual int32_t getButtonState() const;
- virtual void setPosition(float x, float y);
- virtual void getPosition(float* outX, float* outY) const;
- virtual void fade(Transition transition) {}
- virtual void unfade(Transition transition) {}
- virtual void setPresentation(Presentation presentation) {}
- virtual void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
- BitSet32 spotIdBits) {}
- virtual void clearSpots() {}
-};
-
-bool
-GeckoPointerController::getBounds(float* outMinX,
- float* outMinY,
- float* outMaxX,
- float* outMaxY) const
-{
- DisplayViewport viewport;
-
- mConfig->getDisplayInfo(false, &viewport);
-
- *outMinX = *outMinY = 0;
- *outMaxX = viewport.logicalRight;
- *outMaxY = viewport.logicalBottom;
- return true;
-}
-
-void
-GeckoPointerController::move(float deltaX, float deltaY)
-{
- float minX, minY, maxX, maxY;
- getBounds(&minX, &minY, &maxX, &maxY);
-
- mX = clamped(mX + deltaX, minX, maxX);
- mY = clamped(mY + deltaY, minY, maxY);
-}
-
-void
-GeckoPointerController::setButtonState(int32_t buttonState)
-{
- mButtonState = buttonState;
-}
-
-int32_t
-GeckoPointerController::getButtonState() const
-{
- return mButtonState;
-}
-
-void
-GeckoPointerController::setPosition(float x, float y)
-{
- mX = x;
- mY = y;
-}
-
-void
-GeckoPointerController::getPosition(float* outX, float* outY) const
-{
- *outX = mX;
- *outY = mY;
-}
-
-class GeckoInputReaderPolicy : public InputReaderPolicyInterface {
- InputReaderConfiguration mConfig;
-public:
- GeckoInputReaderPolicy() {}
-
- virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
- virtual sp<PointerControllerInterface> obtainPointerController(int32_t
-deviceId)
- {
- return new GeckoPointerController(&mConfig);
- };
- virtual void notifyInputDevicesChanged(const android::Vector<InputDeviceInfo>& inputDevices) {};
- virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor)
- {
- return nullptr;
- };
- virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier)
- {
- return String8::empty();
- };
-
- void setDisplayInfo();
-
-protected:
- virtual ~GeckoInputReaderPolicy() {}
-};
-
-class GeckoInputDispatcher : public InputDispatcherInterface {
-public:
- GeckoInputDispatcher(sp<EventHub> &aEventHub)
- : mQueueLock("GeckoInputDispatcher::mQueueMutex")
- , mEventHub(aEventHub)
- , mKeyDownCount(0)
- , mKeyEventsFiltered(false)
- , mPowerWakelock(false)
- {
- mTouchDispatcher = GeckoTouchDispatcher::GetInstance();
- }
-
- virtual void dump(String8& dump);
-
- virtual void monitor() {}
-
- // Called on the main thread
- virtual void dispatchOnce();
-
- // notify* methods are called on the InputReaderThread
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
- virtual void notifyKey(const NotifyKeyArgs* args);
- virtual void notifyMotion(const NotifyMotionArgs* args);
- virtual void notifySwitch(const NotifySwitchArgs* args);
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
-
- virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
- uint32_t policyFlags);
-
- virtual void setInputWindows(const android::Vector<sp<InputWindowHandle> >& inputWindowHandles);
- virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
-
- virtual void setInputDispatchMode(bool enabled, bool frozen);
- virtual void setInputFilterEnabled(bool enabled) {}
- virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel) { return true; }
-
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
- virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
-
-
-
-protected:
- virtual ~GeckoInputDispatcher() { }
-
-private:
- // mQueueLock should generally be locked while using mEventQueue.
- // UserInputData is pushed on on the InputReaderThread and
- // popped and dispatched on the main thread.
- mozilla::Mutex mQueueLock;
- std::queue<UserInputData> mEventQueue;
- sp<EventHub> mEventHub;
- RefPtr<GeckoTouchDispatcher> mTouchDispatcher;
-
- int mKeyDownCount;
- bool mKeyEventsFiltered;
- bool mPowerWakelock;
-};
-
-// GeckoInputReaderPolicy
-void
-GeckoInputReaderPolicy::setDisplayInfo()
-{
- static_assert(static_cast<int>(nsIScreen::ROTATION_0_DEG) ==
- static_cast<int>(DISPLAY_ORIENTATION_0),
- "Orientation enums not matched!");
- static_assert(static_cast<int>(nsIScreen::ROTATION_90_DEG) ==
- static_cast<int>(DISPLAY_ORIENTATION_90),
- "Orientation enums not matched!");
- static_assert(static_cast<int>(nsIScreen::ROTATION_180_DEG) ==
- static_cast<int>(DISPLAY_ORIENTATION_180),
- "Orientation enums not matched!");
- static_assert(static_cast<int>(nsIScreen::ROTATION_270_DEG) ==
- static_cast<int>(DISPLAY_ORIENTATION_270),
- "Orientation enums not matched!");
-
- RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen();
-
- uint32_t rotation = nsIScreen::ROTATION_0_DEG;
- DebugOnly<nsresult> rv = screen->GetRotation(&rotation);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- LayoutDeviceIntRect screenBounds = screen->GetNaturalBounds();
-
- DisplayViewport viewport;
- viewport.displayId = 0;
- viewport.orientation = rotation;
- viewport.physicalRight = viewport.deviceWidth = screenBounds.width;
- viewport.physicalBottom = viewport.deviceHeight = screenBounds.height;
- if (viewport.orientation == DISPLAY_ORIENTATION_90 ||
- viewport.orientation == DISPLAY_ORIENTATION_270) {
- viewport.logicalRight = screenBounds.height;
- viewport.logicalBottom = screenBounds.width;
- } else {
- viewport.logicalRight = screenBounds.width;
- viewport.logicalBottom = screenBounds.height;
- }
- mConfig.setDisplayInfo(false, viewport);
-}
-
-void GeckoInputReaderPolicy::getReaderConfiguration(InputReaderConfiguration* outConfig)
-{
- *outConfig = mConfig;
-}
-
-
-// GeckoInputDispatcher
-void
-GeckoInputDispatcher::dump(String8& dump)
-{
-}
-
-static bool
-isExpired(const UserInputData& data)
-{
- uint64_t timeNowMs =
- nanosecsToMillisecs(systemTime(SYSTEM_TIME_MONOTONIC));
- return (timeNowMs - data.timeMs) > kInputExpirationThresholdMs;
-}
-
-void
-GeckoInputDispatcher::dispatchOnce()
-{
- UserInputData data;
- {
- MutexAutoLock lock(mQueueLock);
- if (mEventQueue.empty())
- return;
- data = mEventQueue.front();
- mEventQueue.pop();
- if (!mEventQueue.empty())
- gAppShell->NotifyNativeEvent();
- }
-
- switch (data.type) {
- case UserInputData::MOTION_DATA: {
- MOZ_ASSERT_UNREACHABLE("Should not dispatch touch events here anymore");
- break;
- }
- case UserInputData::KEY_DATA: {
- if (!mKeyDownCount) {
- // No pending events, the filter state can be updated.
- mKeyEventsFiltered = isExpired(data);
- }
-
- mKeyDownCount += (data.action == AKEY_EVENT_ACTION_DOWN) ? 1 : -1;
- if (mKeyEventsFiltered) {
- return;
- }
-
- sp<KeyCharacterMap> kcm = mEventHub->getKeyCharacterMap(data.deviceId);
- KeyEventDispatcher dispatcher(data, kcm.get());
- dispatcher.Dispatch();
- break;
- }
- }
- MutexAutoLock lock(mQueueLock);
- if (mPowerWakelock && mEventQueue.empty()) {
- release_wake_lock(kKey_WAKE_LOCK_ID);
- mPowerWakelock = false;
- }
-}
-
-void
-GeckoInputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs*)
-{
- gAppShell->CheckPowerKey();
-}
-
-void
-GeckoInputDispatcher::notifyKey(const NotifyKeyArgs* args)
-{
- UserInputData data;
- data.timeMs = nanosecsToMillisecs(args->eventTime);
- data.type = UserInputData::KEY_DATA;
- data.action = args->action;
- data.flags = args->flags;
- data.metaState = args->metaState;
- data.deviceId = args->deviceId;
- data.key.keyCode = args->keyCode;
- data.key.scanCode = args->scanCode;
- {
- MutexAutoLock lock(mQueueLock);
- mEventQueue.push(data);
- if (!mPowerWakelock) {
- mPowerWakelock =
- acquire_wake_lock(PARTIAL_WAKE_LOCK, kKey_WAKE_LOCK_ID);
- }
- }
- gAppShell->NotifyNativeEvent();
-}
-
-static void
-addMultiTouch(MultiTouchInput& aMultiTouch,
- const NotifyMotionArgs* args, int aIndex)
-{
- int32_t id = args->pointerProperties[aIndex].id;
- PointerCoords coords = args->pointerCoords[aIndex];
- float force = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
-
- float orientation = coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
- float rotationAngle = orientation * 180 / M_PI;
- if (rotationAngle == 90) {
- rotationAngle = -90;
- }
-
- float radiusX, radiusY;
- if (rotationAngle < 0) {
- radiusX = coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR) / 2;
- radiusY = coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR) / 2;
- rotationAngle += 90;
- } else {
- radiusX = coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR) / 2;
- radiusY = coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR) / 2;
- }
-
- ScreenIntPoint point = ScreenIntPoint::Round(coords.getX(),
- coords.getY());
-
- SingleTouchData touchData(id, point, ScreenSize(radiusX, radiusY),
- rotationAngle, force);
-
- aMultiTouch.mTouches.AppendElement(touchData);
-}
-
-void
-GeckoInputDispatcher::notifyMotion(const NotifyMotionArgs* args)
-{
- uint32_t time = nanosecsToMillisecs(args->eventTime);
- int32_t action = args->action & AMOTION_EVENT_ACTION_MASK;
- int touchCount = args->pointerCount;
- MOZ_ASSERT(touchCount <= MAX_POINTERS);
- TimeStamp timestamp = mozilla::TimeStamp::FromSystemTime(args->eventTime);
- Modifiers modifiers = getDOMModifiers(args->metaState);
-
- MultiTouchInput::MultiTouchType touchType = MultiTouchInput::MULTITOUCH_CANCEL;
- switch (action) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- touchType = MultiTouchInput::MULTITOUCH_START;
- break;
- case AMOTION_EVENT_ACTION_MOVE:
- touchType = MultiTouchInput::MULTITOUCH_MOVE;
- break;
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_POINTER_UP:
- touchType = MultiTouchInput::MULTITOUCH_END;
- break;
- case AMOTION_EVENT_ACTION_OUTSIDE:
- case AMOTION_EVENT_ACTION_CANCEL:
- touchType = MultiTouchInput::MULTITOUCH_CANCEL;
- break;
- case AMOTION_EVENT_ACTION_HOVER_EXIT:
- case AMOTION_EVENT_ACTION_HOVER_ENTER:
- case AMOTION_EVENT_ACTION_HOVER_MOVE:
- NS_WARNING("Ignoring hover touch events");
- return;
- default:
- MOZ_ASSERT_UNREACHABLE("Could not assign a touch type");
- break;
- }
-
- MultiTouchInput touchData(touchType, time, timestamp, modifiers);
-
- // For touch ends, we have to filter out which finger is actually
- // the touch end since the touch array has all fingers, not just the touch
- // that we want to end
- if (touchType == MultiTouchInput::MULTITOUCH_END) {
- int touchIndex = args->action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK;
- touchIndex >>= AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
- addMultiTouch(touchData, args, touchIndex);
- } else {
- for (int32_t i = 0; i < touchCount; ++i) {
- addMultiTouch(touchData, args, i);
- }
- }
-
- mTouchDispatcher->NotifyTouch(touchData, timestamp);
-}
-
-void GeckoInputDispatcher::notifySwitch(const NotifySwitchArgs* args)
-{
- if (!sDevInputAudioJack)
- return;
-
- bool needSwitchUpdate = false;
-
- if (args->switchMask & (1 << SW_HEADPHONE_INSERT)) {
- sHeadphoneState = (args->switchValues & (1 << SW_HEADPHONE_INSERT)) ?
- AKEY_STATE_DOWN : AKEY_STATE_UP;
- needSwitchUpdate = true;
- }
-
- if (args->switchMask & (1 << SW_MICROPHONE_INSERT)) {
- sMicrophoneState = (args->switchValues & (1 << SW_MICROPHONE_INSERT)) ?
- AKEY_STATE_DOWN : AKEY_STATE_UP;
- needSwitchUpdate = true;
- }
-
- if (needSwitchUpdate)
- updateHeadphoneSwitch();
-}
-
-void GeckoInputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args)
-{
-}
-
-int32_t GeckoInputDispatcher::injectInputEvent(
- const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode,
- int32_t timeoutMillis, uint32_t policyFlags)
-{
- return INPUT_EVENT_INJECTION_SUCCEEDED;
-}
-
-void
-GeckoInputDispatcher::setInputWindows(const android::Vector<sp<InputWindowHandle> >& inputWindowHandles)
-{
-}
-
-void
-GeckoInputDispatcher::setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle)
-{
-}
-
-void
-GeckoInputDispatcher::setInputDispatchMode(bool enabled, bool frozen)
-{
-}
-
-status_t
-GeckoInputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor)
-{
- return OK;
-}
-
-status_t
-GeckoInputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel)
-{
- return OK;
-}
-
-nsAppShell::nsAppShell()
- : mNativeCallbackRequest(false)
- , mEnableDraw(false)
- , mHandlers()
- , mPowerKeyChecked(false)
-{
- gAppShell = this;
- if (XRE_IsParentProcess()) {
- Preferences::SetCString("b2g.safe_mode", "unset");
- }
-}
-
-nsAppShell::~nsAppShell()
-{
- // mReaderThread and mEventHub will both be null if InitInputDevices
- // is not called.
- if (mReaderThread.get()) {
- // We separate requestExit() and join() here so we can wake the EventHub's
- // input loop, and stop it from polling for input events
- mReaderThread->requestExit();
- mEventHub->wake();
-
- status_t result = mReaderThread->requestExitAndWait();
- if (result)
- LOG("Could not stop reader thread - %d", result);
- }
- gAppShell = nullptr;
-}
-
-nsresult
-nsAppShell::Init()
-{
- nsresult rv = nsBaseAppShell::Init();
- NS_ENSURE_SUCCESS(rv, rv);
-
- epollfd = epoll_create(16);
- NS_ENSURE_TRUE(epollfd >= 0, NS_ERROR_UNEXPECTED);
-
- int ret = pipe2(signalfds, O_NONBLOCK);
- NS_ENSURE_FALSE(ret, NS_ERROR_UNEXPECTED);
-
- rv = AddFdHandler(signalfds[0], pipeHandler, "");
- NS_ENSURE_SUCCESS(rv, rv);
-
- InitGonkMemoryPressureMonitoring();
-
- if (XRE_IsParentProcess()) {
- printf("*****************************************************************\n");
- printf("***\n");
- printf("*** This is stdout. Most of the useful output will be in logcat.\n");
- printf("***\n");
- printf("*****************************************************************\n");
- GonkPermissionService::instantiate();
-
- // Causes the kernel timezone to be set, which in turn causes the
- // timestamps on SD cards to have the local time rather than UTC time.
- hal::SetTimezone(hal::GetTimezone());
- }
-
- nsCOMPtr<nsIObserverService> obsServ = GetObserverService();
- if (obsServ) {
- obsServ->AddObserver(this, "browser-ui-startup-complete", false);
- obsServ->AddObserver(this, "network-connection-state-changed", false);
- }
-
- // Delay initializing input devices until the screen has been
- // initialized (and we know the resolution).
- return rv;
-}
-
-void
-nsAppShell::CheckPowerKey()
-{
- if (mPowerKeyChecked) {
- return;
- }
-
- uint32_t deviceId = 0;
- int32_t powerState = AKEY_STATE_UNKNOWN;
-
- // EventHub doesn't report the number of devices.
- while (powerState != AKEY_STATE_DOWN && deviceId < 32) {
- powerState = mEventHub->getKeyCodeState(deviceId++, AKEYCODE_POWER);
- }
-
- // If Power is pressed while we startup, mark safe mode.
- // Consumers of the b2g.safe_mode preference need to listen on this
- // preference change to prevent startup races.
- nsCOMPtr<nsIRunnable> prefSetter =
- NS_NewRunnableFunction([powerState] () -> void {
- Preferences::SetCString("b2g.safe_mode",
- (powerState == AKEY_STATE_DOWN) ? "yes" : "no");
- });
- NS_DispatchToMainThread(prefSetter.forget());
-
- mPowerKeyChecked = true;
-}
-
-NS_IMETHODIMP
-nsAppShell::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- if (!strcmp(aTopic, "network-connection-state-changed")) {
- NS_ConvertUTF16toUTF8 type(aData);
- if (!type.IsEmpty()) {
- hal::NotifyNetworkChange(hal::NetworkInformation(atoi(type.get()), 0, 0));
- }
- return NS_OK;
- } else if (!strcmp(aTopic, "browser-ui-startup-complete")) {
- if (sDevInputAudioJack) {
- sHeadphoneState = mReader->getSwitchState(-1, AINPUT_SOURCE_SWITCH, SW_HEADPHONE_INSERT);
- sMicrophoneState = mReader->getSwitchState(-1, AINPUT_SOURCE_SWITCH, SW_MICROPHONE_INSERT);
- updateHeadphoneSwitch();
- }
- mEnableDraw = true;
-
- // System is almost booting up. Stop the bootAnim now.
- StopBootAnimation();
-
- NotifyEvent();
- return NS_OK;
- }
-
- return nsBaseAppShell::Observe(aSubject, aTopic, aData);
-}
-
-NS_IMETHODIMP
-nsAppShell::Exit()
-{
- OrientationObserver::ShutDown();
- nsCOMPtr<nsIObserverService> obsServ = GetObserverService();
- if (obsServ) {
- obsServ->RemoveObserver(this, "browser-ui-startup-complete");
- obsServ->RemoveObserver(this, "network-connection-state-changed");
- }
- return nsBaseAppShell::Exit();
-}
-
-void
-nsAppShell::InitInputDevices()
-{
- sDevInputAudioJack = hal::IsHeadphoneEventFromInputDev();
- sHeadphoneState = AKEY_STATE_UNKNOWN;
- sMicrophoneState = AKEY_STATE_UNKNOWN;
-
- mEventHub = new EventHub();
- mReaderPolicy = new GeckoInputReaderPolicy();
- mReaderPolicy->setDisplayInfo();
- mDispatcher = new GeckoInputDispatcher(mEventHub);
-
- mReader = new InputReader(mEventHub, mReaderPolicy, mDispatcher);
- mReaderThread = new InputReaderThread(mReader);
-
- status_t result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
- if (result) {
- LOG("Failed to initialize InputReader thread, bad things are going to happen...");
- }
-}
-
-nsresult
-nsAppShell::AddFdHandler(int fd, FdHandlerCallback handlerFunc,
- const char* deviceName)
-{
- epoll_event event = {
- EPOLLIN,
- { 0 }
- };
-
- FdHandler *handler = mHandlers.AppendElement();
- handler->fd = fd;
- strncpy(handler->name, deviceName, sizeof(handler->name) - 1);
- handler->func = handlerFunc;
- event.data.u32 = mHandlers.Length() - 1;
- return epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event) ?
- NS_ERROR_UNEXPECTED : NS_OK;
-}
-
-void
-nsAppShell::ScheduleNativeEventCallback()
-{
- mNativeCallbackRequest = true;
- NotifyEvent();
-}
-
-bool
-nsAppShell::ProcessNextNativeEvent(bool mayWait)
-{
- PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent",
- js::ProfileEntry::Category::EVENTS);
-
- epoll_event events[16] = {{ 0 }};
-
- int event_count;
- {
- PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent::Wait",
- js::ProfileEntry::Category::EVENTS);
-
- if ((event_count = epoll_wait(epollfd, events, 16, mayWait ? -1 : 0)) <= 0)
- return true;
- }
-
- for (int i = 0; i < event_count; i++)
- mHandlers[events[i].data.u32].run();
-
- if (mDispatcher.get())
- mDispatcher->dispatchOnce();
-
- // NativeEventCallback always schedules more if it needs it
- // so we can coalesce these.
- // See the implementation in nsBaseAppShell.cpp for more info
- if (mNativeCallbackRequest) {
- mNativeCallbackRequest = false;
- NativeEventCallback();
- }
-
- if (gDrawRequest && mEnableDraw) {
- gDrawRequest = false;
- nsWindow::DoDraw();
- }
-
- return true;
-}
-
-void
-nsAppShell::NotifyNativeEvent()
-{
- write(signalfds[1], "w", 1);
-}
-
-/* static */ void
-nsAppShell::NotifyScreenInitialized()
-{
- gAppShell->InitInputDevices();
-
- // Getting the instance of OrientationObserver to initialize it.
- OrientationObserver::GetInstance();
-}
-
-/* static */ void
-nsAppShell::NotifyScreenRotation()
-{
- gAppShell->mReaderPolicy->setDisplayInfo();
- gAppShell->mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
-
- RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen();
- hal::NotifyScreenConfigurationChange(screen->GetConfiguration());
-}
diff --git a/widget/gonk/nsAppShell.h b/widget/gonk/nsAppShell.h
deleted file mode 100644
index 046a99ea1..000000000
--- a/widget/gonk/nsAppShell.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 nsAppShell_h
-#define nsAppShell_h
-
-#include <queue>
-
-#include "mozilla/Mutex.h"
-#include "nsBaseAppShell.h"
-#include "nsTArray.h"
-
-#include "utils/RefBase.h"
-
-namespace mozilla {
-bool ProcessNextEvent();
-void NotifyEvent();
-}
-
-extern bool gDrawRequest;
-
-class FdHandler;
-typedef void(*FdHandlerCallback)(int, FdHandler *);
-
-class FdHandler {
-public:
- FdHandler()
- {
- memset(name, 0, sizeof(name));
- }
-
- int fd;
- char name[64];
- FdHandlerCallback func;
- void run()
- {
- func(fd, this);
- }
-};
-
-namespace android {
-class EventHub;
-class InputReader;
-class InputReaderThread;
-}
-
-class GeckoInputReaderPolicy;
-class GeckoInputDispatcher;
-
-class nsAppShell : public nsBaseAppShell {
-public:
- nsAppShell();
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIOBSERVER
-
- nsresult Init();
-
- NS_IMETHOD Exit() override;
-
- virtual bool ProcessNextNativeEvent(bool maywait);
-
- void NotifyNativeEvent();
-
- static void NotifyScreenInitialized();
- static void NotifyScreenRotation();
-
- void CheckPowerKey();
-
-protected:
- virtual ~nsAppShell();
-
- virtual void ScheduleNativeEventCallback();
-
-private:
- nsresult AddFdHandler(int fd, FdHandlerCallback handlerFunc,
- const char* deviceName);
- void InitInputDevices();
-
- // This is somewhat racy but is perfectly safe given how the callback works
- bool mNativeCallbackRequest;
-
- // This gets flipped when we observe a browser-ui-startup-complete.
- // browser-ui-startup-complete means that we're really ready to draw
- // and can stop the boot animation
- bool mEnableDraw;
- nsTArray<FdHandler> mHandlers;
-
- android::sp<android::EventHub> mEventHub;
- android::sp<GeckoInputReaderPolicy> mReaderPolicy;
- android::sp<GeckoInputDispatcher> mDispatcher;
- android::sp<android::InputReader> mReader;
- android::sp<android::InputReaderThread> mReaderThread;
-
- // Guard against checking power key after the first configuration change.
- bool mPowerKeyChecked;
-};
-
-#endif /* nsAppShell_h */
-
diff --git a/widget/gonk/nsClipboard.cpp b/widget/gonk/nsClipboard.cpp
deleted file mode 100644
index a1eabe8e5..000000000
--- a/widget/gonk/nsClipboard.cpp
+++ /dev/null
@@ -1,366 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsClipboard.h"
-
-#include "gfxDrawable.h"
-#include "gfxUtils.h"
-#include "ImageOps.h"
-#include "imgIContainer.h"
-#include "imgTools.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/Preferences.h"
-#include "nsArrayUtils.h"
-#include "nsClipboardProxy.h"
-#include "nsISupportsPrimitives.h"
-#include "nsComponentManagerUtils.h"
-#include "nsCOMPtr.h"
-#include "nsServiceManagerUtils.h"
-#include "nsStringStream.h"
-#include "nsXULAppAPI.h"
-
-using namespace mozilla;
-using mozilla::dom::ContentChild;
-
-#define LOG_TAG "Clipboard"
-#define LOGI(args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, ## args)
-#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, ## args)
-
-
-NS_IMPL_ISUPPORTS(nsClipboard, nsIClipboard)
-
-nsClipboard::nsClipboard()
- : mClipboard(mozilla::MakeUnique<GonkClipboardData>())
-{
-}
-
-NS_IMETHODIMP
-nsClipboard::SetData(nsITransferable *aTransferable,
- nsIClipboardOwner *anOwner,
- int32_t aWhichClipboard)
-{
- if (aWhichClipboard != kGlobalClipboard) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-
- if (!XRE_IsParentProcess()) {
- // Re-direct to the clipboard proxy.
- RefPtr<nsClipboardProxy> clipboardProxy = new nsClipboardProxy();
- return clipboardProxy->SetData(aTransferable, anOwner, aWhichClipboard);
- }
-
- // Clear out the clipboard in order to set the new data.
- EmptyClipboard(aWhichClipboard);
-
- // Use a pref to toggle rich text/non-text support.
- if (Preferences::GetBool("clipboard.plainTextOnly")) {
- nsCOMPtr<nsISupports> clip;
- uint32_t len;
- nsresult rv = aTransferable->GetTransferData(kUnicodeMime,
- getter_AddRefs(clip),
- &len);
- if (NS_FAILED(rv)) {
- return rv;
- }
- nsCOMPtr<nsISupportsString> wideString = do_QueryInterface(clip);
- if (!wideString) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- nsAutoString utf16string;
- wideString->GetData(utf16string);
- mClipboard->SetText(utf16string);
- return NS_OK;
- }
-
- // Get the types of supported flavors.
- nsCOMPtr<nsIArray> flavorList;
- nsresult rv = aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
- if (!flavorList || NS_FAILED(rv)) {
- return NS_ERROR_FAILURE;
- }
-
- uint32_t flavorCount = 0;
- flavorList->GetLength(&flavorCount);
- bool imageAdded = false;
- for (uint32_t i = 0; i < flavorCount; ++i) {
- nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
-
- if (currentFlavor) {
- // MIME type
- nsXPIDLCString flavorStr;
- currentFlavor->ToString(getter_Copies(flavorStr));
-
- // Clip is the data which will be sent to the clipboard.
- nsCOMPtr<nsISupports> clip;
- uint32_t len;
-
- if (flavorStr.EqualsLiteral(kUnicodeMime)) {
- // text/plain
- rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(clip), &len);
- nsCOMPtr<nsISupportsString> wideString = do_QueryInterface(clip);
- if (!wideString || NS_FAILED(rv)) {
- continue;
- }
-
- nsAutoString utf16string;
- wideString->GetData(utf16string);
- mClipboard->SetText(utf16string);
- } else if (flavorStr.EqualsLiteral(kHTMLMime)) {
- // text/html
- rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(clip), &len);
- nsCOMPtr<nsISupportsString> wideString = do_QueryInterface(clip);
- if (!wideString || NS_FAILED(rv)) {
- continue;
- }
-
- nsAutoString utf16string;
- wideString->GetData(utf16string);
- mClipboard->SetHTML(utf16string);
- } else if (!imageAdded && // image is added only once to the clipboard.
- (flavorStr.EqualsLiteral(kNativeImageMime) ||
- flavorStr.EqualsLiteral(kPNGImageMime) ||
- flavorStr.EqualsLiteral(kJPEGImageMime) ||
- flavorStr.EqualsLiteral(kJPGImageMime))) {
- // image/[png|jpeg|jpg] or application/x-moz-nativeimage
-
- // Look through our transfer data for the image.
- static const char* const imageMimeTypes[] = {
- kNativeImageMime, kPNGImageMime, kJPEGImageMime, kJPGImageMime };
-
- nsCOMPtr<nsISupportsInterfacePointer> imgPtr;
- for (uint32_t i = 0; !imgPtr && i < ArrayLength(imageMimeTypes); ++i) {
- aTransferable->GetTransferData(imageMimeTypes[i], getter_AddRefs(clip), &len);
- imgPtr = do_QueryInterface(clip);
- }
- if (!imgPtr) {
- continue;
- }
-
- nsCOMPtr<nsISupports> imageData;
- imgPtr->GetData(getter_AddRefs(imageData));
- nsCOMPtr<imgIContainer> image(do_QueryInterface(imageData));
- if (!image) {
- continue;
- }
-
- RefPtr<gfx::SourceSurface> surface =
- image->GetFrame(imgIContainer::FRAME_CURRENT,
- imgIContainer::FLAG_SYNC_DECODE);
- if (!surface) {
- continue;
- }
-
- RefPtr<gfx::DataSourceSurface> dataSurface;
- if (surface->GetFormat() == gfx::SurfaceFormat::B8G8R8A8) {
- dataSurface = surface->GetDataSurface();
- } else {
- // Convert format to SurfaceFormat::B8G8R8A8.
- dataSurface = gfxUtils::CopySurfaceToDataSourceSurfaceWithFormat(surface, gfx::SurfaceFormat::B8G8R8A8);
- }
-
- mClipboard->SetImage(dataSurface);
- imageAdded = true;
- }
- }
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsClipboard::GetData(nsITransferable *aTransferable,
- int32_t aWhichClipboard)
-{
- if (aWhichClipboard != kGlobalClipboard) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-
- if (!XRE_IsParentProcess()) {
- // Re-direct to the clipboard proxy.
- RefPtr<nsClipboardProxy> clipboardProxy = new nsClipboardProxy();
- return clipboardProxy->GetData(aTransferable, aWhichClipboard);
- }
-
- // Use a pref to toggle rich text/non-text support.
- if (Preferences::GetBool("clipboard.plainTextOnly")) {
- nsresult rv;
- nsCOMPtr<nsISupportsString> dataWrapper =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
- rv = dataWrapper->SetData(mClipboard->GetText());
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- nsCOMPtr<nsISupports> genericDataWrapper = do_QueryInterface(dataWrapper);
- uint32_t len = mClipboard->GetText().Length() * sizeof(char16_t);
- rv = aTransferable->SetTransferData(kUnicodeMime, genericDataWrapper, len);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return NS_OK;
- }
-
- // Get flavor list that includes all acceptable flavors (including
- // ones obtained through conversion).
- // Note: We don't need to call nsITransferable::AddDataFlavor here
- // because ContentParent already did.
- nsCOMPtr<nsIArray> flavorList;
- nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
-
- if (!flavorList || NS_FAILED(rv)) {
- return NS_ERROR_FAILURE;
- }
-
- // Walk through flavors and see which flavor matches the one being pasted.
- uint32_t flavorCount;
- flavorList->GetLength(&flavorCount);
-
- for (uint32_t i = 0; i < flavorCount; ++i) {
- nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
-
- if (currentFlavor) {
- // flavorStr is the mime type.
- nsXPIDLCString flavorStr;
- currentFlavor->ToString(getter_Copies(flavorStr));
-
- // text/plain, text/Unicode
- if (flavorStr.EqualsLiteral(kUnicodeMime) && mClipboard->HasText()) {
- nsresult rv;
- nsCOMPtr<nsISupportsString> dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
- rv = dataWrapper->SetData(mClipboard->GetText());
- if (NS_WARN_IF(NS_FAILED(rv))) {
- continue;
- }
-
- nsCOMPtr<nsISupports> genericDataWrapper = do_QueryInterface(dataWrapper);
- uint32_t len = mClipboard->GetText().Length() * sizeof(char16_t);
- rv = aTransferable->SetTransferData(flavorStr, genericDataWrapper, len);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- continue;
- }
- break;
- }
-
- // text/html
- if (flavorStr.EqualsLiteral(kHTMLMime) && mClipboard->HasHTML()) {
- nsresult rv;
- nsCOMPtr<nsISupportsString> dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
- rv = dataWrapper->SetData(mClipboard->GetHTML());
- if (NS_WARN_IF(NS_FAILED(rv))) {
- continue;
- }
-
- nsCOMPtr<nsISupports> genericDataWrapper = do_QueryInterface(dataWrapper);
- uint32_t len = mClipboard->GetHTML().Length() * sizeof(char16_t);
- rv = aTransferable->SetTransferData(flavorStr, genericDataWrapper, len);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- continue;
- }
- break;
- }
-
- // image/[png|jpeg|jpg]
- if ((flavorStr.EqualsLiteral(kPNGImageMime) ||
- flavorStr.EqualsLiteral(kJPEGImageMime) ||
- flavorStr.EqualsLiteral(kJPGImageMime)) &&
- mClipboard->HasImage() ) {
- // Get image buffer from clipboard.
- RefPtr<gfx::DataSourceSurface> image = mClipboard->GetImage();
-
- // Encode according to MIME type.
- RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, image->GetSize());
- nsCOMPtr<imgIContainer> imageContainer(image::ImageOps::CreateFromDrawable(drawable));
- nsCOMPtr<imgITools> imgTool = do_GetService(NS_IMGTOOLS_CID);
-
- nsCOMPtr<nsIInputStream> byteStream;
- nsresult rv = imgTool->EncodeImage(imageContainer,
- flavorStr,
- EmptyString(),
- getter_AddRefs(byteStream));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- continue;
- }
-
- // Set transferable.
- rv = aTransferable->SetTransferData(flavorStr,
- byteStream,
- sizeof(nsIInputStream*));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- continue;
- }
- break;
- }
- }
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
-{
- if (aWhichClipboard != kGlobalClipboard) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- if (XRE_IsParentProcess()) {
- mClipboard->Clear();
- } else {
- ContentChild::GetSingleton()->SendEmptyClipboard(aWhichClipboard);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsClipboard::HasDataMatchingFlavors(const char **aFlavorList,
- uint32_t aLength, int32_t aWhichClipboard,
- bool *aHasType)
-{
- *aHasType = false;
- if (aWhichClipboard != kGlobalClipboard) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- if (XRE_IsParentProcess()) {
- // Retrieve the union of all aHasType in aFlavorList
- for (uint32_t i = 0; i < aLength; ++i) {
- const char *flavor = aFlavorList[i];
- if (!flavor) {
- continue;
- }
- if (!strcmp(flavor, kUnicodeMime) && mClipboard->HasText()) {
- *aHasType = true;
- } else if (!strcmp(flavor, kHTMLMime) && mClipboard->HasHTML()) {
- *aHasType = true;
- } else if (!strcmp(flavor, kJPEGImageMime) ||
- !strcmp(flavor, kJPGImageMime) ||
- !strcmp(flavor, kPNGImageMime)) {
- // We will encode the image into any format you want, so we don't
- // need to check each specific format
- if (mClipboard->HasImage()) {
- *aHasType = true;
- }
- }
- }
- } else {
- RefPtr<nsClipboardProxy> clipboardProxy = new nsClipboardProxy();
- return clipboardProxy->HasDataMatchingFlavors(aFlavorList, aLength, aWhichClipboard, aHasType);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsClipboard::SupportsSelectionClipboard(bool *aIsSupported)
-{
- *aIsSupported = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsClipboard::SupportsFindClipboard(bool* _retval)
-{
- NS_ENSURE_ARG_POINTER(_retval);
-
- *_retval = false;
- return NS_OK;
-}
-
diff --git a/widget/gonk/nsClipboard.h b/widget/gonk/nsClipboard.h
deleted file mode 100644
index cd2e0dbd5..000000000
--- a/widget/gonk/nsClipboard.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsClipbard_h__
-#define nsClipbard_h__
-
-#include "GonkClipboardData.h"
-#include "mozilla/UniquePtr.h"
-#include "nsIClipboard.h"
-
-class nsClipboard final : public nsIClipboard
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSICLIPBOARD
-
- nsClipboard();
-
-protected:
- ~nsClipboard() {}
-
-private:
- mozilla::UniquePtr<mozilla::GonkClipboardData> mClipboard;
-};
-
-#endif
diff --git a/widget/gonk/nsIdleServiceGonk.cpp b/widget/gonk/nsIdleServiceGonk.cpp
deleted file mode 100644
index dc7588e5e..000000000
--- a/widget/gonk/nsIdleServiceGonk.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim:expandtab:shiftwidth=4:tabstop=4: */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "nsIdleServiceGonk.h"
-#include "nsIServiceManager.h"
-
-NS_IMPL_ISUPPORTS_INHERITED0(nsIdleServiceGonk, nsIdleService)
-
-bool
-nsIdleServiceGonk::PollIdleTime(uint32_t *aIdleTime)
-{
- return false;
-}
-
-bool
-nsIdleServiceGonk::UsePollMode()
-{
- return false;
-}
diff --git a/widget/gonk/nsIdleServiceGonk.h b/widget/gonk/nsIdleServiceGonk.h
deleted file mode 100644
index 32520dce6..000000000
--- a/widget/gonk/nsIdleServiceGonk.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim:expandtab:shiftwidth=4:tabstop=4: */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 nsIdleServiceGonk_h__
-#define nsIdleServiceGonk_h__
-
-#include "nsIdleService.h"
-
-class nsIdleServiceGonk : public nsIdleService
-{
-public:
- NS_DECL_ISUPPORTS_INHERITED
-
- bool PollIdleTime(uint32_t* aIdleTime);
-
- static already_AddRefed<nsIdleServiceGonk> GetInstance()
- {
- RefPtr<nsIdleServiceGonk> idleService =
- nsIdleService::GetInstance().downcast<nsIdleServiceGonk>();
- if (!idleService) {
- idleService = new nsIdleServiceGonk();
- }
-
- return idleService.forget();
- }
-
-protected:
- nsIdleServiceGonk() { }
- virtual ~nsIdleServiceGonk() { }
- bool UsePollMode();
-};
-
-#endif // nsIdleServiceGonk_h__
diff --git a/widget/gonk/nsLookAndFeel.cpp b/widget/gonk/nsLookAndFeel.cpp
deleted file mode 100644
index 120f257df..000000000
--- a/widget/gonk/nsLookAndFeel.cpp
+++ /dev/null
@@ -1,465 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "nsLookAndFeel.h"
-#include "nsStyleConsts.h"
-#include "gfxFont.h"
-#include "gfxFontConstants.h"
-#include "mozilla/gfx/2D.h"
-#include "cutils/properties.h"
-
-static const char16_t UNICODE_BULLET = 0x2022;
-
-nsLookAndFeel::nsLookAndFeel()
- : nsXPLookAndFeel()
-{
-}
-
-nsLookAndFeel::~nsLookAndFeel()
-{
-}
-
-nsresult
-nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
-{
- nsresult rv = NS_OK;
-
-#define BASE_ACTIVE_COLOR NS_RGB(0xaa,0xaa,0xaa)
-#define BASE_NORMAL_COLOR NS_RGB(0xff,0xff,0xff)
-#define BASE_SELECTED_COLOR NS_RGB(0xaa,0xaa,0xaa)
-#define BG_ACTIVE_COLOR NS_RGB(0xff,0xff,0xff)
-#define BG_INSENSITIVE_COLOR NS_RGB(0xaa,0xaa,0xaa)
-#define BG_NORMAL_COLOR NS_RGB(0xff,0xff,0xff)
-#define BG_PRELIGHT_COLOR NS_RGB(0xee,0xee,0xee)
-#define BG_SELECTED_COLOR NS_RGB(0x99,0x99,0x99)
-#define DARK_NORMAL_COLOR NS_RGB(0x88,0x88,0x88)
-#define FG_INSENSITIVE_COLOR NS_RGB(0x44,0x44,0x44)
-#define FG_NORMAL_COLOR NS_RGB(0x00,0x00,0x00)
-#define FG_PRELIGHT_COLOR NS_RGB(0x77,0x77,0x77)
-#define FG_SELECTED_COLOR NS_RGB(0xaa,0xaa,0xaa)
-#define LIGHT_NORMAL_COLOR NS_RGB(0xaa,0xaa,0xaa)
-#define TEXT_ACTIVE_COLOR NS_RGB(0x99,0x99,0x99)
-#define TEXT_NORMAL_COLOR NS_RGB(0x00,0x00,0x00)
-#define TEXT_SELECTED_COLOR NS_RGB(0x00,0x00,0x00)
-
- switch (aID) {
- // These colors don't seem to be used for anything anymore in Mozilla
- // (except here at least TextSelectBackground and TextSelectForeground)
- // The CSS2 colors below are used.
- case eColorID_WindowBackground:
- aColor = BASE_NORMAL_COLOR;
- break;
- case eColorID_WindowForeground:
- aColor = TEXT_NORMAL_COLOR;
- break;
- case eColorID_WidgetBackground:
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID_WidgetForeground:
- aColor = FG_NORMAL_COLOR;
- break;
- case eColorID_WidgetSelectBackground:
- aColor = BG_SELECTED_COLOR;
- break;
- case eColorID_WidgetSelectForeground:
- aColor = FG_SELECTED_COLOR;
- break;
- case eColorID_Widget3DHighlight:
- aColor = NS_RGB(0xa0,0xa0,0xa0);
- break;
- case eColorID_Widget3DShadow:
- aColor = NS_RGB(0x40,0x40,0x40);
- break;
- case eColorID_TextBackground:
- // not used?
- aColor = BASE_NORMAL_COLOR;
- break;
- case eColorID_TextForeground:
- // not used?
- aColor = TEXT_NORMAL_COLOR;
- break;
- case eColorID_TextSelectBackground:
- aColor = NS_RGBA(0x33,0xb5,0xe5,0x66);
- break;
- case eColorID_IMESelectedRawTextBackground:
- case eColorID_IMESelectedConvertedTextBackground:
- // still used
- aColor = BASE_SELECTED_COLOR;
- break;
- case eColorID_TextSelectForegroundCustom:
- aColor = NS_RGB(0x4d,0x4d,0x4d);
- break;
- case eColorID_TextSelectForeground:
- aColor = NS_CHANGE_COLOR_IF_SAME_AS_BG;
- break;
- case eColorID_IMESelectedRawTextForeground:
- case eColorID_IMESelectedConvertedTextForeground:
- // still used
- aColor = TEXT_SELECTED_COLOR;
- break;
- case eColorID_IMERawInputBackground:
- case eColorID_IMEConvertedTextBackground:
- aColor = NS_TRANSPARENT;
- break;
- case eColorID_IMERawInputForeground:
- case eColorID_IMEConvertedTextForeground:
- aColor = NS_SAME_AS_FOREGROUND_COLOR;
- break;
- case eColorID_IMERawInputUnderline:
- case eColorID_IMEConvertedTextUnderline:
- aColor = NS_SAME_AS_FOREGROUND_COLOR;
- break;
- case eColorID_IMESelectedRawTextUnderline:
- case eColorID_IMESelectedConvertedTextUnderline:
- aColor = NS_TRANSPARENT;
- break;
- case eColorID_SpellCheckerUnderline:
- aColor = NS_RGB(0xff, 0, 0);
- break;
-
- // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
- case eColorID_activeborder:
- // active window border
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID_activecaption:
- // active window caption background
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID_appworkspace:
- // MDI background color
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID_background:
- // desktop background
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID_captiontext:
- // text in active window caption, size box, and scrollbar arrow box (!)
- aColor = FG_NORMAL_COLOR;
- break;
- case eColorID_graytext:
- // disabled text in windows, menus, etc.
- aColor = FG_INSENSITIVE_COLOR;
- break;
- case eColorID_highlight:
- // background of selected item
- aColor = BASE_SELECTED_COLOR;
- break;
- case eColorID_highlighttext:
- // text of selected item
- aColor = TEXT_SELECTED_COLOR;
- break;
- case eColorID_inactiveborder:
- // inactive window border
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID_inactivecaption:
- // inactive window caption
- aColor = BG_INSENSITIVE_COLOR;
- break;
- case eColorID_inactivecaptiontext:
- // text in inactive window caption
- aColor = FG_INSENSITIVE_COLOR;
- break;
- case eColorID_infobackground:
- // tooltip background color
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID_infotext:
- // tooltip text color
- aColor = TEXT_NORMAL_COLOR;
- break;
- case eColorID_menu:
- // menu background
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID_menutext:
- // menu text
- aColor = TEXT_NORMAL_COLOR;
- break;
- case eColorID_scrollbar:
- // scrollbar gray area
- aColor = BG_ACTIVE_COLOR;
- break;
-
- case eColorID_threedface:
- case eColorID_buttonface:
- // 3-D face color
- aColor = BG_NORMAL_COLOR;
- break;
-
- case eColorID_buttontext:
- // text on push buttons
- aColor = TEXT_NORMAL_COLOR;
- break;
-
- case eColorID_buttonhighlight:
- // 3-D highlighted edge color
- case eColorID_threedhighlight:
- // 3-D highlighted outer edge color
- aColor = LIGHT_NORMAL_COLOR;
- break;
-
- case eColorID_threedlightshadow:
- // 3-D highlighted inner edge color
- aColor = BG_NORMAL_COLOR;
- break;
-
- case eColorID_buttonshadow:
- // 3-D shadow edge color
- case eColorID_threedshadow:
- // 3-D shadow inner edge color
- aColor = DARK_NORMAL_COLOR;
- break;
-
- case eColorID_threeddarkshadow:
- // 3-D shadow outer edge color
- aColor = NS_RGB(0,0,0);
- break;
-
- case eColorID_window:
- case eColorID_windowframe:
- aColor = BG_NORMAL_COLOR;
- break;
-
- case eColorID_windowtext:
- aColor = FG_NORMAL_COLOR;
- break;
-
- case eColorID__moz_eventreerow:
- case eColorID__moz_field:
- aColor = BASE_NORMAL_COLOR;
- break;
- case eColorID__moz_fieldtext:
- aColor = TEXT_NORMAL_COLOR;
- break;
- case eColorID__moz_dialog:
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID__moz_dialogtext:
- aColor = FG_NORMAL_COLOR;
- break;
- case eColorID__moz_dragtargetzone:
- aColor = BG_SELECTED_COLOR;
- break;
- case eColorID__moz_buttondefault:
- // default button border color
- aColor = NS_RGB(0,0,0);
- break;
- case eColorID__moz_buttonhoverface:
- aColor = BG_PRELIGHT_COLOR;
- break;
- case eColorID__moz_buttonhovertext:
- aColor = FG_PRELIGHT_COLOR;
- break;
- case eColorID__moz_cellhighlight:
- case eColorID__moz_html_cellhighlight:
- aColor = BASE_ACTIVE_COLOR;
- break;
- case eColorID__moz_cellhighlighttext:
- case eColorID__moz_html_cellhighlighttext:
- aColor = TEXT_ACTIVE_COLOR;
- break;
- case eColorID__moz_menuhover:
- aColor = BG_PRELIGHT_COLOR;
- break;
- case eColorID__moz_menuhovertext:
- aColor = FG_PRELIGHT_COLOR;
- break;
- case eColorID__moz_oddtreerow:
- aColor = NS_TRANSPARENT;
- break;
- case eColorID__moz_nativehyperlinktext:
- aColor = NS_SAME_AS_FOREGROUND_COLOR;
- break;
- case eColorID__moz_comboboxtext:
- aColor = TEXT_NORMAL_COLOR;
- break;
- case eColorID__moz_combobox:
- aColor = BG_NORMAL_COLOR;
- break;
- case eColorID__moz_menubartext:
- aColor = TEXT_NORMAL_COLOR;
- break;
- case eColorID__moz_menubarhovertext:
- aColor = FG_PRELIGHT_COLOR;
- break;
- default:
- /* default color is BLACK */
- aColor = 0;
- rv = NS_ERROR_FAILURE;
- break;
- }
-
- return rv;
-}
-
-nsresult
-nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult)
-{
- nsresult rv = nsXPLookAndFeel::GetIntImpl(aID, aResult);
- if (NS_SUCCEEDED(rv))
- return rv;
-
- rv = NS_OK;
-
- switch (aID) {
- case eIntID_CaretBlinkTime:
- aResult = 500;
- break;
-
- case eIntID_CaretWidth:
- aResult = 1;
- break;
-
- case eIntID_ShowCaretDuringSelection:
- aResult = 0;
- break;
-
- case eIntID_SelectTextfieldsOnKeyFocus:
- // Select textfield content when focused by kbd
- // used by EventStateManager::sTextfieldSelectModel
- aResult = 1;
- break;
-
- case eIntID_SubmenuDelay:
- aResult = 200;
- break;
-
- case eIntID_TooltipDelay:
- aResult = 500;
- break;
-
- case eIntID_MenusCanOverlapOSBar:
- // we want XUL popups to be able to overlap the task bar.
- aResult = 1;
- break;
-
- case eIntID_ScrollArrowStyle:
- aResult = eScrollArrowStyle_Single;
- break;
-
- case eIntID_ScrollSliderStyle:
- aResult = eScrollThumbStyle_Proportional;
- break;
-
- case eIntID_TouchEnabled:
- aResult = 1;
- break;
-
- case eIntID_WindowsDefaultTheme:
- case eIntID_WindowsThemeIdentifier:
- case eIntID_OperatingSystemVersionIdentifier:
- aResult = 0;
- rv = NS_ERROR_NOT_IMPLEMENTED;
- break;
-
- case eIntID_IMERawInputUnderlineStyle:
- case eIntID_IMEConvertedTextUnderlineStyle:
- aResult = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
- break;
-
- case eIntID_IMESelectedRawTextUnderlineStyle:
- case eIntID_IMESelectedConvertedTextUnderline:
- aResult = NS_STYLE_TEXT_DECORATION_STYLE_NONE;
- break;
-
- case eIntID_SpellCheckerUnderlineStyle:
- aResult = NS_STYLE_TEXT_DECORATION_STYLE_WAVY;
- break;
-
- case eIntID_ScrollbarButtonAutoRepeatBehavior:
- aResult = 0;
- break;
-
- case eIntID_PhysicalHomeButton: {
- char propValue[PROPERTY_VALUE_MAX];
- property_get("ro.moz.has_home_button", propValue, "1");
- aResult = atoi(propValue);
- break;
- }
-
- case eIntID_ContextMenuOffsetVertical:
- case eIntID_ContextMenuOffsetHorizontal:
- aResult = 2;
- break;
-
- default:
- aResult = 0;
- rv = NS_ERROR_FAILURE;
- }
-
- return rv;
-}
-
-nsresult
-nsLookAndFeel::GetFloatImpl(FloatID aID, float &aResult)
-{
- nsresult res = nsXPLookAndFeel::GetFloatImpl(aID, aResult);
- if (NS_SUCCEEDED(res))
- return res;
- res = NS_OK;
-
- switch (aID) {
- case eFloatID_IMEUnderlineRelativeSize:
- aResult = 1.0f;
- break;
- case eFloatID_SpellCheckerUnderlineRelativeSize:
- aResult = 1.0f;
- break;
- default:
- aResult = -1.0;
- res = NS_ERROR_FAILURE;
- }
- return res;
-}
-
-/*virtual*/
-bool
-nsLookAndFeel::GetFontImpl(FontID aID, nsString& aFontName,
- gfxFontStyle& aFontStyle,
- float aDevPixPerCSSPixel)
-{
- aFontName.AssignLiteral("\"Fira Sans\"");
- aFontStyle.style = NS_FONT_STYLE_NORMAL;
- aFontStyle.weight = NS_FONT_WEIGHT_NORMAL;
- aFontStyle.stretch = NS_FONT_STRETCH_NORMAL;
- aFontStyle.size = 9.0 * 96.0f / 72.0f;
- aFontStyle.systemFont = true;
- return true;
-}
-
-/*virtual*/
-bool
-nsLookAndFeel::GetEchoPasswordImpl() {
- return true;
-}
-
-/*virtual*/
-uint32_t
-nsLookAndFeel::GetPasswordMaskDelayImpl()
-{
- // Same value on Android framework
- return 1500;
-}
-
-/* virtual */
-char16_t
-nsLookAndFeel::GetPasswordCharacterImpl()
-{
- return UNICODE_BULLET;
-}
diff --git a/widget/gonk/nsLookAndFeel.h b/widget/gonk/nsLookAndFeel.h
deleted file mode 100644
index aa7dce823..000000000
--- a/widget/gonk/nsLookAndFeel.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 __nsLookAndFeel
-#define __nsLookAndFeel
-
-#include "nsXPLookAndFeel.h"
-
-class nsLookAndFeel : public nsXPLookAndFeel
-{
-public:
- nsLookAndFeel();
- virtual ~nsLookAndFeel();
-
- virtual bool GetFontImpl(FontID aID, nsString& aName, gfxFontStyle& aStyle,
- float aDevPixPerCSSPixel);
- virtual nsresult GetIntImpl(IntID aID, int32_t &aResult);
- virtual nsresult GetFloatImpl(FloatID aID, float &aResult);
- virtual bool GetEchoPasswordImpl();
- virtual uint32_t GetPasswordMaskDelayImpl();
- virtual char16_t GetPasswordCharacterImpl();
-
-protected:
- virtual nsresult NativeGetColor(ColorID aID, nscolor &aColor);
-};
-
-#endif
diff --git a/widget/gonk/nsScreenManagerGonk.cpp b/widget/gonk/nsScreenManagerGonk.cpp
deleted file mode 100644
index e359fd195..000000000
--- a/widget/gonk/nsScreenManagerGonk.cpp
+++ /dev/null
@@ -1,1081 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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/log.h"
-#include "GLContext.h"
-#include "gfxPrefs.h"
-#include "gfxUtils.h"
-#include "mozilla/MouseEvents.h"
-#include "mozilla/TouchEvents.h"
-#include "mozilla/Hal.h"
-#include "libdisplay/BootAnimation.h"
-#include "libdisplay/GonkDisplay.h"
-#include "nsScreenManagerGonk.h"
-#include "nsThreadUtils.h"
-#include "HwcComposer2D.h"
-#include "VsyncSource.h"
-#include "nsWindow.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/layers/CompositorBridgeParent.h"
-#include "mozilla/layers/CompositorThread.h"
-#include "mozilla/Services.h"
-#include "mozilla/ProcessPriorityManager.h"
-#include "nsIdleService.h"
-#include "nsIObserverService.h"
-#include "nsAppShell.h"
-#include "nsProxyRelease.h"
-#include "nsTArray.h"
-#include "pixelflinger/format.h"
-#include "nsIDisplayInfo.h"
-#include "base/task.h"
-
-#if ANDROID_VERSION >= 17
-#include "libdisplay/DisplaySurface.h"
-#endif
-
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "nsScreenGonk" , ## args)
-#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "nsScreenGonk", ## args)
-#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "nsScreenGonk", ## args)
-
-using namespace mozilla;
-using namespace mozilla::hal;
-using namespace mozilla::gfx;
-using namespace mozilla::gl;
-using namespace mozilla::layers;
-using namespace mozilla::dom;
-
-namespace {
-
-class ScreenOnOffEvent : public mozilla::Runnable {
-public:
- ScreenOnOffEvent(bool on)
- : mIsOn(on)
- {}
-
- NS_IMETHOD Run() override {
- // Notify observers that the screen state has just changed.
- nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
- if (observerService) {
- observerService->NotifyObservers(
- nullptr, "screen-state-changed",
- mIsOn ? u"on" : u"off"
- );
- }
-
- RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen();
- const nsTArray<nsWindow*>& windows = screen->GetTopWindows();
-
- for (uint32_t i = 0; i < windows.Length(); i++) {
- nsWindow *win = windows[i];
-
- if (nsIWidgetListener* listener = win->GetWidgetListener()) {
- listener->SizeModeChanged(mIsOn ? nsSizeMode_Fullscreen : nsSizeMode_Minimized);
- }
- }
-
- return NS_OK;
- }
-
-private:
- bool mIsOn;
-};
-
-static void
-displayEnabledCallback(bool enabled)
-{
- RefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance();
- screenManager->DisplayEnabled(enabled);
-}
-
-} // namespace
-
-static uint32_t
-SurfaceFormatToColorDepth(int32_t aSurfaceFormat)
-{
- switch (aSurfaceFormat) {
- case GGL_PIXEL_FORMAT_RGB_565:
- return 16;
- case GGL_PIXEL_FORMAT_RGBA_8888:
- return 32;
- }
- return 24; // GGL_PIXEL_FORMAT_RGBX_8888
-}
-
-// nsScreenGonk.cpp
-
-nsScreenGonk::nsScreenGonk(uint32_t aId,
- GonkDisplay::DisplayType aDisplayType,
- const GonkDisplay::NativeData& aNativeData,
- NotifyDisplayChangedEvent aEventVisibility)
- : mId(aId)
- , mEventVisibility(aEventVisibility)
- , mNativeWindow(aNativeData.mNativeWindow)
- , mDpi(aNativeData.mXdpi)
- , mScreenRotation(nsIScreen::ROTATION_0_DEG)
- , mPhysicalScreenRotation(nsIScreen::ROTATION_0_DEG)
-#if ANDROID_VERSION >= 17
- , mDisplaySurface(aNativeData.mDisplaySurface)
-#endif
- , mIsMirroring(false)
- , mDisplayType(aDisplayType)
- , mEGLDisplay(EGL_NO_DISPLAY)
- , mEGLSurface(EGL_NO_SURFACE)
- , mGLContext(nullptr)
- , mFramebuffer(nullptr)
- , mMappedBuffer(nullptr)
-{
- if (mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &mVirtualBounds.width) ||
- mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &mVirtualBounds.height) ||
- mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_FORMAT, &mSurfaceFormat)) {
- NS_RUNTIMEABORT("Failed to get native window size, aborting...");
- }
-
- mNaturalBounds = mVirtualBounds;
-
- if (IsPrimaryScreen()) {
- char propValue[PROPERTY_VALUE_MAX];
- property_get("ro.sf.hwrotation", propValue, "0");
- mPhysicalScreenRotation = atoi(propValue) / 90;
- }
-
- mColorDepth = SurfaceFormatToColorDepth(mSurfaceFormat);
-}
-
-static void
-ReleaseGLContextSync(mozilla::gl::GLContext* aGLContext)
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- aGLContext->Release();
-}
-
-nsScreenGonk::~nsScreenGonk()
-{
- // Release GLContext on compositor thread
- if (mGLContext) {
- CompositorThreadHolder::Loop()->PostTask(
- NewRunnableFunction(&ReleaseGLContextSync,
- mGLContext.forget().take()));
- mGLContext = nullptr;
- }
-}
-
-bool
-nsScreenGonk::IsPrimaryScreen()
-{
- return mDisplayType == GonkDisplay::DISPLAY_PRIMARY;
-}
-
-NS_IMETHODIMP
-nsScreenGonk::GetId(uint32_t *outId)
-{
- *outId = mId;
- return NS_OK;
-}
-
-uint32_t
-nsScreenGonk::GetId()
-{
- return mId;
-}
-
-NotifyDisplayChangedEvent
-nsScreenGonk::GetEventVisibility()
-{
- return mEventVisibility;
-}
-
-NS_IMETHODIMP
-nsScreenGonk::GetRect(int32_t *outLeft, int32_t *outTop,
- int32_t *outWidth, int32_t *outHeight)
-{
- *outLeft = mVirtualBounds.x;
- *outTop = mVirtualBounds.y;
-
- *outWidth = mVirtualBounds.width;
- *outHeight = mVirtualBounds.height;
-
- return NS_OK;
-}
-
-LayoutDeviceIntRect
-nsScreenGonk::GetRect()
-{
- return mVirtualBounds;
-}
-
-NS_IMETHODIMP
-nsScreenGonk::GetAvailRect(int32_t *outLeft, int32_t *outTop,
- int32_t *outWidth, int32_t *outHeight)
-{
- return GetRect(outLeft, outTop, outWidth, outHeight);
-}
-
-NS_IMETHODIMP
-nsScreenGonk::GetPixelDepth(int32_t *aPixelDepth)
-{
- // XXX: this should actually return 32 when we're using 24-bit
- // color, because we use RGBX.
- *aPixelDepth = mColorDepth;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsScreenGonk::GetColorDepth(int32_t *aColorDepth)
-{
- *aColorDepth = mColorDepth;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsScreenGonk::GetRotation(uint32_t* aRotation)
-{
- *aRotation = mScreenRotation;
- return NS_OK;
-}
-
-float
-nsScreenGonk::GetDpi()
-{
- return mDpi;
-}
-
-int32_t
-nsScreenGonk::GetSurfaceFormat()
-{
- return mSurfaceFormat;
-}
-
-ANativeWindow*
-nsScreenGonk::GetNativeWindow()
-{
- return mNativeWindow.get();
-}
-
-NS_IMETHODIMP
-nsScreenGonk::SetRotation(uint32_t aRotation)
-{
- if (!(aRotation <= ROTATION_270_DEG)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
-
- if (mScreenRotation == aRotation) {
- return NS_OK;
- }
-
- mScreenRotation = aRotation;
- uint32_t rotation = EffectiveScreenRotation();
- if (rotation == nsIScreen::ROTATION_90_DEG ||
- rotation == nsIScreen::ROTATION_270_DEG) {
- mVirtualBounds = LayoutDeviceIntRect(0, 0,
- mNaturalBounds.height,
- mNaturalBounds.width);
- } else {
- mVirtualBounds = mNaturalBounds;
- }
-
- nsAppShell::NotifyScreenRotation();
-
- for (unsigned int i = 0; i < mTopWindows.Length(); i++) {
- mTopWindows[i]->Resize(mVirtualBounds.width,
- mVirtualBounds.height,
- true);
- }
-
- return NS_OK;
-}
-
-LayoutDeviceIntRect
-nsScreenGonk::GetNaturalBounds()
-{
- return mNaturalBounds;
-}
-
-uint32_t
-nsScreenGonk::EffectiveScreenRotation()
-{
- return (mScreenRotation + mPhysicalScreenRotation) % (360 / 90);
-}
-
-// NB: This isn't gonk-specific, but gonk is the only widget backend
-// that does this calculation itself, currently.
-static ScreenOrientationInternal
-ComputeOrientation(uint32_t aRotation, const LayoutDeviceIntSize& aScreenSize)
-{
- bool naturallyPortrait = (aScreenSize.height > aScreenSize.width);
- switch (aRotation) {
- case nsIScreen::ROTATION_0_DEG:
- return (naturallyPortrait ? eScreenOrientation_PortraitPrimary :
- eScreenOrientation_LandscapePrimary);
- case nsIScreen::ROTATION_90_DEG:
- // Arbitrarily choosing 90deg to be primary "unnatural"
- // rotation.
- return (naturallyPortrait ? eScreenOrientation_LandscapePrimary :
- eScreenOrientation_PortraitPrimary);
- case nsIScreen::ROTATION_180_DEG:
- return (naturallyPortrait ? eScreenOrientation_PortraitSecondary :
- eScreenOrientation_LandscapeSecondary);
- case nsIScreen::ROTATION_270_DEG:
- return (naturallyPortrait ? eScreenOrientation_LandscapeSecondary :
- eScreenOrientation_PortraitSecondary);
- default:
- MOZ_CRASH("Gonk screen must always have a known rotation");
- }
-}
-
-static uint16_t
-RotationToAngle(uint32_t aRotation)
-{
- uint16_t angle = 90 * aRotation;
- MOZ_ASSERT(angle == 0 || angle == 90 || angle == 180 || angle == 270);
- return angle;
-}
-
-ScreenConfiguration
-nsScreenGonk::GetConfiguration()
-{
- ScreenOrientationInternal orientation =
- ComputeOrientation(mScreenRotation, mNaturalBounds.Size());
-
- // NB: perpetuating colorDepth == pixelDepth illusion here, for
- // consistency.
- return ScreenConfiguration(mVirtualBounds.ToUnknownRect(), orientation,
- RotationToAngle(mScreenRotation),
- mColorDepth, mColorDepth);
-}
-
-void
-nsScreenGonk::RegisterWindow(nsWindow* aWindow)
-{
- mTopWindows.AppendElement(aWindow);
-}
-
-void
-nsScreenGonk::UnregisterWindow(nsWindow* aWindow)
-{
- mTopWindows.RemoveElement(aWindow);
-}
-
-void
-nsScreenGonk::BringToTop(nsWindow* aWindow)
-{
- mTopWindows.RemoveElement(aWindow);
- mTopWindows.InsertElementAt(0, aWindow);
-}
-
-static gralloc_module_t const*
-gralloc_module()
-{
- hw_module_t const *module;
- if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)) {
- return nullptr;
- }
- return reinterpret_cast<gralloc_module_t const*>(module);
-}
-
-static SurfaceFormat
-HalFormatToSurfaceFormat(int aHalFormat)
-{
- switch (aHalFormat) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- // Needs RB swap
- return SurfaceFormat::B8G8R8A8;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- // Needs RB swap
- return SurfaceFormat::B8G8R8X8;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return SurfaceFormat::B8G8R8A8;
- case HAL_PIXEL_FORMAT_RGB_565:
- return SurfaceFormat::R5G6B5_UINT16;
- default:
- MOZ_CRASH("Unhandled HAL pixel format");
- return SurfaceFormat::UNKNOWN; // not reached
- }
-}
-
-static bool
-NeedsRBSwap(int aHalFormat)
-{
- switch (aHalFormat) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- return true;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- return true;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return false;
- case HAL_PIXEL_FORMAT_RGB_565:
- return false;
- default:
- MOZ_CRASH("Unhandled HAL pixel format");
- return false; // not reached
- }
-}
-
-already_AddRefed<DrawTarget>
-nsScreenGonk::StartRemoteDrawing()
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- MOZ_ASSERT(!mFramebuffer);
- MOZ_ASSERT(!mMappedBuffer);
-
- mFramebuffer = DequeueBuffer();
- int width = mFramebuffer->width, height = mFramebuffer->height;
- if (gralloc_module()->lock(gralloc_module(), mFramebuffer->handle,
- GRALLOC_USAGE_SW_READ_NEVER |
- GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_FB,
- 0, 0, width, height,
- reinterpret_cast<void**>(&mMappedBuffer))) {
- EndRemoteDrawing();
- return nullptr;
- }
- SurfaceFormat format = HalFormatToSurfaceFormat(GetSurfaceFormat());
- mFramebufferTarget = Factory::CreateDrawTargetForData(
- BackendType::CAIRO,
- mMappedBuffer,
- IntSize(width, height),
- mFramebuffer->stride * gfx::BytesPerPixel(format),
- format);
- if (!mFramebufferTarget) {
- MOZ_CRASH("nsWindow::StartRemoteDrawing failed in CreateDrawTargetForData");
- }
- if (!mBackBuffer ||
- mBackBuffer->GetSize() != mFramebufferTarget->GetSize() ||
- mBackBuffer->GetFormat() != mFramebufferTarget->GetFormat()) {
- mBackBuffer = mFramebufferTarget->CreateSimilarDrawTarget(
- mFramebufferTarget->GetSize(), mFramebufferTarget->GetFormat());
- }
- RefPtr<DrawTarget> buffer(mBackBuffer);
- return buffer.forget();
-}
-
-void
-nsScreenGonk::EndRemoteDrawing()
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-
- if (mFramebufferTarget && mFramebuffer) {
- IntSize size = mFramebufferTarget->GetSize();
- Rect rect(0, 0, size.width, size.height);
- RefPtr<SourceSurface> source = mBackBuffer->Snapshot();
- mFramebufferTarget->DrawSurface(source, rect, rect);
-
- // Convert from BGR to RGB
- // XXX this is a temporary solution. It consumes extra cpu cycles,
- // it should not be used on product device.
- if (NeedsRBSwap(GetSurfaceFormat())) {
- LOGE("Very slow composition path, it should not be used on product!!!");
- SurfaceFormat format = HalFormatToSurfaceFormat(GetSurfaceFormat());
- gfxUtils::ConvertBGRAtoRGBA(
- mMappedBuffer,
- mFramebuffer->stride * mFramebuffer->height * gfx::BytesPerPixel(format));
- }
- }
- if (mMappedBuffer) {
- MOZ_ASSERT(mFramebuffer);
- gralloc_module()->unlock(gralloc_module(), mFramebuffer->handle);
- mMappedBuffer = nullptr;
- }
- if (mFramebuffer) {
- QueueBuffer(mFramebuffer);
- }
- mFramebuffer = nullptr;
- mFramebufferTarget = nullptr;
-}
-
-ANativeWindowBuffer*
-nsScreenGonk::DequeueBuffer()
-{
- ANativeWindowBuffer* buf = nullptr;
-#if ANDROID_VERSION >= 17
- int fenceFd = -1;
- mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
- android::sp<android::Fence> fence(new android::Fence(fenceFd));
-#if ANDROID_VERSION == 17
- fence->waitForever(1000, "nsScreenGonk_DequeueBuffer");
- // 1000 is what Android uses. It is a warning timeout in ms.
- // This timeout was removed in ANDROID_VERSION 18.
-#else
- fence->waitForever("nsScreenGonk_DequeueBuffer");
-#endif
-#else
- mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
-#endif
- return buf;
-}
-
-bool
-nsScreenGonk::QueueBuffer(ANativeWindowBuffer* buf)
-{
-#if ANDROID_VERSION >= 17
- int ret = mNativeWindow->queueBuffer(mNativeWindow.get(), buf, -1);
- return ret == 0;
-#else
- int ret = mNativeWindow->queueBuffer(mNativeWindow.get(), buf);
- return ret == 0;
-#endif
-}
-
-nsresult
-nsScreenGonk::MakeSnapshot(ANativeWindowBuffer* aBuffer)
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- MOZ_ASSERT(aBuffer);
-
- layers::CompositorBridgeParent* compositorParent = mCompositorBridgeParent;
- if (!compositorParent) {
- return NS_ERROR_FAILURE;
- }
-
- int width = aBuffer->width, height = aBuffer->height;
- uint8_t* mappedBuffer = nullptr;
- if (gralloc_module()->lock(gralloc_module(), aBuffer->handle,
- GRALLOC_USAGE_SW_READ_OFTEN |
- GRALLOC_USAGE_SW_WRITE_OFTEN,
- 0, 0, width, height,
- reinterpret_cast<void**>(&mappedBuffer))) {
- return NS_ERROR_FAILURE;
- }
-
- SurfaceFormat format = HalFormatToSurfaceFormat(GetSurfaceFormat());
- RefPtr<DrawTarget> mTarget =
- Factory::CreateDrawTargetForData(
- BackendType::CAIRO,
- mappedBuffer,
- IntSize(width, height),
- aBuffer->stride * gfx::BytesPerPixel(format),
- format);
- if (!mTarget) {
- return NS_ERROR_FAILURE;
- }
-
- gfx::IntRect rect = GetRect().ToUnknownRect();
- compositorParent->ForceComposeToTarget(mTarget, &rect);
-
- // Convert from BGR to RGB
- // XXX this is a temporary solution. It consumes extra cpu cycles,
- if (NeedsRBSwap(GetSurfaceFormat())) {
- LOGE("Slow path of making Snapshot!!!");
- SurfaceFormat format = HalFormatToSurfaceFormat(GetSurfaceFormat());
- gfxUtils::ConvertBGRAtoRGBA(
- mappedBuffer,
- aBuffer->stride * aBuffer->height * gfx::BytesPerPixel(format));
- mappedBuffer = nullptr;
- }
- gralloc_module()->unlock(gralloc_module(), aBuffer->handle);
- return NS_OK;
-}
-
-void
-nsScreenGonk::SetCompositorBridgeParent(layers::CompositorBridgeParent* aCompositorBridgeParent)
-{
- MOZ_ASSERT(NS_IsMainThread());
- mCompositorBridgeParent = aCompositorBridgeParent;
-}
-
-#if ANDROID_VERSION >= 17
-android::DisplaySurface*
-nsScreenGonk::GetDisplaySurface()
-{
- return mDisplaySurface.get();
-}
-
-int
-nsScreenGonk::GetPrevDispAcquireFd()
-{
- if (!mDisplaySurface.get()) {
- return -1;
- }
- return mDisplaySurface->GetPrevDispAcquireFd();
-}
-#endif
-
-GonkDisplay::DisplayType
-nsScreenGonk::GetDisplayType()
-{
- return mDisplayType;
-}
-
-void
-nsScreenGonk::SetEGLInfo(hwc_display_t aDisplay,
- hwc_surface_t aSurface,
- gl::GLContext* aGLContext)
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- mEGLDisplay = aDisplay;
- mEGLSurface = aSurface;
- mGLContext = aGLContext;
-}
-
-hwc_display_t
-nsScreenGonk::GetEGLDisplay()
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- return mEGLDisplay;
-}
-
-hwc_surface_t
-nsScreenGonk::GetEGLSurface()
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- return mEGLSurface;
-}
-
-already_AddRefed<mozilla::gl::GLContext>
-nsScreenGonk::GetGLContext()
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- RefPtr<mozilla::gl::GLContext>glContext = mGLContext;
- return glContext.forget();
-}
-
-static void
-UpdateMirroringWidgetSync(nsMainThreadPtrHandle<nsScreenGonk>&& aScreen, nsWindow* aWindow)
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- already_AddRefed<nsWindow> window(aWindow);
- aScreen->UpdateMirroringWidget(window);
-}
-
-bool
-nsScreenGonk::EnableMirroring()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!IsPrimaryScreen());
-
- RefPtr<nsScreenGonk> primaryScreen = nsScreenManagerGonk::GetPrimaryScreen();
- NS_ENSURE_TRUE(primaryScreen, false);
-
- bool ret = primaryScreen->SetMirroringScreen(this);
- NS_ENSURE_TRUE(ret, false);
-
- // Create a widget for mirroring
- nsWidgetInitData initData;
- initData.mScreenId = mId;
- RefPtr<nsWindow> window = new nsWindow();
- nsresult rv = window->Create(nullptr, nullptr, mNaturalBounds, &initData);
- NS_ENSURE_SUCCESS(rv, false);
- MOZ_ASSERT(static_cast<nsWindow*>(window)->GetScreen() == this);
-
- // Update mMirroringWidget on compositor thread
- nsMainThreadPtrHandle<nsScreenGonk> primary =
- nsMainThreadPtrHandle<nsScreenGonk>(new nsMainThreadPtrHolder<nsScreenGonk>(primaryScreen, false));
- CompositorThreadHolder::Loop()->PostTask(
- NewRunnableFunction(&UpdateMirroringWidgetSync,
- primary,
- window.forget().take()));
-
- mIsMirroring = true;
- return true;
-}
-
-bool
-nsScreenGonk::DisableMirroring()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!IsPrimaryScreen());
-
- mIsMirroring = false;
- RefPtr<nsScreenGonk> primaryScreen = nsScreenManagerGonk::GetPrimaryScreen();
- NS_ENSURE_TRUE(primaryScreen, false);
-
- bool ret = primaryScreen->ClearMirroringScreen(this);
- NS_ENSURE_TRUE(ret, false);
-
- // Update mMirroringWidget on compositor thread
- nsMainThreadPtrHandle<nsScreenGonk> primary =
- nsMainThreadPtrHandle<nsScreenGonk>(new nsMainThreadPtrHolder<nsScreenGonk>(primaryScreen, false));
- CompositorThreadHolder::Loop()->PostTask(
- NewRunnableFunction(&UpdateMirroringWidgetSync,
- primary,
- nullptr));
- return true;
-}
-
-bool
-nsScreenGonk::SetMirroringScreen(nsScreenGonk* aScreen)
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(IsPrimaryScreen());
-
- if (mMirroringScreen) {
- return false;
- }
- mMirroringScreen = aScreen;
- return true;
-}
-
-bool
-nsScreenGonk::ClearMirroringScreen(nsScreenGonk* aScreen)
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(IsPrimaryScreen());
-
- if (mMirroringScreen != aScreen) {
- return false;
- }
- mMirroringScreen = nullptr;
- return true;
-}
-
-void
-nsScreenGonk::UpdateMirroringWidget(already_AddRefed<nsWindow>& aWindow)
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- MOZ_ASSERT(IsPrimaryScreen());
-
- if (mMirroringWidget) {
- nsCOMPtr<nsIWidget> widget = mMirroringWidget.forget();
- NS_ReleaseOnMainThread(widget.forget());
- }
- mMirroringWidget = aWindow;
-}
-
-nsWindow*
-nsScreenGonk::GetMirroringWidget()
-{
- MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- MOZ_ASSERT(IsPrimaryScreen());
-
- return mMirroringWidget;
-}
-
-NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager)
-
-nsScreenManagerGonk::nsScreenManagerGonk()
- : mInitialized(false)
-#if ANDROID_VERSION >= 19
- , mDisplayEnabled(false)
-#endif
-{
-}
-
-nsScreenManagerGonk::~nsScreenManagerGonk()
-{
-}
-
-static StaticRefPtr<nsScreenManagerGonk> sScreenManagerGonk;
-
-/* static */ already_AddRefed<nsScreenManagerGonk>
-nsScreenManagerGonk::GetInstance()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- // Avoid creating nsScreenManagerGonk from content process.
- if (!XRE_IsParentProcess()) {
- MOZ_CRASH("Non-chrome processes should not get here.");
- }
-
- // Avoid creating multiple nsScreenManagerGonk instance inside main process.
- if (!sScreenManagerGonk) {
- sScreenManagerGonk = new nsScreenManagerGonk();
- ClearOnShutdown(&sScreenManagerGonk);
- }
-
- RefPtr<nsScreenManagerGonk> screenMgr = sScreenManagerGonk.get();
- return screenMgr.forget();
-}
-
-/* static */ already_AddRefed< nsScreenGonk>
-nsScreenManagerGonk::GetPrimaryScreen()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- RefPtr<nsScreenManagerGonk> manager = nsScreenManagerGonk::GetInstance();
- nsCOMPtr<nsIScreen> screen;
- manager->GetPrimaryScreen(getter_AddRefs(screen));
- MOZ_ASSERT(screen);
- return already_AddRefed<nsScreenGonk>(
- static_cast<nsScreenGonk*>(screen.forget().take()));
-}
-
-void
-nsScreenManagerGonk::Initialize()
-{
- if (mInitialized) {
- return;
- }
-
- mScreenOnEvent = new ScreenOnOffEvent(true);
- mScreenOffEvent = new ScreenOnOffEvent(false);
- GetGonkDisplay()->OnEnabled(displayEnabledCallback);
-
- AddScreen(GonkDisplay::DISPLAY_PRIMARY);
-
- nsAppShell::NotifyScreenInitialized();
- mInitialized = true;
-}
-
-void
-nsScreenManagerGonk::DisplayEnabled(bool aEnabled)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
-#if ANDROID_VERSION >= 19
- /* Bug 1244044
- * This function could be called before |mCompositorVsyncScheduler| is set.
- * To avoid this issue, keep the value stored in |mDisplayEnabled|.
- */
- mDisplayEnabled = aEnabled;
- if (mCompositorVsyncScheduler) {
- mCompositorVsyncScheduler->SetDisplay(mDisplayEnabled);
- }
-#endif
-
- VsyncControl(aEnabled);
- NS_DispatchToMainThread(aEnabled ? mScreenOnEvent : mScreenOffEvent);
-}
-
-NS_IMETHODIMP
-nsScreenManagerGonk::GetPrimaryScreen(nsIScreen **outScreen)
-{
- NS_IF_ADDREF(*outScreen = mScreens[0].get());
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsScreenManagerGonk::ScreenForId(uint32_t aId,
- nsIScreen **outScreen)
-{
- for (size_t i = 0; i < mScreens.Length(); i++) {
- if (mScreens[i]->GetId() == aId) {
- NS_IF_ADDREF(*outScreen = mScreens[i].get());
- return NS_OK;
- }
- }
-
- *outScreen = nullptr;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsScreenManagerGonk::ScreenForRect(int32_t inLeft,
- int32_t inTop,
- int32_t inWidth,
- int32_t inHeight,
- nsIScreen **outScreen)
-{
- // Since all screens have independent coordinate system, we could
- // only return the primary screen no matter what rect is given.
- return GetPrimaryScreen(outScreen);
-}
-
-NS_IMETHODIMP
-nsScreenManagerGonk::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen)
-{
- for (size_t i = 0; i < mScreens.Length(); i++) {
- if (aWidget == mScreens[i]->GetNativeWindow()) {
- NS_IF_ADDREF(*outScreen = mScreens[i].get());
- return NS_OK;
- }
- }
-
- *outScreen = nullptr;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsScreenManagerGonk::GetNumberOfScreens(uint32_t *aNumberOfScreens)
-{
- *aNumberOfScreens = mScreens.Length();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsScreenManagerGonk::GetSystemDefaultScale(float *aDefaultScale)
-{
- *aDefaultScale = 1.0f;
- return NS_OK;
-}
-
-void
-nsScreenManagerGonk::VsyncControl(bool aEnabled)
-{
- if (!NS_IsMainThread()) {
- NS_DispatchToMainThread(
- NewRunnableMethod<bool>(this,
- &nsScreenManagerGonk::VsyncControl,
- aEnabled));
- return;
- }
-
- MOZ_ASSERT(NS_IsMainThread());
- VsyncSource::Display &display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
- if (aEnabled) {
- display.EnableVsync();
- } else {
- display.DisableVsync();
- }
-}
-
-uint32_t
-nsScreenManagerGonk::GetIdFromType(GonkDisplay::DisplayType aDisplayType)
-{
- // This is the only place where we make the assumption that
- // display type is equivalent to screen id.
-
- // Bug 1138287 will address the conversion from type to id.
- return aDisplayType;
-}
-
-bool
-nsScreenManagerGonk::IsScreenConnected(uint32_t aId)
-{
- for (size_t i = 0; i < mScreens.Length(); ++i) {
- if (mScreens[i]->GetId() == aId) {
- return true;
- }
- }
-
- return false;
-}
-
-namespace {
-
-// A concrete class as a subject for 'display-changed' observer event.
-class DisplayInfo : public nsIDisplayInfo {
-public:
- NS_DECL_ISUPPORTS
-
- DisplayInfo(uint32_t aId, bool aConnected)
- : mId(aId)
- , mConnected(aConnected)
- {
- }
-
- NS_IMETHODIMP GetId(int32_t *aId)
- {
- *aId = mId;
- return NS_OK;
- }
-
- NS_IMETHODIMP GetConnected(bool *aConnected)
- {
- *aConnected = mConnected;
- return NS_OK;
- }
-
-private:
- virtual ~DisplayInfo() {}
-
- uint32_t mId;
- bool mConnected;
-};
-
-NS_IMPL_ISUPPORTS(DisplayInfo, nsIDisplayInfo, nsISupports)
-
-class NotifyTask : public mozilla::Runnable {
-public:
- NotifyTask(uint32_t aId, bool aConnected)
- : mDisplayInfo(new DisplayInfo(aId, aConnected))
- {
- }
-
- NS_IMETHOD Run() override
- {
- nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
- if (os) {
- os->NotifyObservers(mDisplayInfo, "display-changed", nullptr);
- }
-
- return NS_OK;
- }
-private:
- RefPtr<DisplayInfo> mDisplayInfo;
-};
-
-void
-NotifyDisplayChange(uint32_t aId, bool aConnected)
-{
- NS_DispatchToMainThread(new NotifyTask(aId, aConnected));
-}
-
-} // end of unnamed namespace.
-
-nsresult
-nsScreenManagerGonk::AddScreen(GonkDisplay::DisplayType aDisplayType,
- android::IGraphicBufferProducer* aSink,
- NotifyDisplayChangedEvent aEventVisibility)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- NS_ENSURE_TRUE(aDisplayType < GonkDisplay::DisplayType::NUM_DISPLAY_TYPES,
- NS_ERROR_FAILURE);
-
- uint32_t id = GetIdFromType(aDisplayType);
- NS_ENSURE_TRUE(!IsScreenConnected(id), NS_ERROR_FAILURE);
-
- GonkDisplay::NativeData nativeData =
- GetGonkDisplay()->GetNativeData(aDisplayType, aSink);
- nsScreenGonk* screen = new nsScreenGonk(id,
- aDisplayType,
- nativeData,
- aEventVisibility);
- mScreens.AppendElement(screen);
-
- if (aEventVisibility == NotifyDisplayChangedEvent::Observable) {
- NotifyDisplayChange(id, true);
- }
-
- // By default, non primary screen does mirroring.
- if (aDisplayType != GonkDisplay::DISPLAY_PRIMARY &&
- gfxPrefs::ScreenMirroringEnabled()) {
- screen->EnableMirroring();
- }
-
- return NS_OK;
-}
-
-nsresult
-nsScreenManagerGonk::RemoveScreen(GonkDisplay::DisplayType aDisplayType)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- NS_ENSURE_TRUE(aDisplayType < GonkDisplay::DisplayType::NUM_DISPLAY_TYPES,
- NS_ERROR_FAILURE);
-
- NotifyDisplayChangedEvent eventVisibility = NotifyDisplayChangedEvent::Observable;
- uint32_t screenId = GetIdFromType(aDisplayType);
- NS_ENSURE_TRUE(IsScreenConnected(screenId), NS_ERROR_FAILURE);
-
- for (size_t i = 0; i < mScreens.Length(); i++) {
- if (mScreens[i]->GetId() == screenId) {
- if (mScreens[i]->IsMirroring()) {
- mScreens[i]->DisableMirroring();
- }
- eventVisibility = mScreens[i]->GetEventVisibility();
- mScreens.RemoveElementAt(i);
- break;
- }
- }
-
- if (eventVisibility == NotifyDisplayChangedEvent::Observable) {
- NotifyDisplayChange(screenId, false);
- }
- return NS_OK;
-}
-
-#if ANDROID_VERSION >= 19
-void
-nsScreenManagerGonk::SetCompositorVsyncScheduler(mozilla::layers::CompositorVsyncScheduler *aObserver)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- // We assume on b2g that there is only 1 CompositorBridgeParent
- MOZ_ASSERT(mCompositorVsyncScheduler == nullptr);
- MOZ_ASSERT(aObserver);
- mCompositorVsyncScheduler = aObserver;
- mCompositorVsyncScheduler->SetDisplay(mDisplayEnabled);
-}
-#endif
diff --git a/widget/gonk/nsScreenManagerGonk.h b/widget/gonk/nsScreenManagerGonk.h
deleted file mode 100644
index 33ef5edb8..000000000
--- a/widget/gonk/nsScreenManagerGonk.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 nsScreenManagerGonk_h___
-#define nsScreenManagerGonk_h___
-
-#include "cutils/properties.h"
-#include "hardware/hwcomposer.h"
-
-#include "libdisplay/GonkDisplay.h"
-#include "mozilla/Atomics.h"
-#include "mozilla/Hal.h"
-#include "mozilla/Mutex.h"
-#include "nsBaseScreen.h"
-#include "nsCOMPtr.h"
-#include "nsIScreenManager.h"
-#include "nsProxyRelease.h"
-
-#include <android/native_window.h>
-
-class nsWindow;
-
-namespace android {
- class DisplaySurface;
- class IGraphicBufferProducer;
-};
-
-namespace mozilla {
- class Runnable;
-namespace gl {
- class GLContext;
-}
-namespace layers {
-class CompositorVsyncScheduler;
-class CompositorBridgeParent;
-}
-}
-
-enum class NotifyDisplayChangedEvent : int8_t {
- Observable,
- Suppressed
-};
-
-class nsScreenGonk : public nsBaseScreen
-{
- typedef mozilla::hal::ScreenConfiguration ScreenConfiguration;
- typedef mozilla::GonkDisplay GonkDisplay;
- typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
- typedef mozilla::layers::CompositorBridgeParent CompositorBridgeParent;
- typedef mozilla::gfx::DrawTarget DrawTarget;
-
-public:
- nsScreenGonk(uint32_t aId,
- GonkDisplay::DisplayType aDisplayType,
- const GonkDisplay::NativeData& aNativeData,
- NotifyDisplayChangedEvent aEventVisibility);
-
- ~nsScreenGonk();
-
- NS_IMETHOD GetId(uint32_t* aId);
- NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
- NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
- NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth);
- NS_IMETHOD GetColorDepth(int32_t* aColorDepth);
- NS_IMETHOD GetRotation(uint32_t* aRotation);
- NS_IMETHOD SetRotation(uint32_t aRotation);
-
- uint32_t GetId();
- NotifyDisplayChangedEvent GetEventVisibility();
- LayoutDeviceIntRect GetRect();
- float GetDpi();
- int32_t GetSurfaceFormat();
- ANativeWindow* GetNativeWindow();
- LayoutDeviceIntRect GetNaturalBounds();
- uint32_t EffectiveScreenRotation();
- ScreenConfiguration GetConfiguration();
- bool IsPrimaryScreen();
-
- already_AddRefed<DrawTarget> StartRemoteDrawing();
- void EndRemoteDrawing();
-
- nsresult MakeSnapshot(ANativeWindowBuffer* aBuffer);
- void SetCompositorBridgeParent(CompositorBridgeParent* aCompositorBridgeParent);
-
-#if ANDROID_VERSION >= 17
- android::DisplaySurface* GetDisplaySurface();
- int GetPrevDispAcquireFd();
-#endif
- GonkDisplay::DisplayType GetDisplayType();
-
- void RegisterWindow(nsWindow* aWindow);
- void UnregisterWindow(nsWindow* aWindow);
- void BringToTop(nsWindow* aWindow);
-
- const nsTArray<nsWindow*>& GetTopWindows() const
- {
- return mTopWindows;
- }
-
- // Non-primary screen only
- bool EnableMirroring();
- bool DisableMirroring();
- bool IsMirroring()
- {
- return mIsMirroring;
- }
-
- // Primary screen only
- bool SetMirroringScreen(nsScreenGonk* aScreen);
- bool ClearMirroringScreen(nsScreenGonk* aScreen);
-
- // Called only on compositor thread
- void SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface,
- mozilla::gl::GLContext* aGLContext);
- hwc_display_t GetEGLDisplay();
- hwc_surface_t GetEGLSurface();
- already_AddRefed<mozilla::gl::GLContext> GetGLContext();
- void UpdateMirroringWidget(already_AddRefed<nsWindow>& aWindow); // Primary screen only
- nsWindow* GetMirroringWidget(); // Primary screen only
-
-protected:
- ANativeWindowBuffer* DequeueBuffer();
- bool QueueBuffer(ANativeWindowBuffer* buf);
-
- uint32_t mId;
- NotifyDisplayChangedEvent mEventVisibility;
- int32_t mColorDepth;
- android::sp<ANativeWindow> mNativeWindow;
- float mDpi;
- int32_t mSurfaceFormat;
- LayoutDeviceIntRect mNaturalBounds; // Screen bounds w/o rotation taken into account.
- LayoutDeviceIntRect mVirtualBounds; // Screen bounds w/ rotation taken into account.
- uint32_t mScreenRotation;
- uint32_t mPhysicalScreenRotation;
- nsTArray<nsWindow*> mTopWindows;
-#if ANDROID_VERSION >= 17
- android::sp<android::DisplaySurface> mDisplaySurface;
-#endif
- bool mIsMirroring; // Non-primary screen only
- RefPtr<nsScreenGonk> mMirroringScreen; // Primary screen only
- mozilla::Atomic<CompositorBridgeParent*> mCompositorBridgeParent;
-
- // Accessed and updated only on compositor thread
- GonkDisplay::DisplayType mDisplayType;
- hwc_display_t mEGLDisplay;
- hwc_surface_t mEGLSurface;
- RefPtr<mozilla::gl::GLContext> mGLContext;
- RefPtr<nsWindow> mMirroringWidget; // Primary screen only
-
- // If we're using a BasicCompositor, these fields are temporarily
- // set during frame composition. They wrap the hardware
- // framebuffer.
- RefPtr<DrawTarget> mFramebufferTarget;
- ANativeWindowBuffer* mFramebuffer;
- /**
- * Points to a mapped gralloc buffer between calls to lock and unlock.
- * Should be null outside of the lock-unlock pair.
- */
- uint8_t* mMappedBuffer;
- // If we're using a BasicCompositor, this is our window back
- // buffer. The gralloc framebuffer driver expects us to draw the
- // entire framebuffer on every frame, but gecko expects the
- // windowing system to be tracking buffer updates for invalidated
- // regions. We get stuck holding that bag.
- //
- // Only accessed on the compositor thread, except during
- // destruction.
- RefPtr<DrawTarget> mBackBuffer;
-};
-
-class nsScreenManagerGonk final : public nsIScreenManager
-{
-public:
- typedef mozilla::GonkDisplay GonkDisplay;
-
-public:
- nsScreenManagerGonk();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSISCREENMANAGER
-
- static already_AddRefed<nsScreenManagerGonk> GetInstance();
- static already_AddRefed<nsScreenGonk> GetPrimaryScreen();
-
- void Initialize();
- void DisplayEnabled(bool aEnabled);
-
- nsresult AddScreen(GonkDisplay::DisplayType aDisplayType,
- android::IGraphicBufferProducer* aSink = nullptr,
- NotifyDisplayChangedEvent aEventVisibility = NotifyDisplayChangedEvent::Observable);
-
- nsresult RemoveScreen(GonkDisplay::DisplayType aDisplayType);
-
-#if ANDROID_VERSION >= 19
- void SetCompositorVsyncScheduler(mozilla::layers::CompositorVsyncScheduler* aObserver);
-#endif
-
-protected:
- ~nsScreenManagerGonk();
- void VsyncControl(bool aEnabled);
- uint32_t GetIdFromType(GonkDisplay::DisplayType aDisplayType);
- bool IsScreenConnected(uint32_t aId);
-
- bool mInitialized;
- nsTArray<RefPtr<nsScreenGonk>> mScreens;
- RefPtr<mozilla::Runnable> mScreenOnEvent;
- RefPtr<mozilla::Runnable> mScreenOffEvent;
-
-#if ANDROID_VERSION >= 19
- bool mDisplayEnabled;
- RefPtr<mozilla::layers::CompositorVsyncScheduler> mCompositorVsyncScheduler;
-#endif
-};
-
-#endif /* nsScreenManagerGonk_h___ */
diff --git a/widget/gonk/nsWidgetFactory.cpp b/widget/gonk/nsWidgetFactory.cpp
deleted file mode 100644
index 1c7525544..000000000
--- a/widget/gonk/nsWidgetFactory.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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/basictypes.h"
-
-#include "mozilla/ModuleUtils.h"
-#include "mozilla/WidgetUtils.h"
-
-#include "nsCOMPtr.h"
-#include "nsWidgetsCID.h"
-#include "nsAppShell.h"
-
-#include "nsWindow.h"
-#include "nsLookAndFeel.h"
-#include "nsAppShellSingleton.h"
-#include "nsScreenManagerGonk.h"
-#include "nsIdleServiceGonk.h"
-#include "nsTransferable.h"
-#include "nsClipboard.h"
-#include "nsClipboardHelper.h"
-
-#include "nsHTMLFormatConverter.h"
-#include "nsXULAppAPI.h"
-
-#include "PuppetWidget.h"
-
-using namespace mozilla::widget;
-
-// taken from android/nsWidgetFactory.cpp. GfxInfo is a legacy kludge, unfortunately
-// for the time being we still have to implement it on all platforms.
-#include "GfxInfo.h"
-namespace mozilla {
-namespace widget {
-// This constructor should really be shared with all platforms.
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init)
-}
-}
-
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsScreenManagerGonk, nsScreenManagerGonk::GetInstance)
-NS_GENERIC_FACTORY_CONSTRUCTOR(PuppetScreenManager)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceGonk, nsIdleServiceGonk::GetInstance)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
-
-NS_DEFINE_NAMED_CID(NS_APPSHELL_CID);
-NS_DEFINE_NAMED_CID(NS_WINDOW_CID);
-NS_DEFINE_NAMED_CID(NS_CHILD_CID);
-NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
-NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
-NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
-NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID);
-NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
-NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
-NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID);
-
-static nsresult
-ScreenManagerConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult)
-{
- return (XRE_IsParentProcess()) ?
- nsScreenManagerGonkConstructor(aOuter, aIID, aResult) :
- PuppetScreenManagerConstructor(aOuter, aIID, aResult);
-}
-
-static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
- { &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor },
- { &kNS_CHILD_CID, false, nullptr, nsWindowConstructor },
- { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor },
- { &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor },
- { &kNS_HTMLFORMATCONVERTER_CID, false, nullptr, nsHTMLFormatConverterConstructor },
- { &kNS_IDLE_SERVICE_CID, false, nullptr, nsIdleServiceGonkConstructor },
- { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor },
- { &kNS_GFXINFO_CID, false, nullptr, mozilla::widget::GfxInfoConstructor },
- { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardConstructor },
- { &kNS_CLIPBOARDHELPER_CID, false, nullptr, nsClipboardHelperConstructor },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
- { "@mozilla.org/widgets/window/gonk;1", &kNS_WINDOW_CID },
- { "@mozilla.org/widgets/child_window/gonk;1", &kNS_CHILD_CID },
- { "@mozilla.org/widget/appshell/gonk;1", &kNS_APPSHELL_CID },
- { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
- { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
- { "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },
- { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID },
- { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID },
- { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID },
- { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID },
- { nullptr }
-};
-
-static void
-nsWidgetGonkModuleDtor()
-{
- // Shutdown all XP level widget classes.
- WidgetUtils::Shutdown();
-
- nsLookAndFeel::Shutdown();
- nsAppShellShutdown();
-}
-
-static const mozilla::Module kWidgetModule = {
- mozilla::Module::kVersion,
- kWidgetCIDs,
- kWidgetContracts,
- nullptr,
- nullptr,
- nsAppShellInit,
- nsWidgetGonkModuleDtor
-};
-
-NSMODULE_DEFN(nsWidgetGonkModule) = &kWidgetModule;
diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp
deleted file mode 100644
index e11b7f233..000000000
--- a/widget/gonk/nsWindow.cpp
+++ /dev/null
@@ -1,744 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "nsWindow.h"
-
-#include "mozilla/DebugOnly.h"
-
-#include <fcntl.h>
-
-#include "android/log.h"
-#include "mozilla/dom/TabParent.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/Services.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "gfxContext.h"
-#include "gfxPlatform.h"
-#include "GLContextProvider.h"
-#include "GLContext.h"
-#include "GLContextEGL.h"
-#include "nsAppShell.h"
-#include "nsScreenManagerGonk.h"
-#include "nsTArray.h"
-#include "nsIWidgetListener.h"
-#include "ClientLayerManager.h"
-#include "BasicLayers.h"
-#include "libdisplay/GonkDisplay.h"
-#include "mozilla/TextEvents.h"
-#include "mozilla/gfx/2D.h"
-#include "mozilla/gfx/Logging.h"
-#include "mozilla/layers/APZCTreeManager.h"
-#include "mozilla/layers/APZThreadUtils.h"
-#include "mozilla/layers/CompositorBridgeParent.h"
-#include "mozilla/layers/CompositorThread.h"
-#include "mozilla/layers/CompositorSession.h"
-#include "mozilla/TouchEvents.h"
-#include "HwcComposer2D.h"
-
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
-#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
-#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
-
-#define IS_TOPLEVEL() (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)
-
-using namespace mozilla;
-using namespace mozilla::dom;
-using namespace mozilla::hal;
-using namespace mozilla::gfx;
-using namespace mozilla::gl;
-using namespace mozilla::layers;
-using namespace mozilla::widget;
-
-static nsWindow *gFocusedWindow = nullptr;
-
-NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
-
-nsWindow::nsWindow()
-{
- RefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance();
- screenManager->Initialize();
-
- // This is a hack to force initialization of the compositor
- // resources, if we're going to use omtc.
- //
- // NB: GetPlatform() will create the gfxPlatform, which wants
- // to know the color depth, which asks our native window.
- // This has to happen after other init has finished.
- gfxPlatform::GetPlatform();
- if (!ShouldUseOffMainThreadCompositing()) {
- MOZ_CRASH("How can we render apps, then?");
- }
-}
-
-nsWindow::~nsWindow()
-{
- if (mScreen->IsPrimaryScreen()) {
- mComposer2D->SetCompositorBridgeParent(nullptr);
- }
-}
-
-void
-nsWindow::DoDraw(void)
-{
- if (!hal::GetScreenEnabled()) {
- gDrawRequest = true;
- return;
- }
-
- RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen();
- const nsTArray<nsWindow*>& windows = screen->GetTopWindows();
-
- if (windows.IsEmpty()) {
- LOG(" no window to draw, bailing");
- return;
- }
-
- RefPtr<nsWindow> targetWindow = (nsWindow *)windows[0];
- while (targetWindow->GetLastChild()) {
- targetWindow = (nsWindow *)targetWindow->GetLastChild();
- }
-
- nsIWidgetListener* listener = targetWindow->GetWidgetListener();
- if (listener) {
- listener->WillPaintWindow(targetWindow);
- }
-
- listener = targetWindow->GetWidgetListener();
- if (listener) {
- LayerManager* lm = targetWindow->GetLayerManager();
- if (mozilla::layers::LayersBackend::LAYERS_CLIENT == lm->GetBackendType()) {
- // No need to do anything, the compositor will handle drawing
- } else {
- NS_RUNTIMEABORT("Unexpected layer manager type");
- }
-
- listener->DidPaintWindow();
- }
-}
-
-void
-nsWindow::ConfigureAPZControllerThread()
-{
- APZThreadUtils::SetControllerThread(CompositorThreadHolder::Loop());
-}
-
-/*static*/ nsEventStatus
-nsWindow::DispatchKeyInput(WidgetKeyboardEvent& aEvent)
-{
- if (!gFocusedWindow) {
- return nsEventStatus_eIgnore;
- }
-
- gFocusedWindow->UserActivity();
-
- nsEventStatus status;
- aEvent.mWidget = gFocusedWindow;
- gFocusedWindow->DispatchEvent(&aEvent, status);
- return status;
-}
-
-/*static*/ void
-nsWindow::DispatchTouchInput(MultiTouchInput& aInput)
-{
- APZThreadUtils::AssertOnControllerThread();
-
- if (!gFocusedWindow) {
- return;
- }
-
- gFocusedWindow->DispatchTouchInputViaAPZ(aInput);
-}
-
-class DispatchTouchInputOnMainThread : public mozilla::Runnable
-{
-public:
- DispatchTouchInputOnMainThread(const MultiTouchInput& aInput,
- const ScrollableLayerGuid& aGuid,
- const uint64_t& aInputBlockId,
- nsEventStatus aApzResponse)
- : mInput(aInput)
- , mGuid(aGuid)
- , mInputBlockId(aInputBlockId)
- , mApzResponse(aApzResponse)
- {}
-
- NS_IMETHOD Run() override {
- if (gFocusedWindow) {
- gFocusedWindow->DispatchTouchEventForAPZ(mInput, mGuid, mInputBlockId, mApzResponse);
- }
- return NS_OK;
- }
-
-private:
- MultiTouchInput mInput;
- ScrollableLayerGuid mGuid;
- uint64_t mInputBlockId;
- nsEventStatus mApzResponse;
-};
-
-void
-nsWindow::DispatchTouchInputViaAPZ(MultiTouchInput& aInput)
-{
- APZThreadUtils::AssertOnControllerThread();
-
- if (!mAPZC) {
- // In general mAPZC should not be null, but during initial setup
- // it might be, so we handle that case by ignoring touch input there.
- return;
- }
-
- // First send it through the APZ code
- mozilla::layers::ScrollableLayerGuid guid;
- uint64_t inputBlockId;
- nsEventStatus result = mAPZC->ReceiveInputEvent(aInput, &guid, &inputBlockId);
- // If the APZ says to drop it, then we drop it
- if (result == nsEventStatus_eConsumeNoDefault) {
- return;
- }
-
- // Can't use NS_NewRunnableMethod because it only takes up to one arg and
- // we need more. Also we can't pass in |this| to the task because nsWindow
- // refcounting is not threadsafe. Instead we just use the gFocusedWindow
- // static ptr inside the task.
- NS_DispatchToMainThread(new DispatchTouchInputOnMainThread(
- aInput, guid, inputBlockId, result));
-}
-
-void
-nsWindow::DispatchTouchEventForAPZ(const MultiTouchInput& aInput,
- const ScrollableLayerGuid& aGuid,
- const uint64_t aInputBlockId,
- nsEventStatus aApzResponse)
-{
- MOZ_ASSERT(NS_IsMainThread());
- UserActivity();
-
- // Convert it to an event we can send to Gecko
- WidgetTouchEvent event = aInput.ToWidgetTouchEvent(this);
-
- // Dispatch the event into the gecko root process for "normal" flow.
- // The event might get sent to a child process,
- // but if it doesn't we need to notify the APZ of various things.
- // All of that happens in ProcessUntransformedAPZEvent
- ProcessUntransformedAPZEvent(&event, aGuid, aInputBlockId, aApzResponse);
-}
-
-class DispatchTouchInputOnControllerThread : public Runnable
-{
-public:
- DispatchTouchInputOnControllerThread(const MultiTouchInput& aInput)
- : mInput(aInput)
- {}
-
- NS_IMETHOD Run() override {
- if (gFocusedWindow) {
- gFocusedWindow->DispatchTouchInputViaAPZ(mInput);
- }
- return NS_OK;
- }
-
-private:
- MultiTouchInput mInput;
-};
-
-nsresult
-nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId,
- TouchPointerState aPointerState,
- LayoutDeviceIntPoint aPoint,
- double aPointerPressure,
- uint32_t aPointerOrientation,
- nsIObserver* aObserver)
-{
- AutoObserverNotifier notifier(aObserver, "touchpoint");
-
- if (aPointerState == TOUCH_HOVER) {
- return NS_ERROR_UNEXPECTED;
- }
-
- if (!mSynthesizedTouchInput) {
- mSynthesizedTouchInput = MakeUnique<MultiTouchInput>();
- }
-
- // We should probably use a real timestamp here, but this is B2G and
- // so this probably never even exercised any more.
- uint32_t time = 0;
- TimeStamp timestamp = TimeStamp::FromSystemTime(time);
-
- MultiTouchInput inputToDispatch = UpdateSynthesizedTouchState(
- mSynthesizedTouchInput.get(), time, timestamp, aPointerId, aPointerState,
- aPoint, aPointerPressure, aPointerOrientation);
-
- // Can't use NewRunnableMethod here because that will pass a const-ref
- // argument to DispatchTouchInputViaAPZ whereas that function takes a
- // non-const ref. At this callsite we don't care about the mutations that
- // the function performs so this is fine. Also we can't pass |this| to the
- // task because nsWindow refcounting is not threadsafe. Instead we just use
- // the gFocusedWindow static ptr instead the task.
- APZThreadUtils::RunOnControllerThread(
- MakeAndAddRef<DispatchTouchInputOnControllerThread>(inputToDispatch));
-
- return NS_OK;
-}
-
-nsresult
-nsWindow::Create(nsIWidget* aParent,
- void* aNativeParent,
- const LayoutDeviceIntRect& aRect,
- nsWidgetInitData* aInitData)
-{
- BaseCreate(aParent, aInitData);
-
- nsCOMPtr<nsIScreen> screen;
-
- uint32_t screenId = aParent ? ((nsWindow*)aParent)->mScreen->GetId() :
- aInitData->mScreenId;
-
- RefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance();
- screenManager->ScreenForId(screenId, getter_AddRefs(screen));
-
- mScreen = static_cast<nsScreenGonk*>(screen.get());
-
- mBounds = aRect;
-
- mParent = (nsWindow *)aParent;
- mVisible = false;
-
- if (!aParent) {
- mBounds = mScreen->GetRect();
- }
-
- mComposer2D = HwcComposer2D::GetInstance();
-
- if (!IS_TOPLEVEL()) {
- return NS_OK;
- }
-
- mScreen->RegisterWindow(this);
-
- Resize(0, 0, mBounds.width, mBounds.height, false);
-
- return NS_OK;
-}
-
-void
-nsWindow::Destroy()
-{
- mOnDestroyCalled = true;
- mScreen->UnregisterWindow(this);
- if (this == gFocusedWindow) {
- gFocusedWindow = nullptr;
- }
- nsBaseWidget::OnDestroy();
-}
-
-NS_IMETHODIMP
-nsWindow::Show(bool aState)
-{
- if (mWindowType == eWindowType_invisible) {
- return NS_OK;
- }
-
- if (mVisible == aState) {
- return NS_OK;
- }
-
- mVisible = aState;
- if (!IS_TOPLEVEL()) {
- return mParent ? mParent->Show(aState) : NS_OK;
- }
-
- if (aState) {
- BringToTop();
- } else {
- const nsTArray<nsWindow*>& windows =
- mScreen->GetTopWindows();
- for (unsigned int i = 0; i < windows.Length(); i++) {
- nsWindow *win = windows[i];
- if (!win->mVisible) {
- continue;
- }
- win->BringToTop();
- break;
- }
- }
-
- return NS_OK;
-}
-
-bool
-nsWindow::IsVisible() const
-{
- return mVisible;
-}
-
-NS_IMETHODIMP
-nsWindow::Move(double aX,
- double aY)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsWindow::Resize(double aWidth,
- double aHeight,
- bool aRepaint)
-{
- return Resize(0, 0, aWidth, aHeight, aRepaint);
-}
-
-NS_IMETHODIMP
-nsWindow::Resize(double aX,
- double aY,
- double aWidth,
- double aHeight,
- bool aRepaint)
-{
- mBounds = LayoutDeviceIntRect(NSToIntRound(aX), NSToIntRound(aY),
- NSToIntRound(aWidth), NSToIntRound(aHeight));
- if (mWidgetListener) {
- mWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
- }
-
- if (aRepaint) {
- Invalidate(mBounds);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsWindow::Enable(bool aState)
-{
- return NS_OK;
-}
-
-bool
-nsWindow::IsEnabled() const
-{
- return true;
-}
-
-NS_IMETHODIMP
-nsWindow::SetFocus(bool aRaise)
-{
- if (aRaise) {
- BringToTop();
- }
-
- if (!IS_TOPLEVEL() && mScreen->IsPrimaryScreen()) {
- // We should only set focused window on non-toplevel primary window.
- gFocusedWindow = this;
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>&)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsWindow::Invalidate(const LayoutDeviceIntRect& aRect)
-{
- nsWindow *top = mParent;
- while (top && top->mParent) {
- top = top->mParent;
- }
- const nsTArray<nsWindow*>& windows = mScreen->GetTopWindows();
- if (top != windows[0] && this != windows[0]) {
- return NS_OK;
- }
-
- gDrawRequest = true;
- mozilla::NotifyEvent();
- return NS_OK;
-}
-
-LayoutDeviceIntPoint
-nsWindow::WidgetToScreenOffset()
-{
- LayoutDeviceIntPoint p(0, 0);
- nsWindow *w = this;
-
- while (w && w->mParent) {
- p.x += w->mBounds.x;
- p.y += w->mBounds.y;
-
- w = w->mParent;
- }
-
- return p;
-}
-
-void*
-nsWindow::GetNativeData(uint32_t aDataType)
-{
- switch (aDataType) {
- case NS_NATIVE_WINDOW:
- // Called before primary display's EGLSurface creation.
- return mScreen->GetNativeWindow();
- case NS_NATIVE_OPENGL_CONTEXT:
- return mScreen->GetGLContext().take();
- case NS_RAW_NATIVE_IME_CONTEXT: {
- void* pseudoIMEContext = GetPseudoIMEContext();
- if (pseudoIMEContext) {
- return pseudoIMEContext;
- }
- // There is only one IME context on Gonk.
- return NS_ONLY_ONE_NATIVE_IME_CONTEXT;
- }
- }
-
- return nullptr;
-}
-
-void
-nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal)
-{
- switch (aDataType) {
- case NS_NATIVE_OPENGL_CONTEXT:
- GLContext* context = reinterpret_cast<GLContext*>(aVal);
- if (!context) {
- mScreen->SetEGLInfo(EGL_NO_DISPLAY,
- EGL_NO_SURFACE,
- nullptr);
- return;
- }
- mScreen->SetEGLInfo(GLContextEGL::Cast(context)->GetEGLDisplay(),
- GLContextEGL::Cast(context)->GetEGLSurface(),
- context);
- return;
- }
-}
-
-NS_IMETHODIMP
-nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
-{
- if (mWidgetListener) {
- aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP_(void)
-nsWindow::SetInputContext(const InputContext& aContext,
- const InputContextAction& aAction)
-{
- mInputContext = aContext;
-}
-
-NS_IMETHODIMP_(InputContext)
-nsWindow::GetInputContext()
-{
- return mInputContext;
-}
-
-nsresult
-nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*)
-{
- if (mWindowType != eWindowType_toplevel) {
- // Ignore fullscreen request for non-toplevel windows.
- NS_WARNING("MakeFullScreen() on a dialog or child widget?");
- nsBaseWidget::InfallibleMakeFullScreen(aFullScreen);
- return NS_OK;
- }
-
- if (aFullScreen) {
- // Fullscreen is "sticky" for toplevel widgets on gonk: we
- // must paint the entire screen, and should only have one
- // toplevel widget, so it doesn't make sense to ever "exit"
- // fullscreen. If we do, we can leave parts of the screen
- // unpainted.
- nsIntRect virtualBounds;
- mScreen->GetRect(&virtualBounds.x, &virtualBounds.y,
- &virtualBounds.width, &virtualBounds.height);
- Resize(virtualBounds.x, virtualBounds.y,
- virtualBounds.width, virtualBounds.height,
- /*repaint*/true);
- }
-
- if (nsIWidgetListener* listener = GetWidgetListener()) {
- listener->FullscreenChanged(aFullScreen);
- }
- return NS_OK;
-}
-
-already_AddRefed<DrawTarget>
-nsWindow::StartRemoteDrawing()
-{
- RefPtr<DrawTarget> buffer = mScreen->StartRemoteDrawing();
- return buffer.forget();
-}
-
-void
-nsWindow::EndRemoteDrawing()
-{
- mScreen->EndRemoteDrawing();
-}
-
-float
-nsWindow::GetDPI()
-{
- return mScreen->GetDpi();
-}
-
-double
-nsWindow::GetDefaultScaleInternal()
-{
- float dpi = GetDPI();
- // The mean pixel density for mdpi devices is 160dpi, 240dpi for hdpi,
- // and 320dpi for xhdpi, respectively.
- // We'll take the mid-value between these three numbers as the boundary.
- if (dpi < 200.0) {
- return 1.0; // mdpi devices.
- }
- if (dpi < 280.0) {
- return 1.5; // hdpi devices.
- }
- // xhdpi devices and beyond.
- return floor(dpi / 150.0 + 0.5);
-}
-
-LayerManager *
-nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
- LayersBackend aBackendHint,
- LayerManagerPersistence aPersistence)
-{
- if (mLayerManager) {
- // This layer manager might be used for painting outside of DoDraw(), so we need
- // to set the correct rotation on it.
- if (ClientLayerManager* manager = mLayerManager->AsClientLayerManager()) {
- uint32_t rotation = mScreen->EffectiveScreenRotation();
- manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE,
- ScreenRotation(rotation));
- }
- return mLayerManager;
- }
-
- const nsTArray<nsWindow*>& windows = mScreen->GetTopWindows();
- nsWindow *topWindow = windows[0];
-
- if (!topWindow) {
- LOGW(" -- no topwindow\n");
- return nullptr;
- }
-
- CreateCompositor();
- if (RefPtr<CompositorBridgeParent> bridge = GetCompositorBridgeParent()) {
- mScreen->SetCompositorBridgeParent(bridge);
- if (mScreen->IsPrimaryScreen()) {
- mComposer2D->SetCompositorBridgeParent(bridge);
- }
- }
- MOZ_ASSERT(mLayerManager);
- return mLayerManager;
-}
-
-void
-nsWindow::DestroyCompositor()
-{
- if (RefPtr<CompositorBridgeParent> bridge = GetCompositorBridgeParent()) {
- mScreen->SetCompositorBridgeParent(nullptr);
- if (mScreen->IsPrimaryScreen()) {
- // Unset CompositorBridgeParent
- mComposer2D->SetCompositorBridgeParent(nullptr);
- }
- }
- nsBaseWidget::DestroyCompositor();
-}
-
-void
-nsWindow::BringToTop()
-{
- const nsTArray<nsWindow*>& windows = mScreen->GetTopWindows();
- if (!windows.IsEmpty()) {
- if (nsIWidgetListener* listener = windows[0]->GetWidgetListener()) {
- listener->WindowDeactivated();
- }
- }
-
- mScreen->BringToTop(this);
-
- if (mWidgetListener) {
- mWidgetListener->WindowActivated();
- }
-
- Invalidate(mBounds);
-}
-
-void
-nsWindow::UserActivity()
-{
- if (!mIdleService) {
- mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
- }
-
- if (mIdleService) {
- mIdleService->ResetIdleTimeOut(0);
- }
-}
-
-uint32_t
-nsWindow::GetGLFrameBufferFormat()
-{
- if (mLayerManager &&
- mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) {
- // We directly map the hardware fb on Gonk. The hardware fb
- // has RGB format.
- return LOCAL_GL_RGB;
- }
- return LOCAL_GL_NONE;
-}
-
-LayoutDeviceIntRect
-nsWindow::GetNaturalBounds()
-{
- return mScreen->GetNaturalBounds();
-}
-
-nsScreenGonk*
-nsWindow::GetScreen()
-{
- return mScreen;
-}
-
-bool
-nsWindow::NeedsPaint()
-{
- if (!mLayerManager) {
- return false;
- }
- return nsIWidget::NeedsPaint();
-}
-
-Composer2D*
-nsWindow::GetComposer2D()
-{
- if (mScreen->GetDisplayType() == GonkDisplay::DISPLAY_VIRTUAL) {
- return nullptr;
- }
-
- return mComposer2D;
-}
-
-CompositorBridgeParent*
-nsWindow::GetCompositorBridgeParent() const
-{
- return mCompositorSession ? mCompositorSession->GetInProcessBridge() : nullptr;
-}
diff --git a/widget/gonk/nsWindow.h b/widget/gonk/nsWindow.h
deleted file mode 100644
index 6106982f9..000000000
--- a/widget/gonk/nsWindow.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 nsWindow_h
-#define nsWindow_h
-
-#include "InputData.h"
-#include "mozilla/UniquePtr.h"
-#include "nsBaseWidget.h"
-#include "nsRegion.h"
-#include "nsIIdleServiceInternal.h"
-#include "Units.h"
-
-class ANativeWindowBuffer;
-
-namespace widget {
-struct InputContext;
-struct InputContextAction;
-}
-
-namespace mozilla {
-class HwcComposer2D;
-}
-
-class nsScreenGonk;
-
-class nsWindow : public nsBaseWidget
-{
-public:
- nsWindow();
-
- NS_DECL_ISUPPORTS_INHERITED
-
- static void DoDraw(void);
- static nsEventStatus DispatchKeyInput(mozilla::WidgetKeyboardEvent& aEvent);
- static void DispatchTouchInput(mozilla::MultiTouchInput& aInput);
-
- using nsBaseWidget::Create; // for Create signature not overridden here
- virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
- void* aNativeParent,
- const LayoutDeviceIntRect& aRect,
- nsWidgetInitData* aInitData) override;
- virtual void Destroy();
-
- NS_IMETHOD Show(bool aState);
- virtual bool IsVisible() const;
- NS_IMETHOD Move(double aX,
- double aY);
- NS_IMETHOD Resize(double aWidth,
- double aHeight,
- bool aRepaint);
- NS_IMETHOD Resize(double aX,
- double aY,
- double aWidth,
- double aHeight,
- bool aRepaint);
- NS_IMETHOD Enable(bool aState);
- virtual bool IsEnabled() const;
- NS_IMETHOD SetFocus(bool aRaise = false);
- NS_IMETHOD ConfigureChildren(const nsTArray<nsIWidget::Configuration>&);
- NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect);
- virtual void* GetNativeData(uint32_t aDataType);
- virtual void SetNativeData(uint32_t aDataType, uintptr_t aVal);
- NS_IMETHOD SetTitle(const nsAString& aTitle)
- {
- return NS_OK;
- }
- virtual LayoutDeviceIntPoint WidgetToScreenOffset();
- void DispatchTouchInputViaAPZ(mozilla::MultiTouchInput& aInput);
- void DispatchTouchEventForAPZ(const mozilla::MultiTouchInput& aInput,
- const ScrollableLayerGuid& aGuid,
- const uint64_t aInputBlockId,
- nsEventStatus aApzResponse);
- NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
- nsEventStatus& aStatus);
- virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
- TouchPointerState aPointerState,
- LayoutDeviceIntPoint aPoint,
- double aPointerPressure,
- uint32_t aPointerOrientation,
- nsIObserver* aObserver) override;
-
- virtual nsresult MakeFullScreen(
- bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override;
-
- virtual already_AddRefed<mozilla::gfx::DrawTarget>
- StartRemoteDrawing() override;
- virtual void EndRemoteDrawing() override;
-
- virtual float GetDPI();
- virtual double GetDefaultScaleInternal();
- virtual mozilla::layers::LayerManager*
- GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr,
- LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
- LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT);
- virtual void DestroyCompositor();
-
- NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
- const InputContextAction& aAction);
- NS_IMETHOD_(InputContext) GetInputContext();
-
- virtual uint32_t GetGLFrameBufferFormat() override;
-
- virtual LayoutDeviceIntRect GetNaturalBounds() override;
- virtual bool NeedsPaint();
-
- virtual Composer2D* GetComposer2D() override;
-
- void ConfigureAPZControllerThread() override;
-
- nsScreenGonk* GetScreen();
-
-protected:
- nsWindow* mParent;
- bool mVisible;
- InputContext mInputContext;
- nsCOMPtr<nsIIdleServiceInternal> mIdleService;
-
- virtual ~nsWindow();
-
- void BringToTop();
-
- // Call this function when the users activity is the direct cause of an
- // event (like a keypress or mouse click).
- void UserActivity();
-
- bool UseExternalCompositingSurface() const override {
- return true;
- }
- CompositorBridgeParent* GetCompositorBridgeParent() const;
-
-private:
- // This is used by SynthesizeNativeTouchPoint to maintain state between
- // multiple synthesized points
- mozilla::UniquePtr<mozilla::MultiTouchInput> mSynthesizedTouchInput;
-
- RefPtr<nsScreenGonk> mScreen;
-
- RefPtr<mozilla::HwcComposer2D> mComposer2D;
-};
-
-#endif /* nsWindow_h */
diff --git a/widget/moz.build b/widget/moz.build
index f69f2d87c..5138a89ef 100644
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -6,9 +6,9 @@
toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
-if toolkit in ('cocoa', 'android', 'gonk', 'uikit'):
+if toolkit in ('cocoa', 'android', 'uikit'):
DIRS += [toolkit]
-if toolkit in ('android', 'gonk', 'gtk2', 'gtk3'):
+if toolkit in ('android', 'gtk2', 'gtk3'):
EXPORTS += ['nsIPrintDialogService.h']
if toolkit == 'windows':
@@ -222,7 +222,7 @@ if toolkit in ('cocoa', 'windows'):
]
if toolkit in {'gtk2', 'gtk3', 'cocoa', 'windows',
- 'android', 'gonk', 'uikit'}:
+ 'android', 'uikit'}:
UNIFIED_SOURCES += [
'nsBaseFilePicker.cpp',
]