Compare commits
429 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8ea2a8ec1 | |||
| 9ed3b3a9df | |||
| 12487553de | |||
| 9c1a618b4a | |||
| ac0e784417 | |||
| 48cab6b203 | |||
| e1c0472069 | |||
| 2c498ce707 | |||
| bc483edb29 | |||
| 9762f4c412 | |||
| 5bfce88fc5 | |||
| 94ef66994d | |||
| 257c29daca | |||
| 173483eb84 | |||
| 06099b2663 | |||
| 33c1f0a71c | |||
| a3d78f1d80 | |||
| c573d213f8 | |||
| c72707aef9 | |||
| 313ef06c86 | |||
| 6b79340c15 | |||
| d9a5b29372 | |||
| d2b0e093fc | |||
| 945e563912 | |||
| a7efa379eb | |||
| d04df4ebe5 | |||
| 2a2c84ef3a | |||
| bc97db893a | |||
| f216834df7 | |||
| be25a7d594 | |||
| 10f43e8024 | |||
| bbb3e8d071 | |||
| 4c3af35156 | |||
| 8656228014 | |||
| 03f9ea8435 | |||
| 9cf27d8fb1 | |||
| d1b24ea6af | |||
| b07ffbde29 | |||
| 1673236940 | |||
| 06861a2d17 | |||
| ef7ac62f97 | |||
| 245a9f2751 | |||
| 1d38f158b5 | |||
| 62a526854d | |||
| 3dda940c92 | |||
| ab77c4720d | |||
| c8f1f9325e | |||
| 658940d3fb | |||
| 51b4ca401e | |||
| 10e4ca4ef3 | |||
| 2bcc2bdfe5 | |||
| 6462b580bb | |||
| b83d91c944 | |||
| 07f842bc9e | |||
| 3913e845fa | |||
| 09f0913974 | |||
| aa9ca35115 | |||
| 010dfdf834 | |||
| 150fac9c09 | |||
| ec3aef13d8 | |||
| 2b56005bd2 | |||
| 9bc893b6ad | |||
| 3feb92e788 | |||
| 1265952814 | |||
| f5ad5d97db | |||
| 5ac0939731 | |||
| b653694860 | |||
| 49051a5095 | |||
| 7734de6465 | |||
| edac646434 | |||
| 51c7665fdc | |||
| 37545821fc | |||
| 8a1ed0f146 | |||
| 7a0228fb81 | |||
| 3aecf9e031 | |||
| c2d4d221af | |||
| 53f89fbe22 | |||
| eb5f7ef7af | |||
| e2fc76d21d | |||
| 1754103175 | |||
| dacd00708f | |||
| a73129243c | |||
| 54a6aa9081 | |||
| 0fbb53c606 | |||
| eb2e79977d | |||
| b70a47f5e5 | |||
| 9d5ff72548 | |||
| 6b972b56a5 | |||
| a80d30baf7 | |||
| b9280e9a8e | |||
| c6640d201c | |||
| 795fdc3605 | |||
| 05311da33d | |||
| 2e442cb1d1 | |||
| fe322590cc | |||
| 6cf9b25c04 | |||
| 417babb3d4 | |||
| bdaaa6f0c7 | |||
| 7e92dd7fe4 | |||
| 50601e24ed | |||
| bfc3116661 | |||
| 264b6e54f2 | |||
| 1ed7ecc82f | |||
| 19b8032d06 | |||
| 1e254ea8f4 | |||
| babfc99c35 | |||
| 5c802555a2 | |||
| fbc41c9a4e | |||
| 1eca461cb1 | |||
| ebd327c7a6 | |||
| 602febe876 | |||
| 84fcd3ae6a | |||
| 84296c6e1c | |||
| 6012e0ea8c | |||
| 9c76defad0 | |||
| ffd6fab35c | |||
| 296f97f7ca | |||
| 9cbef34f29 | |||
| 7a65136d29 | |||
| acaebea846 | |||
| ce850ac12f | |||
| a93422d3ed | |||
| b2e605838e | |||
| 2e14002442 | |||
| c743949df5 | |||
| f207a3f6d1 | |||
| d6211605a1 | |||
| b16676b54a | |||
| dc9bfe5189 | |||
| 80620ed4c6 | |||
| 76bd0ab696 | |||
| e0914df58a | |||
| 20039a422e | |||
| 22b9c9ca68 | |||
| 0c546e35ec | |||
| b70370ac09 | |||
| aa10bb7dc5 | |||
| c6100a9be1 | |||
| 529a2f7bf8 | |||
| 9ec7e916c5 | |||
| 982b36cf98 | |||
| a73eab5e92 | |||
| a8479ccb5f | |||
| f55e4e0e01 | |||
| d08c32ce04 | |||
| 1d599c5e60 | |||
| e888ae59e4 | |||
| 951d544894 | |||
| 49898b34e1 | |||
| 3854a6a42e | |||
| d4da5bc281 | |||
| 04954f5242 | |||
| 9fc5496526 | |||
| e363d24b1c | |||
| 801f4027a2 | |||
| c0dc344f76 | |||
| b5b3d81f00 | |||
| 8dd8dbc1d1 | |||
| 8f31aa59a8 | |||
| 5b581b6c0f | |||
| 297ac64fde | |||
| d4490f0e17 | |||
| d04e7a3231 | |||
| 5b456aba27 | |||
| 0c065dcc1f | |||
| 531f73329d | |||
| d6ba72032d | |||
| bfdc7a2609 | |||
| 031abf03da | |||
| 6aac8e6be6 | |||
| 8ff93d21c3 | |||
| 6df3d0bc44 | |||
| 0b18e8fdb4 | |||
| 19d8ae0f78 | |||
| d7ffb5dddc | |||
| 2859b73dfe | |||
| 6f9021a5e6 | |||
| 3bfeaefdbd | |||
| db1eace975 | |||
| cab0fa176e | |||
| 2f9ae107a2 | |||
| 18c93abcb3 | |||
| bd64dfb661 | |||
| 82619063ee | |||
| 5dbf18d66e | |||
| 6a34ff2728 | |||
| f7c7487756 | |||
| f966cb4ca0 | |||
| 549563a3d2 | |||
| c5f2a3f8fe | |||
| 81a3bbd5e8 | |||
| 1509a2a799 | |||
| fc547b734f | |||
| b3700b5a19 | |||
| 2b29682095 | |||
| 286094ee33 | |||
| c7a061d24e | |||
| 4bdc2e0aba | |||
| e69061082b | |||
| 1da2ec3cb1 | |||
| 8ffc3b80b2 | |||
| 08f8b6cb8e | |||
| fb09c9692c | |||
| 4901b0c78f | |||
| 0a2117241f | |||
| f352cfd15b | |||
| ac7c5c1064 | |||
| 077cb2103d | |||
| cdeda011a4 | |||
| 894c146988 | |||
| 61cc9e151f | |||
| cfe4c9ff21 | |||
| d4bd29b320 | |||
| 7f2f2056c3 | |||
| 4dd3b2cfb7 | |||
| 2e62ad0f00 | |||
| 41ef292b82 | |||
| aa60671c88 | |||
| f1ccba39e8 | |||
| 226e580a30 | |||
| 6f8e719200 | |||
| c127af1e05 | |||
| 648904cc69 | |||
| dc85ddb3f9 | |||
| 23a7d8555f | |||
| bc9e250d34 | |||
| 2203186527 | |||
| 53d3d9ecb8 | |||
| de549f67a1 | |||
| 755c41481a | |||
| aebc2126bc | |||
| f43547fb31 | |||
| 398e4df7cf | |||
| ff68efc3f5 | |||
| 8ba2f51bda | |||
| 87b79b278b | |||
| 121e3ea9be | |||
| ec6ed79ee1 | |||
| ca125826a7 | |||
| dd0aecf108 | |||
| ef5cb2f0cd | |||
| e5a7bb40e9 | |||
| bfdda48fee | |||
| ebea1bb5c1 | |||
| 14bc1552fc | |||
| a5b80d3944 | |||
| 75d0eedc2b | |||
| 29ac7028fa | |||
| 8a63b61495 | |||
| eb9e6443e2 | |||
| 362c466a16 | |||
| 5dac42646b | |||
| c25faf6426 | |||
| 81df1245b4 | |||
| 2bf4d92185 | |||
| ae6073fe80 | |||
| d0463da2a1 | |||
| c0f8001627 | |||
| f39bf61b04 | |||
| 9c8237dab0 | |||
| b88251fa79 | |||
| 208855917e | |||
| 34bdf450e9 | |||
| 998fa1f4e9 | |||
| 5c80f7d58c | |||
| 7552181e24 | |||
| 4b2e26050e | |||
| 530b48de71 | |||
| f4721901f8 | |||
| 8b692269c1 | |||
| 079eca7b4d | |||
| fee40cdbe2 | |||
| 66920bb4cb | |||
| fdbf810aa2 | |||
| 08bfc1de4a | |||
| 76149328fe | |||
| 285f33f3f1 | |||
| b17c1b7588 | |||
| 5b25c90db8 | |||
| 931a0a5168 | |||
| f6a46438bd | |||
| 4a60ec1755 | |||
| ec222413dd | |||
| 5a28239813 | |||
| da45cba2ff | |||
| 54bc34496a | |||
| 294910ac84 | |||
| 71d2c6a5d5 | |||
| 79bf17fe24 | |||
| 31f66031bc | |||
| d3f2284791 | |||
| ec647608c4 | |||
| 597582ddd8 | |||
| c6d9889182 | |||
| 7c58234174 | |||
| ae9282b0af | |||
| 310ba646fc | |||
| d479908939 | |||
| 5cd5d68d22 | |||
| 3e0bf25acb | |||
| f3d277c94a | |||
| 04545ecbb0 | |||
| 5350651d6f | |||
| f2e2e28419 | |||
| b9031785ac | |||
| 91a72474a1 | |||
| b6e7c425c6 | |||
| 834ace4566 | |||
| 54af70005d | |||
| f2bf168925 | |||
| 27ffbd8dec | |||
| eaa82592fe | |||
| 73784585a8 | |||
| 262d562dd9 | |||
| ab4f904dc9 | |||
| fc4fdd5ee2 | |||
| 41c5b62b1a | |||
| 239cb0435c | |||
| c6ccc7a6e2 | |||
| 6cedb9019c | |||
| 8bc64f0438 | |||
| 89e6e39e58 | |||
| 645761f677 | |||
| 0fc60f7855 | |||
| ce38460d87 | |||
| de8e759d3a | |||
| 06f6134538 | |||
| ac352b3a23 | |||
| 9b8e65e552 | |||
| 35999a05f0 | |||
| 86ee30e9b4 | |||
| a81c4a1e23 | |||
| 394ce458a0 | |||
| f187e57899 | |||
| a15335872d | |||
| beb77b4dab | |||
| aa80d8cd0a | |||
| 77d197f14e | |||
| f98fbb778c | |||
| c46a0106f2 | |||
| cbf3db0be0 | |||
| 21f3710083 | |||
| 8ac5768f4f | |||
| 2458b9305c | |||
| a8909ea2a5 | |||
| ac7c35c6c2 | |||
| e4631b5a85 | |||
| e1c50b5dc5 | |||
| c6c5a5cd12 | |||
| bd4854a607 | |||
| cd0181e6f4 | |||
| 287b1d2b4d | |||
| 10c61bb0a7 | |||
| 92215ac34f | |||
| f64d50d8c8 | |||
| b74e0ce48f | |||
| 27cb0029a8 | |||
| ce6f193f06 | |||
| a862ffdde4 | |||
| 3f1cd8a118 | |||
| bb4b5838e3 | |||
| ea98d64184 | |||
| 98f3c56da5 | |||
| 20b7619380 | |||
| 7b1c3f05c7 | |||
| 9166998442 | |||
| e1f6b577bf | |||
| ba0d08b2a6 | |||
| e79c12a038 | |||
| 2ca5182a28 | |||
| 205e627209 | |||
| 425d4f3f63 | |||
| d69843e122 | |||
| d2586d3b59 | |||
| edab84c89b | |||
| dd08754f1f | |||
| 2cdfe85091 | |||
| a11acef36f | |||
| 1e34dbf616 | |||
| b3d4763ef6 | |||
| fe630e9383 | |||
| 826a20785f | |||
| 75932d7621 | |||
| 62d095af4f | |||
| 1594735aa0 | |||
| cbd0bdf9fc | |||
| d3e8e8fb9c | |||
| 66406c5a48 | |||
| 753c600dd2 | |||
| b28b1df348 | |||
| b94649162e | |||
| ee50e19dbd | |||
| cc23f8b831 | |||
| bac7b68bb1 | |||
| f9a622c89b | |||
| c321dc5e81 | |||
| 72f37c9df4 | |||
| 544eac0c8a | |||
| 823593ddae | |||
| 3600e704c4 | |||
| 0c79d756a4 | |||
| eb531a7a88 | |||
| d6634d30dc | |||
| f87806b1b4 | |||
| 2a5afeb5ff | |||
| fc5495f1ec | |||
| 699cc361a2 | |||
| 31bf4f10c0 | |||
| fe704af62f | |||
| e74517543d | |||
| 44acf19742 | |||
| bf20aa253e | |||
| 81c815840d | |||
| e9cd63dc5f | |||
| 1ae8f67d93 | |||
| daa1e10333 | |||
| a8a356e703 | |||
| ca440cc5dd | |||
| 95a9fb4f62 | |||
| 7db9e27112 | |||
| 03bcdbe3f7 | |||
| 67fbc6b3ad | |||
| d9662d7396 | |||
| 5ccbbf259d | |||
| 179c2f8723 | |||
| c76e0a40a7 | |||
| 03407e528f | |||
| 0c41d742cf | |||
| ed2f471a4e |
@@ -3,7 +3,7 @@
|
||||
[](https://ci.appveyor.com/project/cgutman/moonlight-android/branch/master)
|
||||
[](https://hosted.weblate.org/projects/moonlight/moonlight-android/)
|
||||
|
||||
[Moonlight for Android](https://moonlight-stream.org) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield.
|
||||
[Moonlight for Android](https://moonlight-stream.org) is an open source client for NVIDIA GameStream, as used by the NVIDIA Shield.
|
||||
|
||||
Moonlight for Android will allow you to stream your full collection of games from your Windows PC to your Android device,
|
||||
whether in your own home or over the internet.
|
||||
|
||||
+25
-16
@@ -1,25 +1,28 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
ndkVersion "22.0.7026061"
|
||||
ndkVersion "23.2.8568313"
|
||||
|
||||
compileSdkVersion 30
|
||||
compileSdk 33
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
minSdk 16
|
||||
targetSdk 33
|
||||
|
||||
versionName "9.8.4"
|
||||
versionCode = 255
|
||||
versionName "10.8.4"
|
||||
versionCode = 293
|
||||
|
||||
// Generate native debug symbols to allow Google Play to symbolicate our native crashes
|
||||
ndk.debugSymbolLevel = 'FULL'
|
||||
}
|
||||
|
||||
flavorDimensions "root"
|
||||
flavorDimensions.add("root")
|
||||
|
||||
productFlavors {
|
||||
root {
|
||||
// Android O has native mouse capture, so don't show the rooted
|
||||
// version to devices running O on the Play Store.
|
||||
maxSdkVersion 25
|
||||
maxSdk 25
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
@@ -29,6 +32,7 @@ android {
|
||||
|
||||
applicationId "com.limelight.root"
|
||||
dimension "root"
|
||||
buildConfigField "boolean", "ROOT_BUILD", "true"
|
||||
}
|
||||
|
||||
nonRoot {
|
||||
@@ -40,12 +44,13 @@ android {
|
||||
|
||||
applicationId "com.limelight"
|
||||
dimension "root"
|
||||
buildConfigField "boolean", "ROOT_BUILD", "false"
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
lint {
|
||||
disable 'MissingTranslation'
|
||||
lintConfig file("lint.xml")
|
||||
lintConfig file('lint.xml')
|
||||
}
|
||||
|
||||
bundle {
|
||||
@@ -55,7 +60,7 @@ android {
|
||||
enableSplit = false
|
||||
}
|
||||
density {
|
||||
// FIXME: This should not be neccessary but we get
|
||||
// FIXME: This should not be necessary but we get
|
||||
// weird crashes due to missing drawable resources
|
||||
// when this split is enabled.
|
||||
enableSplit = false
|
||||
@@ -65,9 +70,10 @@ android {
|
||||
buildTypes {
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
resValue "string", "app_label", "Moonlight (Debug)"
|
||||
resValue "string", "app_label_root", "Moonlight (Root Debug)"
|
||||
|
||||
minifyEnabled true
|
||||
useProguard false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
release {
|
||||
@@ -102,6 +108,8 @@ android {
|
||||
//
|
||||
// TL;DR: Leave the following line alone!
|
||||
applicationIdSuffix ".unofficial"
|
||||
resValue "string", "app_label", "Moonlight"
|
||||
resValue "string", "app_label_root", "Moonlight (Root)"
|
||||
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
@@ -116,10 +124,11 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.66'
|
||||
implementation 'org.bouncycastle:bcpkix-jdk15on:1.66'
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
|
||||
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
|
||||
implementation 'org.jcodec:jcodec:0.2.3'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.12.12'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
|
||||
implementation 'com.squareup.okio:okio:1.17.5'
|
||||
implementation 'org.jmdns:jmdns:3.5.5'
|
||||
implementation 'org.jmdns:jmdns:3.5.7'
|
||||
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0'
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_label" translatable="false">Moonlight (Debug)</string>
|
||||
<string name="app_label_root" translatable="false">Moonlight (Root Debug)</string>
|
||||
|
||||
</resources>
|
||||
@@ -35,6 +35,7 @@
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:dataExtractionRules="@xml/backup_rules_s"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:isGame="true"
|
||||
android:banner="@drawable/atv_banner"
|
||||
@@ -43,22 +44,31 @@
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:installLocation="auto"
|
||||
android:gwpAsanMode="always"
|
||||
android:localeConfig="@xml/locales_config"
|
||||
android:enableOnBackInvokedCallback="false"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<provider
|
||||
android:name=".PosterContentProvider"
|
||||
android:authorities="poster.${applicationId}"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
</provider>
|
||||
|
||||
<!-- Samsung multi-window support -->
|
||||
<uses-library
|
||||
android:name="com.sec.android.app.multiwindow"
|
||||
android:required="false" />
|
||||
|
||||
<meta-data
|
||||
android:name="com.sec.android.support.multiwindow"
|
||||
android:value="true" />
|
||||
|
||||
<!-- Disable Game Mode downscaling since it can break our UI dialogs and doesn't benefit
|
||||
performance much for us since we don't use GL/Vulkan for rendering anyway -->
|
||||
<meta-data
|
||||
android:name="com.android.graphics.intervention.wm.allowDownscale"
|
||||
android:value="false"/>
|
||||
|
||||
<!-- Samsung DeX support requires explicit placement of android:resizeableActivity="true"
|
||||
in each activity even though it is implied by targeting API 24+ -->
|
||||
|
||||
@@ -98,6 +108,7 @@
|
||||
<activity
|
||||
android:name=".preferences.StreamSettings"
|
||||
android:resizeableActivity="true"
|
||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
||||
android:label="Streaming Settings">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
@@ -107,16 +118,15 @@
|
||||
android:name=".preferences.AddComputerManually"
|
||||
android:resizeableActivity="true"
|
||||
android:windowSoftInputMode="stateVisible"
|
||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
||||
android:label="Add Computer Manually">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.limelight.PcView" />
|
||||
</activity>
|
||||
<!-- This will fall back to sensorLandscape at runtime on Android 4.2 and below -->
|
||||
<activity
|
||||
android:name=".Game"
|
||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
||||
android:screenOrientation="userLandscape"
|
||||
android:noHistory="true"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:resizeableActivity="true"
|
||||
|
||||
@@ -293,6 +293,11 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
|
||||
setContentView(R.layout.activity_app_view);
|
||||
|
||||
// Allow floating expanded PiP overlays while browsing apps
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
setShouldDockBigOverlays(false);
|
||||
}
|
||||
|
||||
UiHelper.notifyNewRootView(this);
|
||||
|
||||
showHiddenApps = getIntent().getBooleanExtra(SHOW_HIDDEN_APPS_EXTRA, false);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,9 +2,12 @@ package com.limelight;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.window.OnBackInvokedCallback;
|
||||
import android.window.OnBackInvokedDispatcher;
|
||||
|
||||
import com.limelight.utils.SpinnerDialog;
|
||||
|
||||
@@ -13,10 +16,26 @@ public class HelpActivity extends Activity {
|
||||
private SpinnerDialog loadingDialog;
|
||||
private WebView webView;
|
||||
|
||||
private boolean backCallbackRegistered;
|
||||
private OnBackInvokedCallback onBackInvokedCallback;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
onBackInvokedCallback = new OnBackInvokedCallback() {
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
// We should always be able to go back because we unregister our callback
|
||||
// when we can't go back. Nonetheless, we will still check anyway.
|
||||
if (webView.canGoBack()) {
|
||||
webView.goBack();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
webView = new WebView(this);
|
||||
setContentView(webView);
|
||||
|
||||
@@ -39,6 +58,8 @@ public class HelpActivity extends Activity {
|
||||
getResources().getString(R.string.help_loading_title),
|
||||
getResources().getString(R.string.help_loading_msg), false);
|
||||
}
|
||||
|
||||
refreshBackDispatchState();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,6 +68,8 @@ public class HelpActivity extends Activity {
|
||||
loadingDialog.dismiss();
|
||||
loadingDialog = null;
|
||||
}
|
||||
|
||||
refreshBackDispatchState();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,7 +82,33 @@ public class HelpActivity extends Activity {
|
||||
webView.loadUrl(getIntent().getData().toString());
|
||||
}
|
||||
|
||||
private void refreshBackDispatchState() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (webView.canGoBack() && !backCallbackRegistered) {
|
||||
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
|
||||
OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback);
|
||||
backCallbackRegistered = true;
|
||||
}
|
||||
else if (!webView.canGoBack() && backCallbackRegistered) {
|
||||
getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(onBackInvokedCallback);
|
||||
backCallbackRegistered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (backCallbackRegistered) {
|
||||
getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(onBackInvokedCallback);
|
||||
}
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
// NOTE: This will NOT be called on Android 13+ with android:enableOnBackInvokedCallback="true"
|
||||
public void onBackPressed() {
|
||||
// Back goes back through the WebView history
|
||||
// until no more history remains
|
||||
|
||||
@@ -124,6 +124,11 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
|
||||
UiHelper.notifyNewRootView(this);
|
||||
|
||||
// Allow floating expanded PiP overlays while browsing PCs
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
setShouldDockBigOverlays(false);
|
||||
}
|
||||
|
||||
// Set default preferences if we've never been run
|
||||
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
|
||||
|
||||
@@ -155,6 +160,13 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
}
|
||||
});
|
||||
|
||||
// Amazon review didn't like the help button because the wiki was not entirely
|
||||
// navigable via the Fire TV remote (though the relevant parts were). Let's hide
|
||||
// it on Fire TV.
|
||||
if (getPackageManager().hasSystemFeature("amazon.hardware.fire_tv")) {
|
||||
helpButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
getFragmentManager().beginTransaction()
|
||||
.replace(R.id.pcFragmentContainer, new AdapterFragment())
|
||||
.commitAllowingStateLoss();
|
||||
@@ -367,8 +379,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
}
|
||||
|
||||
private void doPair(final ComputerDetails computer) {
|
||||
if (computer.state == ComputerDetails.State.OFFLINE ||
|
||||
ServerHelper.getCurrentAddressFromComputer(computer) == null) {
|
||||
if (computer.state == ComputerDetails.State.OFFLINE || computer.activeAddress == null) {
|
||||
Toast.makeText(PcView.this, getResources().getString(R.string.pair_pc_offline), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
@@ -505,8 +516,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
}
|
||||
|
||||
private void doUnpair(final ComputerDetails computer) {
|
||||
if (computer.state == ComputerDetails.State.OFFLINE ||
|
||||
ServerHelper.getCurrentAddressFromComputer(computer) == null) {
|
||||
if (computer.state == ComputerDetails.State.OFFLINE || computer.activeAddress == null) {
|
||||
Toast.makeText(PcView.this, getResources().getString(R.string.error_pc_offline), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,11 +13,13 @@ import com.limelight.computers.ComputerManagerService;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.nvstream.http.NvApp;
|
||||
import com.limelight.nvstream.http.PairingManager;
|
||||
import com.limelight.nvstream.wol.WakeOnLanSender;
|
||||
import com.limelight.utils.Dialog;
|
||||
import com.limelight.utils.ServerHelper;
|
||||
import com.limelight.utils.SpinnerDialog;
|
||||
import com.limelight.utils.UiHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -26,6 +28,7 @@ public class ShortcutTrampoline extends Activity {
|
||||
private NvApp app;
|
||||
private ArrayList<Intent> intentStack = new ArrayList<>();
|
||||
|
||||
private int wakeHostTries = 10;
|
||||
private ComputerDetails computer;
|
||||
private SpinnerDialog blockingLoadSpinner;
|
||||
|
||||
@@ -79,6 +82,23 @@ public class ShortcutTrampoline extends Activity {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to wake the target PC if it's offline (up to some retry limit)
|
||||
if (details.state == ComputerDetails.State.OFFLINE && details.macAddress != null && --wakeHostTries >= 0) {
|
||||
try {
|
||||
// Make a best effort attempt to wake the target PC
|
||||
WakeOnLanSender.sendWolPacket(computer);
|
||||
|
||||
// If we sent at least one WoL packet, reset the computer state
|
||||
// to force ComputerManager to poll it again.
|
||||
managerBinder.invalidateStateForComputer(computer.uuid);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
// If we got an exception, we couldn't send a single WoL packet,
|
||||
// so fallthrough into the offline error path.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (details.state != ComputerDetails.State.UNKNOWN) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -8,16 +8,6 @@ import com.limelight.nvstream.av.audio.AudioRenderer;
|
||||
import com.limelight.nvstream.http.LimelightCryptoProvider;
|
||||
|
||||
public class PlatformBinding {
|
||||
public static String getDeviceName() {
|
||||
String deviceName = android.os.Build.MODEL;
|
||||
deviceName = deviceName.replace(" ", "");
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
public static AudioRenderer getAudioRenderer() {
|
||||
return new AndroidAudioRenderer();
|
||||
}
|
||||
|
||||
public static LimelightCryptoProvider getCryptoProvider(Context c) {
|
||||
return new AndroidCryptoProvider(c);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.limelight.binding.audio;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioTrack;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.os.Build;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
@@ -12,8 +15,16 @@ import com.limelight.nvstream.jni.MoonBridge;
|
||||
|
||||
public class AndroidAudioRenderer implements AudioRenderer {
|
||||
|
||||
private final Context context;
|
||||
private final boolean enableAudioFx;
|
||||
|
||||
private AudioTrack track;
|
||||
|
||||
public AndroidAudioRenderer(Context context, boolean enableAudioFx) {
|
||||
this.context = context;
|
||||
this.enableAudioFx = enableAudioFx;
|
||||
}
|
||||
|
||||
private AudioTrack createAudioTrack(int channelConfig, int sampleRate, int bufferSize, boolean lowLatency) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return new AudioTrack(AudioManager.STREAM_MUSIC,
|
||||
@@ -161,6 +172,12 @@ public class AndroidAudioRenderer implements AudioRenderer {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip low latency options when using audio effects, since low latency mode
|
||||
// precludes the use of the audio effect pipeline (as of Android 13).
|
||||
if (enableAudioFx && lowLatency) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
track = createAudioTrack(channelConfig, sampleRate, bufferSize, lowLatency);
|
||||
track.play();
|
||||
@@ -203,10 +220,27 @@ public class AndroidAudioRenderer implements AudioRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {}
|
||||
public void start() {
|
||||
if (enableAudioFx) {
|
||||
// Open an audio effect control session to allow equalizers to apply audio effects
|
||||
Intent i = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, track.getAudioSessionId());
|
||||
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName());
|
||||
i.putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_GAME);
|
||||
context.sendBroadcast(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {}
|
||||
public void stop() {
|
||||
if (enableAudioFx) {
|
||||
// Close our audio effect control session when we're stopping
|
||||
Intent i = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, track.getAudioSessionId());
|
||||
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName());
|
||||
context.sendBroadcast(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.limelight.binding.input;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputManager;
|
||||
@@ -7,9 +8,13 @@ import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.media.AudioAttributes;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.os.CombinedVibration;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.VibratorManager;
|
||||
import android.util.SparseArray;
|
||||
import android.view.InputDevice;
|
||||
import android.view.InputEvent;
|
||||
@@ -28,9 +33,9 @@ import com.limelight.preferences.PreferenceConfiguration;
|
||||
import com.limelight.ui.GameGestures;
|
||||
import com.limelight.utils.Vector2d;
|
||||
|
||||
import org.cgutman.shieldcontrollerextensions.SceManager;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class ControllerHandler implements InputManager.InputDeviceListener, UsbDriverListener {
|
||||
|
||||
@@ -43,9 +48,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
private static final int EMULATING_SPECIAL = 0x1;
|
||||
private static final int EMULATING_SELECT = 0x2;
|
||||
|
||||
private static final int EMULATED_SPECIAL_UP_DELAY_MS = 100;
|
||||
private static final int EMULATED_SELECT_UP_DELAY_MS = 30;
|
||||
|
||||
private final Vector2d inputVector = new Vector2d();
|
||||
|
||||
private final SparseArray<InputDeviceContext> inputDeviceContexts = new SparseArray<>();
|
||||
@@ -57,6 +59,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
private final InputDeviceContext defaultContext = new InputDeviceContext();
|
||||
private final GameGestures gestures;
|
||||
private final Vibrator deviceVibrator;
|
||||
private final SceManager sceManager;
|
||||
private final Handler handler;
|
||||
private boolean hasGameController;
|
||||
|
||||
private final PreferenceConfiguration prefConfig;
|
||||
@@ -68,10 +72,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
this.gestures = gestures;
|
||||
this.prefConfig = prefConfig;
|
||||
this.deviceVibrator = (Vibrator) activityContext.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
this.handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
// HACK: For now we're hardcoding a 7% deadzone. Some deadzone
|
||||
// is required for controller batching support to work.
|
||||
int deadzonePercentage = 7;
|
||||
this.sceManager = new SceManager(activityContext);
|
||||
this.sceManager.start();
|
||||
|
||||
int deadzonePercentage = prefConfig.deadzonePercentage;
|
||||
|
||||
int[] ids = InputDevice.getDeviceIds();
|
||||
for (int id : ids) {
|
||||
@@ -155,11 +161,36 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
}
|
||||
|
||||
// This can happen when gaining/losing input focus with some devices.
|
||||
// Input devices that have a trackpad may gain/lose AXIS_RELATIVE_X/Y.
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
// Remove and re-add
|
||||
onInputDeviceRemoved(deviceId);
|
||||
onInputDeviceAdded(deviceId);
|
||||
InputDevice device = InputDevice.getDevice(deviceId);
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't have a context for this device, we don't need to update anything
|
||||
InputDeviceContext existingContext = inputDeviceContexts.get(deviceId);
|
||||
if (existingContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
LimeLog.info("Device changed: "+existingContext.name+" ("+deviceId+")");
|
||||
|
||||
// Don't release the controller number, because we will carry it over if it is present.
|
||||
// We also want to make sure the change is invisible to the host PC to avoid an add/remove
|
||||
// cycle for the gamepad which may break some games.
|
||||
existingContext.destroy();
|
||||
|
||||
InputDeviceContext newContext = createInputDeviceContextForDevice(device);
|
||||
|
||||
// Copy over existing controller number state
|
||||
newContext.assignedControllerNumber = existingContext.assignedControllerNumber;
|
||||
newContext.reservedControllerNumber = existingContext.reservedControllerNumber;
|
||||
newContext.controllerNumber = existingContext.controllerNumber;
|
||||
|
||||
inputDeviceContexts.put(deviceId, newContext);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
@@ -173,6 +204,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
deviceContext.destroy();
|
||||
}
|
||||
|
||||
sceManager.stop();
|
||||
deviceVibrator.cancel();
|
||||
}
|
||||
|
||||
@@ -478,6 +510,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
LimeLog.info(dev.toString());
|
||||
|
||||
context.inputDevice = dev;
|
||||
context.name = devName;
|
||||
context.id = dev.getId();
|
||||
context.external = isExternal(dev);
|
||||
@@ -487,7 +520,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
context.productId = dev.getProductId();
|
||||
}
|
||||
|
||||
if (dev.getVibrator().hasVibrator()) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && hasDualAmplitudeControlledRumbleVibrators(dev.getVibratorManager())) {
|
||||
context.vibratorManager = dev.getVibratorManager();
|
||||
}
|
||||
else if (dev.getVibrator().hasVibrator()) {
|
||||
context.vibrator = dev.getVibrator();
|
||||
}
|
||||
|
||||
@@ -672,9 +708,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
// SHIELD controllers will use small stick deadzones
|
||||
else if (devName.contains("SHIELD") || devName.contains("NVIDIA Controller")) {
|
||||
context.leftStickDeadzoneRadius = 0.07f;
|
||||
context.rightStickDeadzoneRadius = 0.07f;
|
||||
|
||||
// The big Nvidia button on the Shield controllers acts like a Search button. It
|
||||
// summons the Google Assistant on the Shield TV. On my Pixel 4, it seems to do
|
||||
// nothing, so we can hijack it to act like a mode button.
|
||||
@@ -1261,29 +1294,64 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
}
|
||||
|
||||
private void toggleMouseEmulation(final GenericControllerContext context) {
|
||||
if (context.mouseEmulationTimer != null) {
|
||||
context.mouseEmulationTimer.cancel();
|
||||
context.mouseEmulationTimer = null;
|
||||
@TargetApi(31)
|
||||
private boolean hasDualAmplitudeControlledRumbleVibrators(VibratorManager vm) {
|
||||
int[] vibratorIds = vm.getVibratorIds();
|
||||
|
||||
// There must be exactly 2 vibrators on this device
|
||||
if (vibratorIds.length != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
context.mouseEmulationActive = !context.mouseEmulationActive;
|
||||
Toast.makeText(activityContext, "Mouse emulation is: " + (context.mouseEmulationActive ? "ON" : "OFF"), Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (context.mouseEmulationActive) {
|
||||
context.mouseEmulationTimer = new Timer();
|
||||
context.mouseEmulationTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Send mouse movement events from analog sticks
|
||||
sendEmulatedMouseEvent(context.leftStickX, context.leftStickY);
|
||||
sendEmulatedMouseEvent(context.rightStickX, context.rightStickY);
|
||||
}
|
||||
}, 50, 50);
|
||||
// Both vibrators must have amplitude control
|
||||
for (int vid : vibratorIds) {
|
||||
if (!vm.getVibrator(vid).hasAmplitudeControl()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void rumbleVibrator(Vibrator vibrator, short lowFreqMotor, short highFreqMotor) {
|
||||
// This must only be called if hasDualAmplitudeControlledRumbleVibrators() is true!
|
||||
@TargetApi(31)
|
||||
private void rumbleDualVibrators(VibratorManager vm, short lowFreqMotor, short highFreqMotor) {
|
||||
// Normalize motor values to 0-255 amplitudes for VibrationManager
|
||||
highFreqMotor = (short)((highFreqMotor >> 8) & 0xFF);
|
||||
lowFreqMotor = (short)((lowFreqMotor >> 8) & 0xFF);
|
||||
|
||||
// If they're both zero, we can just call cancel().
|
||||
if (lowFreqMotor == 0 && highFreqMotor == 0) {
|
||||
vm.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
// There's no documentation that states that vibrators for FF_RUMBLE input devices will
|
||||
// always be enumerated in this order, but it seems consistent between Xbox Series X (USB),
|
||||
// PS3 (USB), and PS4 (USB+BT) controllers on Android 12 Beta 3.
|
||||
int[] vibratorIds = vm.getVibratorIds();
|
||||
int[] vibratorAmplitudes = new int[] { highFreqMotor, lowFreqMotor };
|
||||
|
||||
CombinedVibration.ParallelCombination combo = CombinedVibration.startParallel();
|
||||
|
||||
for (int i = 0; i < vibratorIds.length; i++) {
|
||||
// It's illegal to create a VibrationEffect with an amplitude of 0.
|
||||
// Simply excluding that vibrator from our ParallelCombination will turn it off.
|
||||
if (vibratorAmplitudes[i] != 0) {
|
||||
combo.addVibrator(vibratorIds[i], VibrationEffect.createOneShot(60000, vibratorAmplitudes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
VibrationAttributes.Builder vibrationAttributes = new VibrationAttributes.Builder();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
vibrationAttributes.setUsage(VibrationAttributes.USAGE_MEDIA);
|
||||
}
|
||||
|
||||
vm.vibrate(combo.combine(), vibrationAttributes.build());
|
||||
}
|
||||
|
||||
private void rumbleSingleVibrator(Vibrator vibrator, short lowFreqMotor, short highFreqMotor) {
|
||||
// Since we can only use a single amplitude value, compute the desired amplitude
|
||||
// by taking 80% of the big motor and 33% of the small motor, then capping to 255.
|
||||
// NB: This value is now 0-255 as required by VibrationEffect.
|
||||
@@ -1305,10 +1373,18 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (vibrator.hasAmplitudeControl()) {
|
||||
VibrationEffect effect = VibrationEffect.createOneShot(60000, simulatedAmplitude);
|
||||
AudioAttributes audioAttributes = new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_GAME)
|
||||
.build();
|
||||
vibrator.vibrate(effect, audioAttributes);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
VibrationAttributes vibrationAttributes = new VibrationAttributes.Builder()
|
||||
.setUsage(VibrationAttributes.USAGE_MEDIA)
|
||||
.build();
|
||||
vibrator.vibrate(effect, vibrationAttributes);
|
||||
}
|
||||
else {
|
||||
AudioAttributes audioAttributes = new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_GAME)
|
||||
.build();
|
||||
vibrator.vibrate(effect, audioAttributes);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1318,7 +1394,13 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
long pwmPeriod = 20;
|
||||
long onTime = (long)((simulatedAmplitude / 255.0) * pwmPeriod);
|
||||
long offTime = pwmPeriod - onTime;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
VibrationAttributes vibrationAttributes = new VibrationAttributes.Builder()
|
||||
.setUsage(VibrationAttributes.USAGE_MEDIA)
|
||||
.build();
|
||||
vibrator.vibrate(VibrationEffect.createWaveform(new long[]{0, onTime, offTime}, 0), vibrationAttributes);
|
||||
}
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
AudioAttributes audioAttributes = new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_GAME)
|
||||
.build();
|
||||
@@ -1339,9 +1421,19 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
if (deviceContext.controllerNumber == controllerNumber) {
|
||||
foundMatchingDevice = true;
|
||||
|
||||
if (deviceContext.vibrator != null) {
|
||||
// Prefer the documented Android 12 rumble API which can handle dual vibrators on PS/Xbox controllers
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && deviceContext.vibratorManager != null) {
|
||||
vibrated = true;
|
||||
rumbleVibrator(deviceContext.vibrator, lowFreqMotor, highFreqMotor);
|
||||
rumbleDualVibrators(deviceContext.vibratorManager, lowFreqMotor, highFreqMotor);
|
||||
}
|
||||
// On Shield devices, we can use their special API to rumble Shield controllers
|
||||
else if (sceManager.rumble(deviceContext.inputDevice, lowFreqMotor, highFreqMotor)) {
|
||||
vibrated = true;
|
||||
}
|
||||
// If all else fails, we have to try the old Vibrator API
|
||||
else if (deviceContext.vibrator != null) {
|
||||
vibrated = true;
|
||||
rumbleSingleVibrator(deviceContext.vibrator, lowFreqMotor, highFreqMotor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1361,12 +1453,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
// controls that triggered the rumble. Vibrate the device if
|
||||
// the user has requested that behavior.
|
||||
if (!foundMatchingDevice && prefConfig.onscreenController && !prefConfig.onlyL3R3 && prefConfig.vibrateOsc) {
|
||||
rumbleVibrator(deviceVibrator, lowFreqMotor, highFreqMotor);
|
||||
rumbleSingleVibrator(deviceVibrator, lowFreqMotor, highFreqMotor);
|
||||
}
|
||||
else if (foundMatchingDevice && !vibrated && prefConfig.vibrateFallbackToDevice) {
|
||||
// We found a device to vibrate but it didn't have rumble support. The user
|
||||
// has requested us to vibrate the device in this case.
|
||||
rumbleVibrator(deviceVibrator, lowFreqMotor, highFreqMotor);
|
||||
rumbleSingleVibrator(deviceVibrator, lowFreqMotor, highFreqMotor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1390,13 +1482,21 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
// If the button hasn't been down long enough, sleep for a bit before sending the up event
|
||||
// This allows "instant" button presses (like OUYA's virtual menu button) to work. This
|
||||
// path should not be triggered during normal usage.
|
||||
if (SystemClock.uptimeMillis() - event.getDownTime() < ControllerHandler.MINIMUM_BUTTON_DOWN_TIME_MS)
|
||||
int buttonDownTime = (int)(event.getEventTime() - event.getDownTime());
|
||||
if (buttonDownTime < ControllerHandler.MINIMUM_BUTTON_DOWN_TIME_MS)
|
||||
{
|
||||
// Since our sleep time is so short (10 ms), it shouldn't cause a problem doing this in the
|
||||
// UI thread.
|
||||
// Since our sleep time is so short (<= 25 ms), it shouldn't cause a problem doing this
|
||||
// in the UI thread.
|
||||
try {
|
||||
Thread.sleep(ControllerHandler.MINIMUM_BUTTON_DOWN_TIME_MS);
|
||||
} catch (InterruptedException ignored) {}
|
||||
Thread.sleep(ControllerHandler.MINIMUM_BUTTON_DOWN_TIME_MS - buttonDownTime);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
// InterruptedException clears the thread's interrupt status. Since we can't
|
||||
// handle that here, we will re-interrupt the thread to set the interrupt
|
||||
// status back to true.
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
switch (keyCode) {
|
||||
@@ -1409,9 +1509,9 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
// Make sure it's real by checking that the key is actually down before taking
|
||||
// any action.
|
||||
if ((context.inputMap & ControllerPacket.PLAY_FLAG) != 0 &&
|
||||
SystemClock.uptimeMillis() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS &&
|
||||
event.getEventTime() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS &&
|
||||
prefConfig.mouseEmulation) {
|
||||
toggleMouseEmulation(context);
|
||||
context.toggleMouseEmulation();
|
||||
}
|
||||
context.inputMap &= ~ControllerPacket.PLAY_FLAG;
|
||||
break;
|
||||
@@ -1462,11 +1562,11 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L1:
|
||||
context.inputMap &= ~ControllerPacket.LB_FLAG;
|
||||
context.lastLbUpTime = SystemClock.uptimeMillis();
|
||||
context.lastLbUpTime = event.getEventTime();
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R1:
|
||||
context.inputMap &= ~ControllerPacket.RB_FLAG;
|
||||
context.lastRbUpTime = SystemClock.uptimeMillis();
|
||||
context.lastRbUpTime = event.getEventTime();
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBL:
|
||||
context.inputMap &= ~ControllerPacket.LS_CLK_FLAG;
|
||||
@@ -1502,10 +1602,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
context.inputMap &= ~ControllerPacket.BACK_FLAG;
|
||||
|
||||
context.emulatingButtonFlags &= ~ControllerHandler.EMULATING_SELECT;
|
||||
|
||||
try {
|
||||
Thread.sleep(EMULATED_SELECT_UP_DELAY_MS);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1520,10 +1616,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
context.inputMap &= ~ControllerPacket.SPECIAL_BUTTON_FLAG;
|
||||
|
||||
context.emulatingButtonFlags &= ~ControllerHandler.EMULATING_SPECIAL;
|
||||
|
||||
try {
|
||||
Thread.sleep(EMULATED_SPECIAL_UP_DELAY_MS);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1561,7 +1653,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
case KeyEvent.KEYCODE_BUTTON_START:
|
||||
case KeyEvent.KEYCODE_MENU:
|
||||
if (event.getRepeatCount() == 0) {
|
||||
context.startDownTime = SystemClock.uptimeMillis();
|
||||
context.startDownTime = event.getEventTime();
|
||||
}
|
||||
context.inputMap |= ControllerPacket.PLAY_FLAG;
|
||||
break;
|
||||
@@ -1652,7 +1744,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
if (!context.hasSelect) {
|
||||
if (context.inputMap == (ControllerPacket.PLAY_FLAG | ControllerPacket.LB_FLAG) ||
|
||||
(context.inputMap == ControllerPacket.PLAY_FLAG &&
|
||||
SystemClock.uptimeMillis() - context.lastLbUpTime <= MAXIMUM_BUMPER_UP_DELAY_MS))
|
||||
event.getEventTime() - context.lastLbUpTime <= MAXIMUM_BUMPER_UP_DELAY_MS))
|
||||
{
|
||||
context.inputMap &= ~(ControllerPacket.PLAY_FLAG | ControllerPacket.LB_FLAG);
|
||||
context.inputMap |= ControllerPacket.BACK_FLAG;
|
||||
@@ -1675,7 +1767,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
else {
|
||||
if (context.inputMap == (ControllerPacket.PLAY_FLAG | ControllerPacket.RB_FLAG) ||
|
||||
(context.inputMap == ControllerPacket.PLAY_FLAG &&
|
||||
SystemClock.uptimeMillis() - context.lastRbUpTime <= MAXIMUM_BUMPER_UP_DELAY_MS))
|
||||
event.getEventTime() - context.lastRbUpTime <= MAXIMUM_BUMPER_UP_DELAY_MS))
|
||||
{
|
||||
context.inputMap &= ~(ControllerPacket.PLAY_FLAG | ControllerPacket.RB_FLAG);
|
||||
context.inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG;
|
||||
@@ -1766,7 +1858,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
usbDeviceContexts.put(controller.getControllerId(), context);
|
||||
}
|
||||
|
||||
static class GenericControllerContext {
|
||||
class GenericControllerContext {
|
||||
public int id;
|
||||
public boolean external;
|
||||
|
||||
@@ -1790,20 +1882,46 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
public short leftStickY = 0x0000;
|
||||
|
||||
public boolean mouseEmulationActive;
|
||||
public Timer mouseEmulationTimer;
|
||||
public short mouseEmulationLastInputMap;
|
||||
public final int mouseEmulationReportPeriod = 50;
|
||||
|
||||
public final Runnable mouseEmulationRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!mouseEmulationActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send mouse movement events from analog sticks
|
||||
sendEmulatedMouseEvent(leftStickX, leftStickY);
|
||||
sendEmulatedMouseEvent(rightStickX, rightStickY);
|
||||
|
||||
// Requeue the callback
|
||||
handler.postDelayed(this, mouseEmulationReportPeriod);
|
||||
}
|
||||
};
|
||||
|
||||
public void toggleMouseEmulation() {
|
||||
handler.removeCallbacks(mouseEmulationRunnable);
|
||||
mouseEmulationActive = !mouseEmulationActive;
|
||||
Toast.makeText(activityContext, "Mouse emulation is: " + (mouseEmulationActive ? "ON" : "OFF"), Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (mouseEmulationActive) {
|
||||
handler.postDelayed(mouseEmulationRunnable, mouseEmulationReportPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (mouseEmulationTimer != null) {
|
||||
mouseEmulationTimer.cancel();
|
||||
mouseEmulationTimer = null;
|
||||
}
|
||||
mouseEmulationActive = false;
|
||||
handler.removeCallbacks(mouseEmulationRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
class InputDeviceContext extends GenericControllerContext {
|
||||
public String name;
|
||||
public VibratorManager vibratorManager;
|
||||
public Vibrator vibrator;
|
||||
public InputDevice inputDevice;
|
||||
|
||||
public int leftStickXAxis = -1;
|
||||
public int leftStickYAxis = -1;
|
||||
@@ -1849,7 +1967,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
if (vibrator != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && vibratorManager != null) {
|
||||
vibratorManager.cancel();
|
||||
}
|
||||
else if (vibrator != null) {
|
||||
vibrator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
package com.limelight.binding.input;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Build;
|
||||
import android.util.SparseArray;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Class to translate a Android key code into the codes GFE is expecting
|
||||
* @author Diego Waxemberg
|
||||
* @author Cameron Gutman
|
||||
*/
|
||||
public class KeyboardTranslator {
|
||||
public class KeyboardTranslator implements InputManager.InputDeviceListener {
|
||||
|
||||
/**
|
||||
* GFE's prefix for every key code
|
||||
@@ -48,6 +55,55 @@ public class KeyboardTranslator {
|
||||
public static final int VK_QUOTE = 222;
|
||||
public static final int VK_PAUSE = 19;
|
||||
|
||||
private static class KeyboardMapping {
|
||||
private final InputDevice device;
|
||||
private final int[] deviceKeyCodeToQwertyKeyCode;
|
||||
|
||||
@TargetApi(33)
|
||||
public KeyboardMapping(InputDevice device) {
|
||||
int maxKeyCode = KeyEvent.getMaxKeyCode();
|
||||
|
||||
this.device = device;
|
||||
this.deviceKeyCodeToQwertyKeyCode = new int[maxKeyCode + 1];
|
||||
|
||||
// Any unmatched keycodes are treated as unknown
|
||||
Arrays.fill(deviceKeyCodeToQwertyKeyCode, KeyEvent.KEYCODE_UNKNOWN);
|
||||
|
||||
for (int i = 0; i <= maxKeyCode; i++) {
|
||||
int deviceKeyCode = device.getKeyCodeForKeyLocation(i);
|
||||
if (deviceKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
|
||||
deviceKeyCodeToQwertyKeyCode[deviceKeyCode] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(33)
|
||||
public int getDeviceKeyCodeForQwertyKeyCode(int qwertyKeyCode) {
|
||||
return device.getKeyCodeForKeyLocation(qwertyKeyCode);
|
||||
}
|
||||
|
||||
public int getQwertyKeyCodeForDeviceKeyCode(int deviceKeyCode) {
|
||||
if (deviceKeyCode > KeyEvent.getMaxKeyCode()) {
|
||||
return KeyEvent.KEYCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
return deviceKeyCodeToQwertyKeyCode[deviceKeyCode];
|
||||
}
|
||||
}
|
||||
|
||||
private final SparseArray<KeyboardMapping> keyboardMappings = new SparseArray<>();
|
||||
|
||||
public KeyboardTranslator() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
for (int deviceId : InputDevice.getDeviceIds()) {
|
||||
InputDevice device = InputDevice.getDevice(deviceId);
|
||||
if (device != null && device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
|
||||
keyboardMappings.set(deviceId, new KeyboardMapping(device));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean needsShift(int keycode) {
|
||||
switch (keycode)
|
||||
{
|
||||
@@ -65,10 +121,24 @@ public class KeyboardTranslator {
|
||||
/**
|
||||
* Translates the given keycode and returns the GFE keycode
|
||||
* @param keycode the code to be translated
|
||||
* @param deviceId InputDevice.getId() or -1 if unknown
|
||||
* @return a GFE keycode for the given keycode
|
||||
*/
|
||||
public static short translate(int keycode) {
|
||||
public short translate(int keycode, int deviceId) {
|
||||
int translated;
|
||||
|
||||
// If a device ID was provided, look up the keyboard mapping
|
||||
if (deviceId >= 0) {
|
||||
KeyboardMapping mapping = keyboardMappings.get(deviceId);
|
||||
if (mapping != null) {
|
||||
// Try to map this device-specific keycode onto a QWERTY layout.
|
||||
// GFE assumes incoming keycodes are from a QWERTY keyboard.
|
||||
int qwertyKeyCode = mapping.getQwertyKeyCodeForDeviceKeyCode(keycode);
|
||||
if (qwertyKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
|
||||
keycode = qwertyKeyCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a poor man's mapping between Android key codes
|
||||
// and Windows VK_* codes. For all defined VK_ codes, see:
|
||||
@@ -294,4 +364,30 @@ public class KeyboardTranslator {
|
||||
return (short) ((KEY_PREFIX << 8) | translated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceAdded(int index) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
InputDevice device = InputDevice.getDevice(index);
|
||||
if (device != null && device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
|
||||
keyboardMappings.put(index, new KeyboardMapping(device));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceRemoved(int index) {
|
||||
keyboardMappings.remove(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int index) {
|
||||
keyboardMappings.remove(index);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
InputDevice device = InputDevice.getDevice(index);
|
||||
if (device != null && device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
|
||||
keyboardMappings.set(index, new KeyboardMapping(device));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+95
-4
@@ -2,7 +2,9 @@ package com.limelight.binding.input.capture;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
@@ -12,11 +14,13 @@ import android.view.View;
|
||||
// pointer icon hiding behavior over our stream view just in case pointer capture
|
||||
// is unavailable on this system (ex: DeX, ChromeOS)
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptureProvider {
|
||||
public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptureProvider implements InputManager.InputDeviceListener {
|
||||
private InputManager inputManager;
|
||||
private View targetView;
|
||||
|
||||
public AndroidNativePointerCaptureProvider(Activity activity, View targetView) {
|
||||
super(activity, targetView);
|
||||
this.inputManager = activity.getSystemService(InputManager.class);
|
||||
this.targetView = targetView;
|
||||
}
|
||||
|
||||
@@ -24,25 +28,85 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
}
|
||||
|
||||
// We only capture the pointer if we have a compatible InputDevice
|
||||
// present. This is a workaround for an Android 12 regression causing
|
||||
// incorrect mouse input when using the SPen.
|
||||
// https://github.com/moonlight-stream/moonlight-android/issues/1030
|
||||
private boolean hasCaptureCompatibleInputDevice() {
|
||||
for (int id : InputDevice.getDeviceIds()) {
|
||||
InputDevice device = InputDevice.getDevice(id);
|
||||
if (device == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip touchscreens when considering compatible capture devices.
|
||||
// Samsung devices on Android 12 will report a sec_touchpad device
|
||||
// with SOURCE_TOUCHSCREEN, SOURCE_KEYBOARD, and SOURCE_MOUSE.
|
||||
// Upon enabling pointer capture, that device will switch to
|
||||
// SOURCE_KEYBOARD and SOURCE_TOUCHPAD.
|
||||
if (device.supportsSource(InputDevice.SOURCE_TOUCHSCREEN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (device.supportsSource(InputDevice.SOURCE_MOUSE) ||
|
||||
device.supportsSource(InputDevice.SOURCE_MOUSE_RELATIVE) ||
|
||||
device.supportsSource(InputDevice.SOURCE_TOUCHPAD)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableCapture() {
|
||||
super.enableCapture();
|
||||
targetView.requestPointerCapture();
|
||||
|
||||
// Listen for device events to enable/disable capture
|
||||
inputManager.registerInputDeviceListener(this, null);
|
||||
|
||||
// Capture now if we have a capture-capable device
|
||||
if (hasCaptureCompatibleInputDevice()) {
|
||||
targetView.requestPointerCapture();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableCapture() {
|
||||
super.disableCapture();
|
||||
inputManager.unregisterInputDeviceListener(this);
|
||||
targetView.releasePointerCapture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean focusActive) {
|
||||
if (!focusActive || !isCapturing) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Recapture the pointer if focus was regained. On Android Q,
|
||||
// we have to delay a bit before requesting capture because otherwise
|
||||
// we'll hit the "requestPointerCapture called for a window that has no focus"
|
||||
// error and it will not actually capture the cursor.
|
||||
Handler h = new Handler();
|
||||
h.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (hasCaptureCompatibleInputDevice()) {
|
||||
targetView.requestPointerCapture();
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eventHasRelativeMouseAxes(MotionEvent event) {
|
||||
// SOURCE_MOUSE_RELATIVE is how SOURCE_MOUSE appears when our view has pointer capture.
|
||||
// SOURCE_TOUCHPAD will have relative axes populated iff our view has pointer capture.
|
||||
// See https://developer.android.com/reference/android/view/View#requestPointerCapture()
|
||||
return event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE ||
|
||||
(event.getSource() == InputDevice.SOURCE_TOUCHPAD && targetView.hasPointerCapture());
|
||||
int eventSource = event.getSource();
|
||||
return (eventSource == InputDevice.SOURCE_MOUSE_RELATIVE && event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) ||
|
||||
(eventSource == InputDevice.SOURCE_TOUCHPAD && targetView.hasPointerCapture());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,4 +130,31 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceAdded(int deviceId) {
|
||||
// Check if we've added a capture-compatible device
|
||||
if (!targetView.hasPointerCapture() && hasCaptureCompatibleInputDevice()) {
|
||||
targetView.requestPointerCapture();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceRemoved(int deviceId) {
|
||||
// Check if the capture-compatible device was removed
|
||||
if (targetView.hasPointerCapture() && !hasCaptureCompatibleInputDevice()) {
|
||||
targetView.releasePointerCapture();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
// Emulating a remove+add should be sufficient for our purposes.
|
||||
//
|
||||
// Note: This callback must be handled carefully because it can happen as a result of
|
||||
// calling requestPointerCapture(). This can cause trackpad devices to gain SOURCE_MOUSE_RELATIVE
|
||||
// and re-enter this callback.
|
||||
onInputDeviceRemoved(deviceId);
|
||||
onInputDeviceAdded(deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.limelight.binding.input.capture;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.limelight.BuildConfig;
|
||||
import com.limelight.LimeLog;
|
||||
import com.limelight.LimelightBuildProps;
|
||||
import com.limelight.R;
|
||||
import com.limelight.binding.input.evdev.EvdevCaptureProviderShim;
|
||||
import com.limelight.binding.input.evdev.EvdevListener;
|
||||
@@ -16,7 +16,7 @@ public class InputCaptureManager {
|
||||
}
|
||||
// LineageOS implemented broken NVIDIA capture extensions, so avoid using them on root builds.
|
||||
// See https://github.com/LineageOS/android_frameworks_base/commit/d304f478a023430f4712dbdc3ee69d9ad02cebd3
|
||||
else if (!LimelightBuildProps.ROOT_BUILD && ShieldCaptureProvider.isCaptureProviderSupported()) {
|
||||
else if (!BuildConfig.ROOT_BUILD && ShieldCaptureProvider.isCaptureProviderSupported()) {
|
||||
LimeLog.info("Using NVIDIA mouse capture extension");
|
||||
return new ShieldCaptureProvider(activity);
|
||||
}
|
||||
|
||||
@@ -33,4 +33,6 @@ public abstract class InputCaptureProvider {
|
||||
public float getRelativeAxisY(MotionEvent event) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void onWindowFocusChanged(boolean focusActive) {}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbEndpoint;
|
||||
import android.hardware.usb.UsbInterface;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
import com.limelight.binding.video.MediaCodecHelper;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
@@ -37,7 +37,9 @@ public abstract class AbstractXboxController extends AbstractController {
|
||||
// around when we call notifyDeviceAdded(), we won't be able to claim
|
||||
// the controller number used by the original InputDevice.
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {}
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Report that we're added _before_ reporting input
|
||||
notifyDeviceAdded();
|
||||
@@ -56,7 +58,7 @@ public abstract class AbstractXboxController extends AbstractController {
|
||||
|
||||
do {
|
||||
// Read the next input state packet
|
||||
long lastMillis = MediaCodecHelper.getMonotonicMillis();
|
||||
long lastMillis = SystemClock.uptimeMillis();
|
||||
res = connection.bulkTransfer(inEndpt, buffer, buffer.length, 3000);
|
||||
|
||||
// If we get a zero length response, treat it as an error
|
||||
@@ -64,7 +66,7 @@ public abstract class AbstractXboxController extends AbstractController {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if (res == -1 && MediaCodecHelper.getMonotonicMillis() - lastMillis < 1000) {
|
||||
if (res == -1 && SystemClock.uptimeMillis() - lastMillis < 1000) {
|
||||
LimeLog.warning("Detected device I/O error");
|
||||
AbstractXboxController.this.stop();
|
||||
break;
|
||||
|
||||
@@ -29,6 +29,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
|
||||
private UsbManager usbManager;
|
||||
private PreferenceConfiguration prefConfig;
|
||||
private boolean started;
|
||||
|
||||
private final UsbEventReceiver receiver = new UsbEventReceiver();
|
||||
private final UsbDriverBinder binder = new UsbDriverBinder();
|
||||
@@ -36,6 +37,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
private final ArrayList<AbstractController> controllers = new ArrayList<>();
|
||||
|
||||
private UsbDriverListener listener;
|
||||
private UsbDriverStateListener stateListener;
|
||||
private int nextDeviceId;
|
||||
|
||||
@Override
|
||||
@@ -93,6 +95,11 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
else if (action.equals(ACTION_USB_PERMISSION)) {
|
||||
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
||||
|
||||
// Permission dialog is now closed
|
||||
if (stateListener != null) {
|
||||
stateListener.onUsbPermissionPromptCompleted();
|
||||
}
|
||||
|
||||
// If we got this far, we've already found we're able to handle this device
|
||||
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
|
||||
handleUsbDeviceState(device);
|
||||
@@ -112,6 +119,18 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setStateListener(UsbDriverStateListener stateListener) {
|
||||
UsbDriverService.this.stateListener = stateListener;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
UsbDriverService.this.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
UsbDriverService.this.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleUsbDeviceState(UsbDevice device) {
|
||||
@@ -121,15 +140,29 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
if (!usbManager.hasPermission(device)) {
|
||||
// Let's ask for permission
|
||||
try {
|
||||
// Tell the state listener that we're about to display a permission dialog
|
||||
if (stateListener != null) {
|
||||
stateListener.onUsbPermissionPromptStarting();
|
||||
}
|
||||
|
||||
int intentFlags = 0;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
// This PendingIntent must be mutable to allow the framework to populate EXTRA_DEVICE and EXTRA_PERMISSION_GRANTED.
|
||||
intentFlags |= PendingIntent.FLAG_MUTABLE;
|
||||
}
|
||||
|
||||
// This function is not documented as throwing any exceptions (denying access
|
||||
// is indicated by calling the PendingIntent with a false result). However,
|
||||
// Samsung Knox has some policies which block this request, but rather than
|
||||
// just returning a false result or returning 0 enumerated devices,
|
||||
// they throw an undocumented SecurityException from this call, crashing
|
||||
// the whole app. :(
|
||||
usbManager.requestPermission(device, PendingIntent.getBroadcast(UsbDriverService.this, 0, new Intent(ACTION_USB_PERMISSION), 0));
|
||||
usbManager.requestPermission(device, PendingIntent.getBroadcast(UsbDriverService.this, 0, new Intent(ACTION_USB_PERMISSION), intentFlags));
|
||||
} catch (SecurityException e) {
|
||||
Toast.makeText(this, this.getText(R.string.error_usb_prohibited), Toast.LENGTH_LONG).show();
|
||||
if (stateListener != null) {
|
||||
stateListener.onUsbPermissionPromptCompleted();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -220,16 +253,23 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
((!isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360Controller.canClaimDevice(device));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
this.usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
this.prefConfig = PreferenceConfiguration.readPreferences(this);
|
||||
private void start() {
|
||||
if (started) {
|
||||
return;
|
||||
}
|
||||
|
||||
started = true;
|
||||
|
||||
// Register for USB attach broadcasts and permission completions
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
|
||||
filter.addAction(ACTION_USB_PERMISSION);
|
||||
registerReceiver(receiver, filter);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
registerReceiver(receiver, filter, RECEIVER_NOT_EXPORTED);
|
||||
}
|
||||
else {
|
||||
registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
// Enumerate existing devices
|
||||
for (UsbDevice dev : usbManager.getDeviceList().values()) {
|
||||
@@ -240,14 +280,16 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
private void stop() {
|
||||
if (!started) {
|
||||
return;
|
||||
}
|
||||
|
||||
started = false;
|
||||
|
||||
// Stop the attachment receiver
|
||||
unregisterReceiver(receiver);
|
||||
|
||||
// Remove listeners
|
||||
listener = null;
|
||||
|
||||
// Stop all controllers
|
||||
while (controllers.size() > 0) {
|
||||
// Stop and remove the controller
|
||||
@@ -255,8 +297,28 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
this.usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
this.prefConfig = PreferenceConfiguration.readPreferences(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
stop();
|
||||
|
||||
// Remove listeners
|
||||
listener = null;
|
||||
stateListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return binder;
|
||||
}
|
||||
|
||||
public interface UsbDriverStateListener {
|
||||
void onUsbPermissionPromptStarting();
|
||||
void onUsbPermissionPromptCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ public class Xbox360Controller extends AbstractXboxController {
|
||||
0x15e4, // Numark
|
||||
0x162e, // Joytech
|
||||
0x1689, // Razer Onza
|
||||
0x1949, // Lab126 (Amazon Luna)
|
||||
0x1bad, // Harmonix
|
||||
0x20d6, // PowerA
|
||||
0x24c6, // PowerA
|
||||
|
||||
@@ -3,12 +3,12 @@ package com.limelight.binding.input.evdev;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.limelight.LimelightBuildProps;
|
||||
import com.limelight.BuildConfig;
|
||||
import com.limelight.binding.input.capture.InputCaptureProvider;
|
||||
|
||||
public class EvdevCaptureProviderShim {
|
||||
public static boolean isCaptureProviderSupported() {
|
||||
return LimelightBuildProps.ROOT_BUILD;
|
||||
return BuildConfig.ROOT_BUILD;
|
||||
}
|
||||
|
||||
// We need to construct our capture provider using reflection because it isn't included in non-root builds
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
package com.limelight.binding.input.touch;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
import com.limelight.nvstream.input.MouseButtonPacket;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class AbsoluteTouchContext implements TouchContext {
|
||||
private int lastTouchDownX = 0;
|
||||
private int lastTouchDownY = 0;
|
||||
@@ -21,15 +19,43 @@ public class AbsoluteTouchContext implements TouchContext {
|
||||
private boolean cancelled;
|
||||
private boolean confirmedLongPress;
|
||||
private boolean confirmedTap;
|
||||
private Timer longPressTimer;
|
||||
private Timer tapDownTimer;
|
||||
private float accumulatedScrollDelta;
|
||||
|
||||
private final Runnable longPressRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// This timer should have already expired, but cancel it just in case
|
||||
cancelTapDownTimer();
|
||||
|
||||
// Switch from a left click to a right click after a long press
|
||||
confirmedLongPress = true;
|
||||
if (confirmedTap) {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||
}
|
||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable tapDownRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Start our tap
|
||||
tapConfirmed();
|
||||
}
|
||||
};
|
||||
|
||||
private final NvConnection conn;
|
||||
private final int actionIndex;
|
||||
private final View targetView;
|
||||
private final Handler handler;
|
||||
|
||||
private static final int SCROLL_SPEED_DIVISOR = 20;
|
||||
private final Runnable leftButtonUpRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||
}
|
||||
};
|
||||
|
||||
private static final int SCROLL_SPEED_FACTOR = 3;
|
||||
|
||||
private static final int LONG_PRESS_TIME_THRESHOLD = 650;
|
||||
private static final int LONG_PRESS_DISTANCE_THRESHOLD = 30;
|
||||
@@ -45,6 +71,7 @@ public class AbsoluteTouchContext implements TouchContext {
|
||||
this.conn = conn;
|
||||
this.actionIndex = actionIndex;
|
||||
this.targetView = view;
|
||||
this.handler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,7 +81,7 @@ public class AbsoluteTouchContext implements TouchContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchDownEvent(int eventX, int eventY, boolean isNewFinger)
|
||||
public boolean touchDownEvent(int eventX, int eventY, long eventTime, boolean isNewFinger)
|
||||
{
|
||||
if (!isNewFinger) {
|
||||
// We don't handle finger transitions for absolute mode
|
||||
@@ -63,9 +90,8 @@ public class AbsoluteTouchContext implements TouchContext {
|
||||
|
||||
lastTouchLocationX = lastTouchDownX = eventX;
|
||||
lastTouchLocationY = lastTouchDownY = eventY;
|
||||
lastTouchDownTime = SystemClock.uptimeMillis();
|
||||
lastTouchDownTime = eventTime;
|
||||
cancelled = confirmedTap = confirmedLongPress = false;
|
||||
accumulatedScrollDelta = 0;
|
||||
|
||||
if (actionIndex == 0) {
|
||||
// Start the timers
|
||||
@@ -92,7 +118,7 @@ public class AbsoluteTouchContext implements TouchContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touchUpEvent(int eventX, int eventY)
|
||||
public void touchUpEvent(int eventX, int eventY, long eventTime)
|
||||
{
|
||||
if (cancelled) {
|
||||
return;
|
||||
@@ -115,80 +141,35 @@ public class AbsoluteTouchContext implements TouchContext {
|
||||
// deadzone time. We'll need to send the touch down and up events now at the
|
||||
// original touch down position.
|
||||
tapConfirmed();
|
||||
try {
|
||||
// FIXME: Sleeping on the main thread sucks
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException ignored) {}
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||
|
||||
// Release the left mouse button in 100ms to allow for apps that use polling
|
||||
// to detect mouse button presses.
|
||||
handler.removeCallbacks(leftButtonUpRunnable);
|
||||
handler.postDelayed(leftButtonUpRunnable, 100);
|
||||
}
|
||||
}
|
||||
|
||||
lastTouchLocationX = lastTouchUpX = eventX;
|
||||
lastTouchLocationY = lastTouchUpY = eventY;
|
||||
lastTouchUpTime = SystemClock.uptimeMillis();
|
||||
lastTouchUpTime = eventTime;
|
||||
}
|
||||
|
||||
private synchronized void startLongPressTimer() {
|
||||
longPressTimer = new Timer(true);
|
||||
longPressTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (AbsoluteTouchContext.this) {
|
||||
// Check if someone cancelled us
|
||||
if (longPressTimer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Uncancellable now
|
||||
longPressTimer = null;
|
||||
|
||||
// This timer should have already expired, but cancel it just in case
|
||||
cancelTapDownTimer();
|
||||
|
||||
// Switch from a left click to a right click after a long press
|
||||
confirmedLongPress = true;
|
||||
if (confirmedTap) {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||
}
|
||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
||||
}
|
||||
}
|
||||
}, LONG_PRESS_TIME_THRESHOLD);
|
||||
private void startLongPressTimer() {
|
||||
cancelLongPressTimer();
|
||||
handler.postDelayed(longPressRunnable, LONG_PRESS_TIME_THRESHOLD);
|
||||
}
|
||||
|
||||
private synchronized void cancelLongPressTimer() {
|
||||
if (longPressTimer != null) {
|
||||
longPressTimer.cancel();
|
||||
longPressTimer = null;
|
||||
}
|
||||
private void cancelLongPressTimer() {
|
||||
handler.removeCallbacks(longPressRunnable);
|
||||
}
|
||||
|
||||
private synchronized void startTapDownTimer() {
|
||||
tapDownTimer = new Timer(true);
|
||||
tapDownTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (AbsoluteTouchContext.this) {
|
||||
// Check if someone cancelled us
|
||||
if (tapDownTimer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Uncancellable now
|
||||
tapDownTimer = null;
|
||||
|
||||
// Start our tap
|
||||
tapConfirmed();
|
||||
}
|
||||
}
|
||||
}, TOUCH_DOWN_DEAD_ZONE_TIME_THRESHOLD);
|
||||
private void startTapDownTimer() {
|
||||
cancelTapDownTimer();
|
||||
handler.postDelayed(tapDownRunnable, TOUCH_DOWN_DEAD_ZONE_TIME_THRESHOLD);
|
||||
}
|
||||
|
||||
private synchronized void cancelTapDownTimer() {
|
||||
if (tapDownTimer != null) {
|
||||
tapDownTimer.cancel();
|
||||
tapDownTimer = null;
|
||||
}
|
||||
private void cancelTapDownTimer() {
|
||||
handler.removeCallbacks(tapDownRunnable);
|
||||
}
|
||||
|
||||
private void tapConfirmed() {
|
||||
@@ -209,7 +190,7 @@ public class AbsoluteTouchContext implements TouchContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchMoveEvent(int eventX, int eventY)
|
||||
public boolean touchMoveEvent(int eventX, int eventY, long eventTime)
|
||||
{
|
||||
if (cancelled) {
|
||||
return true;
|
||||
@@ -228,11 +209,7 @@ public class AbsoluteTouchContext implements TouchContext {
|
||||
}
|
||||
}
|
||||
else if (actionIndex == 1) {
|
||||
accumulatedScrollDelta += (eventY - lastTouchLocationY) / (float)SCROLL_SPEED_DIVISOR;
|
||||
if ((short)accumulatedScrollDelta != 0) {
|
||||
conn.sendMouseHighResScroll((short)accumulatedScrollDelta);
|
||||
accumulatedScrollDelta -= (short)accumulatedScrollDelta;
|
||||
}
|
||||
conn.sendMouseHighResScroll((short)((eventY - lastTouchLocationY) * SCROLL_SPEED_FACTOR));
|
||||
}
|
||||
|
||||
lastTouchLocationX = eventX;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package com.limelight.binding.input.touch;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
import com.limelight.nvstream.input.MouseButtonPacket;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import com.limelight.preferences.PreferenceConfiguration;
|
||||
|
||||
public class RelativeTouchContext implements TouchContext {
|
||||
private int lastTouchX = 0;
|
||||
@@ -19,7 +18,6 @@ public class RelativeTouchContext implements TouchContext {
|
||||
private boolean confirmedMove;
|
||||
private boolean confirmedDrag;
|
||||
private boolean confirmedScroll;
|
||||
private Timer dragTimer;
|
||||
private double distanceMoved;
|
||||
private double xFactor, yFactor;
|
||||
private int pointerCount;
|
||||
@@ -30,22 +28,80 @@ public class RelativeTouchContext implements TouchContext {
|
||||
private final int referenceWidth;
|
||||
private final int referenceHeight;
|
||||
private final View targetView;
|
||||
private final PreferenceConfiguration prefConfig;
|
||||
private final Handler handler;
|
||||
|
||||
private final Runnable dragTimerRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Check if someone already set move
|
||||
if (confirmedMove) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The drag should only be processed for the primary finger
|
||||
if (actionIndex != maxPointerCountInGesture - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We haven't been cancelled before the timer expired so begin dragging
|
||||
confirmedDrag = true;
|
||||
conn.sendMouseButtonDown(getMouseButtonIndex());
|
||||
}
|
||||
};
|
||||
|
||||
// Indexed by MouseButtonPacket.BUTTON_XXX - 1
|
||||
private final Runnable[] buttonUpRunnables = new Runnable[] {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_MIDDLE);
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_X1);
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_X2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static final int TAP_MOVEMENT_THRESHOLD = 20;
|
||||
private static final int TAP_DISTANCE_THRESHOLD = 25;
|
||||
private static final int TAP_TIME_THRESHOLD = 250;
|
||||
private static final int DRAG_TIME_THRESHOLD = 650;
|
||||
|
||||
private static final int SCROLL_SPEED_DIVISOR = 20;
|
||||
private static final int SCROLL_SPEED_FACTOR = 5;
|
||||
|
||||
public RelativeTouchContext(NvConnection conn, int actionIndex,
|
||||
int referenceWidth, int referenceHeight, View view)
|
||||
int referenceWidth, int referenceHeight,
|
||||
View view, PreferenceConfiguration prefConfig)
|
||||
{
|
||||
this.conn = conn;
|
||||
this.actionIndex = actionIndex;
|
||||
this.referenceWidth = referenceWidth;
|
||||
this.referenceHeight = referenceHeight;
|
||||
this.targetView = view;
|
||||
this.prefConfig = prefConfig;
|
||||
this.handler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,7 +118,7 @@ public class RelativeTouchContext implements TouchContext {
|
||||
yDelta <= TAP_MOVEMENT_THRESHOLD;
|
||||
}
|
||||
|
||||
private boolean isTap()
|
||||
private boolean isTap(long eventTime)
|
||||
{
|
||||
if (confirmedDrag || confirmedMove || confirmedScroll) {
|
||||
return false;
|
||||
@@ -75,7 +131,7 @@ public class RelativeTouchContext implements TouchContext {
|
||||
return false;
|
||||
}
|
||||
|
||||
long timeDelta = SystemClock.uptimeMillis() - originalTouchTime;
|
||||
long timeDelta = eventTime - originalTouchTime;
|
||||
return isWithinTapBounds(lastTouchX, lastTouchY) && timeDelta <= TAP_TIME_THRESHOLD;
|
||||
}
|
||||
|
||||
@@ -90,7 +146,7 @@ public class RelativeTouchContext implements TouchContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchDownEvent(int eventX, int eventY, boolean isNewFinger)
|
||||
public boolean touchDownEvent(int eventX, int eventY, long eventTime, boolean isNewFinger)
|
||||
{
|
||||
// Get the view dimensions to scale inputs on this touch
|
||||
xFactor = referenceWidth / (double)targetView.getWidth();
|
||||
@@ -101,7 +157,7 @@ public class RelativeTouchContext implements TouchContext {
|
||||
|
||||
if (isNewFinger) {
|
||||
maxPointerCountInGesture = pointerCount;
|
||||
originalTouchTime = SystemClock.uptimeMillis();
|
||||
originalTouchTime = eventTime;
|
||||
cancelled = confirmedDrag = confirmedMove = confirmedScroll = false;
|
||||
distanceMoved = 0;
|
||||
|
||||
@@ -115,7 +171,7 @@ public class RelativeTouchContext implements TouchContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touchUpEvent(int eventX, int eventY)
|
||||
public void touchUpEvent(int eventX, int eventY, long eventTime)
|
||||
{
|
||||
if (cancelled) {
|
||||
return;
|
||||
@@ -130,60 +186,29 @@ public class RelativeTouchContext implements TouchContext {
|
||||
// Raise the button after a drag
|
||||
conn.sendMouseButtonUp(buttonIndex);
|
||||
}
|
||||
else if (isTap())
|
||||
else if (isTap(eventTime))
|
||||
{
|
||||
// Lower the mouse button
|
||||
conn.sendMouseButtonDown(buttonIndex);
|
||||
|
||||
// We need to sleep a bit here because some games
|
||||
// do input detection by polling
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
|
||||
// Raise the mouse button
|
||||
conn.sendMouseButtonUp(buttonIndex);
|
||||
// Release the mouse button in 100ms to allow for apps that use polling
|
||||
// to detect mouse button presses.
|
||||
Runnable buttonUpRunnable = buttonUpRunnables[buttonIndex - 1];
|
||||
handler.removeCallbacks(buttonUpRunnable);
|
||||
handler.postDelayed(buttonUpRunnable, 100);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void startDragTimer() {
|
||||
// Cancel any existing drag timers
|
||||
private void startDragTimer() {
|
||||
cancelDragTimer();
|
||||
|
||||
dragTimer = new Timer(true);
|
||||
dragTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (RelativeTouchContext.this) {
|
||||
// Check if someone already set move
|
||||
if (confirmedMove) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if someone cancelled us
|
||||
if (dragTimer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Uncancellable now
|
||||
dragTimer = null;
|
||||
|
||||
// We haven't been cancelled before the timer expired so begin dragging
|
||||
confirmedDrag = true;
|
||||
conn.sendMouseButtonDown(getMouseButtonIndex());
|
||||
}
|
||||
}
|
||||
}, DRAG_TIME_THRESHOLD);
|
||||
handler.postDelayed(dragTimerRunnable, DRAG_TIME_THRESHOLD);
|
||||
}
|
||||
|
||||
private synchronized void cancelDragTimer() {
|
||||
if (dragTimer != null) {
|
||||
dragTimer.cancel();
|
||||
dragTimer = null;
|
||||
}
|
||||
private void cancelDragTimer() {
|
||||
handler.removeCallbacks(dragTimerRunnable);
|
||||
}
|
||||
|
||||
private synchronized void checkForConfirmedMove(int eventX, int eventY) {
|
||||
private void checkForConfirmedMove(int eventX, int eventY) {
|
||||
// If we've already confirmed something, get out now
|
||||
if (confirmedMove || confirmedDrag) {
|
||||
return;
|
||||
@@ -213,7 +238,7 @@ public class RelativeTouchContext implements TouchContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchMoveEvent(int eventX, int eventY)
|
||||
public boolean touchMoveEvent(int eventX, int eventY, long eventTime)
|
||||
{
|
||||
if (cancelled) {
|
||||
return true;
|
||||
@@ -243,12 +268,19 @@ public class RelativeTouchContext implements TouchContext {
|
||||
|
||||
if (pointerCount == 2) {
|
||||
if (confirmedScroll) {
|
||||
deltaY /= SCROLL_SPEED_DIVISOR;
|
||||
|
||||
conn.sendMouseHighResScroll((short) deltaY);
|
||||
conn.sendMouseHighResScroll((short)(deltaY * SCROLL_SPEED_FACTOR));
|
||||
}
|
||||
} else {
|
||||
conn.sendMouseMove((short) deltaX, (short) deltaY);
|
||||
if (prefConfig.absoluteMouseMode) {
|
||||
conn.sendMouseMoveAsMousePosition(
|
||||
(short) deltaX,
|
||||
(short) deltaY,
|
||||
(short) targetView.getWidth(),
|
||||
(short) targetView.getHeight());
|
||||
}
|
||||
else {
|
||||
conn.sendMouseMove((short) deltaX, (short) deltaY);
|
||||
}
|
||||
}
|
||||
|
||||
// If the scaling factor ended up rounding deltas to zero, wait until they are
|
||||
|
||||
@@ -3,9 +3,9 @@ package com.limelight.binding.input.touch;
|
||||
public interface TouchContext {
|
||||
int getActionIndex();
|
||||
void setPointerCount(int pointerCount);
|
||||
boolean touchDownEvent(int eventX, int eventY, boolean isNewFinger);
|
||||
boolean touchMoveEvent(int eventX, int eventY);
|
||||
void touchUpEvent(int eventX, int eventY);
|
||||
boolean touchDownEvent(int eventX, int eventY, long eventTime, boolean isNewFinger);
|
||||
boolean touchMoveEvent(int eventX, int eventY, long eventTime);
|
||||
void touchUpEvent(int eventX, int eventY, long eventTime);
|
||||
void cancelTouch();
|
||||
boolean isCancelled();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.os.SystemClock;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -254,7 +253,7 @@ public class AnalogStick extends VirtualControllerElement {
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePosition() {
|
||||
private void updatePosition(long eventTime) {
|
||||
// get 100% way
|
||||
float complete = radius_complete - radius_analog_stick;
|
||||
|
||||
@@ -271,7 +270,7 @@ public class AnalogStick extends VirtualControllerElement {
|
||||
// We also release the deadzone if the user keeps the stick pressed for a bit to allow
|
||||
// them to make precise movements.
|
||||
stick_state = (stick_state == STICK_STATE.MOVED_ACTIVE ||
|
||||
SystemClock.uptimeMillis() - timeLastClick > timeoutDeadzone ||
|
||||
eventTime - timeLastClick > timeoutDeadzone ||
|
||||
movement_radius > radius_dead_zone) ?
|
||||
STICK_STATE.MOVED_ACTIVE : STICK_STATE.MOVED_IN_DEAD_ZONE;
|
||||
|
||||
@@ -306,13 +305,12 @@ public class AnalogStick extends VirtualControllerElement {
|
||||
// handle event depending on action
|
||||
switch (event.getActionMasked()) {
|
||||
// down event (touch event)
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
// set to dead zoned, will be corrected in update position if necessary
|
||||
stick_state = STICK_STATE.MOVED_IN_DEAD_ZONE;
|
||||
// check for double click
|
||||
if (lastClickState == CLICK_STATE.SINGLE &&
|
||||
timeLastClick + timeoutDoubleClick > SystemClock.uptimeMillis()) {
|
||||
event.getEventTime() - timeLastClick <= timeoutDoubleClick) {
|
||||
click_state = CLICK_STATE.DOUBLE;
|
||||
notifyOnDoubleClick();
|
||||
} else {
|
||||
@@ -320,14 +318,14 @@ public class AnalogStick extends VirtualControllerElement {
|
||||
notifyOnClick();
|
||||
}
|
||||
// reset last click timestamp
|
||||
timeLastClick = SystemClock.uptimeMillis();
|
||||
timeLastClick = event.getEventTime();
|
||||
// set item pressed and update
|
||||
setPressed(true);
|
||||
break;
|
||||
}
|
||||
// up event (revoke touch)
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP: {
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP: {
|
||||
setPressed(false);
|
||||
break;
|
||||
}
|
||||
@@ -335,7 +333,7 @@ public class AnalogStick extends VirtualControllerElement {
|
||||
|
||||
if (isPressed()) {
|
||||
// when is pressed calculate new positions (will trigger movement if necessary)
|
||||
updatePosition();
|
||||
updatePosition(event.getEventTime());
|
||||
} else {
|
||||
stick_state = STICK_STATE.NO_MOVEMENT;
|
||||
notifyOnRevoke();
|
||||
|
||||
+11
-38
@@ -14,8 +14,6 @@ import android.view.MotionEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* This is a digital button on screen element. It is used to get click and double click user input.
|
||||
@@ -43,22 +41,16 @@ public class DigitalButton extends VirtualControllerElement {
|
||||
void onRelease();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private class TimerLongClickTimerTask extends TimerTask {
|
||||
@Override
|
||||
public void run() {
|
||||
onLongClickCallback();
|
||||
}
|
||||
}
|
||||
|
||||
private List<DigitalButtonListener> listeners = new ArrayList<>();
|
||||
private String text = "";
|
||||
private int icon = -1;
|
||||
private long timerLongClickTimeout = 3000;
|
||||
private Timer timerLongClick = null;
|
||||
private TimerLongClickTimerTask longClickTimerTask = null;
|
||||
private final Runnable longClickRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onLongClickCallback();
|
||||
}
|
||||
};
|
||||
|
||||
private final Paint paint = new Paint();
|
||||
private final RectF rect = new RectF();
|
||||
@@ -177,18 +169,8 @@ public class DigitalButton extends VirtualControllerElement {
|
||||
listener.onClick();
|
||||
}
|
||||
|
||||
if (timerLongClick != null) {
|
||||
timerLongClick.cancel();
|
||||
timerLongClick = null;
|
||||
}
|
||||
if (longClickTimerTask != null) {
|
||||
longClickTimerTask.cancel();
|
||||
longClickTimerTask = null;
|
||||
}
|
||||
|
||||
timerLongClick = new Timer();
|
||||
longClickTimerTask = new TimerLongClickTimerTask();
|
||||
timerLongClick.schedule(longClickTimerTask, timerLongClickTimeout);
|
||||
virtualController.getHandler().removeCallbacks(longClickRunnable);
|
||||
virtualController.getHandler().postDelayed(longClickRunnable, timerLongClickTimeout);
|
||||
}
|
||||
|
||||
private void onLongClickCallback() {
|
||||
@@ -207,14 +189,7 @@ public class DigitalButton extends VirtualControllerElement {
|
||||
}
|
||||
|
||||
// We may be called for a release without a prior click
|
||||
if (timerLongClick != null) {
|
||||
timerLongClick.cancel();
|
||||
timerLongClick = null;
|
||||
}
|
||||
if (longClickTimerTask != null) {
|
||||
longClickTimerTask.cancel();
|
||||
longClickTimerTask = null;
|
||||
}
|
||||
virtualController.getHandler().removeCallbacks(longClickRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -225,8 +200,7 @@ public class DigitalButton extends VirtualControllerElement {
|
||||
int action = event.getActionMasked();
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
movingButton = null;
|
||||
setPressed(true);
|
||||
onClickCallback();
|
||||
@@ -241,8 +215,7 @@ public class DigitalButton extends VirtualControllerElement {
|
||||
return true;
|
||||
}
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP: {
|
||||
case MotionEvent.ACTION_UP: {
|
||||
setPressed(false);
|
||||
onReleaseCallback();
|
||||
|
||||
|
||||
@@ -162,7 +162,6 @@ public class DigitalPad extends VirtualControllerElement {
|
||||
// get masked (not specific to a pointer) action
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
direction = 0;
|
||||
|
||||
@@ -184,8 +183,7 @@ public class DigitalPad extends VirtualControllerElement {
|
||||
return true;
|
||||
}
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP: {
|
||||
case MotionEvent.ACTION_UP: {
|
||||
direction = 0;
|
||||
newDirectionCallback(direction);
|
||||
invalidate();
|
||||
|
||||
+52
-38
@@ -5,21 +5,20 @@
|
||||
package com.limelight.binding.input.virtual_controller;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
import com.limelight.R;
|
||||
import com.limelight.binding.input.ControllerHandler;
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class VirtualController {
|
||||
public static class ControllerInputContext {
|
||||
@@ -40,13 +39,18 @@ public class VirtualController {
|
||||
|
||||
private static final boolean _PRINT_DEBUG_INFORMATION = false;
|
||||
|
||||
private ControllerHandler controllerHandler;
|
||||
private Context context = null;
|
||||
private final ControllerHandler controllerHandler;
|
||||
private final Context context;
|
||||
private final Handler handler;
|
||||
|
||||
private final Runnable delayedRetransmitRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendControllerInputContextInternal();
|
||||
}
|
||||
};
|
||||
|
||||
private FrameLayout frame_layout = null;
|
||||
private RelativeLayout relative_layout = null;
|
||||
|
||||
private Timer retransmitTimer;
|
||||
|
||||
ControllerMode currentMode = ControllerMode.Active;
|
||||
ControllerInputContext inputContext = new ControllerInputContext();
|
||||
@@ -59,10 +63,7 @@ public class VirtualController {
|
||||
this.controllerHandler = controllerHandler;
|
||||
this.frame_layout = layout;
|
||||
this.context = context;
|
||||
|
||||
relative_layout = new RelativeLayout(context);
|
||||
|
||||
frame_layout.addView(relative_layout);
|
||||
this.handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
buttonConfigure = new Button(context);
|
||||
buttonConfigure.setAlpha(0.25f);
|
||||
@@ -87,7 +88,7 @@ public class VirtualController {
|
||||
|
||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
||||
|
||||
relative_layout.invalidate();
|
||||
buttonConfigure.invalidate();
|
||||
|
||||
for (VirtualControllerElement element : elements) {
|
||||
element.invalidate();
|
||||
@@ -97,32 +98,33 @@ public class VirtualController {
|
||||
|
||||
}
|
||||
|
||||
Handler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
retransmitTimer.cancel();
|
||||
relative_layout.setVisibility(View.INVISIBLE);
|
||||
for (VirtualControllerElement element : elements) {
|
||||
element.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
buttonConfigure.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
relative_layout.setVisibility(View.VISIBLE);
|
||||
for (VirtualControllerElement element : elements) {
|
||||
element.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
// HACK: GFE sometimes discards gamepad packets when they are received
|
||||
// very shortly after another. This can be critical if an axis zeroing packet
|
||||
// is lost and causes an analog stick to get stuck. To avoid this, we send
|
||||
// a gamepad input packet every 100 ms to ensure any loss can be recovered.
|
||||
retransmitTimer = new Timer("OSC timer", true);
|
||||
retransmitTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendControllerInputContext();
|
||||
}
|
||||
}, 100, 100);
|
||||
buttonConfigure.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public void removeElements() {
|
||||
for (VirtualControllerElement element : elements) {
|
||||
relative_layout.removeView(element);
|
||||
frame_layout.removeView(element);
|
||||
}
|
||||
elements.clear();
|
||||
|
||||
frame_layout.removeView(buttonConfigure);
|
||||
}
|
||||
|
||||
public void setOpacity(int opacity) {
|
||||
@@ -134,10 +136,10 @@ public class VirtualController {
|
||||
|
||||
public void addElement(VirtualControllerElement element, int x, int y, int width, int height) {
|
||||
elements.add(element);
|
||||
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(width, height);
|
||||
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(width, height);
|
||||
layoutParams.setMargins(x, y, 0, 0);
|
||||
|
||||
relative_layout.addView(element, layoutParams);
|
||||
frame_layout.addView(element, layoutParams);
|
||||
}
|
||||
|
||||
public List<VirtualControllerElement> getElements() {
|
||||
@@ -146,23 +148,20 @@ public class VirtualController {
|
||||
|
||||
private static final void _DBG(String text) {
|
||||
if (_PRINT_DEBUG_INFORMATION) {
|
||||
System.out.println("VirtualController: " + text);
|
||||
LimeLog.info("VirtualController: " + text);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshLayout() {
|
||||
relative_layout.removeAllViews();
|
||||
removeElements();
|
||||
|
||||
DisplayMetrics screen = context.getResources().getDisplayMetrics();
|
||||
|
||||
int buttonSize = (int)(screen.heightPixels*0.06f);
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(buttonSize, buttonSize);
|
||||
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
|
||||
params.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(buttonSize, buttonSize);
|
||||
params.leftMargin = 15;
|
||||
params.topMargin = 15;
|
||||
relative_layout.addView(buttonConfigure, params);
|
||||
frame_layout.addView(buttonConfigure, params);
|
||||
|
||||
// Start with the default layout
|
||||
VirtualControllerConfigurationLoader.createDefaultLayout(this, context);
|
||||
@@ -179,7 +178,7 @@ public class VirtualController {
|
||||
return inputContext;
|
||||
}
|
||||
|
||||
void sendControllerInputContext() {
|
||||
private void sendControllerInputContextInternal() {
|
||||
_DBG("INPUT_MAP + " + inputContext.inputMap);
|
||||
_DBG("LEFT_TRIGGER " + inputContext.leftTrigger);
|
||||
_DBG("RIGHT_TRIGGER " + inputContext.rightTrigger);
|
||||
@@ -198,4 +197,19 @@ public class VirtualController {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void sendControllerInputContext() {
|
||||
// Cancel retransmissions of prior gamepad inputs
|
||||
handler.removeCallbacks(delayedRetransmitRunnable);
|
||||
|
||||
sendControllerInputContextInternal();
|
||||
|
||||
// HACK: GFE sometimes discards gamepad packets when they are received
|
||||
// very shortly after another. This can be critical if an axis zeroing packet
|
||||
// is lost and causes an analog stick to get stuck. To avoid this, we retransmit
|
||||
// the gamepad state a few times unless another input event happens before then.
|
||||
handler.postDelayed(delayedRetransmitRunnable, 25);
|
||||
handler.postDelayed(delayedRetransmitRunnable, 50);
|
||||
handler.postDelayed(delayedRetransmitRunnable, 75);
|
||||
}
|
||||
}
|
||||
|
||||
+17
-13
@@ -40,27 +40,31 @@ public class VirtualControllerConfigurationLoader {
|
||||
VirtualController.ControllerInputContext inputContext =
|
||||
controller.getControllerInputContext();
|
||||
|
||||
if (direction == DigitalPad.DIGITAL_PAD_DIRECTION_NO_DIRECTION) {
|
||||
inputContext.inputMap &= ~ControllerPacket.LEFT_FLAG;
|
||||
inputContext.inputMap &= ~ControllerPacket.RIGHT_FLAG;
|
||||
inputContext.inputMap &= ~ControllerPacket.UP_FLAG;
|
||||
inputContext.inputMap &= ~ControllerPacket.DOWN_FLAG;
|
||||
|
||||
controller.sendControllerInputContext();
|
||||
return;
|
||||
}
|
||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_LEFT) > 0) {
|
||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_LEFT) != 0) {
|
||||
inputContext.inputMap |= ControllerPacket.LEFT_FLAG;
|
||||
}
|
||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_RIGHT) > 0) {
|
||||
else {
|
||||
inputContext.inputMap &= ~ControllerPacket.LEFT_FLAG;
|
||||
}
|
||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_RIGHT) != 0) {
|
||||
inputContext.inputMap |= ControllerPacket.RIGHT_FLAG;
|
||||
}
|
||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_UP) > 0) {
|
||||
else {
|
||||
inputContext.inputMap &= ~ControllerPacket.RIGHT_FLAG;
|
||||
}
|
||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_UP) != 0) {
|
||||
inputContext.inputMap |= ControllerPacket.UP_FLAG;
|
||||
}
|
||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_DOWN) > 0) {
|
||||
else {
|
||||
inputContext.inputMap &= ~ControllerPacket.UP_FLAG;
|
||||
}
|
||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_DOWN) != 0) {
|
||||
inputContext.inputMap |= ControllerPacket.DOWN_FLAG;
|
||||
}
|
||||
else {
|
||||
inputContext.inputMap &= ~ControllerPacket.DOWN_FLAG;
|
||||
}
|
||||
|
||||
controller.sendControllerInputContext();
|
||||
}
|
||||
});
|
||||
|
||||
+16
-9
@@ -12,7 +12,7 @@ import android.graphics.Paint;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -72,7 +72,7 @@ public abstract class VirtualControllerElement extends View {
|
||||
int newPos_x = (int) getX() + x - pressed_x;
|
||||
int newPos_y = (int) getY() + y - pressed_y;
|
||||
|
||||
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
|
||||
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) getLayoutParams();
|
||||
|
||||
layoutParams.leftMargin = newPos_x > 0 ? newPos_x : 0;
|
||||
layoutParams.topMargin = newPos_y > 0 ? newPos_y : 0;
|
||||
@@ -83,7 +83,7 @@ public abstract class VirtualControllerElement extends View {
|
||||
}
|
||||
|
||||
protected void resizeElement(int pressed_x, int pressed_y, int width, int height) {
|
||||
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
|
||||
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) getLayoutParams();
|
||||
|
||||
int newHeight = height + (startSize_y - pressed_y);
|
||||
int newWidth = width + (startSize_x - pressed_x);
|
||||
@@ -223,13 +223,21 @@ public abstract class VirtualControllerElement extends View {
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
// Ignore secondary touches on controls
|
||||
//
|
||||
// NB: We can get an additional pointer down if the user touches a non-StreamView area
|
||||
// while also touching an OSC control, even if that pointer down doesn't correspond to
|
||||
// an area of the OSC control.
|
||||
if (event.getActionIndex() != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (virtualController.getControllerMode() == VirtualController.ControllerMode.Active) {
|
||||
return onElementTouchEvent(event);
|
||||
}
|
||||
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
position_pressed_x = event.getX();
|
||||
position_pressed_y = event.getY();
|
||||
startSize_x = getWidth();
|
||||
@@ -267,8 +275,7 @@ public abstract class VirtualControllerElement extends View {
|
||||
return true;
|
||||
}
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP: {
|
||||
case MotionEvent.ACTION_UP: {
|
||||
actionCancel();
|
||||
return true;
|
||||
}
|
||||
@@ -316,7 +323,7 @@ public abstract class VirtualControllerElement extends View {
|
||||
public JSONObject getConfiguration() throws JSONException {
|
||||
JSONObject configuration = new JSONObject();
|
||||
|
||||
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
|
||||
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) getLayoutParams();
|
||||
|
||||
configuration.put("LEFT", layoutParams.leftMargin);
|
||||
configuration.put("TOP", layoutParams.topMargin);
|
||||
@@ -327,7 +334,7 @@ public abstract class VirtualControllerElement extends View {
|
||||
}
|
||||
|
||||
public void loadConfiguration(JSONObject configuration) throws JSONException {
|
||||
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
|
||||
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) getLayoutParams();
|
||||
|
||||
layoutParams.leftMargin = configuration.getInt("LEFT");
|
||||
layoutParams.topMargin = configuration.getInt("TOP");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,9 +18,11 @@ import android.media.MediaCodecInfo;
|
||||
import android.media.MediaCodecList;
|
||||
import android.media.MediaCodecInfo.CodecCapabilities;
|
||||
import android.media.MediaCodecInfo.CodecProfileLevel;
|
||||
import android.media.MediaFormat;
|
||||
import android.os.Build;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
import com.limelight.preferences.PreferenceConfiguration;
|
||||
|
||||
public class MediaCodecHelper {
|
||||
|
||||
@@ -36,11 +38,14 @@ public class MediaCodecHelper {
|
||||
private static final List<String> whitelistedHevcDecoders;
|
||||
private static final List<String> refFrameInvalidationAvcPrefixes;
|
||||
private static final List<String> refFrameInvalidationHevcPrefixes;
|
||||
private static final List<String> blacklisted49FpsDecoderPrefixes;
|
||||
private static final List<String> blacklisted59FpsDecoderPrefixes;
|
||||
private static final List<String> useFourSlicesPrefixes;
|
||||
private static final List<String> qualcommDecoderPrefixes;
|
||||
private static final List<String> kirinDecoderPrefixes;
|
||||
private static final List<String> exynosDecoderPrefixes;
|
||||
private static final List<String> amlogicDecoderPrefixes;
|
||||
|
||||
public static final boolean IS_EMULATOR = Build.HARDWARE.equals("ranchu") || Build.HARDWARE.equals("cheets");
|
||||
public static final boolean SHOULD_BYPASS_SOFTWARE_BLOCK =
|
||||
Build.HARDWARE.equals("ranchu") || Build.HARDWARE.equals("cheets") || Build.BRAND.equals("Android-x86");
|
||||
|
||||
private static boolean isLowEndSnapdragon = false;
|
||||
private static boolean isAdreno620 = false;
|
||||
@@ -78,18 +83,18 @@ public class MediaCodecHelper {
|
||||
static {
|
||||
blacklistedDecoderPrefixes = new LinkedList<>();
|
||||
|
||||
// Blacklist software decoders that don't support H264 high profile,
|
||||
// but exclude the official AOSP and CrOS emulator from this restriction.
|
||||
if (!IS_EMULATOR) {
|
||||
// Blacklist software decoders that don't support H264 high profile except on systems
|
||||
// that are expected to only have software decoders (like emulators).
|
||||
if (!SHOULD_BYPASS_SOFTWARE_BLOCK) {
|
||||
blacklistedDecoderPrefixes.add("omx.google");
|
||||
blacklistedDecoderPrefixes.add("AVCDecoder");
|
||||
}
|
||||
|
||||
// We want to avoid ffmpeg decoders since they're software decoders,
|
||||
// but on Android-x86 they might be all we have (and also relatively
|
||||
// performant on a modern x86 processor).
|
||||
if (!Build.BRAND.equals("Android-x86")) {
|
||||
blacklistedDecoderPrefixes.add("OMX.ffmpeg");
|
||||
// We want to avoid ffmpeg decoders since they're usually software decoders,
|
||||
// but we'll defer to the Android 10 isSoftwareOnly() API on newer devices
|
||||
// to determine if we should use these or not.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
blacklistedDecoderPrefixes.add("OMX.ffmpeg");
|
||||
}
|
||||
}
|
||||
|
||||
// Force these decoders disabled because:
|
||||
@@ -115,7 +120,7 @@ public class MediaCodecHelper {
|
||||
// if adaptive playback was enabled so let's avoid it to be safe.
|
||||
blacklistedAdaptivePlaybackPrefixes.add("omx.intel");
|
||||
// The MediaTek decoder crashes at 1080p when adaptive playback is enabled
|
||||
// on some Android TV devices with H.265 only.
|
||||
// on some Android TV devices with HEVC only.
|
||||
blacklistedAdaptivePlaybackPrefixes.add("omx.mtk");
|
||||
|
||||
constrainedHighProfilePrefixes = new LinkedList<>();
|
||||
@@ -133,21 +138,26 @@ public class MediaCodecHelper {
|
||||
// Exynos seems to be the only HEVC decoder that works reliably
|
||||
whitelistedHevcDecoders.add("omx.exynos");
|
||||
|
||||
// On Darcy (Shield 2017), HEVC runs fine with no fixups required.
|
||||
// For some reason, other X1 implementations require bitstream fixups.
|
||||
if (Build.DEVICE.equalsIgnoreCase("darcy")) {
|
||||
// On Darcy (Shield 2017), HEVC runs fine with no fixups required. For some reason,
|
||||
// other X1 implementations require bitstream fixups. However, since numReferenceFrames
|
||||
// has been supported in GFE since late 2017, we'll go ahead and enable HEVC for all
|
||||
// device models.
|
||||
//
|
||||
// NVIDIA does partial HEVC acceleration on the Shield Tablet. I don't know
|
||||
// whether the performance is good enough to use for streaming, but they're
|
||||
// using the same omx.nvidia.h265.decode name as the Shield TV which has a
|
||||
// fully accelerated HEVC pipeline. AFAIK, the only K1 devices with this
|
||||
// partially accelerated HEVC decoder are the Shield Tablet and Xiaomi MiPad,
|
||||
// so I'll check for those here.
|
||||
//
|
||||
// In case there are some that I missed, I will also exclude pre-Oreo OSes since
|
||||
// only Shield ATV got an Oreo update and any newer Tegra devices will not ship
|
||||
// with an old OS like Nougat.
|
||||
if (!Build.DEVICE.equalsIgnoreCase("shieldtablet") &&
|
||||
!Build.DEVICE.equalsIgnoreCase("mocha") &&
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
whitelistedHevcDecoders.add("omx.nvidia");
|
||||
}
|
||||
else {
|
||||
// TODO: This needs a similar fixup to the Tegra 3 otherwise it buffers 16 frames
|
||||
}
|
||||
|
||||
// Older Sony ATVs (SVP-DTV15) have broken MediaTek codecs (decoder hangs after rendering the first frame).
|
||||
// I know the Fire TV 2 and 3 works, so I'll whitelist Amazon devices which seem to actually be tested.
|
||||
if (Build.MANUFACTURER.equalsIgnoreCase("Amazon")) {
|
||||
whitelistedHevcDecoders.add("omx.mtk");
|
||||
whitelistedHevcDecoders.add("omx.amlogic");
|
||||
}
|
||||
|
||||
// Plot twist: On newer Sony devices (BRAVIA_ATV2, BRAVIA_ATV3_4K, BRAVIA_UR1_4K) the H.264 decoder crashes
|
||||
// on several configurations (> 60 FPS and 1440p) that work with HEVC, so we'll whitelist those devices for HEVC.
|
||||
@@ -157,11 +167,23 @@ public class MediaCodecHelper {
|
||||
|
||||
// Amlogic requires 1 reference frame for HEVC to avoid hanging. Since it's been years
|
||||
// since GFE added support for maxNumReferenceFrames, we'll just enable all Amlogic SoCs
|
||||
// running Android 9 or later. HEVC is much lower latency than H.264 on Sabrina (S905X2).
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
// running Android 9 or later.
|
||||
//
|
||||
// NB: We don't do this on Sabrina (GCWGTV) because H.264 is lower latency when we use
|
||||
// vendor.low-latency.enable. We will still use HEVC if decoderCanMeetPerformancePointWithHevcAndNotAvc()
|
||||
// determines it's the only way to meet the performance requirements.
|
||||
//
|
||||
// FIXME: Should we do this for all Amlogic S905X SoCs?
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !Build.DEVICE.equalsIgnoreCase("sabrina")) {
|
||||
whitelistedHevcDecoders.add("omx.amlogic");
|
||||
}
|
||||
|
||||
// Realtek SoCs are used inside many Android TV devices and can only do 4K60 with HEVC.
|
||||
// We'll enable those HEVC decoders by default and see if anything breaks.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
whitelistedHevcDecoders.add("omx.realtek");
|
||||
}
|
||||
|
||||
// These theoretically have good HEVC decoding capabilities (potentially better than
|
||||
// their AVC decoders), but haven't been tested enough
|
||||
//whitelistedHevcDecoders.add("omx.rk");
|
||||
@@ -182,21 +204,15 @@ public class MediaCodecHelper {
|
||||
}
|
||||
|
||||
static {
|
||||
blacklisted49FpsDecoderPrefixes = new LinkedList<>();
|
||||
blacklisted59FpsDecoderPrefixes = new LinkedList<>();
|
||||
useFourSlicesPrefixes = new LinkedList<>();
|
||||
|
||||
// We see a bunch of crashes on MediaTek Android TVs running
|
||||
// at 49 FPS (PAL 50 Hz - 1). Blacklist this frame rate for
|
||||
// these devices and hope they fix it in Pie.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
blacklisted49FpsDecoderPrefixes.add("omx.mtk");
|
||||
// Software decoders will use 4 slices per frame to allow for slice multithreading
|
||||
useFourSlicesPrefixes.add("omx.google");
|
||||
useFourSlicesPrefixes.add("AVCDecoder");
|
||||
useFourSlicesPrefixes.add("omx.ffmpeg");
|
||||
useFourSlicesPrefixes.add("c2.android");
|
||||
|
||||
// 59 FPS also seems to crash on the Sony Bravia TV ATV3 model.
|
||||
// Blacklist that frame rate on these devices too.
|
||||
if (Build.DEVICE.startsWith("BRAVIA_ATV3")) {
|
||||
blacklisted59FpsDecoderPrefixes.add("omx.mtk");
|
||||
}
|
||||
}
|
||||
// Old Qualcomm decoders are detected at runtime
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -206,6 +222,27 @@ public class MediaCodecHelper {
|
||||
qualcommDecoderPrefixes.add("c2.qti");
|
||||
}
|
||||
|
||||
static {
|
||||
kirinDecoderPrefixes = new LinkedList<>();
|
||||
|
||||
kirinDecoderPrefixes.add("omx.hisi");
|
||||
kirinDecoderPrefixes.add("c2.hisi"); // Unconfirmed
|
||||
}
|
||||
|
||||
static {
|
||||
exynosDecoderPrefixes = new LinkedList<>();
|
||||
|
||||
exynosDecoderPrefixes.add("omx.exynos");
|
||||
exynosDecoderPrefixes.add("c2.exynos");
|
||||
}
|
||||
|
||||
static {
|
||||
amlogicDecoderPrefixes = new LinkedList<>();
|
||||
|
||||
amlogicDecoderPrefixes.add("omx.amlogic");
|
||||
amlogicDecoderPrefixes.add("c2.amlogic"); // Unconfirmed
|
||||
}
|
||||
|
||||
private static boolean isPowerVR(String glRenderer) {
|
||||
return glRenderer.toLowerCase().contains("powervr");
|
||||
}
|
||||
@@ -264,6 +301,19 @@ public class MediaCodecHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
// Older Sony ATVs (SVP-DTV15) have broken MediaTek codecs (decoder hangs after rendering the first frame).
|
||||
// I know the Fire TV 2 and 3 works, so I'll whitelist Amazon devices which seem to actually be tested.
|
||||
// We still have to check Build.MANUFACTURER to catch Amazon Fire tablets.
|
||||
if (context.getPackageManager().hasSystemFeature("amazon.hardware.fire_tv") ||
|
||||
Build.MANUFACTURER.equalsIgnoreCase("Amazon")) {
|
||||
whitelistedHevcDecoders.add("omx.mtk");
|
||||
|
||||
// This requires setting vdec-lowlatency on the Fire TV 3, otherwise the decoder
|
||||
// never produces any output frames. See comment above for details on why we only
|
||||
// do this for Fire TV devices.
|
||||
whitelistedHevcDecoders.add("omx.amlogic");
|
||||
}
|
||||
|
||||
ActivityManager activityManager =
|
||||
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
|
||||
@@ -309,6 +359,9 @@ public class MediaCodecHelper {
|
||||
}
|
||||
else {
|
||||
blacklistedDecoderPrefixes.add("OMX.qcom.video.decoder.hevc");
|
||||
|
||||
// These older decoders need 4 slices per frame for best performance
|
||||
useFourSlicesPrefixes.add("omx.qcom");
|
||||
}
|
||||
|
||||
// Older MediaTek SoCs have issues with HEVC rendering but the newer chips with
|
||||
@@ -348,11 +401,7 @@ public class MediaCodecHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static long getMonotonicMillis() {
|
||||
return System.nanoTime() / 1000000L;
|
||||
}
|
||||
|
||||
public static boolean decoderSupportsLowLatency(MediaCodecInfo decoderInfo, String mimeType) {
|
||||
private static boolean decoderSupportsAndroidRLowLatency(MediaCodecInfo decoderInfo, String mimeType) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
try {
|
||||
if (decoderInfo.getCapabilitiesForType(mimeType).isFeatureSupported(CodecCapabilities.FEATURE_LowLatency)) {
|
||||
@@ -368,7 +417,7 @@ public class MediaCodecHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean decoderSupportsMaxOperatingRate(String decoderName) {
|
||||
private static boolean decoderSupportsMaxOperatingRate(String decoderName) {
|
||||
// Operate at maximum rate to lower latency as much as possible on
|
||||
// some Qualcomm platforms. We could also set KEY_PRIORITY to 0 (realtime)
|
||||
// but that will actually result in the decoder crashing if it can't satisfy
|
||||
@@ -383,6 +432,119 @@ public class MediaCodecHelper {
|
||||
!isAdreno620;
|
||||
}
|
||||
|
||||
public static boolean setDecoderLowLatencyOptions(MediaFormat videoFormat, MediaCodecInfo decoderInfo, int tryNumber) {
|
||||
// Options here should be tried in the order of most to least risky. The decoder will use
|
||||
// the first MediaFormat that doesn't fail in configure().
|
||||
|
||||
boolean setNewOption = false;
|
||||
|
||||
if (tryNumber < 1) {
|
||||
// Official Android 11+ low latency option (KEY_LOW_LATENCY).
|
||||
videoFormat.setInteger("low-latency", 1);
|
||||
setNewOption = true;
|
||||
|
||||
// If this decoder officially supports FEATURE_LowLatency, we will just use that alone
|
||||
// for try 0. Otherwise, we'll include it as best effort with other options.
|
||||
if (decoderSupportsAndroidRLowLatency(decoderInfo, videoFormat.getString(MediaFormat.KEY_MIME))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tryNumber < 2 &&
|
||||
(!Build.MANUFACTURER.equalsIgnoreCase("xiaomi") || Build.VERSION.SDK_INT > Build.VERSION_CODES.M)) {
|
||||
// MediaTek decoders don't use vendor-defined keys for low latency mode. Instead, they have a modified
|
||||
// version of AOSP's ACodec.cpp which supports the "vdec-lowlatency" option. This option is passed down
|
||||
// to the decoder as OMX.MTK.index.param.video.LowLatencyDecode.
|
||||
//
|
||||
// This option is also plumbed for Amazon Amlogic-based devices like the Fire TV 3. Not only does it
|
||||
// reduce latency on Amlogic, it fixes the HEVC bug that causes the decoder to not output any frames.
|
||||
// Unfortunately, it does the exact opposite for the Xiaomi MITV4-ANSM0, breaking it in the way that
|
||||
// Fire TV was broken prior to vdec-lowlatency :(
|
||||
//
|
||||
// On Fire TV 3, vdec-lowlatency is translated to OMX.amazon.fireos.index.video.lowLatencyDecode.
|
||||
//
|
||||
// https://github.com/yuan1617/Framwork/blob/master/frameworks/av/media/libstagefright/ACodec.cpp
|
||||
// https://github.com/iykex/vendor_mediatek_proprietary_hardware/blob/master/libomx/video/MtkOmxVdecEx/MtkOmxVdecEx.h
|
||||
videoFormat.setInteger("vdec-lowlatency", 1);
|
||||
setNewOption = true;
|
||||
}
|
||||
|
||||
// MediaCodec supports vendor-defined format keys using the "vendor.<extension name>.<parameter name>" syntax.
|
||||
// These allow access to functionality that is not exposed through documented MediaFormat.KEY_* values.
|
||||
// https://cs.android.com/android/platform/superproject/+/master:hardware/qcom/sdm845/media/mm-video-v4l2/vidc/common/inc/vidc_vendor_extensions.h;l=67
|
||||
//
|
||||
// MediaCodec vendor extension support was introduced in Android 8.0:
|
||||
// https://cs.android.com/android/_/android/platform/frameworks/av/+/01c10f8cdcd58d1e7025f426a72e6e75ba5d7fc2
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// Try vendor-specific low latency options
|
||||
if (isDecoderInList(qualcommDecoderPrefixes, decoderInfo.getName())) {
|
||||
// Examples of Qualcomm's vendor extensions for Snapdragon 845:
|
||||
// https://cs.android.com/android/platform/superproject/+/master:hardware/qcom/sdm845/media/mm-video-v4l2/vidc/vdec/src/omx_vdec_extensions.hpp
|
||||
// https://cs.android.com/android/_/android/platform/hardware/qcom/sm8150/media/+/0621ceb1c1b19564999db8293574a0e12952ff6c
|
||||
//
|
||||
// We will first try both, then try vendor.qti-ext-dec-low-latency.enable alone if that fails
|
||||
if (tryNumber < 3) {
|
||||
videoFormat.setInteger("vendor.qti-ext-dec-picture-order.enable", 1);
|
||||
setNewOption = true;
|
||||
}
|
||||
if (tryNumber < 4) {
|
||||
videoFormat.setInteger("vendor.qti-ext-dec-low-latency.enable", 1);
|
||||
setNewOption = true;
|
||||
}
|
||||
}
|
||||
else if (isDecoderInList(kirinDecoderPrefixes, decoderInfo.getName())) {
|
||||
if (tryNumber < 3) {
|
||||
// Kirin low latency options
|
||||
// https://developer.huawei.com/consumer/cn/forum/topic/0202325564295980115
|
||||
videoFormat.setInteger("vendor.hisi-ext-low-latency-video-dec.video-scene-for-low-latency-req", 1);
|
||||
videoFormat.setInteger("vendor.hisi-ext-low-latency-video-dec.video-scene-for-low-latency-rdy", -1);
|
||||
setNewOption = true;
|
||||
}
|
||||
}
|
||||
else if (isDecoderInList(exynosDecoderPrefixes, decoderInfo.getName())) {
|
||||
if (tryNumber < 3) {
|
||||
// Exynos low latency option for H.264 decoder
|
||||
videoFormat.setInteger("vendor.rtc-ext-dec-low-latency.enable", 1);
|
||||
setNewOption = true;
|
||||
}
|
||||
}
|
||||
else if (isDecoderInList(amlogicDecoderPrefixes, decoderInfo.getName())) {
|
||||
if (tryNumber < 3) {
|
||||
// Amlogic low latency vendor extension
|
||||
// https://github.com/codewalkerster/android_vendor_amlogic_common_prebuilt_libstagefrighthw/commit/41fefc4e035c476d58491324a5fe7666bfc2989e
|
||||
videoFormat.setInteger("vendor.low-latency.enable", 1);
|
||||
setNewOption = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: We should probably integrate this into the try system
|
||||
if (MediaCodecHelper.decoderSupportsMaxOperatingRate(decoderInfo.getName())) {
|
||||
videoFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, Short.MAX_VALUE);
|
||||
}
|
||||
|
||||
return setNewOption;
|
||||
}
|
||||
|
||||
public static boolean decoderSupportsFusedIdrFrame(MediaCodecInfo decoderInfo, String mimeType) {
|
||||
// If adaptive playback is supported, we can submit new CSD together with a keyframe
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
if (decoderInfo.getCapabilitiesForType(mimeType).
|
||||
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
|
||||
{
|
||||
LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Tolerate buggy codecs
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo, String mimeType) {
|
||||
// Possibly enable adaptive playback on KitKat and above
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
@@ -408,13 +570,6 @@ public class MediaCodecHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean decoderSupportsQcomVendorLowLatency(String decoderName) {
|
||||
// MediaCodec vendor extension support was introduced in Android 8.0:
|
||||
// https://cs.android.com/android/_/android/platform/frameworks/av/+/01c10f8cdcd58d1e7025f426a72e6e75ba5d7fc2
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
|
||||
isDecoderInList(qualcommDecoderPrefixes, decoderName);
|
||||
}
|
||||
|
||||
public static boolean decoderNeedsConstrainedHighProfile(String decoderName) {
|
||||
return isDecoderInList(constrainedHighProfilePrefixes, decoderName);
|
||||
}
|
||||
@@ -431,15 +586,14 @@ public class MediaCodecHelper {
|
||||
return isDecoderInList(baselineProfileHackPrefixes, decoderName);
|
||||
}
|
||||
|
||||
public static boolean decoderBlacklistedForFrameRate(String decoderName, int fps) {
|
||||
if (fps == 49) {
|
||||
return isDecoderInList(blacklisted49FpsDecoderPrefixes, decoderName);
|
||||
}
|
||||
else if (fps == 59) {
|
||||
return isDecoderInList(blacklisted59FpsDecoderPrefixes, decoderName);
|
||||
public static byte getDecoderOptimalSlicesPerFrame(String decoderName) {
|
||||
if (isDecoderInList(useFourSlicesPrefixes, decoderName)) {
|
||||
// 4 slices per frame reduces decoding latency on older Qualcomm devices
|
||||
return 4;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
// 1 slice per frame produces the optimal encoding efficiency
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,21 +616,7 @@ public class MediaCodecHelper {
|
||||
return isDecoderInList(refFrameInvalidationHevcPrefixes, decoderName);
|
||||
}
|
||||
|
||||
public static boolean decoderIsWhitelistedForHevc(String decoderName, boolean meteredData) {
|
||||
// TODO: Shield Tablet K1/LTE?
|
||||
//
|
||||
// NVIDIA does partial HEVC acceleration on the Shield Tablet. I don't know
|
||||
// whether the performance is good enough to use for streaming, but they're
|
||||
// using the same omx.nvidia.h265.decode name as the Shield TV which has a
|
||||
// fully accelerated HEVC pipeline. AFAIK, the only K1 device with this
|
||||
// partially accelerated HEVC decoder is the Shield Tablet, so I'll
|
||||
// check for it here.
|
||||
//
|
||||
// TODO: Temporarily disabled with NVIDIA HEVC support
|
||||
/*if (Build.DEVICE.equalsIgnoreCase("shieldtablet")) {
|
||||
return false;
|
||||
}*/
|
||||
|
||||
public static boolean decoderIsWhitelistedForHevc(String decoderName, boolean meteredData, PreferenceConfiguration prefs) {
|
||||
// Google didn't have official support for HEVC (or more importantly, a CTS test) until
|
||||
// Lollipop. I've seen some MediaTek devices on 4.4 crash when attempting to use HEVC,
|
||||
// so I'm restricting HEVC usage to Lollipop and higher.
|
||||
@@ -497,9 +637,10 @@ public class MediaCodecHelper {
|
||||
// Some devices have HEVC decoders that we prefer not to use
|
||||
// typically because it can't support reference frame invalidation.
|
||||
// However, we will use it for HDR and for streaming over mobile networks
|
||||
// since it works fine otherwise.
|
||||
// since it works fine otherwise. We will also use it for 4K because RFI
|
||||
// is currently disabled due to issues with video corruption.
|
||||
if (isDecoderInList(deprioritizedHevcDecoders, decoderName)) {
|
||||
if (meteredData) {
|
||||
if (meteredData || (prefs.width == 3840 && prefs.height == 2160)) {
|
||||
LimeLog.info("Selected deprioritized decoder");
|
||||
return true;
|
||||
}
|
||||
@@ -566,13 +707,6 @@ public class MediaCodecHelper {
|
||||
if (codecInfo.isEncoder()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip compatibility aliases on Q+
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (codecInfo.isAlias()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for preferred decoders
|
||||
if (preferredDecoder.equalsIgnoreCase(codecInfo.getName())) {
|
||||
@@ -588,7 +722,7 @@ public class MediaCodecHelper {
|
||||
private static boolean isCodecBlacklisted(MediaCodecInfo codecInfo) {
|
||||
// Use the new isSoftwareOnly() function on Android Q
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (!IS_EMULATOR && codecInfo.isSoftwareOnly()) {
|
||||
if (!SHOULD_BYPASS_SOFTWARE_BLOCK && codecInfo.isSoftwareOnly()) {
|
||||
LimeLog.info("Skipping software-only decoder: "+codecInfo.getName());
|
||||
return true;
|
||||
}
|
||||
@@ -658,43 +792,57 @@ public class MediaCodecHelper {
|
||||
// and we want to be sure all callers are handling this possibility
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
private static MediaCodecInfo findKnownSafeDecoder(String mimeType, int requiredProfile) throws Exception {
|
||||
for (MediaCodecInfo codecInfo : getMediaCodecList()) {
|
||||
// Skip encoders
|
||||
if (codecInfo.isEncoder()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip compatibility aliases on Q+
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (codecInfo.isAlias()) {
|
||||
// Some devices (Exynos devces, at least) have two sets of decoders.
|
||||
// The first set of decoders are C2 which do not support FEATURE_LowLatency,
|
||||
// but the second set of OMX decoders do support FEATURE_LowLatency. We want
|
||||
// to pick the OMX decoders despite the fact that C2 is listed first.
|
||||
// On some Qualcomm devices (like Pixel 4), there are separate low latency decoders
|
||||
// (like c2.qti.hevc.decoder.low_latency) that advertise FEATURE_LowLatency while
|
||||
// the standard ones (like c2.qti.hevc.decoder) do not. Like Exynos, the decoders
|
||||
// with FEATURE_LowLatency support are listed after the standard ones.
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (MediaCodecInfo codecInfo : getMediaCodecList()) {
|
||||
// Skip encoders
|
||||
if (codecInfo.isEncoder()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Find a decoder that supports the requested video format
|
||||
for (String mime : codecInfo.getSupportedTypes()) {
|
||||
if (mime.equalsIgnoreCase(mimeType)) {
|
||||
LimeLog.info("Examining decoder capabilities of "+codecInfo.getName());
|
||||
|
||||
// Skip blacklisted codecs
|
||||
if (isCodecBlacklisted(codecInfo)) {
|
||||
// Skip compatibility aliases on Q+
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (codecInfo.isAlias()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
CodecCapabilities caps = codecInfo.getCapabilitiesForType(mime);
|
||||
// Find a decoder that supports the requested video format
|
||||
for (String mime : codecInfo.getSupportedTypes()) {
|
||||
if (mime.equalsIgnoreCase(mimeType)) {
|
||||
LimeLog.info("Examining decoder capabilities of " + codecInfo.getName() + " (round " + (i + 1) + ")");
|
||||
|
||||
if (requiredProfile != -1) {
|
||||
for (CodecProfileLevel profile : caps.profileLevels) {
|
||||
if (profile.profile == requiredProfile) {
|
||||
LimeLog.info("Decoder " + codecInfo.getName() + " supports required profile");
|
||||
return codecInfo;
|
||||
}
|
||||
// Skip blacklisted codecs
|
||||
if (isCodecBlacklisted(codecInfo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LimeLog.info("Decoder " + codecInfo.getName() + " does NOT support required profile");
|
||||
}
|
||||
else {
|
||||
return codecInfo;
|
||||
CodecCapabilities caps = codecInfo.getCapabilitiesForType(mime);
|
||||
|
||||
if (i == 0 && !decoderSupportsAndroidRLowLatency(codecInfo, mime)) {
|
||||
LimeLog.info("Skipping decoder that lacks FEATURE_LowLatency for round 1");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (requiredProfile != -1) {
|
||||
for (CodecProfileLevel profile : caps.profileLevels) {
|
||||
if (profile.profile == requiredProfile) {
|
||||
LimeLog.info("Decoder " + codecInfo.getName() + " supports required profile");
|
||||
return codecInfo;
|
||||
}
|
||||
}
|
||||
|
||||
LimeLog.info("Decoder " + codecInfo.getName() + " does NOT support required profile");
|
||||
} else {
|
||||
return codecInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import java.io.OutputStream;
|
||||
import java.io.StringReader;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -49,8 +47,7 @@ public class ComputerManagerService extends Service {
|
||||
private static final int APPLIST_POLLING_PERIOD_MS = 30000;
|
||||
private static final int APPLIST_FAILED_POLLING_RETRY_MS = 2000;
|
||||
private static final int MDNS_QUERY_PERIOD_MS = 1000;
|
||||
private static final int FAST_POLL_TIMEOUT = 1000;
|
||||
private static final int OFFLINE_POLL_TRIES = 5;
|
||||
private static final int OFFLINE_POLL_TRIES = 3;
|
||||
private static final int INITIAL_POLL_TRIES = 2;
|
||||
private static final int EMPTY_LIST_THRESHOLD = 3;
|
||||
private static final int POLL_DATA_TTL_MS = 30000;
|
||||
@@ -232,7 +229,13 @@ public class ComputerManagerService extends Service {
|
||||
// Wait for the bind notification
|
||||
discoveryServiceConnection.wait(1000);
|
||||
}
|
||||
} catch (InterruptedException ignored) {
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
// InterruptedException clears the thread's interrupt status. Since we can't
|
||||
// handle that here, we will re-interrupt the thread to set the interrupt
|
||||
// status back to true.
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,11 +244,18 @@ public class ComputerManagerService extends Service {
|
||||
while (activePolls.get() != 0) {
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
} catch (InterruptedException ignored) {}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
// InterruptedException clears the thread's interrupt status. Since we can't
|
||||
// handle that here, we will re-interrupt the thread to set the interrupt
|
||||
// status back to true.
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addComputerBlocking(ComputerDetails fakeDetails) {
|
||||
public boolean addComputerBlocking(ComputerDetails fakeDetails) throws InterruptedException {
|
||||
return ComputerManagerService.this.addComputerBlocking(fakeDetails);
|
||||
}
|
||||
|
||||
@@ -399,9 +409,18 @@ public class ComputerManagerService extends Service {
|
||||
details.ipv6Address = computer.getIpv6Address().getHostAddress();
|
||||
}
|
||||
|
||||
// Kick off a serverinfo poll on this machine
|
||||
if (!addComputerBlocking(details)) {
|
||||
LimeLog.warning("Auto-discovered PC failed to respond: "+details);
|
||||
try {
|
||||
// Kick off a blocking serverinfo poll on this machine
|
||||
if (!addComputerBlocking(details)) {
|
||||
LimeLog.warning("Auto-discovered PC failed to respond: "+details);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
// InterruptedException clears the thread's interrupt status. Since we can't
|
||||
// handle that here, we will re-interrupt the thread to set the interrupt
|
||||
// status back to true.
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,28 +468,25 @@ public class ComputerManagerService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addComputerBlocking(ComputerDetails fakeDetails) {
|
||||
public boolean addComputerBlocking(ComputerDetails fakeDetails) throws InterruptedException {
|
||||
// Block while we try to fill the details
|
||||
try {
|
||||
// We cannot use runPoll() here because it will attempt to persist the state of the machine
|
||||
// in the database, which would be bad because we don't have our pinned cert loaded yet.
|
||||
if (pollComputer(fakeDetails)) {
|
||||
// See if we have record of this PC to pull its pinned cert
|
||||
synchronized (pollingTuples) {
|
||||
for (PollingTuple tuple : pollingTuples) {
|
||||
if (tuple.computer.uuid.equals(fakeDetails.uuid)) {
|
||||
fakeDetails.serverCert = tuple.computer.serverCert;
|
||||
break;
|
||||
}
|
||||
|
||||
// We cannot use runPoll() here because it will attempt to persist the state of the machine
|
||||
// in the database, which would be bad because we don't have our pinned cert loaded yet.
|
||||
if (pollComputer(fakeDetails)) {
|
||||
// See if we have record of this PC to pull its pinned cert
|
||||
synchronized (pollingTuples) {
|
||||
for (PollingTuple tuple : pollingTuples) {
|
||||
if (tuple.computer.uuid.equals(fakeDetails.uuid)) {
|
||||
fakeDetails.serverCert = tuple.computer.serverCert;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Poll again, possibly with the pinned cert, to get accurate pairing information.
|
||||
// This will insert the host into the database too.
|
||||
runPoll(fakeDetails, true, 0);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
|
||||
// Poll again, possibly with the pinned cert, to get accurate pairing information.
|
||||
// This will insert the host into the database too.
|
||||
runPoll(fakeDetails, true, 0);
|
||||
}
|
||||
|
||||
// If the machine is reachable, it was successful
|
||||
@@ -528,11 +544,6 @@ public class ComputerManagerService extends Service {
|
||||
}
|
||||
|
||||
private ComputerDetails tryPollIp(ComputerDetails details, String address) {
|
||||
// Fast poll this address first to determine if we can connect at the TCP layer
|
||||
if (!fastPollIp(address)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
NvHTTP http = new NvHTTP(address, idManager.getUniqueId(), details.serverCert,
|
||||
PlatformBinding.getCryptoProvider(ComputerManagerService.this));
|
||||
@@ -551,146 +562,140 @@ public class ComputerManagerService extends Service {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Set the new active address
|
||||
newDetails.activeAddress = address;
|
||||
|
||||
return newDetails;
|
||||
} catch (XmlPullParserException | IOException e) {
|
||||
} catch (XmlPullParserException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Just try to establish a TCP connection to speculatively detect a running
|
||||
// GFE server
|
||||
private boolean fastPollIp(String address) {
|
||||
if (address == null) {
|
||||
// Don't bother if our address is null
|
||||
return false;
|
||||
private static class ParallelPollTuple {
|
||||
public String address;
|
||||
public ComputerDetails existingDetails;
|
||||
|
||||
public boolean complete;
|
||||
public Thread pollingThread;
|
||||
public ComputerDetails returnedDetails;
|
||||
|
||||
public ParallelPollTuple(String address, ComputerDetails existingDetails) {
|
||||
this.address = address;
|
||||
this.existingDetails = existingDetails;
|
||||
}
|
||||
|
||||
Socket s = new Socket();
|
||||
try {
|
||||
s.connect(new InetSocketAddress(address, NvHTTP.HTTPS_PORT), FAST_POLL_TIMEOUT);
|
||||
s.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
public void interrupt() {
|
||||
if (pollingThread != null) {
|
||||
pollingThread.interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startFastPollThread(final String address, final boolean[] info) {
|
||||
Thread t = new Thread() {
|
||||
private void startParallelPollThread(ParallelPollTuple tuple, HashSet<String> uniqueAddresses) {
|
||||
// Don't bother starting a polling thread for an address that doesn't exist
|
||||
// or if the address has already been polled with an earlier tuple
|
||||
if (tuple.address == null || !uniqueAddresses.add(tuple.address)) {
|
||||
tuple.complete = true;
|
||||
tuple.returnedDetails = null;
|
||||
return;
|
||||
}
|
||||
|
||||
tuple.pollingThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean pollRes = fastPollIp(address);
|
||||
ComputerDetails details = tryPollIp(tuple.existingDetails, tuple.address);
|
||||
|
||||
synchronized (info) {
|
||||
info[0] = true; // Done
|
||||
info[1] = pollRes; // Polling result
|
||||
synchronized (tuple) {
|
||||
tuple.complete = true; // Done
|
||||
tuple.returnedDetails = details; // Polling result
|
||||
|
||||
info.notify();
|
||||
tuple.notify();
|
||||
}
|
||||
}
|
||||
};
|
||||
t.setName("Fast Poll - "+address);
|
||||
t.start();
|
||||
tuple.pollingThread.setName("Parallel Poll - "+tuple.address+" - "+tuple.existingDetails.name);
|
||||
tuple.pollingThread.start();
|
||||
}
|
||||
|
||||
private String fastPollPc(final String localAddress, final String remoteAddress, final String manualAddress, final String ipv6Address) throws InterruptedException {
|
||||
final boolean[] remoteInfo = new boolean[2];
|
||||
final boolean[] localInfo = new boolean[2];
|
||||
final boolean[] manualInfo = new boolean[2];
|
||||
final boolean[] ipv6Info = new boolean[2];
|
||||
private ComputerDetails parallelPollPc(ComputerDetails details) throws InterruptedException {
|
||||
ParallelPollTuple localInfo = new ParallelPollTuple(details.localAddress, details);
|
||||
ParallelPollTuple manualInfo = new ParallelPollTuple(details.manualAddress, details);
|
||||
ParallelPollTuple remoteInfo = new ParallelPollTuple(details.remoteAddress, details);
|
||||
ParallelPollTuple ipv6Info = new ParallelPollTuple(details.ipv6Address, details);
|
||||
|
||||
startFastPollThread(localAddress, localInfo);
|
||||
startFastPollThread(remoteAddress, remoteInfo);
|
||||
startFastPollThread(manualAddress, manualInfo);
|
||||
startFastPollThread(ipv6Address, ipv6Info);
|
||||
// These must be started in order of precedence for the deduplication algorithm
|
||||
// to result in the correct behavior.
|
||||
HashSet<String> uniqueAddresses = new HashSet<>();
|
||||
startParallelPollThread(localInfo, uniqueAddresses);
|
||||
startParallelPollThread(manualInfo, uniqueAddresses);
|
||||
startParallelPollThread(remoteInfo, uniqueAddresses);
|
||||
startParallelPollThread(ipv6Info, uniqueAddresses);
|
||||
|
||||
// Check local first
|
||||
synchronized (localInfo) {
|
||||
while (!localInfo[0]) {
|
||||
localInfo.wait(500);
|
||||
try {
|
||||
// Check local first
|
||||
synchronized (localInfo) {
|
||||
while (!localInfo.complete) {
|
||||
localInfo.wait();
|
||||
}
|
||||
|
||||
if (localInfo.returnedDetails != null) {
|
||||
localInfo.returnedDetails.activeAddress = localInfo.address;
|
||||
return localInfo.returnedDetails;
|
||||
}
|
||||
}
|
||||
|
||||
if (localInfo[1]) {
|
||||
return localAddress;
|
||||
}
|
||||
}
|
||||
// Now manual
|
||||
synchronized (manualInfo) {
|
||||
while (!manualInfo.complete) {
|
||||
manualInfo.wait();
|
||||
}
|
||||
|
||||
// Now manual
|
||||
synchronized (manualInfo) {
|
||||
while (!manualInfo[0]) {
|
||||
manualInfo.wait(500);
|
||||
if (manualInfo.returnedDetails != null) {
|
||||
manualInfo.returnedDetails.activeAddress = manualInfo.address;
|
||||
return manualInfo.returnedDetails;
|
||||
}
|
||||
}
|
||||
|
||||
if (manualInfo[1]) {
|
||||
return manualAddress;
|
||||
}
|
||||
}
|
||||
// Now remote IPv4
|
||||
synchronized (remoteInfo) {
|
||||
while (!remoteInfo.complete) {
|
||||
remoteInfo.wait();
|
||||
}
|
||||
|
||||
// Now remote IPv4
|
||||
synchronized (remoteInfo) {
|
||||
while (!remoteInfo[0]) {
|
||||
remoteInfo.wait(500);
|
||||
if (remoteInfo.returnedDetails != null) {
|
||||
remoteInfo.returnedDetails.activeAddress = remoteInfo.address;
|
||||
return remoteInfo.returnedDetails;
|
||||
}
|
||||
}
|
||||
|
||||
if (remoteInfo[1]) {
|
||||
return remoteAddress;
|
||||
}
|
||||
}
|
||||
// Now global IPv6
|
||||
synchronized (ipv6Info) {
|
||||
while (!ipv6Info.complete) {
|
||||
ipv6Info.wait();
|
||||
}
|
||||
|
||||
// Now global IPv6
|
||||
synchronized (ipv6Info) {
|
||||
while (!ipv6Info[0]) {
|
||||
ipv6Info.wait(500);
|
||||
}
|
||||
|
||||
if (ipv6Info[1]) {
|
||||
return ipv6Address;
|
||||
if (ipv6Info.returnedDetails != null) {
|
||||
ipv6Info.returnedDetails.activeAddress = ipv6Info.address;
|
||||
return ipv6Info.returnedDetails;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Stop any further polling if we've found a working address or we've been
|
||||
// interrupted by an attempt to stop polling.
|
||||
localInfo.interrupt();
|
||||
manualInfo.interrupt();
|
||||
remoteInfo.interrupt();
|
||||
ipv6Info.interrupt();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean pollComputer(ComputerDetails details) throws InterruptedException {
|
||||
ComputerDetails polledDetails;
|
||||
|
||||
// Do a TCP-level connection to the HTTP server to see if it's listening.
|
||||
// Do not write this address to details.activeAddress because:
|
||||
// a) it's only a candidate and may be wrong (multiple PCs behind a single router)
|
||||
// b) if it's null, it will be unexpectedly nulling the activeAddress of a possibly online PC
|
||||
LimeLog.info("Starting fast poll for "+details.name+" ("+details.localAddress +", "+details.remoteAddress +", "+details.manualAddress+", "+details.ipv6Address+")");
|
||||
String candidateAddress = fastPollPc(details.localAddress, details.remoteAddress, details.manualAddress, details.ipv6Address);
|
||||
LimeLog.info("Fast poll for "+details.name+" returned candidate address: "+candidateAddress);
|
||||
|
||||
// If no connection could be established to either IP address, there's nothing we can do
|
||||
if (candidateAddress == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try using the active address from fast-poll
|
||||
polledDetails = tryPollIp(details, candidateAddress);
|
||||
if (polledDetails == null) {
|
||||
// If that failed, try all unique addresses except what we've
|
||||
// already tried
|
||||
HashSet<String> uniqueAddresses = new HashSet<>();
|
||||
uniqueAddresses.add(details.localAddress);
|
||||
uniqueAddresses.add(details.manualAddress);
|
||||
uniqueAddresses.add(details.remoteAddress);
|
||||
uniqueAddresses.add(details.ipv6Address);
|
||||
for (String addr : uniqueAddresses) {
|
||||
if (addr == null || addr.equals(candidateAddress)) {
|
||||
continue;
|
||||
}
|
||||
polledDetails = tryPollIp(details, addr);
|
||||
if (polledDetails != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Poll all addresses in parallel to speed up the process
|
||||
LimeLog.info("Starting parallel poll for "+details.name+" ("+details.localAddress +", "+details.remoteAddress +", "+details.manualAddress+", "+details.ipv6Address+")");
|
||||
ComputerDetails polledDetails = parallelPollPc(details);
|
||||
LimeLog.info("Parallel poll for "+details.name+" returned address: "+details.activeAddress);
|
||||
|
||||
if (polledDetails != null) {
|
||||
details.update(polledDetails);
|
||||
|
||||
@@ -128,6 +128,13 @@ public class CachedAppAssetLoader {
|
||||
try {
|
||||
Thread.sleep((int) (1000 + (Math.random() * 500)));
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
// InterruptedException clears the thread's interrupt status. Since we can't
|
||||
// handle that here, we will re-interrupt the thread to set the interrupt
|
||||
// status back to true.
|
||||
Thread.currentThread().interrupt();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ public class ConnectionContext {
|
||||
// This is the version quad from the appversion tag of /serverinfo
|
||||
public String serverAppVersion;
|
||||
public String serverGfeVersion;
|
||||
|
||||
// This is the sessionUrl0 tag from /resume and /launch
|
||||
public String rtspSessionUrl;
|
||||
|
||||
public int negotiatedWidth, negotiatedHeight;
|
||||
public boolean negotiatedHdr;
|
||||
|
||||
@@ -7,6 +7,8 @@ import java.nio.ByteBuffer;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import javax.crypto.KeyGenerator;
|
||||
@@ -33,12 +35,20 @@ public class NvConnection {
|
||||
private ConnectionContext context;
|
||||
private static Semaphore connectionAllowed = new Semaphore(1);
|
||||
private final boolean isMonkey;
|
||||
|
||||
public NvConnection(String host, String uniqueId, StreamConfiguration config, LimelightCryptoProvider cryptoProvider, X509Certificate serverCert)
|
||||
private final boolean batchMouseInput;
|
||||
|
||||
private static final int MOUSE_BATCH_PERIOD_MS = 5;
|
||||
private Timer mouseInputTimer;
|
||||
private final Object mouseInputLock = new Object();
|
||||
private short relMouseX, relMouseY, relMouseWidth, relMouseHeight;
|
||||
private short absMouseX, absMouseY, absMouseWidth, absMouseHeight;
|
||||
|
||||
public NvConnection(String host, String uniqueId, StreamConfiguration config, LimelightCryptoProvider cryptoProvider, X509Certificate serverCert, boolean batchMouseInput)
|
||||
{
|
||||
this.host = host;
|
||||
this.cryptoProvider = cryptoProvider;
|
||||
this.uniqueId = uniqueId;
|
||||
this.batchMouseInput = batchMouseInput;
|
||||
|
||||
this.context = new ConnectionContext();
|
||||
this.context.streamConfig = config;
|
||||
@@ -70,6 +80,11 @@ public class NvConnection {
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
// Stop sending additional input
|
||||
if (mouseInputTimer != null) {
|
||||
mouseInputTimer.cancel();
|
||||
}
|
||||
|
||||
// Interrupt any pending connection. This is thread-safe.
|
||||
MoonBridge.interruptConnection();
|
||||
|
||||
@@ -83,6 +98,24 @@ public class NvConnection {
|
||||
// Now a pending connection can be processed
|
||||
connectionAllowed.release();
|
||||
}
|
||||
|
||||
private void flushMousePosition() {
|
||||
synchronized (mouseInputLock) {
|
||||
if (relMouseX != 0 || relMouseY != 0) {
|
||||
if (relMouseWidth != 0 || relMouseHeight != 0) {
|
||||
MoonBridge.sendMouseMoveAsMousePosition(relMouseX, relMouseY, relMouseWidth, relMouseHeight);
|
||||
}
|
||||
else {
|
||||
MoonBridge.sendMouseMove(relMouseX, relMouseY);
|
||||
}
|
||||
relMouseX = relMouseY = relMouseWidth = relMouseHeight = 0;
|
||||
}
|
||||
if (absMouseX != 0 || absMouseY != 0 || absMouseWidth != 0 || absMouseHeight != 0) {
|
||||
MoonBridge.sendMousePosition(absMouseX, absMouseY, absMouseWidth, absMouseHeight);
|
||||
absMouseX = absMouseY = absMouseWidth = absMouseHeight = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean startApp() throws XmlPullParserException, IOException
|
||||
{
|
||||
@@ -122,7 +155,7 @@ public class NvConnection {
|
||||
}
|
||||
else if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
|
||||
!context.streamConfig.getHevcSupported()) {
|
||||
context.connListener.displayMessage("Your streaming device must support H.265 to stream at resolutions above 4K.");
|
||||
context.connListener.displayMessage("Your streaming device must support HEVC to stream at resolutions above 4K.");
|
||||
return false;
|
||||
}
|
||||
else if (context.streamConfig.getHeight() >= 2160 && !h.supports4K(serverInfo)) {
|
||||
@@ -275,7 +308,7 @@ public class NvConnection {
|
||||
synchronized (MoonBridge.class) {
|
||||
MoonBridge.setupBridge(videoDecoderRenderer, audioRenderer, connectionListener);
|
||||
int ret = MoonBridge.startConnection(context.serverAddress,
|
||||
context.serverAppVersion, context.serverGfeVersion,
|
||||
context.serverAppVersion, context.serverGfeVersion, context.rtspSessionUrl,
|
||||
context.negotiatedWidth, context.negotiatedHeight,
|
||||
context.streamConfig.getRefreshRate(), context.streamConfig.getBitrate(),
|
||||
context.streamConfig.getMaxPacketSize(),
|
||||
@@ -284,6 +317,7 @@ public class NvConnection {
|
||||
context.negotiatedHdr,
|
||||
context.streamConfig.getHevcBitratePercentageMultiplier(),
|
||||
context.streamConfig.getClientRefreshRateX100(),
|
||||
context.streamConfig.getEncryptionFlags(),
|
||||
context.riKey.getEncoded(), ib.array(),
|
||||
context.videoCapabilities);
|
||||
if (ret != 0) {
|
||||
@@ -291,6 +325,21 @@ public class NvConnection {
|
||||
// to stop the connection themselves. We need to release their
|
||||
// semaphore count for them.
|
||||
connectionAllowed.release();
|
||||
return;
|
||||
}
|
||||
|
||||
if (batchMouseInput) {
|
||||
// High polling rate mice can cause GeForce Experience's input queue to get backed up,
|
||||
// causing massive input latency. We counter this by limiting our mouse events to 200 Hz
|
||||
// which appears to avoid triggering the issue on all known configurations.
|
||||
mouseInputTimer = new Timer("MouseInput", true);
|
||||
mouseInputTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Flush the mouse position every 5 ms
|
||||
flushMousePosition();
|
||||
}
|
||||
}, MOUSE_BATCH_PERIOD_MS, MOUSE_BATCH_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,20 +349,65 @@ public class NvConnection {
|
||||
public void sendMouseMove(final short deltaX, final short deltaY)
|
||||
{
|
||||
if (!isMonkey) {
|
||||
MoonBridge.sendMouseMove(deltaX, deltaY);
|
||||
synchronized (mouseInputLock) {
|
||||
relMouseX += deltaX;
|
||||
relMouseY += deltaY;
|
||||
|
||||
// Reset these to ensure we don't send this as a position update
|
||||
relMouseWidth = 0;
|
||||
relMouseHeight = 0;
|
||||
}
|
||||
|
||||
if (!batchMouseInput) {
|
||||
flushMousePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMousePosition(short x, short y, short referenceWidth, short referenceHeight)
|
||||
{
|
||||
if (!isMonkey) {
|
||||
MoonBridge.sendMousePosition(x, y, referenceWidth, referenceHeight);
|
||||
synchronized (mouseInputLock) {
|
||||
absMouseX = x;
|
||||
absMouseY = y;
|
||||
absMouseWidth = referenceWidth;
|
||||
absMouseHeight = referenceHeight;
|
||||
}
|
||||
|
||||
if (!batchMouseInput) {
|
||||
flushMousePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void sendMouseMoveAsMousePosition(short deltaX, short deltaY, short referenceWidth, short referenceHeight)
|
||||
{
|
||||
if (!isMonkey) {
|
||||
synchronized (mouseInputLock) {
|
||||
// Only accumulate the delta if the reference size is the same
|
||||
if (relMouseWidth == referenceWidth && relMouseHeight == referenceHeight) {
|
||||
relMouseX += deltaX;
|
||||
relMouseY += deltaY;
|
||||
}
|
||||
else {
|
||||
relMouseX = deltaX;
|
||||
relMouseY = deltaY;
|
||||
}
|
||||
|
||||
relMouseWidth = referenceWidth;
|
||||
relMouseHeight = referenceHeight;
|
||||
}
|
||||
|
||||
if (!batchMouseInput) {
|
||||
flushMousePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMouseButtonDown(final byte mouseButton)
|
||||
{
|
||||
if (!isMonkey) {
|
||||
flushMousePosition();
|
||||
MoonBridge.sendMouseButton(MouseButtonPacket.PRESS_EVENT, mouseButton);
|
||||
}
|
||||
}
|
||||
@@ -321,6 +415,7 @@ public class NvConnection {
|
||||
public void sendMouseButtonUp(final byte mouseButton)
|
||||
{
|
||||
if (!isMonkey) {
|
||||
flushMousePosition();
|
||||
MoonBridge.sendMouseButton(MouseButtonPacket.RELEASE_EVENT, mouseButton);
|
||||
}
|
||||
}
|
||||
@@ -356,16 +451,24 @@ public class NvConnection {
|
||||
|
||||
public void sendMouseScroll(final byte scrollClicks) {
|
||||
if (!isMonkey) {
|
||||
flushMousePosition();
|
||||
MoonBridge.sendMouseScroll(scrollClicks);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMouseHighResScroll(final short scrollAmount) {
|
||||
if (!isMonkey) {
|
||||
flushMousePosition();
|
||||
MoonBridge.sendMouseHighResScroll(scrollAmount);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendUtf8Text(final String text) {
|
||||
if (!isMonkey) {
|
||||
MoonBridge.sendUtf8Text(text);
|
||||
}
|
||||
}
|
||||
|
||||
public static String findExternalAddressForMdns(String stunHostname, int stunPort) {
|
||||
return MoonBridge.findExternalAddressIP4(stunHostname, stunPort);
|
||||
}
|
||||
|
||||
@@ -13,4 +13,6 @@ public interface NvConnectionListener {
|
||||
void displayTransientMessage(String message);
|
||||
|
||||
void rumble(short controllerNumber, short lowFreqMotor, short highFreqMotor);
|
||||
|
||||
void setHdrMode(boolean enabled);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ public class StreamConfiguration {
|
||||
private int hevcBitratePercentageMultiplier;
|
||||
private boolean enableHdr;
|
||||
private int attachedGamepadMask;
|
||||
private int encryptionFlags;
|
||||
|
||||
public static class Builder {
|
||||
private StreamConfiguration config = new StreamConfiguration();
|
||||
@@ -110,7 +111,17 @@ public class StreamConfiguration {
|
||||
config.clientRefreshRateX100 = refreshRateX100;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public StreamConfiguration.Builder setAudioEncryption(boolean enable) {
|
||||
if (enable) {
|
||||
config.encryptionFlags |= MoonBridge.ENCFLG_AUDIO;
|
||||
}
|
||||
else {
|
||||
config.encryptionFlags &= ~MoonBridge.ENCFLG_AUDIO;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public StreamConfiguration.Builder setAudioConfiguration(MoonBridge.AudioConfiguration audioConfig) {
|
||||
config.audioConfiguration = audioConfig;
|
||||
return this;
|
||||
@@ -211,4 +222,8 @@ public class StreamConfiguration {
|
||||
public int getClientRefreshRateX100() {
|
||||
return clientRefreshRateX100;
|
||||
}
|
||||
|
||||
public int getEncryptionFlags() {
|
||||
return encryptionFlags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,11 @@ public abstract class VideoDecoderRenderer {
|
||||
// This is called once for each frame-start NALU. This means it will be called several times
|
||||
// for an IDR frame which contains several parameter sets and the I-frame data.
|
||||
public abstract int submitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
|
||||
int frameNumber, long receiveTimeMs, long enqueueTimeMs);
|
||||
int frameNumber, int frameType, long receiveTimeMs, long enqueueTimeMs);
|
||||
|
||||
public abstract void cleanup();
|
||||
|
||||
public abstract int getCapabilities();
|
||||
|
||||
public abstract void setHdrMode(boolean enabled);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class NvApp {
|
||||
public String toString() {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append("Name: ").append(appName).append("\n");
|
||||
str.append("HDR: ").append(hdrSupported ? "Yes" : "No").append("\n");
|
||||
str.append("HDR Supported: ").append(hdrSupported ? "Yes" : "Unknown").append("\n");
|
||||
str.append("ID: ").append(appId).append("\n");
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
@@ -9,10 +9,8 @@ import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.Proxy;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
@@ -53,6 +51,7 @@ import com.limelight.nvstream.ConnectionContext;
|
||||
import com.limelight.nvstream.http.PairingManager.PairState;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
@@ -71,8 +70,8 @@ public class NvHTTP {
|
||||
// Print URL and content to logcat on debug builds
|
||||
private static boolean verbose = BuildConfig.DEBUG;
|
||||
|
||||
public String baseUrlHttps;
|
||||
public String baseUrlHttp;
|
||||
private HttpUrl baseUrlHttps;
|
||||
private HttpUrl baseUrlHttp;
|
||||
|
||||
private OkHttpClient httpClient;
|
||||
private OkHttpClient httpClientWithReadTimeout;
|
||||
@@ -173,6 +172,7 @@ public class NvHTTP {
|
||||
.hostnameVerifier(hv)
|
||||
.readTimeout(0, TimeUnit.MILLISECONDS)
|
||||
.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||
.proxy(Proxy.NO_PROXY)
|
||||
.build();
|
||||
|
||||
httpClientWithReadTimeout = httpClient.newBuilder()
|
||||
@@ -190,22 +190,26 @@ public class NvHTTP {
|
||||
initializeHttpState(cryptoProvider);
|
||||
|
||||
try {
|
||||
// The URI constructor takes care of escaping IPv6 literals
|
||||
this.baseUrlHttps = new URI("https", null, address, HTTPS_PORT, null, null, null).toString();
|
||||
this.baseUrlHttp = new URI("http", null, address, HTTP_PORT, null, null, null).toString();
|
||||
} catch (URISyntaxException e) {
|
||||
// Encapsulate URISyntaxException into IOException for callers to handle more easily
|
||||
this.baseUrlHttp = new HttpUrl.Builder()
|
||||
.scheme("http")
|
||||
.host(address)
|
||||
.port(HTTP_PORT)
|
||||
.build();
|
||||
|
||||
this.baseUrlHttps = new HttpUrl.Builder()
|
||||
.scheme("https")
|
||||
.host(address)
|
||||
.port(HTTPS_PORT)
|
||||
.build();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Encapsulate IllegalArgumentException into IOException for callers to handle more easily
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
this.pm = new PairingManager(this, cryptoProvider);
|
||||
}
|
||||
|
||||
String buildUniqueIdUuidString() {
|
||||
return "uniqueid="+uniqueId+"&uuid="+UUID.randomUUID();
|
||||
}
|
||||
|
||||
static String getXmlString(Reader r, String tagname) throws XmlPullParserException, IOException {
|
||||
|
||||
static String getXmlString(Reader r, String tagname, boolean throwIfMissing) throws XmlPullParserException, IOException {
|
||||
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
XmlPullParser xpp = factory.newPullParser();
|
||||
@@ -234,11 +238,19 @@ public class NvHTTP {
|
||||
eventType = xpp.next();
|
||||
}
|
||||
|
||||
if (throwIfMissing) {
|
||||
// We throw an XmlPullParserException here for ease of handling in all the various callers.
|
||||
// We could also throw an IOException, but some callers expect those in cases where the
|
||||
// host may not be reachable. We want to distinguish unreachable hosts vs. hosts that
|
||||
// are returning garbage XML to us, so we use XmlPullParserException instead.
|
||||
throw new XmlPullParserException("Missing mandatory field in host response: "+tagname);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static String getXmlString(String str, String tagname) throws XmlPullParserException, IOException {
|
||||
return getXmlString(new StringReader(str), tagname);
|
||||
static String getXmlString(String str, String tagname, boolean throwIfMissing) throws XmlPullParserException, IOException {
|
||||
return getXmlString(new StringReader(str), tagname, throwIfMissing);
|
||||
}
|
||||
|
||||
private static void verifyResponseStatus(XmlPullParser xpp) throws GfeHttpResponseException {
|
||||
@@ -272,7 +284,7 @@ public class NvHTTP {
|
||||
if (serverCert != null) {
|
||||
try {
|
||||
try {
|
||||
resp = openHttpConnectionToString(baseUrlHttps + "/serverinfo?"+buildUniqueIdUuidString(), true);
|
||||
resp = openHttpConnectionToString(baseUrlHttps, "serverinfo", true);
|
||||
} catch (SSLHandshakeException e) {
|
||||
// Detect if we failed due to a server cert mismatch
|
||||
if (e.getCause() instanceof CertificateException) {
|
||||
@@ -292,7 +304,7 @@ public class NvHTTP {
|
||||
catch (GfeHttpResponseException e) {
|
||||
if (e.getErrorCode() == 401) {
|
||||
// Cert validation error - fall back to HTTP
|
||||
return openHttpConnectionToString(baseUrlHttp + "/serverinfo", true);
|
||||
return openHttpConnectionToString(baseUrlHttp, "serverinfo", true);
|
||||
}
|
||||
|
||||
// If it's not a cert validation error, throw it
|
||||
@@ -303,7 +315,7 @@ public class NvHTTP {
|
||||
}
|
||||
else {
|
||||
// No pinned cert, so use HTTP
|
||||
return openHttpConnectionToString(baseUrlHttp + "/serverinfo", true);
|
||||
return openHttpConnectionToString(baseUrlHttp , "serverinfo", true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,21 +323,21 @@ public class NvHTTP {
|
||||
ComputerDetails details = new ComputerDetails();
|
||||
String serverInfo = getServerInfo();
|
||||
|
||||
details.name = getXmlString(serverInfo, "hostname");
|
||||
details.name = getXmlString(serverInfo, "hostname", false);
|
||||
if (details.name == null || details.name.isEmpty()) {
|
||||
details.name = "UNKNOWN";
|
||||
}
|
||||
|
||||
details.uuid = getXmlString(serverInfo, "uniqueid");
|
||||
details.macAddress = getXmlString(serverInfo, "mac");
|
||||
details.localAddress = getXmlString(serverInfo, "LocalIP");
|
||||
// UUID is mandatory to determine which machine is responding
|
||||
details.uuid = getXmlString(serverInfo, "uniqueid", true);
|
||||
|
||||
// This may be null, but that's okay
|
||||
details.remoteAddress = getXmlString(serverInfo, "ExternalIP");
|
||||
details.macAddress = getXmlString(serverInfo, "mac", false);
|
||||
details.localAddress = getXmlString(serverInfo, "LocalIP", false);
|
||||
|
||||
// This is missing on on recent GFE versions
|
||||
details.remoteAddress = getXmlString(serverInfo, "ExternalIP", false);
|
||||
|
||||
// This has some extra logic to always report unpaired if the pinned cert isn't there
|
||||
details.pairState = getPairState(serverInfo);
|
||||
|
||||
details.runningGameId = getCurrentGame(serverInfo);
|
||||
|
||||
// We could reach it so it's online
|
||||
@@ -357,12 +369,26 @@ public class NvHTTP {
|
||||
}
|
||||
}
|
||||
|
||||
private HttpUrl getCompleteUrl(HttpUrl baseUrl, String path, String query) {
|
||||
return baseUrl.newBuilder()
|
||||
.addPathSegment(path)
|
||||
.query(query)
|
||||
.addQueryParameter("uniqueid", uniqueId)
|
||||
.addQueryParameter("uuid", UUID.randomUUID().toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
private ResponseBody openHttpConnection(HttpUrl baseUrl, String path, boolean enableReadTimeout) throws IOException {
|
||||
return openHttpConnection(baseUrl, path, null, enableReadTimeout);
|
||||
}
|
||||
|
||||
// Read timeout should be enabled for any HTTP query that requires no outside action
|
||||
// on the GFE server. Examples of queries that DO require outside action are launch, resume, and quit.
|
||||
// The initial pair query does require outside action (user entering a PIN) but subsequent pairing
|
||||
// queries do not.
|
||||
private ResponseBody openHttpConnection(String url, boolean enableReadTimeout) throws IOException {
|
||||
Request request = new Request.Builder().url(url).get().build();
|
||||
private ResponseBody openHttpConnection(HttpUrl baseUrl, String path, String query, boolean enableReadTimeout) throws IOException {
|
||||
HttpUrl completeUrl = getCompleteUrl(baseUrl, path, query);
|
||||
Request request = new Request.Builder().url(completeUrl).get().build();
|
||||
Response response;
|
||||
|
||||
if (enableReadTimeout) {
|
||||
@@ -384,30 +410,31 @@ public class NvHTTP {
|
||||
}
|
||||
|
||||
if (response.code() == 404) {
|
||||
throw new FileNotFoundException(url);
|
||||
throw new FileNotFoundException(completeUrl.toString());
|
||||
}
|
||||
else {
|
||||
throw new GfeHttpResponseException(response.code(), response.message());
|
||||
}
|
||||
}
|
||||
|
||||
String openHttpConnectionToString(String url, boolean enableReadTimeout) throws IOException {
|
||||
try {
|
||||
if (verbose) {
|
||||
LimeLog.info("Requesting URL: "+url);
|
||||
}
|
||||
|
||||
ResponseBody resp = openHttpConnection(url, enableReadTimeout);
|
||||
private String openHttpConnectionToString(HttpUrl baseUrl, String path, boolean enableReadTimeout) throws IOException {
|
||||
return openHttpConnectionToString(baseUrl, path, null, enableReadTimeout);
|
||||
}
|
||||
|
||||
private String openHttpConnectionToString(HttpUrl baseUrl, String path, String query, boolean enableReadTimeout) throws IOException {
|
||||
try {
|
||||
ResponseBody resp = openHttpConnection(baseUrl, path, query, enableReadTimeout);
|
||||
String respString = resp.string();
|
||||
resp.close();
|
||||
|
||||
if (verbose) {
|
||||
LimeLog.info(url+" -> "+respString);
|
||||
if (verbose && !path.equals("serverinfo")) {
|
||||
LimeLog.info(getCompleteUrl(baseUrl, path, query)+" -> "+respString);
|
||||
}
|
||||
|
||||
return respString;
|
||||
} catch (IOException e) {
|
||||
if (verbose) {
|
||||
if (verbose && !path.equals("serverinfo")) {
|
||||
LimeLog.warning(getCompleteUrl(baseUrl, path, query)+" -> "+e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -416,7 +443,8 @@ public class NvHTTP {
|
||||
}
|
||||
|
||||
public String getServerVersion(String serverInfo) throws XmlPullParserException, IOException {
|
||||
return getXmlString(serverInfo, "appversion");
|
||||
// appversion is present in all supported GFE versions
|
||||
return getXmlString(serverInfo, "appversion", true);
|
||||
}
|
||||
|
||||
public PairingManager.PairState getPairState() throws IOException, XmlPullParserException {
|
||||
@@ -424,15 +452,14 @@ public class NvHTTP {
|
||||
}
|
||||
|
||||
public PairingManager.PairState getPairState(String serverInfo) throws IOException, XmlPullParserException {
|
||||
if (!NvHTTP.getXmlString(serverInfo, "PairStatus").equals("1")) {
|
||||
return PairState.NOT_PAIRED;
|
||||
}
|
||||
|
||||
return PairState.PAIRED;
|
||||
// appversion is present in all supported GFE versions
|
||||
return NvHTTP.getXmlString(serverInfo, "PairStatus", true).equals("1") ?
|
||||
PairState.PAIRED : PairState.NOT_PAIRED;
|
||||
}
|
||||
|
||||
public long getMaxLumaPixelsH264(String serverInfo) throws XmlPullParserException, IOException {
|
||||
String str = getXmlString(serverInfo, "MaxLumaPixelsH264");
|
||||
// MaxLumaPixelsH264 wasn't present on old GFE versions
|
||||
String str = getXmlString(serverInfo, "MaxLumaPixelsH264", false);
|
||||
if (str != null) {
|
||||
return Long.parseLong(str);
|
||||
} else {
|
||||
@@ -441,7 +468,8 @@ public class NvHTTP {
|
||||
}
|
||||
|
||||
public long getMaxLumaPixelsHEVC(String serverInfo) throws XmlPullParserException, IOException {
|
||||
String str = getXmlString(serverInfo, "MaxLumaPixelsHEVC");
|
||||
// MaxLumaPixelsHEVC wasn't present on old GFE versions
|
||||
String str = getXmlString(serverInfo, "MaxLumaPixelsHEVC", false);
|
||||
if (str != null) {
|
||||
return Long.parseLong(str);
|
||||
} else {
|
||||
@@ -458,7 +486,8 @@ public class NvHTTP {
|
||||
// Bit 10: HEVC Main10 4:4:4
|
||||
// Bit 11: ???
|
||||
public long getServerCodecModeSupport(String serverInfo) throws XmlPullParserException, IOException {
|
||||
String str = getXmlString(serverInfo, "ServerCodecModeSupport");
|
||||
// ServerCodecModeSupport wasn't present on old GFE versions
|
||||
String str = getXmlString(serverInfo, "ServerCodecModeSupport", false);
|
||||
if (str != null) {
|
||||
return Long.parseLong(str);
|
||||
} else {
|
||||
@@ -467,16 +496,18 @@ public class NvHTTP {
|
||||
}
|
||||
|
||||
public String getGpuType(String serverInfo) throws XmlPullParserException, IOException {
|
||||
return getXmlString(serverInfo, "gputype");
|
||||
// ServerCodecModeSupport wasn't present on old GFE versions
|
||||
return getXmlString(serverInfo, "gputype", false);
|
||||
}
|
||||
|
||||
public String getGfeVersion(String serverInfo) throws XmlPullParserException, IOException {
|
||||
return getXmlString(serverInfo, "GfeVersion");
|
||||
// ServerCodecModeSupport wasn't present on old GFE versions
|
||||
return getXmlString(serverInfo, "GfeVersion", false);
|
||||
}
|
||||
|
||||
public boolean supports4K(String serverInfo) throws XmlPullParserException, IOException {
|
||||
// Only allow 4K on GFE 3.x
|
||||
String gfeVersionStr = getXmlString(serverInfo, "GfeVersion");
|
||||
// Only allow 4K on GFE 3.x. GfeVersion wasn't present on very old versions of GFE.
|
||||
String gfeVersionStr = getXmlString(serverInfo, "GfeVersion", false);
|
||||
if (gfeVersionStr == null || gfeVersionStr.startsWith("2.")) {
|
||||
return false;
|
||||
}
|
||||
@@ -488,10 +519,8 @@ public class NvHTTP {
|
||||
// GFE 2.8 started keeping currentgame set to the last game played. As a result, it no longer
|
||||
// has the semantics that its name would indicate. To contain the effects of this change as much
|
||||
// as possible, we'll force the current game to zero if the server isn't in a streaming session.
|
||||
String serverState = getXmlString(serverInfo, "state");
|
||||
if (serverState != null && serverState.endsWith("_SERVER_BUSY")) {
|
||||
String game = getXmlString(serverInfo, "currentgame");
|
||||
return Integer.parseInt(game);
|
||||
if (getXmlString(serverInfo, "state", true).endsWith("_SERVER_BUSY")) {
|
||||
return Integer.parseInt(getXmlString(serverInfo, "currentgame", true));
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
@@ -588,8 +617,8 @@ public class NvHTTP {
|
||||
return appList;
|
||||
}
|
||||
|
||||
public String getAppListRaw() throws MalformedURLException, IOException {
|
||||
return openHttpConnectionToString(baseUrlHttps + "/applist?"+buildUniqueIdUuidString(), true);
|
||||
public String getAppListRaw() throws IOException {
|
||||
return openHttpConnectionToString(baseUrlHttps, "applist", true);
|
||||
}
|
||||
|
||||
public LinkedList<NvApp> getAppList() throws GfeHttpResponseException, IOException, XmlPullParserException {
|
||||
@@ -598,20 +627,31 @@ public class NvHTTP {
|
||||
return getAppListByReader(new StringReader(getAppListRaw()));
|
||||
}
|
||||
else {
|
||||
ResponseBody resp = openHttpConnection(baseUrlHttps + "/applist?" + buildUniqueIdUuidString(), true);
|
||||
ResponseBody resp = openHttpConnection(baseUrlHttps, "applist", true);
|
||||
LinkedList<NvApp> appList = getAppListByReader(new InputStreamReader(resp.byteStream()));
|
||||
resp.close();
|
||||
return appList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String executePairingCommand(String additionalArguments, boolean enableReadTimeout) throws GfeHttpResponseException, IOException {
|
||||
return openHttpConnectionToString(baseUrlHttp, "pair",
|
||||
"devicename=roth&updateState=1&" + additionalArguments,
|
||||
enableReadTimeout);
|
||||
}
|
||||
|
||||
String executePairingChallenge() throws GfeHttpResponseException, IOException {
|
||||
return openHttpConnectionToString(baseUrlHttps, "pair",
|
||||
"devicename=roth&updateState=1&phrase=pairchallenge",
|
||||
true);
|
||||
}
|
||||
|
||||
public void unpair() throws IOException {
|
||||
openHttpConnectionToString(baseUrlHttp + "/unpair?"+buildUniqueIdUuidString(), true);
|
||||
openHttpConnectionToString(baseUrlHttp, "unpair", true);
|
||||
}
|
||||
|
||||
public InputStream getBoxArt(NvApp app) throws IOException {
|
||||
ResponseBody resp = openHttpConnection(baseUrlHttps + "/appasset?"+ buildUniqueIdUuidString() +
|
||||
"&appid=" + app.getAppId() + "&AssetType=2&AssetIdx=0", true);
|
||||
ResponseBody resp = openHttpConnection(baseUrlHttps, "appasset", "appid=" + app.getAppId() + "&AssetType=2&AssetIdx=0", true);
|
||||
return resp.byteStream();
|
||||
}
|
||||
|
||||
@@ -666,9 +706,8 @@ public class NvHTTP {
|
||||
enableSops = false;
|
||||
}
|
||||
|
||||
String xmlStr = openHttpConnectionToString(baseUrlHttps +
|
||||
"/launch?" + buildUniqueIdUuidString() +
|
||||
"&appid=" + appId +
|
||||
String xmlStr = openHttpConnectionToString(baseUrlHttps, "launch",
|
||||
"appid=" + appId +
|
||||
"&mode=" + context.negotiatedWidth + "x" + context.negotiatedHeight + "x" + fps +
|
||||
"&additionalStates=1&sops=" + (enableSops ? 1 : 0) +
|
||||
"&rikey="+bytesToHex(context.riKey.getEncoded()) +
|
||||
@@ -679,24 +718,35 @@ public class NvHTTP {
|
||||
(context.streamConfig.getAttachedGamepadMask() != 0 ? "&remoteControllersBitmap=" + context.streamConfig.getAttachedGamepadMask() : "") +
|
||||
(context.streamConfig.getAttachedGamepadMask() != 0 ? "&gcmap=" + context.streamConfig.getAttachedGamepadMask() : ""),
|
||||
false);
|
||||
String gameSession = getXmlString(xmlStr, "gamesession");
|
||||
return gameSession != null && !gameSession.equals("0");
|
||||
if (!getXmlString(xmlStr, "gamesession", true).equals("0")) {
|
||||
// sessionUrl0 will be missing for older GFE versions
|
||||
context.rtspSessionUrl = getXmlString(xmlStr, "sessionUrl0", false);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean resumeApp(ConnectionContext context) throws IOException, XmlPullParserException {
|
||||
String xmlStr = openHttpConnectionToString(baseUrlHttps + "/resume?" + buildUniqueIdUuidString() +
|
||||
"&rikey="+bytesToHex(context.riKey.getEncoded()) +
|
||||
String xmlStr = openHttpConnectionToString(baseUrlHttps, "resume",
|
||||
"rikey="+bytesToHex(context.riKey.getEncoded()) +
|
||||
"&rikeyid="+context.riKeyId +
|
||||
"&surroundAudioInfo=" + context.streamConfig.getAudioConfiguration().getSurroundAudioInfo(),
|
||||
false);
|
||||
String resume = getXmlString(xmlStr, "resume");
|
||||
return Integer.parseInt(resume) != 0;
|
||||
if (!getXmlString(xmlStr, "resume", true).equals("0")) {
|
||||
// sessionUrl0 will be missing for older GFE versions
|
||||
context.rtspSessionUrl = getXmlString(xmlStr, "sessionUrl0", false);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean quitApp() throws IOException, XmlPullParserException {
|
||||
String xmlStr = openHttpConnectionToString(baseUrlHttps + "/cancel?" + buildUniqueIdUuidString(), false);
|
||||
String cancel = getXmlString(xmlStr, "cancel");
|
||||
if (Integer.parseInt(cancel) == 0) {
|
||||
String xmlStr = openHttpConnectionToString(baseUrlHttps, "cancel", false);
|
||||
if (getXmlString(xmlStr, "cancel", true).equals("0")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.limelight.nvstream.http;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import org.bouncycastle.crypto.BlockCipher;
|
||||
import org.bouncycastle.crypto.engines.AESLightEngine;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@@ -21,7 +21,6 @@ public class PairingManager {
|
||||
|
||||
private PrivateKey pk;
|
||||
private X509Certificate cert;
|
||||
private SecretKey aesKey;
|
||||
private byte[] pemCertBytes;
|
||||
|
||||
private X509Certificate serverCert;
|
||||
@@ -68,7 +67,8 @@ public class PairingManager {
|
||||
|
||||
private X509Certificate extractPlainCert(String text) throws XmlPullParserException, IOException
|
||||
{
|
||||
String certText = NvHTTP.getXmlString(text, "plaincert");
|
||||
// Plaincert may be null if another client is already trying to pair
|
||||
String certText = NvHTTP.getXmlString(text, "plaincert", false);
|
||||
if (certText != null) {
|
||||
byte[] certBytes = hexToBytes(certText);
|
||||
|
||||
@@ -124,43 +124,35 @@ public class PairingManager {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] decryptAes(byte[] encryptedData, SecretKey secretKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
|
||||
|
||||
int blockRoundedSize = ((encryptedData.length + 15) / 16) * 16;
|
||||
byte[] blockRoundedEncrypted = Arrays.copyOf(encryptedData, blockRoundedSize);
|
||||
byte[] fullDecrypted = new byte[blockRoundedSize];
|
||||
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||||
cipher.doFinal(blockRoundedEncrypted, 0,
|
||||
blockRoundedSize, fullDecrypted);
|
||||
return fullDecrypted;
|
||||
} catch (GeneralSecurityException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
private static byte[] performBlockCipher(BlockCipher blockCipher, byte[] input) {
|
||||
int blockSize = blockCipher.getBlockSize();
|
||||
int blockRoundedSize = (input.length + (blockSize - 1)) & ~(blockSize - 1);
|
||||
|
||||
byte[] blockRoundedInputData = Arrays.copyOf(input, blockRoundedSize);
|
||||
byte[] blockRoundedOutputData = new byte[blockRoundedSize];
|
||||
|
||||
for (int offset = 0; offset < blockRoundedSize; offset += blockSize) {
|
||||
blockCipher.processBlock(blockRoundedInputData, offset, blockRoundedOutputData, offset);
|
||||
}
|
||||
|
||||
return blockRoundedOutputData;
|
||||
}
|
||||
|
||||
private static byte[] encryptAes(byte[] data, SecretKey secretKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
|
||||
|
||||
int blockRoundedSize = ((data.length + 15) / 16) * 16;
|
||||
byte[] blockRoundedData = Arrays.copyOf(data, blockRoundedSize);
|
||||
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
return cipher.doFinal(blockRoundedData);
|
||||
} catch (GeneralSecurityException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
private static byte[] decryptAes(byte[] encryptedData, byte[] aesKey) {
|
||||
BlockCipher aesEngine = new AESLightEngine();
|
||||
aesEngine.init(false, new KeyParameter(aesKey));
|
||||
return performBlockCipher(aesEngine, encryptedData);
|
||||
}
|
||||
|
||||
private static SecretKey generateAesKey(PairingHashAlgorithm hashAlgo, byte[] keyData) {
|
||||
byte[] aesTruncated = Arrays.copyOf(hashAlgo.hashData(keyData), 16);
|
||||
return new SecretKeySpec(aesTruncated, "AES");
|
||||
private static byte[] encryptAes(byte[] plaintextData, byte[] aesKey) {
|
||||
BlockCipher aesEngine = new AESLightEngine();
|
||||
aesEngine.init(true, new KeyParameter(aesKey));
|
||||
return performBlockCipher(aesEngine, plaintextData);
|
||||
}
|
||||
|
||||
private static byte[] generateAesKey(PairingHashAlgorithm hashAlgo, byte[] keyData) {
|
||||
return Arrays.copyOf(hashAlgo.hashData(keyData), 16);
|
||||
}
|
||||
|
||||
private static byte[] concatBytes(byte[] a, byte[] b) {
|
||||
@@ -199,16 +191,14 @@ public class PairingManager {
|
||||
byte[] salt = generateRandomBytes(16);
|
||||
|
||||
// Combine the salt and pin, then create an AES key from them
|
||||
byte[] saltAndPin = saltPin(salt, pin);
|
||||
aesKey = generateAesKey(hashAlgo, saltAndPin);
|
||||
byte[] aesKey = generateAesKey(hashAlgo, saltPin(salt, pin));
|
||||
|
||||
// Send the salt and get the server cert. This doesn't have a read timeout
|
||||
// because the user must enter the PIN before the server responds
|
||||
String getCert = http.openHttpConnectionToString(http.baseUrlHttp +
|
||||
"/pair?"+http.buildUniqueIdUuidString()+"&devicename=roth&updateState=1&phrase=getservercert&salt="+
|
||||
String getCert = http.executePairingCommand("phrase=getservercert&salt="+
|
||||
bytesToHex(salt)+"&clientcert="+bytesToHex(pemCertBytes),
|
||||
false);
|
||||
if (!NvHTTP.getXmlString(getCert, "paired").equals("1")) {
|
||||
if (!NvHTTP.getXmlString(getCert, "paired", true).equals("1")) {
|
||||
return PairState.FAILED;
|
||||
}
|
||||
|
||||
@@ -217,7 +207,7 @@ public class PairingManager {
|
||||
if (serverCert == null) {
|
||||
// Attempting to pair while another device is pairing will cause GFE
|
||||
// to give an empty cert in the response.
|
||||
http.openHttpConnectionToString(http.baseUrlHttp + "/unpair?"+http.buildUniqueIdUuidString(), true);
|
||||
http.unpair();
|
||||
return PairState.ALREADY_IN_PROGRESS;
|
||||
}
|
||||
|
||||
@@ -229,16 +219,14 @@ public class PairingManager {
|
||||
byte[] encryptedChallenge = encryptAes(randomChallenge, aesKey);
|
||||
|
||||
// Send the encrypted challenge to the server
|
||||
String challengeResp = http.openHttpConnectionToString(http.baseUrlHttp +
|
||||
"/pair?"+http.buildUniqueIdUuidString()+"&devicename=roth&updateState=1&clientchallenge="+bytesToHex(encryptedChallenge),
|
||||
true);
|
||||
if (!NvHTTP.getXmlString(challengeResp, "paired").equals("1")) {
|
||||
http.openHttpConnectionToString(http.baseUrlHttp + "/unpair?"+http.buildUniqueIdUuidString(), true);
|
||||
String challengeResp = http.executePairingCommand("clientchallenge="+bytesToHex(encryptedChallenge), true);
|
||||
if (!NvHTTP.getXmlString(challengeResp, "paired", true).equals("1")) {
|
||||
http.unpair();
|
||||
return PairState.FAILED;
|
||||
}
|
||||
|
||||
// Decode the server's response and subsequent challenge
|
||||
byte[] encServerChallengeResponse = hexToBytes(NvHTTP.getXmlString(challengeResp, "challengeresponse"));
|
||||
byte[] encServerChallengeResponse = hexToBytes(NvHTTP.getXmlString(challengeResp, "challengeresponse", true));
|
||||
byte[] decServerChallengeResponse = decryptAes(encServerChallengeResponse, aesKey);
|
||||
|
||||
byte[] serverResponse = Arrays.copyOfRange(decServerChallengeResponse, 0, hashAlgo.getHashLength());
|
||||
@@ -248,23 +236,21 @@ public class PairingManager {
|
||||
byte[] clientSecret = generateRandomBytes(16);
|
||||
byte[] challengeRespHash = hashAlgo.hashData(concatBytes(concatBytes(serverChallenge, cert.getSignature()), clientSecret));
|
||||
byte[] challengeRespEncrypted = encryptAes(challengeRespHash, aesKey);
|
||||
String secretResp = http.openHttpConnectionToString(http.baseUrlHttp +
|
||||
"/pair?"+http.buildUniqueIdUuidString()+"&devicename=roth&updateState=1&serverchallengeresp="+bytesToHex(challengeRespEncrypted),
|
||||
true);
|
||||
if (!NvHTTP.getXmlString(secretResp, "paired").equals("1")) {
|
||||
http.openHttpConnectionToString(http.baseUrlHttp + "/unpair?"+http.buildUniqueIdUuidString(), true);
|
||||
String secretResp = http.executePairingCommand("serverchallengeresp="+bytesToHex(challengeRespEncrypted), true);
|
||||
if (!NvHTTP.getXmlString(secretResp, "paired", true).equals("1")) {
|
||||
http.unpair();
|
||||
return PairState.FAILED;
|
||||
}
|
||||
|
||||
// Get the server's signed secret
|
||||
byte[] serverSecretResp = hexToBytes(NvHTTP.getXmlString(secretResp, "pairingsecret"));
|
||||
byte[] serverSecretResp = hexToBytes(NvHTTP.getXmlString(secretResp, "pairingsecret", true));
|
||||
byte[] serverSecret = Arrays.copyOfRange(serverSecretResp, 0, 16);
|
||||
byte[] serverSignature = Arrays.copyOfRange(serverSecretResp, 16, 272);
|
||||
|
||||
// Ensure the authenticity of the data
|
||||
if (!verifySignature(serverSecret, serverSignature, serverCert)) {
|
||||
// Cancel the pairing process
|
||||
http.openHttpConnectionToString(http.baseUrlHttp + "/unpair?"+http.buildUniqueIdUuidString(), true);
|
||||
http.unpair();
|
||||
|
||||
// Looks like a MITM
|
||||
return PairState.FAILED;
|
||||
@@ -274,7 +260,7 @@ public class PairingManager {
|
||||
byte[] serverChallengeRespHash = hashAlgo.hashData(concatBytes(concatBytes(randomChallenge, serverCert.getSignature()), serverSecret));
|
||||
if (!Arrays.equals(serverChallengeRespHash, serverResponse)) {
|
||||
// Cancel the pairing process
|
||||
http.openHttpConnectionToString(http.baseUrlHttp + "/unpair?"+http.buildUniqueIdUuidString(), true);
|
||||
http.unpair();
|
||||
|
||||
// Probably got the wrong PIN
|
||||
return PairState.PIN_WRONG;
|
||||
@@ -282,19 +268,16 @@ public class PairingManager {
|
||||
|
||||
// Send the server our signed secret
|
||||
byte[] clientPairingSecret = concatBytes(clientSecret, signData(clientSecret, pk));
|
||||
String clientSecretResp = http.openHttpConnectionToString(http.baseUrlHttp +
|
||||
"/pair?"+http.buildUniqueIdUuidString()+"&devicename=roth&updateState=1&clientpairingsecret="+bytesToHex(clientPairingSecret),
|
||||
true);
|
||||
if (!NvHTTP.getXmlString(clientSecretResp, "paired").equals("1")) {
|
||||
http.openHttpConnectionToString(http.baseUrlHttp + "/unpair?"+http.buildUniqueIdUuidString(), true);
|
||||
String clientSecretResp = http.executePairingCommand("clientpairingsecret="+bytesToHex(clientPairingSecret), true);
|
||||
if (!NvHTTP.getXmlString(clientSecretResp, "paired", true).equals("1")) {
|
||||
http.unpair();
|
||||
return PairState.FAILED;
|
||||
}
|
||||
|
||||
// Do the initial challenge (seems neccessary for us to show as paired)
|
||||
String pairChallenge = http.openHttpConnectionToString(http.baseUrlHttps +
|
||||
"/pair?"+http.buildUniqueIdUuidString()+"&devicename=roth&updateState=1&phrase=pairchallenge", true);
|
||||
if (!NvHTTP.getXmlString(pairChallenge, "paired").equals("1")) {
|
||||
http.openHttpConnectionToString(http.baseUrlHttp + "/unpair?"+http.buildUniqueIdUuidString(), true);
|
||||
// Do the initial challenge (seems necessary for us to show as paired)
|
||||
String pairChallenge = http.executePairingChallenge();
|
||||
if (!NvHTTP.getXmlString(pairChallenge, "paired", true).equals("1")) {
|
||||
http.unpair();
|
||||
return PairState.FAILED;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,18 @@ public class MoonBridge {
|
||||
public static final int VIDEO_FORMAT_MASK_H264 = 0x00FF;
|
||||
public static final int VIDEO_FORMAT_MASK_H265 = 0xFF00;
|
||||
|
||||
public static final int ENCFLG_NONE = 0;
|
||||
public static final int ENCFLG_AUDIO = 1;
|
||||
public static final int ENCFLG_ALL = 0xFFFFFFFF;
|
||||
|
||||
public static final int BUFFER_TYPE_PICDATA = 0;
|
||||
public static final int BUFFER_TYPE_SPS = 1;
|
||||
public static final int BUFFER_TYPE_PPS = 2;
|
||||
public static final int BUFFER_TYPE_VPS = 3;
|
||||
|
||||
public static final int FRAME_TYPE_PFRAME = 0;
|
||||
public static final int FRAME_TYPE_IDR = 1;
|
||||
|
||||
public static final int CAPABILITY_DIRECT_SUBMIT = 1;
|
||||
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC = 2;
|
||||
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC = 4;
|
||||
@@ -37,6 +44,7 @@ public class MoonBridge {
|
||||
public static final int ML_ERROR_NO_VIDEO_TRAFFIC = -100;
|
||||
public static final int ML_ERROR_NO_VIDEO_FRAME = -101;
|
||||
public static final int ML_ERROR_UNEXPECTED_EARLY_TERMINATION = -102;
|
||||
public static final int ML_ERROR_PROTECTED_CONTENT = -103;
|
||||
|
||||
public static final int ML_PORT_INDEX_TCP_47984 = 0;
|
||||
public static final int ML_PORT_INDEX_TCP_47989 = 1;
|
||||
@@ -148,12 +156,12 @@ public class MoonBridge {
|
||||
}
|
||||
}
|
||||
|
||||
public static int bridgeDrSubmitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength,
|
||||
int decodeUnitType, int frameNumber,
|
||||
public static int bridgeDrSubmitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
|
||||
int frameNumber, int frameType,
|
||||
long receiveTimeMs, long enqueueTimeMs) {
|
||||
if (videoRenderer != null) {
|
||||
return videoRenderer.submitDecodeUnit(decodeUnitData, decodeUnitLength,
|
||||
decodeUnitType, frameNumber, receiveTimeMs, enqueueTimeMs);
|
||||
decodeUnitType, frameNumber, frameType, receiveTimeMs, enqueueTimeMs);
|
||||
}
|
||||
else {
|
||||
return DR_OK;
|
||||
@@ -235,6 +243,12 @@ public class MoonBridge {
|
||||
}
|
||||
}
|
||||
|
||||
public static void bridgeClSetHdrMode(boolean enabled) {
|
||||
if (connectionListener != null) {
|
||||
connectionListener.setHdrMode(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setupBridge(VideoDecoderRenderer videoRenderer, AudioRenderer audioRenderer, NvConnectionListener connectionListener) {
|
||||
MoonBridge.videoRenderer = videoRenderer;
|
||||
MoonBridge.audioRenderer = audioRenderer;
|
||||
@@ -248,12 +262,14 @@ public class MoonBridge {
|
||||
}
|
||||
|
||||
public static native int startConnection(String address, String appVersion, String gfeVersion,
|
||||
String rtspSessionUrl,
|
||||
int width, int height, int fps,
|
||||
int bitrate, int packetSize, int streamingRemotely,
|
||||
int audioConfiguration, boolean supportsHevc,
|
||||
boolean enableHdr,
|
||||
int hevcBitratePercentageMultiplier,
|
||||
int clientRefreshRateX100,
|
||||
int encryptionFlags,
|
||||
byte[] riAesKey, byte[] riAesIv,
|
||||
int videoCapabilities);
|
||||
|
||||
@@ -265,6 +281,8 @@ public class MoonBridge {
|
||||
|
||||
public static native void sendMousePosition(short x, short y, short referenceWidth, short referenceHeight);
|
||||
|
||||
public static native void sendMouseMoveAsMousePosition(short deltaX, short deltaY, short referenceWidth, short referenceHeight);
|
||||
|
||||
public static native void sendMouseButton(byte buttonEvent, byte mouseButton);
|
||||
|
||||
public static native void sendMultiControllerInput(short controllerNumber,
|
||||
@@ -284,6 +302,8 @@ public class MoonBridge {
|
||||
|
||||
public static native void sendMouseHighResScroll(short scrollAmount);
|
||||
|
||||
public static native void sendUtf8Text(String text);
|
||||
|
||||
public static native String getStageName(int stage);
|
||||
|
||||
public static native String findExternalAddressIP4(String stunHostName, int stunPort);
|
||||
@@ -300,5 +320,8 @@ public class MoonBridge {
|
||||
|
||||
public static native String stringifyPortFlags(int portFlags, String separator);
|
||||
|
||||
// The RTT is in the top 32 bits, and the RTT variance is in the bottom 32 bits
|
||||
public static native long getEstimatedRttInfo();
|
||||
|
||||
public static native void init();
|
||||
}
|
||||
|
||||
@@ -88,15 +88,15 @@ public class AddComputerManually extends Activity {
|
||||
|
||||
// Couldn't find a matching interface
|
||||
return true;
|
||||
} catch (SocketException e) {
|
||||
} catch (Exception e) {
|
||||
// Catch all exceptions because some broken Android devices
|
||||
// will throw an NPE from inside getNetworkInterfaces().
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (UnknownHostException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void doAddPc(String host) {
|
||||
private void doAddPc(String host) throws InterruptedException {
|
||||
boolean wrongSiteLocal = false;
|
||||
boolean success;
|
||||
int portTestResult;
|
||||
@@ -108,12 +108,18 @@ public class AddComputerManually extends Activity {
|
||||
ComputerDetails details = new ComputerDetails();
|
||||
details.manualAddress = host;
|
||||
success = managerBinder.addComputerBlocking(details);
|
||||
} catch (InterruptedException e) {
|
||||
// Propagate the InterruptedException to the caller for proper handling
|
||||
dialog.dismiss();
|
||||
throw e;
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This can be thrown from OkHttp if the host fails to canonicalize to a valid name.
|
||||
// https://github.com/square/okhttp/blob/okhttp_27/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java#L705
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
|
||||
// Keep the SpinnerDialog open while testing connectivity
|
||||
if (!success){
|
||||
wrongSiteLocal = isWrongSubnetSiteLocalAddress(host);
|
||||
}
|
||||
@@ -162,15 +168,12 @@ public class AddComputerManually extends Activity {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!isInterrupted()) {
|
||||
String computer;
|
||||
|
||||
try {
|
||||
computer = computersToAdd.take();
|
||||
String computer = computersToAdd.take();
|
||||
doAddPc(computer);
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
doAddPc(computer);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -184,7 +187,14 @@ public class AddComputerManually extends Activity {
|
||||
|
||||
try {
|
||||
addThread.join();
|
||||
} catch (InterruptedException ignored) {}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
// InterruptedException clears the thread's interrupt status. Since we can't
|
||||
// handle that here, we will re-interrupt the thread to set the interrupt
|
||||
// status back to true.
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
addThread = null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.limelight.preferences;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.preference.ListPreference;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class LanguagePreference extends ListPreference {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public LanguagePreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LanguagePreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
try {
|
||||
// Launch the Android native app locale settings page
|
||||
Intent intent = new Intent(Settings.ACTION_APP_LOCALE_SETTINGS);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
intent.setData(Uri.parse("package:" + getContext().getPackageName()));
|
||||
getContext().startActivity(intent, null);
|
||||
return;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
// App locale settings should be present on all Android 13 devices,
|
||||
// but if not, we'll launch the old language chooser.
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have native app locale settings, launch the normal dialog
|
||||
super.onClick();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.Display;
|
||||
|
||||
import com.limelight.nvstream.jni.MoonBridge;
|
||||
|
||||
@@ -30,7 +31,7 @@ public class PreferenceConfiguration {
|
||||
private static final String VIDEO_FORMAT_PREF_STRING = "video_format";
|
||||
private static final String ONSCREEN_CONTROLLER_PREF_STRING = "checkbox_show_onscreen_controls";
|
||||
private static final String ONLY_L3_R3_PREF_STRING = "checkbox_only_show_L3R3";
|
||||
private static final String DISABLE_FRAME_DROP_PREF_STRING = "checkbox_disable_frame_drop";
|
||||
private static final String LEGACY_DISABLE_FRAME_DROP_PREF_STRING = "checkbox_disable_frame_drop";
|
||||
private static final String ENABLE_HDR_PREF_STRING = "checkbox_enable_hdr";
|
||||
private static final String ENABLE_PIP_PREF_STRING = "checkbox_enable_pip";
|
||||
private static final String ENABLE_PERF_OVERLAY_STRING = "checkbox_enable_perf_overlay";
|
||||
@@ -43,6 +44,10 @@ public class PreferenceConfiguration {
|
||||
private static final String FLIP_FACE_BUTTONS_PREF_STRING = "checkbox_flip_face_buttons";
|
||||
private static final String TOUCHSCREEN_TRACKPAD_PREF_STRING = "checkbox_touchscreen_trackpad";
|
||||
private static final String LATENCY_TOAST_PREF_STRING = "checkbox_enable_post_stream_toast";
|
||||
private static final String FRAME_PACING_PREF_STRING = "frame_pacing";
|
||||
private static final String ABSOLUTE_MOUSE_MODE_PREF_STRING = "checkbox_absolute_mouse_mode";
|
||||
private static final String ENABLE_AUDIO_FX_PREF_STRING = "checkbox_enable_audiofx";
|
||||
private static final String REDUCE_REFRESH_RATE_PREF_STRING = "checkbox_reduce_refresh_rate";
|
||||
|
||||
static final String DEFAULT_RESOLUTION = "1280x720";
|
||||
static final String DEFAULT_FPS = "60";
|
||||
@@ -50,7 +55,7 @@ public class PreferenceConfiguration {
|
||||
private static final boolean DEFAULT_SOPS = true;
|
||||
private static final boolean DEFAULT_DISABLE_TOASTS = false;
|
||||
private static final boolean DEFAULT_HOST_AUDIO = false;
|
||||
private static final int DEFAULT_DEADZONE = 15;
|
||||
private static final int DEFAULT_DEADZONE = 7;
|
||||
private static final int DEFAULT_OPACITY = 90;
|
||||
public static final String DEFAULT_LANGUAGE = "default";
|
||||
private static final boolean DEFAULT_MULTI_CONTROLLER = true;
|
||||
@@ -58,7 +63,6 @@ public class PreferenceConfiguration {
|
||||
private static final String DEFAULT_VIDEO_FORMAT = "auto";
|
||||
private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false;
|
||||
private static final boolean ONLY_L3_R3_DEFAULT = false;
|
||||
private static final boolean DEFAULT_DISABLE_FRAME_DROP = false;
|
||||
private static final boolean DEFAULT_ENABLE_HDR = false;
|
||||
private static final boolean DEFAULT_ENABLE_PIP = false;
|
||||
private static final boolean DEFAULT_ENABLE_PERF_OVERLAY = false;
|
||||
@@ -72,11 +76,20 @@ public class PreferenceConfiguration {
|
||||
private static final boolean DEFAULT_TOUCHSCREEN_TRACKPAD = true;
|
||||
private static final String DEFAULT_AUDIO_CONFIG = "2"; // Stereo
|
||||
private static final boolean DEFAULT_LATENCY_TOAST = false;
|
||||
private static final String DEFAULT_FRAME_PACING = "latency";
|
||||
private static final boolean DEFAULT_ABSOLUTE_MOUSE_MODE = false;
|
||||
private static final boolean DEFAULT_ENABLE_AUDIO_FX = false;
|
||||
private static final boolean DEFAULT_REDUCE_REFRESH_RATE = false;
|
||||
|
||||
public static final int FORCE_H265_ON = -1;
|
||||
public static final int AUTOSELECT_H265 = 0;
|
||||
public static final int FORCE_H265_OFF = 1;
|
||||
|
||||
public static final int FRAME_PACING_MIN_LATENCY = 0;
|
||||
public static final int FRAME_PACING_BALANCED = 1;
|
||||
public static final int FRAME_PACING_CAP_FPS = 2;
|
||||
public static final int FRAME_PACING_MAX_SMOOTHNESS = 3;
|
||||
|
||||
public static final String RES_360P = "640x360";
|
||||
public static final String RES_480P = "854x480";
|
||||
public static final String RES_720P = "1280x720";
|
||||
@@ -95,7 +108,6 @@ public class PreferenceConfiguration {
|
||||
public boolean smallIconMode, multiController, usbDriver, flipFaceButtons;
|
||||
public boolean onscreenController;
|
||||
public boolean onlyL3R3;
|
||||
public boolean disableFrameDrop;
|
||||
public boolean enableHdr;
|
||||
public boolean enablePip;
|
||||
public boolean enablePerfOverlay;
|
||||
@@ -108,6 +120,10 @@ public class PreferenceConfiguration {
|
||||
public boolean vibrateFallbackToDevice;
|
||||
public boolean touchscreenTrackpad;
|
||||
public MoonBridge.AudioConfiguration audioConfiguration;
|
||||
public int framePacing;
|
||||
public boolean absoluteMouseMode;
|
||||
public boolean enableAudioFx;
|
||||
public boolean reduceRefreshRate;
|
||||
|
||||
public static boolean isNativeResolution(int width, int height) {
|
||||
// It's not a native resolution if it matches an existing resolution option
|
||||
@@ -133,6 +149,31 @@ public class PreferenceConfiguration {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we have a screen that has semi-square dimensions, we may want to change our behavior
|
||||
// to allow any orientation and vertical+horizontal resolutions.
|
||||
public static boolean isSquarishScreen(int width, int height) {
|
||||
float longDim = Math.max(width, height);
|
||||
float shortDim = Math.min(width, height);
|
||||
|
||||
// We just put the arbitrary cutoff for a square-ish screen at 1.3
|
||||
return longDim / shortDim < 1.3f;
|
||||
}
|
||||
|
||||
public static boolean isSquarishScreen(Display display) {
|
||||
int width, height;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
width = display.getMode().getPhysicalWidth();
|
||||
height = display.getMode().getPhysicalHeight();
|
||||
}
|
||||
else {
|
||||
width = display.getWidth();
|
||||
height = display.getHeight();
|
||||
}
|
||||
|
||||
return isSquarishScreen(width, height);
|
||||
}
|
||||
|
||||
private static String convertFromLegacyResolutionString(String resString) {
|
||||
if (resString.equalsIgnoreCase("360p")) {
|
||||
return RES_360P;
|
||||
@@ -264,6 +305,37 @@ public class PreferenceConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private static int getFramePacingValue(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
// Migrate legacy never drop frames option to the new location
|
||||
if (prefs.contains(LEGACY_DISABLE_FRAME_DROP_PREF_STRING)) {
|
||||
boolean legacyNeverDropFrames = prefs.getBoolean(LEGACY_DISABLE_FRAME_DROP_PREF_STRING, false);
|
||||
prefs.edit()
|
||||
.remove(LEGACY_DISABLE_FRAME_DROP_PREF_STRING)
|
||||
.putString(FRAME_PACING_PREF_STRING, legacyNeverDropFrames ? "balanced" : "latency")
|
||||
.apply();
|
||||
}
|
||||
|
||||
String str = prefs.getString(FRAME_PACING_PREF_STRING, DEFAULT_FRAME_PACING);
|
||||
if (str.equals("latency")) {
|
||||
return FRAME_PACING_MIN_LATENCY;
|
||||
}
|
||||
else if (str.equals("balanced")) {
|
||||
return FRAME_PACING_BALANCED;
|
||||
}
|
||||
else if (str.equals("cap-fps")) {
|
||||
return FRAME_PACING_CAP_FPS;
|
||||
}
|
||||
else if (str.equals("smoothness")) {
|
||||
return FRAME_PACING_MAX_SMOOTHNESS;
|
||||
}
|
||||
else {
|
||||
// Should never get here
|
||||
return FRAME_PACING_MIN_LATENCY;
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetStreamingSettings(Context context) {
|
||||
// We consider resolution, FPS, bitrate, HDR, and video format as "streaming settings" here
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
@@ -279,6 +351,19 @@ public class PreferenceConfiguration {
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void completeLanguagePreferenceMigration(Context context) {
|
||||
// Put our language option back to default which tells us that we've already migrated it
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
prefs.edit().putString(LANGUAGE_PREF_STRING, DEFAULT_LANGUAGE).apply();
|
||||
}
|
||||
|
||||
public static boolean isShieldAtvFirmwareWithBrokenHdr() {
|
||||
// This particular Shield TV firmware crashes when using HDR
|
||||
// https://www.nvidia.com/en-us/geforce/forums/notifications/comment/155192/
|
||||
return Build.MANUFACTURER.equalsIgnoreCase("NVIDIA") &&
|
||||
Build.FINGERPRINT.contains("PPR1.180610.011/4079208_2235.1395");
|
||||
}
|
||||
|
||||
public static PreferenceConfiguration readPreferences(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
PreferenceConfiguration config = new PreferenceConfiguration();
|
||||
@@ -387,6 +472,7 @@ public class PreferenceConfiguration {
|
||||
}
|
||||
|
||||
config.videoFormat = getVideoFormatValue(context);
|
||||
config.framePacing = getFramePacingValue(context);
|
||||
|
||||
config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE);
|
||||
|
||||
@@ -404,8 +490,7 @@ public class PreferenceConfiguration {
|
||||
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
|
||||
config.onscreenController = prefs.getBoolean(ONSCREEN_CONTROLLER_PREF_STRING, ONSCREEN_CONTROLLER_DEFAULT);
|
||||
config.onlyL3R3 = prefs.getBoolean(ONLY_L3_R3_PREF_STRING, ONLY_L3_R3_DEFAULT);
|
||||
config.disableFrameDrop = prefs.getBoolean(DISABLE_FRAME_DROP_PREF_STRING, DEFAULT_DISABLE_FRAME_DROP);
|
||||
config.enableHdr = prefs.getBoolean(ENABLE_HDR_PREF_STRING, DEFAULT_ENABLE_HDR);
|
||||
config.enableHdr = prefs.getBoolean(ENABLE_HDR_PREF_STRING, DEFAULT_ENABLE_HDR) && !isShieldAtvFirmwareWithBrokenHdr();
|
||||
config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
|
||||
config.enablePerfOverlay = prefs.getBoolean(ENABLE_PERF_OVERLAY_STRING, DEFAULT_ENABLE_PERF_OVERLAY);
|
||||
config.bindAllUsb = prefs.getBoolean(BIND_ALL_USB_STRING, DEFAULT_BIND_ALL_USB);
|
||||
@@ -417,6 +502,9 @@ public class PreferenceConfiguration {
|
||||
config.flipFaceButtons = prefs.getBoolean(FLIP_FACE_BUTTONS_PREF_STRING, DEFAULT_FLIP_FACE_BUTTONS);
|
||||
config.touchscreenTrackpad = prefs.getBoolean(TOUCHSCREEN_TRACKPAD_PREF_STRING, DEFAULT_TOUCHSCREEN_TRACKPAD);
|
||||
config.enableLatencyToast = prefs.getBoolean(LATENCY_TOAST_PREF_STRING, DEFAULT_LATENCY_TOAST);
|
||||
config.absoluteMouseMode = prefs.getBoolean(ABSOLUTE_MOUSE_MODE_PREF_STRING, DEFAULT_ABSOLUTE_MOUSE_MODE);
|
||||
config.enableAudioFx = prefs.getBoolean(ENABLE_AUDIO_FX_PREF_STRING, DEFAULT_ENABLE_AUDIO_FX);
|
||||
config.reduceRefreshRate = prefs.getBoolean(REDUCE_REFRESH_RATE_PREF_STRING, DEFAULT_REDUCE_REFRESH_RATE);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -3,23 +3,29 @@ package com.limelight.preferences;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.media.MediaCodecInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.os.Vibrator;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Range;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayCutout;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
import com.limelight.PcView;
|
||||
@@ -28,15 +34,24 @@ import com.limelight.binding.video.MediaCodecHelper;
|
||||
import com.limelight.utils.Dialog;
|
||||
import com.limelight.utils.UiHelper;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class StreamSettings extends Activity {
|
||||
private PreferenceConfiguration previousPrefs;
|
||||
private int previousDisplayPixelCount;
|
||||
|
||||
// HACK for Android 9
|
||||
static DisplayCutout displayCutoutP;
|
||||
|
||||
void reloadSettings() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
Display.Mode mode = getWindowManager().getDefaultDisplay().getMode();
|
||||
previousDisplayPixelCount = mode.getPhysicalWidth() * mode.getPhysicalHeight();
|
||||
}
|
||||
getFragmentManager().beginTransaction().replace(
|
||||
R.id.stream_settings, new SettingsFragment()
|
||||
).commit();
|
||||
).commitAllowingStateLoss();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,22 +63,61 @@ public class StreamSettings extends Activity {
|
||||
UiHelper.setLocale(this);
|
||||
|
||||
setContentView(R.layout.activity_stream_settings);
|
||||
reloadSettings();
|
||||
|
||||
UiHelper.notifyNewRootView(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
// We have to use this hack on Android 9 because we don't have Display.getCutout()
|
||||
// which was added in Android 10.
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) {
|
||||
// Insets can be null when the activity is recreated on screen rotation
|
||||
// https://stackoverflow.com/questions/61241255/windowinsets-getdisplaycutout-is-null-everywhere-except-within-onattachedtowindo
|
||||
WindowInsets insets = getWindow().getDecorView().getRootWindowInsets();
|
||||
if (insets != null) {
|
||||
displayCutoutP = insets.getDisplayCutout();
|
||||
}
|
||||
}
|
||||
|
||||
reloadSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
Display.Mode mode = getWindowManager().getDefaultDisplay().getMode();
|
||||
|
||||
// If the display's physical pixel count has changed, we consider that it's a new display
|
||||
// and we should reload our settings (which include display-dependent values).
|
||||
//
|
||||
// NB: We aren't using displayId here because that stays the same (DEFAULT_DISPLAY) when
|
||||
// switching between screens on a foldable device.
|
||||
if (mode.getPhysicalWidth() * mode.getPhysicalHeight() != previousDisplayPixelCount) {
|
||||
reloadSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// NOTE: This will NOT be called on Android 13+ with android:enableOnBackInvokedCallback="true"
|
||||
public void onBackPressed() {
|
||||
finish();
|
||||
|
||||
// Check for changes that require a UI reload to take effect
|
||||
PreferenceConfiguration newPrefs = PreferenceConfiguration.readPreferences(this);
|
||||
if (!newPrefs.language.equals(previousPrefs.language)) {
|
||||
// Restart the PC view to apply UI changes
|
||||
Intent intent = new Intent(this, PcView.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent, null);
|
||||
// Language changes are handled via configuration changes in Android 13+,
|
||||
// so manual activity relaunching is no longer required.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||
PreferenceConfiguration newPrefs = PreferenceConfiguration.readPreferences(this);
|
||||
if (!newPrefs.language.equals(previousPrefs.language)) {
|
||||
// Restart the PC view to apply UI changes
|
||||
Intent intent = new Intent(this, PcView.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +130,29 @@ public class StreamSettings extends Activity {
|
||||
pref.setValue(value);
|
||||
}
|
||||
|
||||
private void addNativeResolutionEntry(int nativeWidth, int nativeHeight) {
|
||||
private void addNativeResolutionEntry(int nativeWidth, int nativeHeight, boolean insetsRemoved, boolean portrait) {
|
||||
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING);
|
||||
|
||||
String newName = getResources().getString(R.string.resolution_prefix_native) + " ("+nativeWidth+"x"+nativeHeight+")";
|
||||
String newName;
|
||||
|
||||
if (insetsRemoved) {
|
||||
newName = getResources().getString(R.string.resolution_prefix_native_fullscreen);
|
||||
}
|
||||
else {
|
||||
newName = getResources().getString(R.string.resolution_prefix_native);
|
||||
}
|
||||
|
||||
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
||||
if (portrait) {
|
||||
newName += " " + getResources().getString(R.string.resolution_prefix_native_portrait);
|
||||
}
|
||||
else {
|
||||
newName += " " + getResources().getString(R.string.resolution_prefix_native_landscape);
|
||||
}
|
||||
}
|
||||
|
||||
newName += " ("+nativeWidth+"x"+nativeHeight+")";
|
||||
|
||||
String newValue = nativeWidth+"x"+nativeHeight;
|
||||
|
||||
CharSequence[] values = pref.getEntryValues();
|
||||
@@ -107,6 +180,13 @@ public class StreamSettings extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
private void addNativeResolutionEntries(int nativeWidth, int nativeHeight, boolean insetsRemoved) {
|
||||
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
||||
addNativeResolutionEntry(nativeHeight, nativeWidth, insetsRemoved, true);
|
||||
}
|
||||
addNativeResolutionEntry(nativeWidth, nativeHeight, insetsRemoved, false);
|
||||
}
|
||||
|
||||
private void removeValue(String preferenceKey, String value, Runnable onMatched) {
|
||||
int matchingCount = 0;
|
||||
|
||||
@@ -173,7 +253,7 @@ public class StreamSettings extends Activity {
|
||||
|
||||
// hide on-screen controls category on non touch screen devices
|
||||
if (!getActivity().getPackageManager().
|
||||
hasSystemFeature("android.hardware.touchscreen")) {
|
||||
hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
|
||||
{
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_onscreen_controls");
|
||||
@@ -187,6 +267,15 @@ public class StreamSettings extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
// Hide remote desktop mouse mode on pre-Oreo (which doesn't have pointer capture)
|
||||
// and NVIDIA SHIELD devices (which support raw mouse input in pointer capture mode)
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
|
||||
getActivity().getPackageManager().hasSystemFeature("com.nvidia.feature.shield")) {
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_input_settings");
|
||||
category.removePreference(findPreference("checkbox_absolute_mouse_mode"));
|
||||
}
|
||||
|
||||
// Remove PiP mode on devices pre-Oreo, where the feature is not available (some low RAM devices),
|
||||
// and on Fire OS where it violates the Amazon App Store guidelines for some reason.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
|
||||
@@ -197,6 +286,13 @@ public class StreamSettings extends Activity {
|
||||
category.removePreference(findPreference("checkbox_enable_pip"));
|
||||
}
|
||||
|
||||
// Fire TV apps are not allowed to use WebViews or browsers, so hide the Help category
|
||||
/*if (getActivity().getPackageManager().hasSystemFeature("amazon.hardware.fire_tv")) {
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_help");
|
||||
screen.removePreference(category);
|
||||
}*/
|
||||
|
||||
// Remove the vibration options if the device can't vibrate
|
||||
if (!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
|
||||
PreferenceCategory category =
|
||||
@@ -218,6 +314,38 @@ public class StreamSettings extends Activity {
|
||||
|
||||
int maxSupportedResW = 0;
|
||||
|
||||
// Add a native resolution with any insets included for users that don't want content
|
||||
// behind the notch of their display
|
||||
boolean hasInsets = false;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
DisplayCutout cutout;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
// Use the much nicer Display.getCutout() API on Android 10+
|
||||
cutout = display.getCutout();
|
||||
}
|
||||
else {
|
||||
// Android 9 only
|
||||
cutout = displayCutoutP;
|
||||
}
|
||||
|
||||
if (cutout != null) {
|
||||
int widthInsets = cutout.getSafeInsetLeft() + cutout.getSafeInsetRight();
|
||||
int heightInsets = cutout.getSafeInsetBottom() + cutout.getSafeInsetTop();
|
||||
|
||||
if (widthInsets != 0 || heightInsets != 0) {
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
display.getRealMetrics(metrics);
|
||||
|
||||
int width = Math.max(metrics.widthPixels - widthInsets, metrics.heightPixels - heightInsets);
|
||||
int height = Math.min(metrics.widthPixels - widthInsets, metrics.heightPixels - heightInsets);
|
||||
|
||||
addNativeResolutionEntries(width, height, false);
|
||||
hasInsets = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always allow resolutions that are smaller or equal to the active
|
||||
// display resolution because decoders can report total non-sense to us.
|
||||
// For example, a p201 device reports:
|
||||
@@ -233,7 +361,12 @@ public class StreamSettings extends Activity {
|
||||
int width = Math.max(candidate.getPhysicalWidth(), candidate.getPhysicalHeight());
|
||||
int height = Math.min(candidate.getPhysicalWidth(), candidate.getPhysicalHeight());
|
||||
|
||||
addNativeResolutionEntry(width, height);
|
||||
// Some TVs report strange values here, so let's avoid native resolutions on a TV
|
||||
// unless they report greater than 4K resolutions.
|
||||
if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION) ||
|
||||
(width > 3840 || height > 2160)) {
|
||||
addNativeResolutionEntries(width, height, hasInsets);
|
||||
}
|
||||
|
||||
if ((width >= 3840 || height >= 2160) && maxSupportedResW < 3840) {
|
||||
maxSupportedResW = 3840;
|
||||
@@ -334,11 +467,29 @@ public class StreamSettings extends Activity {
|
||||
// Never remove 720p
|
||||
}
|
||||
}
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
// On Android 4.2 and later, we can get the true metrics via the
|
||||
// getRealMetrics() function (unlike the lies that getWidth() and getHeight()
|
||||
// tell to us).
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
getActivity().getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
|
||||
int width = Math.max(metrics.widthPixels, metrics.heightPixels);
|
||||
int height = Math.min(metrics.widthPixels, metrics.heightPixels);
|
||||
addNativeResolutionEntries(width, height, false);
|
||||
}
|
||||
else {
|
||||
// On Android 4.1, we have to resort to reflection to invoke hidden APIs
|
||||
// to get the real screen dimensions.
|
||||
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
||||
int width = Math.max(display.getWidth(), display.getHeight());
|
||||
int height = Math.min(display.getWidth(), display.getHeight());
|
||||
addNativeResolutionEntry(width, height);
|
||||
try {
|
||||
Method getRawHeightFunc = Display.class.getMethod("getRawHeight");
|
||||
Method getRawWidthFunc = Display.class.getMethod("getRawWidth");
|
||||
int width = (Integer) getRawWidthFunc.invoke(display);
|
||||
int height = (Integer) getRawHeightFunc.invoke(display);
|
||||
addNativeResolutionEntries(Math.max(width, height), Math.min(width, height), false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!PreferenceConfiguration.readPreferences(this.getActivity()).unlockFps) {
|
||||
@@ -439,6 +590,15 @@ public class StreamSettings extends Activity {
|
||||
(PreferenceCategory) findPreference("category_advanced_settings");
|
||||
category.removePreference(findPreference("checkbox_enable_hdr"));
|
||||
}
|
||||
else if (PreferenceConfiguration.isShieldAtvFirmwareWithBrokenHdr()) {
|
||||
LimeLog.info("Disabling HDR toggle on old broken SHIELD TV firmware");
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_advanced_settings");
|
||||
CheckBoxPreference hdrPref = (CheckBoxPreference) category.findPreference("checkbox_enable_hdr");
|
||||
hdrPref.setEnabled(false);
|
||||
hdrPref.setChecked(false);
|
||||
hdrPref.setSummary("Update the firmware on your NVIDIA SHIELD Android TV to enable HDR");
|
||||
}
|
||||
}
|
||||
|
||||
// Add a listener to the FPS and resolution preference
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.limelight.preferences;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import com.limelight.utils.HelpLauncher;
|
||||
|
||||
public class WebLauncherPreference extends Preference {
|
||||
private String url;
|
||||
|
||||
public WebLauncherPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initialize(attrs);
|
||||
}
|
||||
|
||||
public WebLauncherPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initialize(attrs);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public WebLauncherPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initialize(attrs);
|
||||
}
|
||||
|
||||
private void initialize(AttributeSet attrs) {
|
||||
if (attrs == null) {
|
||||
throw new IllegalStateException("WebLauncherPreference must have attributes!");
|
||||
}
|
||||
|
||||
url = attrs.getAttributeValue(null, "url");
|
||||
if (url == null) {
|
||||
throw new IllegalStateException("WebLauncherPreference must have 'url' attribute!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
HelpLauncher.launchUrl(getContext(), url);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
package com.limelight.ui;
|
||||
|
||||
public interface GameGestures {
|
||||
void showKeyboard();
|
||||
void toggleKeyboard();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import android.net.Uri;
|
||||
import com.limelight.HelpActivity;
|
||||
|
||||
public class HelpLauncher {
|
||||
private static void launchUrl(Context context, String url) {
|
||||
public static void launchUrl(Context context, String url) {
|
||||
// Try to launch the default browser
|
||||
try {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
|
||||
@@ -27,7 +27,10 @@ import java.security.cert.CertificateEncodingException;
|
||||
public class ServerHelper {
|
||||
public static final String CONNECTION_TEST_SERVER = "android.conntest.moonlight-stream.org";
|
||||
|
||||
public static String getCurrentAddressFromComputer(ComputerDetails computer) {
|
||||
public static String getCurrentAddressFromComputer(ComputerDetails computer) throws IOException {
|
||||
if (computer.activeAddress == null) {
|
||||
throw new IOException("No active address for "+computer.name);
|
||||
}
|
||||
return computer.activeAddress;
|
||||
}
|
||||
|
||||
@@ -53,7 +56,7 @@ public class ServerHelper {
|
||||
public static Intent createStartIntent(Activity parent, NvApp app, ComputerDetails computer,
|
||||
ComputerManagerService.ComputerManagerBinder managerBinder) {
|
||||
Intent intent = new Intent(parent, Game.class);
|
||||
intent.putExtra(Game.EXTRA_HOST, getCurrentAddressFromComputer(computer));
|
||||
intent.putExtra(Game.EXTRA_HOST, computer.activeAddress);
|
||||
intent.putExtra(Game.EXTRA_APP_NAME, app.getAppName());
|
||||
intent.putExtra(Game.EXTRA_APP_ID, app.getAppId());
|
||||
intent.putExtra(Game.EXTRA_APP_HDR, app.isHdrSupported());
|
||||
@@ -72,8 +75,7 @@ public class ServerHelper {
|
||||
|
||||
public static void doStart(Activity parent, NvApp app, ComputerDetails computer,
|
||||
ComputerManagerService.ComputerManagerBinder managerBinder) {
|
||||
if (computer.state == ComputerDetails.State.OFFLINE ||
|
||||
ServerHelper.getCurrentAddressFromComputer(computer) == null) {
|
||||
if (computer.state == ComputerDetails.State.OFFLINE || computer.activeAddress == null) {
|
||||
Toast.makeText(parent, parent.getResources().getString(R.string.pair_pc_offline), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class ShortcutHelper {
|
||||
@TargetApi(Build.VERSION_CODES.N_MR1)
|
||||
private void reapShortcutsForDynamicAdd() {
|
||||
List<ShortcutInfo> dynamicShortcuts = sm.getDynamicShortcuts();
|
||||
while (dynamicShortcuts.size() >= sm.getMaxShortcutCountPerActivity()) {
|
||||
while (!dynamicShortcuts.isEmpty() && dynamicShortcuts.size() >= sm.getMaxShortcutCountPerActivity()) {
|
||||
ShortcutInfo maxRankShortcut = dynamicShortcuts.get(0);
|
||||
for (ShortcutInfo scut : dynamicShortcuts) {
|
||||
if (maxRankShortcut.getRank() < scut.getRank()) {
|
||||
@@ -118,8 +118,16 @@ public class ShortcutHelper {
|
||||
// To avoid a random carousel of shortcuts popping in and out based on polling status,
|
||||
// we only add shortcuts if it's not at the limit or the user made a conscious action
|
||||
// to interact with this PC.
|
||||
if (forceAdd || sm.getDynamicShortcuts().size() < sm.getMaxShortcutCountPerActivity()) {
|
||||
|
||||
if (forceAdd) {
|
||||
// This should free an entry for us to add one below
|
||||
reapShortcutsForDynamicAdd();
|
||||
}
|
||||
|
||||
// We still need to check the maximum shortcut count even after reaping,
|
||||
// because there's a possibility that it could be zero.
|
||||
if (sm.getDynamicShortcuts().size() < sm.getMaxShortcutCountPerActivity()) {
|
||||
// Add a shortcut if there is room
|
||||
sm.addDynamicShortcuts(Collections.singletonList(sinfo));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package com.limelight.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.GameManager;
|
||||
import android.app.GameState;
|
||||
import android.app.LocaleManager;
|
||||
import android.app.UiModeManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
@@ -9,10 +12,12 @@ import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Insets;
|
||||
import android.os.Build;
|
||||
import android.os.LocaleList;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.limelight.Game;
|
||||
import com.limelight.R;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.preferences.PreferenceConfiguration;
|
||||
@@ -24,25 +29,66 @@ public class UiHelper {
|
||||
private static final int TV_VERTICAL_PADDING_DP = 15;
|
||||
private static final int TV_HORIZONTAL_PADDING_DP = 15;
|
||||
|
||||
private static void setGameModeStatus(Context context, boolean streaming, boolean loading, boolean interruptible) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
GameManager gameManager = context.getSystemService(GameManager.class);
|
||||
|
||||
if (streaming) {
|
||||
gameManager.setGameState(new GameState(loading, interruptible ? GameState.MODE_GAMEPLAY_INTERRUPTIBLE : GameState.MODE_GAMEPLAY_UNINTERRUPTIBLE));
|
||||
}
|
||||
else {
|
||||
gameManager.setGameState(new GameState(loading, GameState.MODE_NONE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyStreamConnecting(Context context) {
|
||||
setGameModeStatus(context, true, true, true);
|
||||
}
|
||||
|
||||
public static void notifyStreamConnected(Context context) {
|
||||
setGameModeStatus(context, true, false, false);
|
||||
}
|
||||
|
||||
public static void notifyStreamEnteringPiP(Context context) {
|
||||
setGameModeStatus(context, true, false, true);
|
||||
}
|
||||
|
||||
public static void notifyStreamExitingPiP(Context context) {
|
||||
setGameModeStatus(context, true, false, false);
|
||||
}
|
||||
|
||||
public static void notifyStreamEnded(Context context) {
|
||||
setGameModeStatus(context, false, false, false);
|
||||
}
|
||||
|
||||
public static void setLocale(Activity activity)
|
||||
{
|
||||
String locale = PreferenceConfiguration.readPreferences(activity).language;
|
||||
if (!locale.equals(PreferenceConfiguration.DEFAULT_LANGUAGE)) {
|
||||
Configuration config = new Configuration(activity.getResources().getConfiguration());
|
||||
|
||||
// Some locales include both language and country which must be separated
|
||||
// before calling the Locale constructor.
|
||||
if (locale.contains("-"))
|
||||
{
|
||||
config.locale = new Locale(locale.substring(0, locale.indexOf('-')),
|
||||
locale.substring(locale.indexOf('-') + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
config.locale = new Locale(locale);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
// On Android 13, migrate this non-default language setting into the OS native API
|
||||
LocaleManager localeManager = activity.getSystemService(LocaleManager.class);
|
||||
localeManager.setApplicationLocales(LocaleList.forLanguageTags(locale));
|
||||
PreferenceConfiguration.completeLanguagePreferenceMigration(activity);
|
||||
}
|
||||
else {
|
||||
Configuration config = new Configuration(activity.getResources().getConfiguration());
|
||||
|
||||
activity.getResources().updateConfiguration(config, activity.getResources().getDisplayMetrics());
|
||||
// Some locales include both language and country which must be separated
|
||||
// before calling the Locale constructor.
|
||||
if (locale.contains("-"))
|
||||
{
|
||||
config.locale = new Locale(locale.substring(0, locale.indexOf('-')),
|
||||
locale.substring(locale.indexOf('-') + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
config.locale = new Locale(locale);
|
||||
}
|
||||
|
||||
activity.getResources().updateConfiguration(config, activity.getResources().getDisplayMetrics());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +114,9 @@ public class UiHelper {
|
||||
View rootView = activity.findViewById(android.R.id.content);
|
||||
UiModeManager modeMgr = (UiModeManager) activity.getSystemService(Context.UI_MODE_SERVICE);
|
||||
|
||||
// Set GameState.MODE_NONE initially for all activities
|
||||
setGameModeStatus(activity, false, false, false);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
// Allow this non-streaming activity to layout under notches.
|
||||
//
|
||||
|
||||
@@ -18,9 +18,10 @@ LOCAL_SRC_FILES := moonlight-common-c/src/AudioStream.c \
|
||||
moonlight-common-c/src/LinkedBlockingQueue.c \
|
||||
moonlight-common-c/src/Misc.c \
|
||||
moonlight-common-c/src/Platform.c \
|
||||
moonlight-common-c/src/PlatformCrypto.c \
|
||||
moonlight-common-c/src/PlatformSockets.c \
|
||||
moonlight-common-c/src/RtpFecQueue.c \
|
||||
moonlight-common-c/src/RtpReorderQueue.c \
|
||||
moonlight-common-c/src/RtpAudioQueue.c \
|
||||
moonlight-common-c/src/RtpVideoQueue.c \
|
||||
moonlight-common-c/src/RtspConnection.c \
|
||||
moonlight-common-c/src/RtspParser.c \
|
||||
moonlight-common-c/src/SdpGenerator.c \
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH
|
||||
OUTPUT_DIR=~/openssl
|
||||
|
||||
BASE_ARGS="no-shared no-ssl3 no-stdio no-engine no-hw"
|
||||
|
||||
set -e
|
||||
|
||||
./Configure android-arm $BASE_ARGS -D__ANDROID_API__=16
|
||||
make clean
|
||||
make build_libs -j`nproc`
|
||||
cp lib*.a $OUTPUT_DIR/armeabi-v7a/
|
||||
|
||||
./Configure android-arm64 $BASE_ARGS -D__ANDROID_API__=21
|
||||
make clean
|
||||
make build_libs -j`nproc`
|
||||
cp lib*.a $OUTPUT_DIR/arm64-v8a/
|
||||
|
||||
./Configure android-x86 $BASE_ARGS -D__ANDROID_API__=16
|
||||
make clean
|
||||
make build_libs -j`nproc`
|
||||
cp lib*.a $OUTPUT_DIR/x86/
|
||||
|
||||
./Configure android-x86_64 $BASE_ARGS -D__ANDROID_API__=21
|
||||
make clean
|
||||
make build_libs -j`nproc`
|
||||
cp lib*.a $OUTPUT_DIR/x86_64/
|
||||
cp -R include/ $OUTPUT_DIR/include
|
||||
@@ -32,6 +32,7 @@ static jmethodID BridgeClConnectionStartedMethod;
|
||||
static jmethodID BridgeClConnectionTerminatedMethod;
|
||||
static jmethodID BridgeClRumbleMethod;
|
||||
static jmethodID BridgeClConnectionStatusUpdateMethod;
|
||||
static jmethodID BridgeClSetHdrModeMethod;
|
||||
static jbyteArray DecodedFrameBuffer;
|
||||
static jshortArray DecodedAudioBuffer;
|
||||
|
||||
@@ -79,7 +80,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_init(JNIEnv *env, jclass clazz) {
|
||||
BridgeDrStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStart", "()V");
|
||||
BridgeDrStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStop", "()V");
|
||||
BridgeDrCleanupMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrCleanup", "()V");
|
||||
BridgeDrSubmitDecodeUnitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrSubmitDecodeUnit", "([BIIIJJ)I");
|
||||
BridgeDrSubmitDecodeUnitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrSubmitDecodeUnit", "([BIIIIJJ)I");
|
||||
BridgeArInitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArInit", "(III)I");
|
||||
BridgeArStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStart", "()V");
|
||||
BridgeArStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStop", "()V");
|
||||
@@ -92,6 +93,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_init(JNIEnv *env, jclass clazz) {
|
||||
BridgeClConnectionTerminatedMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClConnectionTerminated", "(I)V");
|
||||
BridgeClRumbleMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClRumble", "(SSS)V");
|
||||
BridgeClConnectionStatusUpdateMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClConnectionStatusUpdate", "(I)V");
|
||||
BridgeClSetHdrModeMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetHdrMode", "(Z)V");
|
||||
}
|
||||
|
||||
int BridgeDrSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
@@ -157,8 +159,8 @@ int BridgeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod,
|
||||
DecodedFrameBuffer, currentEntry->length, currentEntry->bufferType,
|
||||
decodeUnit->frameNumber, (jlong)decodeUnit->receiveTimeMs,
|
||||
(jlong)decodeUnit->enqueueTimeMs);
|
||||
decodeUnit->frameNumber, decodeUnit->frameType,
|
||||
(jlong)decodeUnit->receiveTimeMs, (jlong)decodeUnit->enqueueTimeMs);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
// We will crash here
|
||||
(*JVM)->DetachCurrentThread(JVM);
|
||||
@@ -178,7 +180,7 @@ int BridgeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod,
|
||||
DecodedFrameBuffer, offset, BUFFER_TYPE_PICDATA,
|
||||
decodeUnit->frameNumber,
|
||||
decodeUnit->frameNumber, decodeUnit->frameType,
|
||||
(jlong)decodeUnit->receiveTimeMs, (jlong)decodeUnit->enqueueTimeMs);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
// We will crash here
|
||||
@@ -326,6 +328,16 @@ void BridgeClConnectionStatusUpdate(int connectionStatus) {
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeClSetHdrMode(bool enabled) {
|
||||
JNIEnv* env = GetThreadEnv();
|
||||
|
||||
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClSetHdrModeMethod, enabled);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
// We will crash here
|
||||
(*JVM)->DetachCurrentThread(JVM);
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeClLogMessage(const char* format, ...) {
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
@@ -359,23 +371,27 @@ static CONNECTION_LISTENER_CALLBACKS BridgeConnListenerCallbacks = {
|
||||
.logMessage = BridgeClLogMessage,
|
||||
.rumble = BridgeClRumble,
|
||||
.connectionStatusUpdate = BridgeClConnectionStatusUpdate,
|
||||
.setHdrMode = BridgeClSetHdrMode,
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass clazz,
|
||||
jstring address, jstring appVersion, jstring gfeVersion,
|
||||
jstring rtspSessionUrl,
|
||||
jint width, jint height, jint fps,
|
||||
jint bitrate, jint packetSize, jint streamingRemotely,
|
||||
jint audioConfiguration, jboolean supportsHevc,
|
||||
jboolean enableHdr,
|
||||
jint hevcBitratePercentageMultiplier,
|
||||
jint clientRefreshRateX100,
|
||||
jint encryptionFlags,
|
||||
jbyteArray riAesKey, jbyteArray riAesIv,
|
||||
jint videoCapabilities) {
|
||||
SERVER_INFORMATION serverInfo = {
|
||||
.address = (*env)->GetStringUTFChars(env, address, 0),
|
||||
.serverInfoAppVersion = (*env)->GetStringUTFChars(env, appVersion, 0),
|
||||
.serverInfoGfeVersion = gfeVersion ? (*env)->GetStringUTFChars(env, gfeVersion, 0) : NULL,
|
||||
.rtspSessionUrl = rtspSessionUrl ? (*env)->GetStringUTFChars(env, rtspSessionUrl, 0) : NULL,
|
||||
};
|
||||
STREAM_CONFIGURATION streamConfig = {
|
||||
.width = width,
|
||||
@@ -388,7 +404,8 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
|
||||
.supportsHevc = supportsHevc,
|
||||
.enableHdr = enableHdr,
|
||||
.hevcBitratePercentageMultiplier = hevcBitratePercentageMultiplier,
|
||||
.clientRefreshRateX100 = clientRefreshRateX100
|
||||
.clientRefreshRateX100 = clientRefreshRateX100,
|
||||
.encryptionFlags = encryptionFlags,
|
||||
};
|
||||
|
||||
jbyte* riAesKeyBuf = (*env)->GetByteArrayElements(env, riAesKey, NULL);
|
||||
@@ -414,6 +431,9 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
|
||||
if (gfeVersion != NULL) {
|
||||
(*env)->ReleaseStringUTFChars(env, gfeVersion, serverInfo.serverInfoGfeVersion);
|
||||
}
|
||||
if (rtspSessionUrl != NULL) {
|
||||
(*env)->ReleaseStringUTFChars(env, rtspSessionUrl, serverInfo.rtspSessionUrl);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Submodule app/src/main/jni/moonlight-core/moonlight-common-c updated: 021fe902d9...54825845e7
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -8,9 +8,15 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is only used by HP C on VMS, and is included automatically
|
||||
* This file is only used by HP C/C++ on VMS, and is included automatically
|
||||
* after each header file from this directory
|
||||
*/
|
||||
|
||||
/*
|
||||
* The C++ compiler doesn't understand these pragmas, even though it
|
||||
* understands the corresponding command line qualifier.
|
||||
*/
|
||||
#ifndef __cplusplus
|
||||
/* restore state. Must correspond to the save in __decc_include_prologue.h */
|
||||
#pragma names restore
|
||||
# pragma names restore
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -8,13 +8,19 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is only used by HP C on VMS, and is included automatically
|
||||
* This file is only used by HP C/C++ on VMS, and is included automatically
|
||||
* after each header file from this directory
|
||||
*/
|
||||
|
||||
/*
|
||||
* The C++ compiler doesn't understand these pragmas, even though it
|
||||
* understands the corresponding command line qualifier.
|
||||
*/
|
||||
#ifndef __cplusplus
|
||||
/* save state */
|
||||
#pragma names save
|
||||
# pragma names save
|
||||
/* have the compiler shorten symbols larger than 31 chars to 23 chars
|
||||
* followed by a 8 hex char CRC
|
||||
*/
|
||||
#pragma names as_is,shortened
|
||||
# pragma names as_is,shortened
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,8 @@
|
||||
#ifndef HEADER_ASN1ERR_H
|
||||
# define HEADER_ASN1ERR_H
|
||||
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
@@ -49,6 +51,7 @@ int ERR_load_ASN1_strings(void);
|
||||
# define ASN1_F_ASN1_ITEM_DUP 191
|
||||
# define ASN1_F_ASN1_ITEM_EMBED_D2I 120
|
||||
# define ASN1_F_ASN1_ITEM_EMBED_NEW 121
|
||||
# define ASN1_F_ASN1_ITEM_EX_I2D 144
|
||||
# define ASN1_F_ASN1_ITEM_FLAGS_I2D 118
|
||||
# define ASN1_F_ASN1_ITEM_I2D_BIO 192
|
||||
# define ASN1_F_ASN1_ITEM_I2D_FP 193
|
||||
@@ -141,6 +144,7 @@ int ERR_load_ASN1_strings(void);
|
||||
# define ASN1_R_ASN1_SIG_PARSE_ERROR 204
|
||||
# define ASN1_R_AUX_ERROR 100
|
||||
# define ASN1_R_BAD_OBJECT_HEADER 102
|
||||
# define ASN1_R_BAD_TEMPLATE 230
|
||||
# define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 214
|
||||
# define ASN1_R_BN_LIB 105
|
||||
# define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_ASYNCERR_H
|
||||
# define HEADER_ASYNCERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -20,10 +20,6 @@
|
||||
# include <openssl/crypto.h>
|
||||
# include <openssl/bioerr.h>
|
||||
|
||||
# ifndef OPENSSL_NO_SCTP
|
||||
# include <openssl/e_os2.h>
|
||||
# endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -173,6 +169,7 @@ extern "C" {
|
||||
*/
|
||||
# define BIO_FLAGS_MEM_RDONLY 0x200
|
||||
# define BIO_FLAGS_NONCLEAR_RST 0x400
|
||||
# define BIO_FLAGS_IN_EOF 0x800
|
||||
|
||||
typedef union bio_addr_st BIO_ADDR;
|
||||
typedef struct bio_addrinfo_st BIO_ADDRINFO;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_BIOERR_H
|
||||
# define HEADER_BIOERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
@@ -56,7 +56,7 @@ extern "C" {
|
||||
* avoid leaking exponent information through timing,
|
||||
* BN_mod_exp_mont() will call BN_mod_exp_mont_consttime,
|
||||
* BN_div() will call BN_div_no_branch,
|
||||
* BN_mod_inverse() will call BN_mod_inverse_no_branch.
|
||||
* BN_mod_inverse() will call bn_mod_inverse_no_branch.
|
||||
*/
|
||||
# define BN_FLG_CONSTTIME 0x04
|
||||
# define BN_FLG_SECURE 0x08
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_BNERR_H
|
||||
# define HEADER_BNERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_BUFERR_H
|
||||
# define HEADER_BUFERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
|
||||
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
* WARNING: do not edit!
|
||||
* Generated by Makefile from include/openssl/cmp.h.in
|
||||
*
|
||||
* Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright Nokia 2007-2019
|
||||
* Copyright Siemens AG 2015-2019
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef OPENSSL_CMP_H
|
||||
# define OPENSSL_CMP_H
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
# ifndef OPENSSL_NO_CMP
|
||||
|
||||
# include <openssl/crmf.h>
|
||||
# include <openssl/cmperr.h>
|
||||
# include <openssl/cmp_util.h>
|
||||
# include <openssl/http.h>
|
||||
|
||||
/* explicit #includes not strictly needed since implied by the above: */
|
||||
# include <openssl/types.h>
|
||||
# include <openssl/safestack.h>
|
||||
# include <openssl/x509.h>
|
||||
# include <openssl/x509v3.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
# define OSSL_CMP_PVNO 2
|
||||
|
||||
/*-
|
||||
* PKIFailureInfo ::= BIT STRING {
|
||||
* -- since we can fail in more than one way!
|
||||
* -- More codes may be added in the future if/when required.
|
||||
* badAlg (0),
|
||||
* -- unrecognized or unsupported Algorithm Identifier
|
||||
* badMessageCheck (1),
|
||||
* -- integrity check failed (e.g., signature did not verify)
|
||||
* badRequest (2),
|
||||
* -- transaction not permitted or supported
|
||||
* badTime (3),
|
||||
* -- messageTime was not sufficiently close to the system time,
|
||||
* -- as defined by local policy
|
||||
* badCertId (4),
|
||||
* -- no certificate could be found matching the provided criteria
|
||||
* badDataFormat (5),
|
||||
* -- the data submitted has the wrong format
|
||||
* wrongAuthority (6),
|
||||
* -- the authority indicated in the request is different from the
|
||||
* -- one creating the response token
|
||||
* incorrectData (7),
|
||||
* -- the requester's data is incorrect (for notary services)
|
||||
* missingTimeStamp (8),
|
||||
* -- when the timestamp is missing but should be there
|
||||
* -- (by policy)
|
||||
* badPOP (9),
|
||||
* -- the proof-of-possession failed
|
||||
* certRevoked (10),
|
||||
* -- the certificate has already been revoked
|
||||
* certConfirmed (11),
|
||||
* -- the certificate has already been confirmed
|
||||
* wrongIntegrity (12),
|
||||
* -- invalid integrity, password based instead of signature or
|
||||
* -- vice versa
|
||||
* badRecipientNonce (13),
|
||||
* -- invalid recipient nonce, either missing or wrong value
|
||||
* timeNotAvailable (14),
|
||||
* -- the TSA's time source is not available
|
||||
* unacceptedPolicy (15),
|
||||
* -- the requested TSA policy is not supported by the TSA.
|
||||
* unacceptedExtension (16),
|
||||
* -- the requested extension is not supported by the TSA.
|
||||
* addInfoNotAvailable (17),
|
||||
* -- the additional information requested could not be
|
||||
* -- understood or is not available
|
||||
* badSenderNonce (18),
|
||||
* -- invalid sender nonce, either missing or wrong size
|
||||
* badCertTemplate (19),
|
||||
* -- invalid cert. template or missing mandatory information
|
||||
* signerNotTrusted (20),
|
||||
* -- signer of the message unknown or not trusted
|
||||
* transactionIdInUse (21),
|
||||
* -- the transaction identifier is already in use
|
||||
* unsupportedVersion (22),
|
||||
* -- the version of the message is not supported
|
||||
* notAuthorized (23),
|
||||
* -- the sender was not authorized to make the preceding
|
||||
* -- request or perform the preceding action
|
||||
* systemUnavail (24),
|
||||
* -- the request cannot be handled due to system unavailability
|
||||
* systemFailure (25),
|
||||
* -- the request cannot be handled due to system failure
|
||||
* duplicateCertReq (26)
|
||||
* -- certificate cannot be issued because a duplicate
|
||||
* -- certificate already exists
|
||||
* }
|
||||
*/
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badAlg 0
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badMessageCheck 1
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badRequest 2
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badTime 3
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badCertId 4
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badDataFormat 5
|
||||
# define OSSL_CMP_PKIFAILUREINFO_wrongAuthority 6
|
||||
# define OSSL_CMP_PKIFAILUREINFO_incorrectData 7
|
||||
# define OSSL_CMP_PKIFAILUREINFO_missingTimeStamp 8
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badPOP 9
|
||||
# define OSSL_CMP_PKIFAILUREINFO_certRevoked 10
|
||||
# define OSSL_CMP_PKIFAILUREINFO_certConfirmed 11
|
||||
# define OSSL_CMP_PKIFAILUREINFO_wrongIntegrity 12
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badRecipientNonce 13
|
||||
# define OSSL_CMP_PKIFAILUREINFO_timeNotAvailable 14
|
||||
# define OSSL_CMP_PKIFAILUREINFO_unacceptedPolicy 15
|
||||
# define OSSL_CMP_PKIFAILUREINFO_unacceptedExtension 16
|
||||
# define OSSL_CMP_PKIFAILUREINFO_addInfoNotAvailable 17
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badSenderNonce 18
|
||||
# define OSSL_CMP_PKIFAILUREINFO_badCertTemplate 19
|
||||
# define OSSL_CMP_PKIFAILUREINFO_signerNotTrusted 20
|
||||
# define OSSL_CMP_PKIFAILUREINFO_transactionIdInUse 21
|
||||
# define OSSL_CMP_PKIFAILUREINFO_unsupportedVersion 22
|
||||
# define OSSL_CMP_PKIFAILUREINFO_notAuthorized 23
|
||||
# define OSSL_CMP_PKIFAILUREINFO_systemUnavail 24
|
||||
# define OSSL_CMP_PKIFAILUREINFO_systemFailure 25
|
||||
# define OSSL_CMP_PKIFAILUREINFO_duplicateCertReq 26
|
||||
# define OSSL_CMP_PKIFAILUREINFO_MAX 26
|
||||
# define OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN \
|
||||
((1 << (OSSL_CMP_PKIFAILUREINFO_MAX + 1)) - 1)
|
||||
# if OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN > INT_MAX
|
||||
# error CMP_PKIFAILUREINFO_MAX bit pattern does not fit in type int
|
||||
# endif
|
||||
|
||||
typedef ASN1_BIT_STRING OSSL_CMP_PKIFAILUREINFO;
|
||||
|
||||
# define OSSL_CMP_CTX_FAILINFO_badAlg (1 << 0)
|
||||
# define OSSL_CMP_CTX_FAILINFO_badMessageCheck (1 << 1)
|
||||
# define OSSL_CMP_CTX_FAILINFO_badRequest (1 << 2)
|
||||
# define OSSL_CMP_CTX_FAILINFO_badTime (1 << 3)
|
||||
# define OSSL_CMP_CTX_FAILINFO_badCertId (1 << 4)
|
||||
# define OSSL_CMP_CTX_FAILINFO_badDataFormat (1 << 5)
|
||||
# define OSSL_CMP_CTX_FAILINFO_wrongAuthority (1 << 6)
|
||||
# define OSSL_CMP_CTX_FAILINFO_incorrectData (1 << 7)
|
||||
# define OSSL_CMP_CTX_FAILINFO_missingTimeStamp (1 << 8)
|
||||
# define OSSL_CMP_CTX_FAILINFO_badPOP (1 << 9)
|
||||
# define OSSL_CMP_CTX_FAILINFO_certRevoked (1 << 10)
|
||||
# define OSSL_CMP_CTX_FAILINFO_certConfirmed (1 << 11)
|
||||
# define OSSL_CMP_CTX_FAILINFO_wrongIntegrity (1 << 12)
|
||||
# define OSSL_CMP_CTX_FAILINFO_badRecipientNonce (1 << 13)
|
||||
# define OSSL_CMP_CTX_FAILINFO_timeNotAvailable (1 << 14)
|
||||
# define OSSL_CMP_CTX_FAILINFO_unacceptedPolicy (1 << 15)
|
||||
# define OSSL_CMP_CTX_FAILINFO_unacceptedExtension (1 << 16)
|
||||
# define OSSL_CMP_CTX_FAILINFO_addInfoNotAvailable (1 << 17)
|
||||
# define OSSL_CMP_CTX_FAILINFO_badSenderNonce (1 << 18)
|
||||
# define OSSL_CMP_CTX_FAILINFO_badCertTemplate (1 << 19)
|
||||
# define OSSL_CMP_CTX_FAILINFO_signerNotTrusted (1 << 20)
|
||||
# define OSSL_CMP_CTX_FAILINFO_transactionIdInUse (1 << 21)
|
||||
# define OSSL_CMP_CTX_FAILINFO_unsupportedVersion (1 << 22)
|
||||
# define OSSL_CMP_CTX_FAILINFO_notAuthorized (1 << 23)
|
||||
# define OSSL_CMP_CTX_FAILINFO_systemUnavail (1 << 24)
|
||||
# define OSSL_CMP_CTX_FAILINFO_systemFailure (1 << 25)
|
||||
# define OSSL_CMP_CTX_FAILINFO_duplicateCertReq (1 << 26)
|
||||
|
||||
/*-
|
||||
* PKIStatus ::= INTEGER {
|
||||
* accepted (0),
|
||||
* -- you got exactly what you asked for
|
||||
* grantedWithMods (1),
|
||||
* -- you got something like what you asked for; the
|
||||
* -- requester is responsible for ascertaining the differences
|
||||
* rejection (2),
|
||||
* -- you don't get it, more information elsewhere in the message
|
||||
* waiting (3),
|
||||
* -- the request body part has not yet been processed; expect to
|
||||
* -- hear more later (note: proper handling of this status
|
||||
* -- response MAY use the polling req/rep PKIMessages specified
|
||||
* -- in Section 5.3.22; alternatively, polling in the underlying
|
||||
* -- transport layer MAY have some utility in this regard)
|
||||
* revocationWarning (4),
|
||||
* -- this message contains a warning that a revocation is
|
||||
* -- imminent
|
||||
* revocationNotification (5),
|
||||
* -- notification that a revocation has occurred
|
||||
* keyUpdateWarning (6)
|
||||
* -- update already done for the oldCertId specified in
|
||||
* -- CertReqMsg
|
||||
* }
|
||||
*/
|
||||
# define OSSL_CMP_PKISTATUS_accepted 0
|
||||
# define OSSL_CMP_PKISTATUS_grantedWithMods 1
|
||||
# define OSSL_CMP_PKISTATUS_rejection 2
|
||||
# define OSSL_CMP_PKISTATUS_waiting 3
|
||||
# define OSSL_CMP_PKISTATUS_revocationWarning 4
|
||||
# define OSSL_CMP_PKISTATUS_revocationNotification 5
|
||||
# define OSSL_CMP_PKISTATUS_keyUpdateWarning 6
|
||||
|
||||
typedef ASN1_INTEGER OSSL_CMP_PKISTATUS;
|
||||
DECLARE_ASN1_ITEM(OSSL_CMP_PKISTATUS)
|
||||
|
||||
# define OSSL_CMP_CERTORENCCERT_CERTIFICATE 0
|
||||
# define OSSL_CMP_CERTORENCCERT_ENCRYPTEDCERT 1
|
||||
|
||||
/* data type declarations */
|
||||
typedef struct ossl_cmp_ctx_st OSSL_CMP_CTX;
|
||||
typedef struct ossl_cmp_pkiheader_st OSSL_CMP_PKIHEADER;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKIHEADER)
|
||||
typedef struct ossl_cmp_msg_st OSSL_CMP_MSG;
|
||||
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_MSG)
|
||||
DECLARE_ASN1_ENCODE_FUNCTIONS(OSSL_CMP_MSG, OSSL_CMP_MSG, OSSL_CMP_MSG)
|
||||
typedef struct ossl_cmp_certstatus_st OSSL_CMP_CERTSTATUS;
|
||||
SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_CERTSTATUS, OSSL_CMP_CERTSTATUS, OSSL_CMP_CERTSTATUS)
|
||||
#define sk_OSSL_CMP_CERTSTATUS_num(sk) OPENSSL_sk_num(ossl_check_const_OSSL_CMP_CERTSTATUS_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_value(sk, idx) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_value(ossl_check_const_OSSL_CMP_CERTSTATUS_sk_type(sk), (idx)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_new(cmp) ((STACK_OF(OSSL_CMP_CERTSTATUS) *)OPENSSL_sk_new(ossl_check_OSSL_CMP_CERTSTATUS_compfunc_type(cmp)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_new_null() ((STACK_OF(OSSL_CMP_CERTSTATUS) *)OPENSSL_sk_new_null())
|
||||
#define sk_OSSL_CMP_CERTSTATUS_new_reserve(cmp, n) ((STACK_OF(OSSL_CMP_CERTSTATUS) *)OPENSSL_sk_new_reserve(ossl_check_OSSL_CMP_CERTSTATUS_compfunc_type(cmp), (n)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), (n))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_free(sk) OPENSSL_sk_free(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_zero(sk) OPENSSL_sk_zero(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_delete(sk, i) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_delete(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), (i)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_delete_ptr(sk, ptr) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_delete_ptr(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_push(sk, ptr) OPENSSL_sk_push(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_pop(sk) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_shift(sk) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk),ossl_check_OSSL_CMP_CERTSTATUS_freefunc_type(freefunc))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr), (idx))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_set(sk, idx, ptr) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), (idx), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr), pnum)
|
||||
#define sk_OSSL_CMP_CERTSTATUS_sort(sk) OPENSSL_sk_sort(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_OSSL_CMP_CERTSTATUS_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_dup(sk) ((STACK_OF(OSSL_CMP_CERTSTATUS) *)OPENSSL_sk_dup(ossl_check_const_OSSL_CMP_CERTSTATUS_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(OSSL_CMP_CERTSTATUS) *)OPENSSL_sk_deep_copy(ossl_check_const_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_copyfunc_type(copyfunc), ossl_check_OSSL_CMP_CERTSTATUS_freefunc_type(freefunc)))
|
||||
#define sk_OSSL_CMP_CERTSTATUS_set_cmp_func(sk, cmp) ((sk_OSSL_CMP_CERTSTATUS_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_compfunc_type(cmp)))
|
||||
|
||||
typedef struct ossl_cmp_itav_st OSSL_CMP_ITAV;
|
||||
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
|
||||
SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_ITAV, OSSL_CMP_ITAV, OSSL_CMP_ITAV)
|
||||
#define sk_OSSL_CMP_ITAV_num(sk) OPENSSL_sk_num(ossl_check_const_OSSL_CMP_ITAV_sk_type(sk))
|
||||
#define sk_OSSL_CMP_ITAV_value(sk, idx) ((OSSL_CMP_ITAV *)OPENSSL_sk_value(ossl_check_const_OSSL_CMP_ITAV_sk_type(sk), (idx)))
|
||||
#define sk_OSSL_CMP_ITAV_new(cmp) ((STACK_OF(OSSL_CMP_ITAV) *)OPENSSL_sk_new(ossl_check_OSSL_CMP_ITAV_compfunc_type(cmp)))
|
||||
#define sk_OSSL_CMP_ITAV_new_null() ((STACK_OF(OSSL_CMP_ITAV) *)OPENSSL_sk_new_null())
|
||||
#define sk_OSSL_CMP_ITAV_new_reserve(cmp, n) ((STACK_OF(OSSL_CMP_ITAV) *)OPENSSL_sk_new_reserve(ossl_check_OSSL_CMP_ITAV_compfunc_type(cmp), (n)))
|
||||
#define sk_OSSL_CMP_ITAV_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_OSSL_CMP_ITAV_sk_type(sk), (n))
|
||||
#define sk_OSSL_CMP_ITAV_free(sk) OPENSSL_sk_free(ossl_check_OSSL_CMP_ITAV_sk_type(sk))
|
||||
#define sk_OSSL_CMP_ITAV_zero(sk) OPENSSL_sk_zero(ossl_check_OSSL_CMP_ITAV_sk_type(sk))
|
||||
#define sk_OSSL_CMP_ITAV_delete(sk, i) ((OSSL_CMP_ITAV *)OPENSSL_sk_delete(ossl_check_OSSL_CMP_ITAV_sk_type(sk), (i)))
|
||||
#define sk_OSSL_CMP_ITAV_delete_ptr(sk, ptr) ((OSSL_CMP_ITAV *)OPENSSL_sk_delete_ptr(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr)))
|
||||
#define sk_OSSL_CMP_ITAV_push(sk, ptr) OPENSSL_sk_push(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr))
|
||||
#define sk_OSSL_CMP_ITAV_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr))
|
||||
#define sk_OSSL_CMP_ITAV_pop(sk) ((OSSL_CMP_ITAV *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_ITAV_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_ITAV_shift(sk) ((OSSL_CMP_ITAV *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_ITAV_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_ITAV_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_ITAV_sk_type(sk),ossl_check_OSSL_CMP_ITAV_freefunc_type(freefunc))
|
||||
#define sk_OSSL_CMP_ITAV_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr), (idx))
|
||||
#define sk_OSSL_CMP_ITAV_set(sk, idx, ptr) ((OSSL_CMP_ITAV *)OPENSSL_sk_set(ossl_check_OSSL_CMP_ITAV_sk_type(sk), (idx), ossl_check_OSSL_CMP_ITAV_type(ptr)))
|
||||
#define sk_OSSL_CMP_ITAV_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr))
|
||||
#define sk_OSSL_CMP_ITAV_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr))
|
||||
#define sk_OSSL_CMP_ITAV_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr), pnum)
|
||||
#define sk_OSSL_CMP_ITAV_sort(sk) OPENSSL_sk_sort(ossl_check_OSSL_CMP_ITAV_sk_type(sk))
|
||||
#define sk_OSSL_CMP_ITAV_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_OSSL_CMP_ITAV_sk_type(sk))
|
||||
#define sk_OSSL_CMP_ITAV_dup(sk) ((STACK_OF(OSSL_CMP_ITAV) *)OPENSSL_sk_dup(ossl_check_const_OSSL_CMP_ITAV_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_ITAV_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(OSSL_CMP_ITAV) *)OPENSSL_sk_deep_copy(ossl_check_const_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_copyfunc_type(copyfunc), ossl_check_OSSL_CMP_ITAV_freefunc_type(freefunc)))
|
||||
#define sk_OSSL_CMP_ITAV_set_cmp_func(sk, cmp) ((sk_OSSL_CMP_ITAV_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_compfunc_type(cmp)))
|
||||
|
||||
typedef struct ossl_cmp_revrepcontent_st OSSL_CMP_REVREPCONTENT;
|
||||
typedef struct ossl_cmp_pkisi_st OSSL_CMP_PKISI;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
|
||||
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI)
|
||||
SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_PKISI, OSSL_CMP_PKISI, OSSL_CMP_PKISI)
|
||||
#define sk_OSSL_CMP_PKISI_num(sk) OPENSSL_sk_num(ossl_check_const_OSSL_CMP_PKISI_sk_type(sk))
|
||||
#define sk_OSSL_CMP_PKISI_value(sk, idx) ((OSSL_CMP_PKISI *)OPENSSL_sk_value(ossl_check_const_OSSL_CMP_PKISI_sk_type(sk), (idx)))
|
||||
#define sk_OSSL_CMP_PKISI_new(cmp) ((STACK_OF(OSSL_CMP_PKISI) *)OPENSSL_sk_new(ossl_check_OSSL_CMP_PKISI_compfunc_type(cmp)))
|
||||
#define sk_OSSL_CMP_PKISI_new_null() ((STACK_OF(OSSL_CMP_PKISI) *)OPENSSL_sk_new_null())
|
||||
#define sk_OSSL_CMP_PKISI_new_reserve(cmp, n) ((STACK_OF(OSSL_CMP_PKISI) *)OPENSSL_sk_new_reserve(ossl_check_OSSL_CMP_PKISI_compfunc_type(cmp), (n)))
|
||||
#define sk_OSSL_CMP_PKISI_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_OSSL_CMP_PKISI_sk_type(sk), (n))
|
||||
#define sk_OSSL_CMP_PKISI_free(sk) OPENSSL_sk_free(ossl_check_OSSL_CMP_PKISI_sk_type(sk))
|
||||
#define sk_OSSL_CMP_PKISI_zero(sk) OPENSSL_sk_zero(ossl_check_OSSL_CMP_PKISI_sk_type(sk))
|
||||
#define sk_OSSL_CMP_PKISI_delete(sk, i) ((OSSL_CMP_PKISI *)OPENSSL_sk_delete(ossl_check_OSSL_CMP_PKISI_sk_type(sk), (i)))
|
||||
#define sk_OSSL_CMP_PKISI_delete_ptr(sk, ptr) ((OSSL_CMP_PKISI *)OPENSSL_sk_delete_ptr(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr)))
|
||||
#define sk_OSSL_CMP_PKISI_push(sk, ptr) OPENSSL_sk_push(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr))
|
||||
#define sk_OSSL_CMP_PKISI_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr))
|
||||
#define sk_OSSL_CMP_PKISI_pop(sk) ((OSSL_CMP_PKISI *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_PKISI_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_PKISI_shift(sk) ((OSSL_CMP_PKISI *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_PKISI_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_PKISI_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_PKISI_sk_type(sk),ossl_check_OSSL_CMP_PKISI_freefunc_type(freefunc))
|
||||
#define sk_OSSL_CMP_PKISI_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr), (idx))
|
||||
#define sk_OSSL_CMP_PKISI_set(sk, idx, ptr) ((OSSL_CMP_PKISI *)OPENSSL_sk_set(ossl_check_OSSL_CMP_PKISI_sk_type(sk), (idx), ossl_check_OSSL_CMP_PKISI_type(ptr)))
|
||||
#define sk_OSSL_CMP_PKISI_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr))
|
||||
#define sk_OSSL_CMP_PKISI_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr))
|
||||
#define sk_OSSL_CMP_PKISI_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr), pnum)
|
||||
#define sk_OSSL_CMP_PKISI_sort(sk) OPENSSL_sk_sort(ossl_check_OSSL_CMP_PKISI_sk_type(sk))
|
||||
#define sk_OSSL_CMP_PKISI_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_OSSL_CMP_PKISI_sk_type(sk))
|
||||
#define sk_OSSL_CMP_PKISI_dup(sk) ((STACK_OF(OSSL_CMP_PKISI) *)OPENSSL_sk_dup(ossl_check_const_OSSL_CMP_PKISI_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_PKISI_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(OSSL_CMP_PKISI) *)OPENSSL_sk_deep_copy(ossl_check_const_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_copyfunc_type(copyfunc), ossl_check_OSSL_CMP_PKISI_freefunc_type(freefunc)))
|
||||
#define sk_OSSL_CMP_PKISI_set_cmp_func(sk, cmp) ((sk_OSSL_CMP_PKISI_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_compfunc_type(cmp)))
|
||||
|
||||
typedef struct ossl_cmp_certrepmessage_st OSSL_CMP_CERTREPMESSAGE;
|
||||
SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_CERTREPMESSAGE, OSSL_CMP_CERTREPMESSAGE, OSSL_CMP_CERTREPMESSAGE)
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_num(sk) OPENSSL_sk_num(ossl_check_const_OSSL_CMP_CERTREPMESSAGE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_value(sk, idx) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_value(ossl_check_const_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), (idx)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_new(cmp) ((STACK_OF(OSSL_CMP_CERTREPMESSAGE) *)OPENSSL_sk_new(ossl_check_OSSL_CMP_CERTREPMESSAGE_compfunc_type(cmp)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_new_null() ((STACK_OF(OSSL_CMP_CERTREPMESSAGE) *)OPENSSL_sk_new_null())
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_new_reserve(cmp, n) ((STACK_OF(OSSL_CMP_CERTREPMESSAGE) *)OPENSSL_sk_new_reserve(ossl_check_OSSL_CMP_CERTREPMESSAGE_compfunc_type(cmp), (n)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), (n))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_free(sk) OPENSSL_sk_free(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_zero(sk) OPENSSL_sk_zero(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_delete(sk, i) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_delete(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), (i)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_delete_ptr(sk, ptr) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_delete_ptr(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_push(sk, ptr) OPENSSL_sk_push(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_pop(sk) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_shift(sk) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk),ossl_check_OSSL_CMP_CERTREPMESSAGE_freefunc_type(freefunc))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr), (idx))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_set(sk, idx, ptr) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), (idx), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr), pnum)
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_sort(sk) OPENSSL_sk_sort(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_OSSL_CMP_CERTREPMESSAGE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_dup(sk) ((STACK_OF(OSSL_CMP_CERTREPMESSAGE) *)OPENSSL_sk_dup(ossl_check_const_OSSL_CMP_CERTREPMESSAGE_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(OSSL_CMP_CERTREPMESSAGE) *)OPENSSL_sk_deep_copy(ossl_check_const_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_copyfunc_type(copyfunc), ossl_check_OSSL_CMP_CERTREPMESSAGE_freefunc_type(freefunc)))
|
||||
#define sk_OSSL_CMP_CERTREPMESSAGE_set_cmp_func(sk, cmp) ((sk_OSSL_CMP_CERTREPMESSAGE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_compfunc_type(cmp)))
|
||||
|
||||
typedef struct ossl_cmp_pollrep_st OSSL_CMP_POLLREP;
|
||||
typedef STACK_OF(OSSL_CMP_POLLREP) OSSL_CMP_POLLREPCONTENT;
|
||||
typedef struct ossl_cmp_certresponse_st OSSL_CMP_CERTRESPONSE;
|
||||
SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_CERTRESPONSE, OSSL_CMP_CERTRESPONSE, OSSL_CMP_CERTRESPONSE)
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_num(sk) OPENSSL_sk_num(ossl_check_const_OSSL_CMP_CERTRESPONSE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_value(sk, idx) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_value(ossl_check_const_OSSL_CMP_CERTRESPONSE_sk_type(sk), (idx)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_new(cmp) ((STACK_OF(OSSL_CMP_CERTRESPONSE) *)OPENSSL_sk_new(ossl_check_OSSL_CMP_CERTRESPONSE_compfunc_type(cmp)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_new_null() ((STACK_OF(OSSL_CMP_CERTRESPONSE) *)OPENSSL_sk_new_null())
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_new_reserve(cmp, n) ((STACK_OF(OSSL_CMP_CERTRESPONSE) *)OPENSSL_sk_new_reserve(ossl_check_OSSL_CMP_CERTRESPONSE_compfunc_type(cmp), (n)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), (n))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_free(sk) OPENSSL_sk_free(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_zero(sk) OPENSSL_sk_zero(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_delete(sk, i) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_delete(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), (i)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_delete_ptr(sk, ptr) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_delete_ptr(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_push(sk, ptr) OPENSSL_sk_push(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_pop(sk) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_shift(sk) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk),ossl_check_OSSL_CMP_CERTRESPONSE_freefunc_type(freefunc))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr), (idx))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_set(sk, idx, ptr) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), (idx), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr), pnum)
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_sort(sk) OPENSSL_sk_sort(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_OSSL_CMP_CERTRESPONSE_sk_type(sk))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_dup(sk) ((STACK_OF(OSSL_CMP_CERTRESPONSE) *)OPENSSL_sk_dup(ossl_check_const_OSSL_CMP_CERTRESPONSE_sk_type(sk)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(OSSL_CMP_CERTRESPONSE) *)OPENSSL_sk_deep_copy(ossl_check_const_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_copyfunc_type(copyfunc), ossl_check_OSSL_CMP_CERTRESPONSE_freefunc_type(freefunc)))
|
||||
#define sk_OSSL_CMP_CERTRESPONSE_set_cmp_func(sk, cmp) ((sk_OSSL_CMP_CERTRESPONSE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_compfunc_type(cmp)))
|
||||
|
||||
typedef STACK_OF(ASN1_UTF8STRING) OSSL_CMP_PKIFREETEXT;
|
||||
|
||||
/*
|
||||
* function DECLARATIONS
|
||||
*/
|
||||
|
||||
/* from cmp_asn.c */
|
||||
OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value);
|
||||
void OSSL_CMP_ITAV_set0(OSSL_CMP_ITAV *itav, ASN1_OBJECT *type,
|
||||
ASN1_TYPE *value);
|
||||
ASN1_OBJECT *OSSL_CMP_ITAV_get0_type(const OSSL_CMP_ITAV *itav);
|
||||
ASN1_TYPE *OSSL_CMP_ITAV_get0_value(const OSSL_CMP_ITAV *itav);
|
||||
int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
|
||||
OSSL_CMP_ITAV *itav);
|
||||
void OSSL_CMP_ITAV_free(OSSL_CMP_ITAV *itav);
|
||||
void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
|
||||
|
||||
/* from cmp_ctx.c */
|
||||
OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq);
|
||||
void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx);
|
||||
int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx);
|
||||
/* CMP general options: */
|
||||
# define OSSL_CMP_OPT_LOG_VERBOSITY 0
|
||||
/* CMP transfer options: */
|
||||
# define OSSL_CMP_OPT_KEEP_ALIVE 10
|
||||
# define OSSL_CMP_OPT_MSG_TIMEOUT 11
|
||||
# define OSSL_CMP_OPT_TOTAL_TIMEOUT 12
|
||||
/* CMP request options: */
|
||||
# define OSSL_CMP_OPT_VALIDITY_DAYS 20
|
||||
# define OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT 21
|
||||
# define OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL 22
|
||||
# define OSSL_CMP_OPT_POLICIES_CRITICAL 23
|
||||
# define OSSL_CMP_OPT_POPO_METHOD 24
|
||||
# define OSSL_CMP_OPT_IMPLICIT_CONFIRM 25
|
||||
# define OSSL_CMP_OPT_DISABLE_CONFIRM 26
|
||||
# define OSSL_CMP_OPT_REVOCATION_REASON 27
|
||||
/* CMP protection options: */
|
||||
# define OSSL_CMP_OPT_UNPROTECTED_SEND 30
|
||||
# define OSSL_CMP_OPT_UNPROTECTED_ERRORS 31
|
||||
# define OSSL_CMP_OPT_OWF_ALGNID 32
|
||||
# define OSSL_CMP_OPT_MAC_ALGNID 33
|
||||
# define OSSL_CMP_OPT_DIGEST_ALGNID 34
|
||||
# define OSSL_CMP_OPT_IGNORE_KEYUSAGE 35
|
||||
# define OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR 36
|
||||
int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val);
|
||||
int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt);
|
||||
/* CMP-specific callback for logging and outputting the error queue: */
|
||||
int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb);
|
||||
# define OSSL_CMP_CTX_set_log_verbosity(ctx, level) \
|
||||
OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_LOG_VERBOSITY, level)
|
||||
void OSSL_CMP_CTX_print_errors(const OSSL_CMP_CTX *ctx);
|
||||
/* message transfer: */
|
||||
int OSSL_CMP_CTX_set1_serverPath(OSSL_CMP_CTX *ctx, const char *path);
|
||||
int OSSL_CMP_CTX_set1_server(OSSL_CMP_CTX *ctx, const char *address);
|
||||
int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port);
|
||||
int OSSL_CMP_CTX_set1_proxy(OSSL_CMP_CTX *ctx, const char *name);
|
||||
int OSSL_CMP_CTX_set1_no_proxy(OSSL_CMP_CTX *ctx, const char *names);
|
||||
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb);
|
||||
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
|
||||
void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx);
|
||||
typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t) (OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *req);
|
||||
int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb);
|
||||
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
|
||||
void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx);
|
||||
/* server authentication: */
|
||||
int OSSL_CMP_CTX_set1_srvCert(OSSL_CMP_CTX *ctx, X509 *cert);
|
||||
int OSSL_CMP_CTX_set1_expected_sender(OSSL_CMP_CTX *ctx, const X509_NAME *name);
|
||||
int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store);
|
||||
X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx);
|
||||
int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted(const OSSL_CMP_CTX *ctx);
|
||||
/* client authentication: */
|
||||
int OSSL_CMP_CTX_set1_cert(OSSL_CMP_CTX *ctx, X509 *cert);
|
||||
int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted,
|
||||
STACK_OF(X509) *candidates);
|
||||
int OSSL_CMP_CTX_set1_pkey(OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
|
||||
int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
|
||||
const unsigned char *ref, int len);
|
||||
int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
|
||||
const int len);
|
||||
/* CMP message header and extra certificates: */
|
||||
int OSSL_CMP_CTX_set1_recipient(OSSL_CMP_CTX *ctx, const X509_NAME *name);
|
||||
int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
|
||||
int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
|
||||
STACK_OF(X509) *extraCertsOut);
|
||||
/* certificate template: */
|
||||
int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey);
|
||||
EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv);
|
||||
int OSSL_CMP_CTX_set1_issuer(OSSL_CMP_CTX *ctx, const X509_NAME *name);
|
||||
int OSSL_CMP_CTX_set1_subjectName(OSSL_CMP_CTX *ctx, const X509_NAME *name);
|
||||
int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
|
||||
const GENERAL_NAME *name);
|
||||
int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts);
|
||||
int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx);
|
||||
int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo);
|
||||
int OSSL_CMP_CTX_set1_oldCert(OSSL_CMP_CTX *ctx, X509 *cert);
|
||||
int OSSL_CMP_CTX_set1_p10CSR(OSSL_CMP_CTX *ctx, const X509_REQ *csr);
|
||||
/* misc body contents: */
|
||||
int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
|
||||
/* certificate confirmation: */
|
||||
typedef int (*OSSL_CMP_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert,
|
||||
int fail_info, const char **txt);
|
||||
int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
|
||||
const char **text);
|
||||
int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb);
|
||||
int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
|
||||
void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx);
|
||||
/* result fetching: */
|
||||
int OSSL_CMP_CTX_get_status(const OSSL_CMP_CTX *ctx);
|
||||
OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx);
|
||||
int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx);
|
||||
# define OSSL_CMP_PKISI_BUFLEN 1024
|
||||
X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx);
|
||||
int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
|
||||
const ASN1_OCTET_STRING *id);
|
||||
int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
|
||||
const ASN1_OCTET_STRING *nonce);
|
||||
|
||||
/* from cmp_status.c */
|
||||
char *OSSL_CMP_CTX_snprint_PKIStatus(const OSSL_CMP_CTX *ctx, char *buf,
|
||||
size_t bufsize);
|
||||
char *OSSL_CMP_snprint_PKIStatusInfo(const OSSL_CMP_PKISI *statusInfo,
|
||||
char *buf, size_t bufsize);
|
||||
OSSL_CMP_PKISI *
|
||||
OSSL_CMP_STATUSINFO_new(int status, int fail_info, const char *text);
|
||||
|
||||
/* from cmp_hdr.c */
|
||||
ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const
|
||||
OSSL_CMP_PKIHEADER *hdr);
|
||||
ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr);
|
||||
|
||||
/* from cmp_msg.c */
|
||||
OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
|
||||
int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg);
|
||||
int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
|
||||
OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid);
|
||||
OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx,
|
||||
const char *propq);
|
||||
int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg);
|
||||
OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg);
|
||||
int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg);
|
||||
|
||||
/* from cmp_vfy.c */
|
||||
int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg);
|
||||
int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
|
||||
X509_STORE *trusted_store, X509 *cert);
|
||||
|
||||
/* from cmp_http.c */
|
||||
OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *req);
|
||||
|
||||
/* from cmp_server.c */
|
||||
typedef struct ossl_cmp_srv_ctx_st OSSL_CMP_SRV_CTX;
|
||||
OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
|
||||
const OSSL_CMP_MSG *req);
|
||||
OSSL_CMP_MSG * OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx,
|
||||
const OSSL_CMP_MSG *req);
|
||||
OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq);
|
||||
void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx);
|
||||
typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_cert_request_cb_t)
|
||||
(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req, int certReqId,
|
||||
const OSSL_CRMF_MSG *crm, const X509_REQ *p10cr,
|
||||
X509 **certOut, STACK_OF(X509) **chainOut, STACK_OF(X509) **caPubs);
|
||||
typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_rr_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
|
||||
const OSSL_CMP_MSG *req,
|
||||
const X509_NAME *issuer,
|
||||
const ASN1_INTEGER *serial);
|
||||
typedef int (*OSSL_CMP_SRV_genm_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
|
||||
const OSSL_CMP_MSG *req,
|
||||
const STACK_OF(OSSL_CMP_ITAV) *in,
|
||||
STACK_OF(OSSL_CMP_ITAV) **out);
|
||||
typedef void (*OSSL_CMP_SRV_error_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
|
||||
const OSSL_CMP_MSG *req,
|
||||
const OSSL_CMP_PKISI *statusInfo,
|
||||
const ASN1_INTEGER *errorCode,
|
||||
const OSSL_CMP_PKIFREETEXT *errDetails);
|
||||
typedef int (*OSSL_CMP_SRV_certConf_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
|
||||
const OSSL_CMP_MSG *req,
|
||||
int certReqId,
|
||||
const ASN1_OCTET_STRING *certHash,
|
||||
const OSSL_CMP_PKISI *si);
|
||||
typedef int (*OSSL_CMP_SRV_pollReq_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
|
||||
const OSSL_CMP_MSG *req, int certReqId,
|
||||
OSSL_CMP_MSG **certReq,
|
||||
int64_t *check_after);
|
||||
int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
|
||||
OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
|
||||
OSSL_CMP_SRV_rr_cb_t process_rr,
|
||||
OSSL_CMP_SRV_genm_cb_t process_genm,
|
||||
OSSL_CMP_SRV_error_cb_t process_error,
|
||||
OSSL_CMP_SRV_certConf_cb_t process_certConf,
|
||||
OSSL_CMP_SRV_pollReq_cb_t process_pollReq);
|
||||
OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
|
||||
void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
|
||||
int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx,
|
||||
int val);
|
||||
int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val);
|
||||
int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val);
|
||||
int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
|
||||
int val);
|
||||
|
||||
/* from cmp_client.c */
|
||||
X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type,
|
||||
const OSSL_CRMF_MSG *crm);
|
||||
# define OSSL_CMP_IR 0
|
||||
# define OSSL_CMP_CR 2
|
||||
# define OSSL_CMP_P10CR 4
|
||||
# define OSSL_CMP_KUR 7
|
||||
# define OSSL_CMP_exec_IR_ses(ctx) \
|
||||
OSSL_CMP_exec_certreq(ctx, OSSL_CMP_IR, NULL)
|
||||
# define OSSL_CMP_exec_CR_ses(ctx) \
|
||||
OSSL_CMP_exec_certreq(ctx, OSSL_CMP_CR, NULL)
|
||||
# define OSSL_CMP_exec_P10CR_ses(ctx) \
|
||||
OSSL_CMP_exec_certreq(ctx, OSSL_CMP_P10CR, NULL)
|
||||
# define OSSL_CMP_exec_KUR_ses(ctx) \
|
||||
OSSL_CMP_exec_certreq(ctx, OSSL_CMP_KUR, NULL)
|
||||
int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
|
||||
const OSSL_CRMF_MSG *crm, int *checkAfter);
|
||||
int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
# endif /* !defined(OPENSSL_NO_CMP) */
|
||||
#endif /* !defined(OPENSSL_CMP_H) */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -284,8 +284,6 @@ int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
|
||||
void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
|
||||
int lastpos, int type);
|
||||
|
||||
# ifdef HEADER_X509V3_H
|
||||
|
||||
int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
|
||||
CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
|
||||
int allorfirst,
|
||||
@@ -298,7 +296,6 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
|
||||
int *pallorfirst,
|
||||
STACK_OF(GENERAL_NAMES) **plist,
|
||||
STACK_OF(GENERAL_NAMES) **prto);
|
||||
# endif
|
||||
int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri,
|
||||
X509_ALGOR **palg,
|
||||
ASN1_OCTET_STRING **pukm);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_CMSERR_H
|
||||
# define HEADER_CMSERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_CMS
|
||||
@@ -101,6 +105,7 @@ int ERR_load_CMS_strings(void);
|
||||
# define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153
|
||||
# define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154
|
||||
# define CMS_F_CMS_SIGN_RECEIPT 163
|
||||
# define CMS_F_CMS_SI_CHECK_ATTRIBUTES 183
|
||||
# define CMS_F_CMS_STREAM 155
|
||||
# define CMS_F_CMS_UNCOMPRESS 156
|
||||
# define CMS_F_CMS_VERIFY 157
|
||||
@@ -110,6 +115,7 @@ int ERR_load_CMS_strings(void);
|
||||
* CMS reason codes.
|
||||
*/
|
||||
# define CMS_R_ADD_SIGNER_ERROR 99
|
||||
# define CMS_R_ATTRIBUTE_ERROR 161
|
||||
# define CMS_R_CERTIFICATE_ALREADY_PRESENT 175
|
||||
# define CMS_R_CERTIFICATE_HAS_NO_KEYID 160
|
||||
# define CMS_R_CERTIFICATE_VERIFY_ERROR 100
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_COMPERR_H
|
||||
# define HEADER_COMPERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_COMP
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_CONFERR_H
|
||||
# define HEADER_CONFERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* WARNING: do not edit!
|
||||
* Generated by Makefile from include/openssl/configuration.h.in
|
||||
*
|
||||
* Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_CONFIGURATION_H
|
||||
# define OPENSSL_CONFIGURATION_H
|
||||
# pragma once
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
# ifdef OPENSSL_ALGORITHM_DEFINES
|
||||
# error OPENSSL_ALGORITHM_DEFINES no longer supported
|
||||
# endif
|
||||
|
||||
/*
|
||||
* OpenSSL was configured with the following options:
|
||||
*/
|
||||
|
||||
# define OPENSSL_CONFIGURED_API 30000
|
||||
# ifndef OPENSSL_RAND_SEED_OS
|
||||
# define OPENSSL_RAND_SEED_OS
|
||||
# endif
|
||||
# ifndef OPENSSL_THREADS
|
||||
# define OPENSSL_THREADS
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_ACVP_TESTS
|
||||
# define OPENSSL_NO_ACVP_TESTS
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_AFALGENG
|
||||
# define OPENSSL_NO_AFALGENG
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_ASAN
|
||||
# define OPENSSL_NO_ASAN
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_CAPIENG
|
||||
# define OPENSSL_NO_CAPIENG
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
# define OPENSSL_NO_CRYPTO_MDEBUG
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
|
||||
# define OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_DEPRECATED
|
||||
# define OPENSSL_NO_DEPRECATED
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_DEVCRYPTOENG
|
||||
# define OPENSSL_NO_DEVCRYPTOENG
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
|
||||
# define OPENSSL_NO_EC_NISTP_64_GCC_128
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_EGD
|
||||
# define OPENSSL_NO_EGD
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_ENGINE
|
||||
# define OPENSSL_NO_ENGINE
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_EXTERNAL_TESTS
|
||||
# define OPENSSL_NO_EXTERNAL_TESTS
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_FIPS_SECURITYCHECKS
|
||||
# define OPENSSL_NO_FIPS_SECURITYCHECKS
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_FUZZ_AFL
|
||||
# define OPENSSL_NO_FUZZ_AFL
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_FUZZ_LIBFUZZER
|
||||
# define OPENSSL_NO_FUZZ_LIBFUZZER
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_KTLS
|
||||
# define OPENSSL_NO_KTLS
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_LOADERENG
|
||||
# define OPENSSL_NO_LOADERENG
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_MD2
|
||||
# define OPENSSL_NO_MD2
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_MSAN
|
||||
# define OPENSSL_NO_MSAN
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_PADLOCKENG
|
||||
# define OPENSSL_NO_PADLOCKENG
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_RC5
|
||||
# define OPENSSL_NO_RC5
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_SCTP
|
||||
# define OPENSSL_NO_SCTP
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_SRP
|
||||
# define OPENSSL_NO_SRP
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_SSL3
|
||||
# define OPENSSL_NO_SSL3
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_SSL3_METHOD
|
||||
# define OPENSSL_NO_SSL3_METHOD
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_TESTS
|
||||
# define OPENSSL_NO_TESTS
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_TRACE
|
||||
# define OPENSSL_NO_TRACE
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_UBSAN
|
||||
# define OPENSSL_NO_UBSAN
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_UNIT_TEST
|
||||
# define OPENSSL_NO_UNIT_TEST
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_UPLINK
|
||||
# define OPENSSL_NO_UPLINK
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
|
||||
# define OPENSSL_NO_WEAK_SSL_CIPHERS
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_DYNAMIC_ENGINE
|
||||
# define OPENSSL_NO_DYNAMIC_ENGINE
|
||||
# endif
|
||||
|
||||
|
||||
/* Generate 80386 code? */
|
||||
# undef I386_ONLY
|
||||
|
||||
/*
|
||||
* The following are cipher-specific, but are part of the public API.
|
||||
*/
|
||||
# if !defined(OPENSSL_SYS_UEFI)
|
||||
# undef BN_LLONG
|
||||
/* Only one for the following should be defined */
|
||||
# define SIXTY_FOUR_BIT_LONG
|
||||
# undef SIXTY_FOUR_BIT
|
||||
# undef THIRTY_TWO_BIT
|
||||
# endif
|
||||
|
||||
# define RC4_INT unsigned int
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif /* OPENSSL_CONFIGURATION_H */
|
||||
@@ -0,0 +1,227 @@
|
||||
/*-
|
||||
* WARNING: do not edit!
|
||||
* Generated by Makefile from include/openssl/crmf.h.in
|
||||
*
|
||||
* Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright Nokia 2007-2019
|
||||
* Copyright Siemens AG 2015-2019
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*
|
||||
* CRMF (RFC 4211) implementation by M. Peylo, M. Viljanen, and D. von Oheimb.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef OPENSSL_CRMF_H
|
||||
# define OPENSSL_CRMF_H
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_CRMF
|
||||
# include <openssl/opensslv.h>
|
||||
# include <openssl/safestack.h>
|
||||
# include <openssl/crmferr.h>
|
||||
# include <openssl/x509v3.h> /* for GENERAL_NAME etc. */
|
||||
|
||||
/* explicit #includes not strictly needed since implied by the above: */
|
||||
# include <openssl/types.h>
|
||||
# include <openssl/x509.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
# define OSSL_CRMF_POPOPRIVKEY_THISMESSAGE 0
|
||||
# define OSSL_CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE 1
|
||||
# define OSSL_CRMF_POPOPRIVKEY_DHMAC 2
|
||||
# define OSSL_CRMF_POPOPRIVKEY_AGREEMAC 3
|
||||
# define OSSL_CRMF_POPOPRIVKEY_ENCRYPTEDKEY 4
|
||||
|
||||
# define OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT 0
|
||||
# define OSSL_CRMF_SUBSEQUENTMESSAGE_CHALLENGERESP 1
|
||||
|
||||
typedef struct ossl_crmf_encryptedvalue_st OSSL_CRMF_ENCRYPTEDVALUE;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDVALUE)
|
||||
typedef struct ossl_crmf_msg_st OSSL_CRMF_MSG;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_MSG)
|
||||
DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_MSG)
|
||||
SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CRMF_MSG, OSSL_CRMF_MSG, OSSL_CRMF_MSG)
|
||||
#define sk_OSSL_CRMF_MSG_num(sk) OPENSSL_sk_num(ossl_check_const_OSSL_CRMF_MSG_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_MSG_value(sk, idx) ((OSSL_CRMF_MSG *)OPENSSL_sk_value(ossl_check_const_OSSL_CRMF_MSG_sk_type(sk), (idx)))
|
||||
#define sk_OSSL_CRMF_MSG_new(cmp) ((STACK_OF(OSSL_CRMF_MSG) *)OPENSSL_sk_new(ossl_check_OSSL_CRMF_MSG_compfunc_type(cmp)))
|
||||
#define sk_OSSL_CRMF_MSG_new_null() ((STACK_OF(OSSL_CRMF_MSG) *)OPENSSL_sk_new_null())
|
||||
#define sk_OSSL_CRMF_MSG_new_reserve(cmp, n) ((STACK_OF(OSSL_CRMF_MSG) *)OPENSSL_sk_new_reserve(ossl_check_OSSL_CRMF_MSG_compfunc_type(cmp), (n)))
|
||||
#define sk_OSSL_CRMF_MSG_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_OSSL_CRMF_MSG_sk_type(sk), (n))
|
||||
#define sk_OSSL_CRMF_MSG_free(sk) OPENSSL_sk_free(ossl_check_OSSL_CRMF_MSG_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_MSG_zero(sk) OPENSSL_sk_zero(ossl_check_OSSL_CRMF_MSG_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_MSG_delete(sk, i) ((OSSL_CRMF_MSG *)OPENSSL_sk_delete(ossl_check_OSSL_CRMF_MSG_sk_type(sk), (i)))
|
||||
#define sk_OSSL_CRMF_MSG_delete_ptr(sk, ptr) ((OSSL_CRMF_MSG *)OPENSSL_sk_delete_ptr(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr)))
|
||||
#define sk_OSSL_CRMF_MSG_push(sk, ptr) OPENSSL_sk_push(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr))
|
||||
#define sk_OSSL_CRMF_MSG_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr))
|
||||
#define sk_OSSL_CRMF_MSG_pop(sk) ((OSSL_CRMF_MSG *)OPENSSL_sk_pop(ossl_check_OSSL_CRMF_MSG_sk_type(sk)))
|
||||
#define sk_OSSL_CRMF_MSG_shift(sk) ((OSSL_CRMF_MSG *)OPENSSL_sk_shift(ossl_check_OSSL_CRMF_MSG_sk_type(sk)))
|
||||
#define sk_OSSL_CRMF_MSG_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CRMF_MSG_sk_type(sk),ossl_check_OSSL_CRMF_MSG_freefunc_type(freefunc))
|
||||
#define sk_OSSL_CRMF_MSG_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr), (idx))
|
||||
#define sk_OSSL_CRMF_MSG_set(sk, idx, ptr) ((OSSL_CRMF_MSG *)OPENSSL_sk_set(ossl_check_OSSL_CRMF_MSG_sk_type(sk), (idx), ossl_check_OSSL_CRMF_MSG_type(ptr)))
|
||||
#define sk_OSSL_CRMF_MSG_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr))
|
||||
#define sk_OSSL_CRMF_MSG_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr))
|
||||
#define sk_OSSL_CRMF_MSG_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr), pnum)
|
||||
#define sk_OSSL_CRMF_MSG_sort(sk) OPENSSL_sk_sort(ossl_check_OSSL_CRMF_MSG_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_MSG_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_OSSL_CRMF_MSG_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_MSG_dup(sk) ((STACK_OF(OSSL_CRMF_MSG) *)OPENSSL_sk_dup(ossl_check_const_OSSL_CRMF_MSG_sk_type(sk)))
|
||||
#define sk_OSSL_CRMF_MSG_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(OSSL_CRMF_MSG) *)OPENSSL_sk_deep_copy(ossl_check_const_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_copyfunc_type(copyfunc), ossl_check_OSSL_CRMF_MSG_freefunc_type(freefunc)))
|
||||
#define sk_OSSL_CRMF_MSG_set_cmp_func(sk, cmp) ((sk_OSSL_CRMF_MSG_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_compfunc_type(cmp)))
|
||||
|
||||
typedef struct ossl_crmf_attributetypeandvalue_st OSSL_CRMF_ATTRIBUTETYPEANDVALUE;
|
||||
typedef struct ossl_crmf_pbmparameter_st OSSL_CRMF_PBMPARAMETER;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PBMPARAMETER)
|
||||
typedef struct ossl_crmf_poposigningkey_st OSSL_CRMF_POPOSIGNINGKEY;
|
||||
typedef struct ossl_crmf_certrequest_st OSSL_CRMF_CERTREQUEST;
|
||||
typedef struct ossl_crmf_certid_st OSSL_CRMF_CERTID;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTID)
|
||||
DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID)
|
||||
SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CRMF_CERTID, OSSL_CRMF_CERTID, OSSL_CRMF_CERTID)
|
||||
#define sk_OSSL_CRMF_CERTID_num(sk) OPENSSL_sk_num(ossl_check_const_OSSL_CRMF_CERTID_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_CERTID_value(sk, idx) ((OSSL_CRMF_CERTID *)OPENSSL_sk_value(ossl_check_const_OSSL_CRMF_CERTID_sk_type(sk), (idx)))
|
||||
#define sk_OSSL_CRMF_CERTID_new(cmp) ((STACK_OF(OSSL_CRMF_CERTID) *)OPENSSL_sk_new(ossl_check_OSSL_CRMF_CERTID_compfunc_type(cmp)))
|
||||
#define sk_OSSL_CRMF_CERTID_new_null() ((STACK_OF(OSSL_CRMF_CERTID) *)OPENSSL_sk_new_null())
|
||||
#define sk_OSSL_CRMF_CERTID_new_reserve(cmp, n) ((STACK_OF(OSSL_CRMF_CERTID) *)OPENSSL_sk_new_reserve(ossl_check_OSSL_CRMF_CERTID_compfunc_type(cmp), (n)))
|
||||
#define sk_OSSL_CRMF_CERTID_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), (n))
|
||||
#define sk_OSSL_CRMF_CERTID_free(sk) OPENSSL_sk_free(ossl_check_OSSL_CRMF_CERTID_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_CERTID_zero(sk) OPENSSL_sk_zero(ossl_check_OSSL_CRMF_CERTID_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_CERTID_delete(sk, i) ((OSSL_CRMF_CERTID *)OPENSSL_sk_delete(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), (i)))
|
||||
#define sk_OSSL_CRMF_CERTID_delete_ptr(sk, ptr) ((OSSL_CRMF_CERTID *)OPENSSL_sk_delete_ptr(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr)))
|
||||
#define sk_OSSL_CRMF_CERTID_push(sk, ptr) OPENSSL_sk_push(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr))
|
||||
#define sk_OSSL_CRMF_CERTID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr))
|
||||
#define sk_OSSL_CRMF_CERTID_pop(sk) ((OSSL_CRMF_CERTID *)OPENSSL_sk_pop(ossl_check_OSSL_CRMF_CERTID_sk_type(sk)))
|
||||
#define sk_OSSL_CRMF_CERTID_shift(sk) ((OSSL_CRMF_CERTID *)OPENSSL_sk_shift(ossl_check_OSSL_CRMF_CERTID_sk_type(sk)))
|
||||
#define sk_OSSL_CRMF_CERTID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CRMF_CERTID_sk_type(sk),ossl_check_OSSL_CRMF_CERTID_freefunc_type(freefunc))
|
||||
#define sk_OSSL_CRMF_CERTID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr), (idx))
|
||||
#define sk_OSSL_CRMF_CERTID_set(sk, idx, ptr) ((OSSL_CRMF_CERTID *)OPENSSL_sk_set(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), (idx), ossl_check_OSSL_CRMF_CERTID_type(ptr)))
|
||||
#define sk_OSSL_CRMF_CERTID_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr))
|
||||
#define sk_OSSL_CRMF_CERTID_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr))
|
||||
#define sk_OSSL_CRMF_CERTID_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr), pnum)
|
||||
#define sk_OSSL_CRMF_CERTID_sort(sk) OPENSSL_sk_sort(ossl_check_OSSL_CRMF_CERTID_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_CERTID_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_OSSL_CRMF_CERTID_sk_type(sk))
|
||||
#define sk_OSSL_CRMF_CERTID_dup(sk) ((STACK_OF(OSSL_CRMF_CERTID) *)OPENSSL_sk_dup(ossl_check_const_OSSL_CRMF_CERTID_sk_type(sk)))
|
||||
#define sk_OSSL_CRMF_CERTID_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(OSSL_CRMF_CERTID) *)OPENSSL_sk_deep_copy(ossl_check_const_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_copyfunc_type(copyfunc), ossl_check_OSSL_CRMF_CERTID_freefunc_type(freefunc)))
|
||||
#define sk_OSSL_CRMF_CERTID_set_cmp_func(sk, cmp) ((sk_OSSL_CRMF_CERTID_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_compfunc_type(cmp)))
|
||||
|
||||
|
||||
typedef struct ossl_crmf_pkipublicationinfo_st OSSL_CRMF_PKIPUBLICATIONINFO;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PKIPUBLICATIONINFO)
|
||||
typedef struct ossl_crmf_singlepubinfo_st OSSL_CRMF_SINGLEPUBINFO;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_SINGLEPUBINFO)
|
||||
typedef struct ossl_crmf_certtemplate_st OSSL_CRMF_CERTTEMPLATE;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTTEMPLATE)
|
||||
typedef STACK_OF(OSSL_CRMF_MSG) OSSL_CRMF_MSGS;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_MSGS)
|
||||
|
||||
typedef struct ossl_crmf_optionalvalidity_st OSSL_CRMF_OPTIONALVALIDITY;
|
||||
|
||||
/* crmf_pbm.c */
|
||||
OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(OSSL_LIB_CTX *libctx, size_t slen,
|
||||
int owfnid, size_t itercnt,
|
||||
int macnid);
|
||||
int OSSL_CRMF_pbm_new(OSSL_LIB_CTX *libctx, const char *propq,
|
||||
const OSSL_CRMF_PBMPARAMETER *pbmp,
|
||||
const unsigned char *msg, size_t msglen,
|
||||
const unsigned char *sec, size_t seclen,
|
||||
unsigned char **mac, size_t *maclen);
|
||||
|
||||
/* crmf_lib.c */
|
||||
int OSSL_CRMF_MSG_set1_regCtrl_regToken(OSSL_CRMF_MSG *msg,
|
||||
const ASN1_UTF8STRING *tok);
|
||||
ASN1_UTF8STRING
|
||||
*OSSL_CRMF_MSG_get0_regCtrl_regToken(const OSSL_CRMF_MSG *msg);
|
||||
int OSSL_CRMF_MSG_set1_regCtrl_authenticator(OSSL_CRMF_MSG *msg,
|
||||
const ASN1_UTF8STRING *auth);
|
||||
ASN1_UTF8STRING
|
||||
*OSSL_CRMF_MSG_get0_regCtrl_authenticator(const OSSL_CRMF_MSG *msg);
|
||||
int
|
||||
OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
|
||||
OSSL_CRMF_SINGLEPUBINFO *spi);
|
||||
# define OSSL_CRMF_PUB_METHOD_DONTCARE 0
|
||||
# define OSSL_CRMF_PUB_METHOD_X500 1
|
||||
# define OSSL_CRMF_PUB_METHOD_WEB 2
|
||||
# define OSSL_CRMF_PUB_METHOD_LDAP 3
|
||||
int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
|
||||
int method, GENERAL_NAME *nm);
|
||||
# define OSSL_CRMF_PUB_ACTION_DONTPUBLISH 0
|
||||
# define OSSL_CRMF_PUB_ACTION_PLEASEPUBLISH 1
|
||||
int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
|
||||
int action);
|
||||
int OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo(OSSL_CRMF_MSG *msg,
|
||||
const OSSL_CRMF_PKIPUBLICATIONINFO *pi);
|
||||
OSSL_CRMF_PKIPUBLICATIONINFO
|
||||
*OSSL_CRMF_MSG_get0_regCtrl_pkiPublicationInfo(const OSSL_CRMF_MSG *msg);
|
||||
int OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey(OSSL_CRMF_MSG *msg,
|
||||
const X509_PUBKEY *pubkey);
|
||||
X509_PUBKEY
|
||||
*OSSL_CRMF_MSG_get0_regCtrl_protocolEncrKey(const OSSL_CRMF_MSG *msg);
|
||||
int OSSL_CRMF_MSG_set1_regCtrl_oldCertID(OSSL_CRMF_MSG *msg,
|
||||
const OSSL_CRMF_CERTID *cid);
|
||||
OSSL_CRMF_CERTID
|
||||
*OSSL_CRMF_MSG_get0_regCtrl_oldCertID(const OSSL_CRMF_MSG *msg);
|
||||
OSSL_CRMF_CERTID *OSSL_CRMF_CERTID_gen(const X509_NAME *issuer,
|
||||
const ASN1_INTEGER *serial);
|
||||
|
||||
int OSSL_CRMF_MSG_set1_regInfo_utf8Pairs(OSSL_CRMF_MSG *msg,
|
||||
const ASN1_UTF8STRING *utf8pairs);
|
||||
ASN1_UTF8STRING
|
||||
*OSSL_CRMF_MSG_get0_regInfo_utf8Pairs(const OSSL_CRMF_MSG *msg);
|
||||
int OSSL_CRMF_MSG_set1_regInfo_certReq(OSSL_CRMF_MSG *msg,
|
||||
const OSSL_CRMF_CERTREQUEST *cr);
|
||||
OSSL_CRMF_CERTREQUEST
|
||||
*OSSL_CRMF_MSG_get0_regInfo_certReq(const OSSL_CRMF_MSG *msg);
|
||||
|
||||
int OSSL_CRMF_MSG_set0_validity(OSSL_CRMF_MSG *crm,
|
||||
ASN1_TIME *notBefore, ASN1_TIME *notAfter);
|
||||
int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid);
|
||||
int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm);
|
||||
int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm, X509_EXTENSIONS *exts);
|
||||
|
||||
int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm, X509_EXTENSION *ext);
|
||||
# define OSSL_CRMF_POPO_NONE -1
|
||||
# define OSSL_CRMF_POPO_RAVERIFIED 0
|
||||
# define OSSL_CRMF_POPO_SIGNATURE 1
|
||||
# define OSSL_CRMF_POPO_KEYENC 2
|
||||
# define OSSL_CRMF_POPO_KEYAGREE 3
|
||||
int OSSL_CRMF_MSG_create_popo(int meth, OSSL_CRMF_MSG *crm,
|
||||
EVP_PKEY *pkey, const EVP_MD *digest,
|
||||
OSSL_LIB_CTX *libctx, const char *propq);
|
||||
int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
|
||||
int rid, int acceptRAVerified,
|
||||
OSSL_LIB_CTX *libctx, const char *propq);
|
||||
OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm);
|
||||
const ASN1_INTEGER
|
||||
*OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl);
|
||||
const X509_NAME
|
||||
*OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl);
|
||||
const X509_NAME
|
||||
*OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl);
|
||||
X509_EXTENSIONS
|
||||
*OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl);
|
||||
const X509_NAME
|
||||
*OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid);
|
||||
const ASN1_INTEGER
|
||||
*OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid);
|
||||
int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
|
||||
EVP_PKEY *pubkey,
|
||||
const X509_NAME *subject,
|
||||
const X509_NAME *issuer,
|
||||
const ASN1_INTEGER *serial);
|
||||
X509
|
||||
*OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
|
||||
OSSL_LIB_CTX *libctx, const char *propq,
|
||||
EVP_PKEY *pkey);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
# endif /* !defined(OPENSSL_NO_CRMF) */
|
||||
#endif /* !defined(OPENSSL_CRMF_H) */
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,12 +11,13 @@
|
||||
#ifndef HEADER_CRYPTOERR_H
|
||||
# define HEADER_CRYPTOERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
int ERR_load_CRYPTO_strings(void);
|
||||
|
||||
/*
|
||||
|
||||
@@ -463,8 +463,6 @@ __owur int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file);
|
||||
|
||||
/*
|
||||
* Loads the default CT log list into a |store|.
|
||||
* See internal/cryptlib.h for the environment variable and file path that are
|
||||
* consulted to find the default file.
|
||||
* Returns 1 if loading is successful, or 0 otherwise.
|
||||
*/
|
||||
__owur int CTLOG_STORE_load_default_file(CTLOG_STORE *store);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_CTERR_H
|
||||
# define HEADER_CTERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_CT
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_DHERR_H
|
||||
# define HEADER_DHERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_DH
|
||||
|
||||
@@ -162,6 +162,12 @@ DH *DSA_dup_DH(const DSA *r);
|
||||
# define EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
|
||||
EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, nbits, NULL)
|
||||
# define EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, qbits) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
|
||||
EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits, NULL)
|
||||
# define EVP_PKEY_CTX_set_dsa_paramgen_md(ctx, md) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
|
||||
EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, (void *)(md))
|
||||
|
||||
# define EVP_PKEY_CTRL_DSA_PARAMGEN_BITS (EVP_PKEY_ALG_CTRL + 1)
|
||||
# define EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS (EVP_PKEY_ALG_CTRL + 2)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_DSAERR_H
|
||||
# define HEADER_DSAERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_DSA
|
||||
@@ -57,6 +61,7 @@ int ERR_load_DSA_strings(void);
|
||||
# define DSA_R_INVALID_DIGEST_TYPE 106
|
||||
# define DSA_R_INVALID_PARAMETERS 112
|
||||
# define DSA_R_MISSING_PARAMETERS 101
|
||||
# define DSA_R_MISSING_PRIVATE_KEY 111
|
||||
# define DSA_R_MODULUS_TOO_LARGE 103
|
||||
# define DSA_R_NO_PARAMETERS_SET 107
|
||||
# define DSA_R_PARAMETER_ENCODING_ERROR 105
|
||||
|
||||
@@ -43,7 +43,7 @@ extern "C" {
|
||||
|
||||
# define DTLS1_AL_HEADER_LENGTH 2
|
||||
|
||||
/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */
|
||||
/* Timeout multipliers */
|
||||
# define DTLS1_TMO_READ_COUNT 2
|
||||
# define DTLS1_TMO_WRITE_COUNT 2
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -241,7 +241,7 @@ typedef UINT64 uint64_t;
|
||||
defined(__osf__) || defined(__sgi) || defined(__hpux) || \
|
||||
defined(OPENSSL_SYS_VMS) || defined (__OpenBSD__)
|
||||
# include <inttypes.h>
|
||||
# elif defined(_MSC_VER) && _MSC_VER<=1500
|
||||
# elif defined(_MSC_VER) && _MSC_VER<1600
|
||||
/*
|
||||
* minimally required typdefs for systems not supporting inttypes.h or
|
||||
* stdint.h: currently just older VC++
|
||||
@@ -279,7 +279,8 @@ typedef unsigned __int64 uint64_t;
|
||||
# define ossl_inline inline
|
||||
# endif
|
||||
|
||||
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
|
||||
!defined(__cplusplus)
|
||||
# define ossl_noreturn _Noreturn
|
||||
# elif defined(__GNUC__) && __GNUC__ >= 2
|
||||
# define ossl_noreturn __attribute__((noreturn))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
@@ -142,7 +142,7 @@ const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
|
||||
*/
|
||||
int EC_METHOD_get_field_type(const EC_METHOD *meth);
|
||||
|
||||
/** Sets the generator and it's order/cofactor of a EC_GROUP object.
|
||||
/** Sets the generator and its order/cofactor of a EC_GROUP object.
|
||||
* \param group EC_GROUP object
|
||||
* \param generator EC_POINT object with the generator.
|
||||
* \param order the order of the group generated by the generator.
|
||||
@@ -793,12 +793,15 @@ int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
|
||||
EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
|
||||
int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
|
||||
|
||||
# define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)
|
||||
# define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)
|
||||
# define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \
|
||||
(char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))
|
||||
# define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \
|
||||
(unsigned char *)(x))
|
||||
# define d2i_ECPKParameters_bio(bp,x) \
|
||||
ASN1_d2i_bio_of(EC_GROUP, NULL, d2i_ECPKParameters, bp, x)
|
||||
# define i2d_ECPKParameters_bio(bp,x) \
|
||||
ASN1_i2d_bio_of_const(EC_GROUP, i2d_ECPKParameters, bp, x)
|
||||
# define d2i_ECPKParameters_fp(fp,x) \
|
||||
(EC_GROUP *)ASN1_d2i_fp(NULL, (d2i_of_void *)d2i_ECPKParameters, (fp), \
|
||||
(void **)(x))
|
||||
# define i2d_ECPKParameters_fp(fp,x) \
|
||||
ASN1_i2d_fp((i2d_of_void *)i2d_ECPKParameters, (fp), (void *)(x))
|
||||
|
||||
int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
|
||||
# ifndef OPENSSL_NO_STDIO
|
||||
@@ -829,6 +832,8 @@ void EC_KEY_set_flags(EC_KEY *key, int flags);
|
||||
|
||||
void EC_KEY_clear_flags(EC_KEY *key, int flags);
|
||||
|
||||
int EC_KEY_decoded_from_explicit_params(const EC_KEY *key);
|
||||
|
||||
/** Creates a new EC_KEY object using a named curve as underlying
|
||||
* EC_GROUP object.
|
||||
* \param nid NID of the named curve.
|
||||
@@ -1138,7 +1143,8 @@ void ECDSA_SIG_free(ECDSA_SIG *sig);
|
||||
* (*pp += length of the DER encoded signature)).
|
||||
* \param sig pointer to the ECDSA_SIG object
|
||||
* \param pp pointer to a unsigned char pointer for the output or NULL
|
||||
* \return the length of the DER encoded ECDSA_SIG object or 0
|
||||
* \return the length of the DER encoded ECDSA_SIG object or a negative value
|
||||
* on error
|
||||
*/
|
||||
int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_ECERR_H
|
||||
# define HEADER_ECERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_EC
|
||||
@@ -239,6 +243,7 @@ int ERR_load_EC_strings(void);
|
||||
# define EC_R_LADDER_POST_FAILURE 136
|
||||
# define EC_R_LADDER_PRE_FAILURE 153
|
||||
# define EC_R_LADDER_STEP_FAILURE 162
|
||||
# define EC_R_MISSING_OID 167
|
||||
# define EC_R_MISSING_PARAMETERS 124
|
||||
# define EC_R_MISSING_PRIVATE_KEY 125
|
||||
# define EC_R_NEED_NEW_SETUP_VALUES 157
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
@@ -722,6 +722,7 @@ typedef int (*dynamic_bind_engine) (ENGINE *e, const char *id,
|
||||
CRYPTO_set_mem_functions(fns->mem_fns.malloc_fn, \
|
||||
fns->mem_fns.realloc_fn, \
|
||||
fns->mem_fns.free_fn); \
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_NO_ATEXIT, NULL); \
|
||||
skip_cbs: \
|
||||
if (!fn(e, id)) return 0; \
|
||||
return 1; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_ENGINEERR_H
|
||||
# define HEADER_ENGINEERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_ENGINE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -37,6 +37,7 @@ extern "C" {
|
||||
# define ERR_TXT_STRING 0x02
|
||||
|
||||
# define ERR_FLAG_MARK 0x01
|
||||
# define ERR_FLAG_CLEAR 0x02
|
||||
|
||||
# define ERR_NUM_ERRORS 16
|
||||
typedef struct err_state_st {
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* WARNING: do not edit!
|
||||
* Generated by Makefile from include/openssl/ess.h.in
|
||||
*
|
||||
* Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef OPENSSL_ESS_H
|
||||
# define OPENSSL_ESS_H
|
||||
# pragma once
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# include <openssl/safestack.h>
|
||||
# include <openssl/x509.h>
|
||||
# include <openssl/esserr.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
|
||||
typedef struct ESS_issuer_serial ESS_ISSUER_SERIAL;
|
||||
typedef struct ESS_cert_id ESS_CERT_ID;
|
||||
typedef struct ESS_signing_cert ESS_SIGNING_CERT;
|
||||
|
||||
SKM_DEFINE_STACK_OF_INTERNAL(ESS_CERT_ID, ESS_CERT_ID, ESS_CERT_ID)
|
||||
#define sk_ESS_CERT_ID_num(sk) OPENSSL_sk_num(ossl_check_const_ESS_CERT_ID_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_value(sk, idx) ((ESS_CERT_ID *)OPENSSL_sk_value(ossl_check_const_ESS_CERT_ID_sk_type(sk), (idx)))
|
||||
#define sk_ESS_CERT_ID_new(cmp) ((STACK_OF(ESS_CERT_ID) *)OPENSSL_sk_new(ossl_check_ESS_CERT_ID_compfunc_type(cmp)))
|
||||
#define sk_ESS_CERT_ID_new_null() ((STACK_OF(ESS_CERT_ID) *)OPENSSL_sk_new_null())
|
||||
#define sk_ESS_CERT_ID_new_reserve(cmp, n) ((STACK_OF(ESS_CERT_ID) *)OPENSSL_sk_new_reserve(ossl_check_ESS_CERT_ID_compfunc_type(cmp), (n)))
|
||||
#define sk_ESS_CERT_ID_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_ESS_CERT_ID_sk_type(sk), (n))
|
||||
#define sk_ESS_CERT_ID_free(sk) OPENSSL_sk_free(ossl_check_ESS_CERT_ID_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_zero(sk) OPENSSL_sk_zero(ossl_check_ESS_CERT_ID_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_delete(sk, i) ((ESS_CERT_ID *)OPENSSL_sk_delete(ossl_check_ESS_CERT_ID_sk_type(sk), (i)))
|
||||
#define sk_ESS_CERT_ID_delete_ptr(sk, ptr) ((ESS_CERT_ID *)OPENSSL_sk_delete_ptr(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr)))
|
||||
#define sk_ESS_CERT_ID_push(sk, ptr) OPENSSL_sk_push(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr))
|
||||
#define sk_ESS_CERT_ID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr))
|
||||
#define sk_ESS_CERT_ID_pop(sk) ((ESS_CERT_ID *)OPENSSL_sk_pop(ossl_check_ESS_CERT_ID_sk_type(sk)))
|
||||
#define sk_ESS_CERT_ID_shift(sk) ((ESS_CERT_ID *)OPENSSL_sk_shift(ossl_check_ESS_CERT_ID_sk_type(sk)))
|
||||
#define sk_ESS_CERT_ID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ESS_CERT_ID_sk_type(sk),ossl_check_ESS_CERT_ID_freefunc_type(freefunc))
|
||||
#define sk_ESS_CERT_ID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr), (idx))
|
||||
#define sk_ESS_CERT_ID_set(sk, idx, ptr) ((ESS_CERT_ID *)OPENSSL_sk_set(ossl_check_ESS_CERT_ID_sk_type(sk), (idx), ossl_check_ESS_CERT_ID_type(ptr)))
|
||||
#define sk_ESS_CERT_ID_find(sk, ptr) OPENSSL_sk_find(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr))
|
||||
#define sk_ESS_CERT_ID_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr))
|
||||
#define sk_ESS_CERT_ID_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr), pnum)
|
||||
#define sk_ESS_CERT_ID_sort(sk) OPENSSL_sk_sort(ossl_check_ESS_CERT_ID_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_ESS_CERT_ID_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_dup(sk) ((STACK_OF(ESS_CERT_ID) *)OPENSSL_sk_dup(ossl_check_const_ESS_CERT_ID_sk_type(sk)))
|
||||
#define sk_ESS_CERT_ID_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(ESS_CERT_ID) *)OPENSSL_sk_deep_copy(ossl_check_const_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_copyfunc_type(copyfunc), ossl_check_ESS_CERT_ID_freefunc_type(freefunc)))
|
||||
#define sk_ESS_CERT_ID_set_cmp_func(sk, cmp) ((sk_ESS_CERT_ID_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_compfunc_type(cmp)))
|
||||
|
||||
|
||||
|
||||
typedef struct ESS_signing_cert_v2_st ESS_SIGNING_CERT_V2;
|
||||
typedef struct ESS_cert_id_v2_st ESS_CERT_ID_V2;
|
||||
|
||||
SKM_DEFINE_STACK_OF_INTERNAL(ESS_CERT_ID_V2, ESS_CERT_ID_V2, ESS_CERT_ID_V2)
|
||||
#define sk_ESS_CERT_ID_V2_num(sk) OPENSSL_sk_num(ossl_check_const_ESS_CERT_ID_V2_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_V2_value(sk, idx) ((ESS_CERT_ID_V2 *)OPENSSL_sk_value(ossl_check_const_ESS_CERT_ID_V2_sk_type(sk), (idx)))
|
||||
#define sk_ESS_CERT_ID_V2_new(cmp) ((STACK_OF(ESS_CERT_ID_V2) *)OPENSSL_sk_new(ossl_check_ESS_CERT_ID_V2_compfunc_type(cmp)))
|
||||
#define sk_ESS_CERT_ID_V2_new_null() ((STACK_OF(ESS_CERT_ID_V2) *)OPENSSL_sk_new_null())
|
||||
#define sk_ESS_CERT_ID_V2_new_reserve(cmp, n) ((STACK_OF(ESS_CERT_ID_V2) *)OPENSSL_sk_new_reserve(ossl_check_ESS_CERT_ID_V2_compfunc_type(cmp), (n)))
|
||||
#define sk_ESS_CERT_ID_V2_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_ESS_CERT_ID_V2_sk_type(sk), (n))
|
||||
#define sk_ESS_CERT_ID_V2_free(sk) OPENSSL_sk_free(ossl_check_ESS_CERT_ID_V2_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_V2_zero(sk) OPENSSL_sk_zero(ossl_check_ESS_CERT_ID_V2_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_V2_delete(sk, i) ((ESS_CERT_ID_V2 *)OPENSSL_sk_delete(ossl_check_ESS_CERT_ID_V2_sk_type(sk), (i)))
|
||||
#define sk_ESS_CERT_ID_V2_delete_ptr(sk, ptr) ((ESS_CERT_ID_V2 *)OPENSSL_sk_delete_ptr(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr)))
|
||||
#define sk_ESS_CERT_ID_V2_push(sk, ptr) OPENSSL_sk_push(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr))
|
||||
#define sk_ESS_CERT_ID_V2_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr))
|
||||
#define sk_ESS_CERT_ID_V2_pop(sk) ((ESS_CERT_ID_V2 *)OPENSSL_sk_pop(ossl_check_ESS_CERT_ID_V2_sk_type(sk)))
|
||||
#define sk_ESS_CERT_ID_V2_shift(sk) ((ESS_CERT_ID_V2 *)OPENSSL_sk_shift(ossl_check_ESS_CERT_ID_V2_sk_type(sk)))
|
||||
#define sk_ESS_CERT_ID_V2_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ESS_CERT_ID_V2_sk_type(sk),ossl_check_ESS_CERT_ID_V2_freefunc_type(freefunc))
|
||||
#define sk_ESS_CERT_ID_V2_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr), (idx))
|
||||
#define sk_ESS_CERT_ID_V2_set(sk, idx, ptr) ((ESS_CERT_ID_V2 *)OPENSSL_sk_set(ossl_check_ESS_CERT_ID_V2_sk_type(sk), (idx), ossl_check_ESS_CERT_ID_V2_type(ptr)))
|
||||
#define sk_ESS_CERT_ID_V2_find(sk, ptr) OPENSSL_sk_find(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr))
|
||||
#define sk_ESS_CERT_ID_V2_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr))
|
||||
#define sk_ESS_CERT_ID_V2_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr), pnum)
|
||||
#define sk_ESS_CERT_ID_V2_sort(sk) OPENSSL_sk_sort(ossl_check_ESS_CERT_ID_V2_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_V2_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_ESS_CERT_ID_V2_sk_type(sk))
|
||||
#define sk_ESS_CERT_ID_V2_dup(sk) ((STACK_OF(ESS_CERT_ID_V2) *)OPENSSL_sk_dup(ossl_check_const_ESS_CERT_ID_V2_sk_type(sk)))
|
||||
#define sk_ESS_CERT_ID_V2_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(ESS_CERT_ID_V2) *)OPENSSL_sk_deep_copy(ossl_check_const_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_copyfunc_type(copyfunc), ossl_check_ESS_CERT_ID_V2_freefunc_type(freefunc)))
|
||||
#define sk_ESS_CERT_ID_V2_set_cmp_func(sk, cmp) ((sk_ESS_CERT_ID_V2_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_compfunc_type(cmp)))
|
||||
|
||||
|
||||
DECLARE_ASN1_ALLOC_FUNCTIONS(ESS_ISSUER_SERIAL)
|
||||
DECLARE_ASN1_ENCODE_FUNCTIONS_only(ESS_ISSUER_SERIAL, ESS_ISSUER_SERIAL)
|
||||
DECLARE_ASN1_DUP_FUNCTION(ESS_ISSUER_SERIAL)
|
||||
|
||||
DECLARE_ASN1_ALLOC_FUNCTIONS(ESS_CERT_ID)
|
||||
DECLARE_ASN1_ENCODE_FUNCTIONS_only(ESS_CERT_ID, ESS_CERT_ID)
|
||||
DECLARE_ASN1_DUP_FUNCTION(ESS_CERT_ID)
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS(ESS_SIGNING_CERT)
|
||||
DECLARE_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT)
|
||||
|
||||
DECLARE_ASN1_ALLOC_FUNCTIONS(ESS_CERT_ID_V2)
|
||||
DECLARE_ASN1_ENCODE_FUNCTIONS_only(ESS_CERT_ID_V2, ESS_CERT_ID_V2)
|
||||
DECLARE_ASN1_DUP_FUNCTION(ESS_CERT_ID_V2)
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS(ESS_SIGNING_CERT_V2)
|
||||
DECLARE_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2)
|
||||
|
||||
ESS_SIGNING_CERT *OSSL_ESS_signing_cert_new_init(const X509 *signcert,
|
||||
const STACK_OF(X509) *certs,
|
||||
int set_issuer_serial);
|
||||
ESS_SIGNING_CERT_V2 *OSSL_ESS_signing_cert_v2_new_init(const EVP_MD *hash_alg,
|
||||
const X509 *signcert,
|
||||
const
|
||||
STACK_OF(X509) *certs,
|
||||
int set_issuer_serial);
|
||||
int OSSL_ESS_check_signing_certs(const ESS_SIGNING_CERT *ss,
|
||||
const ESS_SIGNING_CERT_V2 *ssv2,
|
||||
const STACK_OF(X509) *chain,
|
||||
int require_signing_cert);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
@@ -180,7 +180,7 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
|
||||
* if the following flag is set.
|
||||
*/
|
||||
# define EVP_MD_CTX_FLAG_FINALISE 0x0200
|
||||
/* NOTE: 0x0400 is reserved for internal usage in evp_int.h */
|
||||
/* NOTE: 0x0400 is reserved for internal usage */
|
||||
|
||||
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
|
||||
EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher);
|
||||
@@ -260,6 +260,8 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
|
||||
# define EVP_CIPH_RAND_KEY 0x200
|
||||
/* cipher has its own additional copying logic */
|
||||
# define EVP_CIPH_CUSTOM_COPY 0x400
|
||||
/* Don't use standard iv length function */
|
||||
# define EVP_CIPH_CUSTOM_IV_LENGTH 0x800
|
||||
/* Allow use default ASN1 get/set iv */
|
||||
# define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000
|
||||
/* Buffer length in bits not bytes: CFB1 mode only */
|
||||
@@ -349,6 +351,8 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
|
||||
/* Set the input buffer lengths to use for a pipelined operation */
|
||||
# define EVP_CTRL_SET_PIPELINE_INPUT_LENS 0x24
|
||||
|
||||
# define EVP_CTRL_GET_IVLEN 0x25
|
||||
|
||||
/* Padding modes */
|
||||
#define EVP_PADDING_PKCS7 1
|
||||
#define EVP_PADDING_ISO7816_4 2
|
||||
@@ -995,6 +999,7 @@ int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
|
||||
int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type);
|
||||
# ifndef OPENSSL_NO_ENGINE
|
||||
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e);
|
||||
ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey);
|
||||
# endif
|
||||
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key);
|
||||
void *EVP_PKEY_get0(const EVP_PKEY *pkey);
|
||||
@@ -1507,6 +1512,20 @@ void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
|
||||
const char *type,
|
||||
const char *value));
|
||||
|
||||
void EVP_PKEY_meth_set_digestsign(EVP_PKEY_METHOD *pmeth,
|
||||
int (*digestsign) (EVP_MD_CTX *ctx,
|
||||
unsigned char *sig,
|
||||
size_t *siglen,
|
||||
const unsigned char *tbs,
|
||||
size_t tbslen));
|
||||
|
||||
void EVP_PKEY_meth_set_digestverify(EVP_PKEY_METHOD *pmeth,
|
||||
int (*digestverify) (EVP_MD_CTX *ctx,
|
||||
const unsigned char *sig,
|
||||
size_t siglen,
|
||||
const unsigned char *tbs,
|
||||
size_t tbslen));
|
||||
|
||||
void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
|
||||
int (*check) (EVP_PKEY *pkey));
|
||||
|
||||
@@ -1612,6 +1631,20 @@ void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth,
|
||||
const char *type,
|
||||
const char *value));
|
||||
|
||||
void EVP_PKEY_meth_get_digestsign(EVP_PKEY_METHOD *pmeth,
|
||||
int (**digestsign) (EVP_MD_CTX *ctx,
|
||||
unsigned char *sig,
|
||||
size_t *siglen,
|
||||
const unsigned char *tbs,
|
||||
size_t tbslen));
|
||||
|
||||
void EVP_PKEY_meth_get_digestverify(EVP_PKEY_METHOD *pmeth,
|
||||
int (**digestverify) (EVP_MD_CTX *ctx,
|
||||
const unsigned char *sig,
|
||||
size_t siglen,
|
||||
const unsigned char *tbs,
|
||||
size_t tbslen));
|
||||
|
||||
void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth,
|
||||
int (**pcheck) (EVP_PKEY *pkey));
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,8 @@
|
||||
#ifndef HEADER_EVPERR_H
|
||||
# define HEADER_EVPERR_H
|
||||
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
@@ -20,11 +22,14 @@ int ERR_load_EVP_strings(void);
|
||||
* EVP function codes.
|
||||
*/
|
||||
# define EVP_F_AESNI_INIT_KEY 165
|
||||
# define EVP_F_AESNI_XTS_INIT_KEY 207
|
||||
# define EVP_F_AES_GCM_CTRL 196
|
||||
# define EVP_F_AES_INIT_KEY 133
|
||||
# define EVP_F_AES_OCB_CIPHER 169
|
||||
# define EVP_F_AES_T4_INIT_KEY 178
|
||||
# define EVP_F_AES_T4_XTS_INIT_KEY 208
|
||||
# define EVP_F_AES_WRAP_CIPHER 170
|
||||
# define EVP_F_AES_XTS_INIT_KEY 209
|
||||
# define EVP_F_ALG_MODULE_INIT 177
|
||||
# define EVP_F_ARIA_CCM_INIT_KEY 175
|
||||
# define EVP_F_ARIA_GCM_CTRL 197
|
||||
@@ -115,6 +120,7 @@ int ERR_load_EVP_strings(void);
|
||||
# define EVP_F_PKEY_SET_TYPE 158
|
||||
# define EVP_F_RC2_MAGIC_TO_METH 109
|
||||
# define EVP_F_RC5_CTRL 125
|
||||
# define EVP_F_R_32_12_16_INIT_KEY 242
|
||||
# define EVP_F_S390X_AES_GCM_CTRL 201
|
||||
# define EVP_F_UPDATE 173
|
||||
|
||||
@@ -124,6 +130,7 @@ int ERR_load_EVP_strings(void);
|
||||
# define EVP_R_AES_KEY_SETUP_FAILED 143
|
||||
# define EVP_R_ARIA_KEY_SETUP_FAILED 176
|
||||
# define EVP_R_BAD_DECRYPT 100
|
||||
# define EVP_R_BAD_KEY_LENGTH 195
|
||||
# define EVP_R_BUFFER_TOO_SMALL 155
|
||||
# define EVP_R_CAMELLIA_KEY_SETUP_FAILED 157
|
||||
# define EVP_R_CIPHER_PARAMETER_ERROR 122
|
||||
@@ -151,6 +158,7 @@ int ERR_load_EVP_strings(void);
|
||||
# define EVP_R_INPUT_NOT_INITIALIZED 111
|
||||
# define EVP_R_INVALID_DIGEST 152
|
||||
# define EVP_R_INVALID_FIPS_MODE 168
|
||||
# define EVP_R_INVALID_IV_LENGTH 194
|
||||
# define EVP_R_INVALID_KEY 163
|
||||
# define EVP_R_INVALID_KEY_LENGTH 130
|
||||
# define EVP_R_INVALID_OPERATION 148
|
||||
@@ -169,6 +177,7 @@ int ERR_load_EVP_strings(void);
|
||||
# define EVP_R_ONLY_ONESHOT_SUPPORTED 177
|
||||
# define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 150
|
||||
# define EVP_R_OPERATON_NOT_INITIALIZED 151
|
||||
# define EVP_R_OUTPUT_WOULD_OVERFLOW 184
|
||||
# define EVP_R_PARTIALLY_OVERLAPPING 162
|
||||
# define EVP_R_PBKDF2_ERROR 181
|
||||
# define EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED 179
|
||||
@@ -190,5 +199,6 @@ int ERR_load_EVP_strings(void);
|
||||
# define EVP_R_UNSUPPORTED_SALT_TYPE 126
|
||||
# define EVP_R_WRAP_MODE_NOT_ALLOWED 170
|
||||
# define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109
|
||||
# define EVP_R_XTS_DUPLICATED_KEYS 183
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* WARNING: do not edit!
|
||||
* Generated by Makefile from include/openssl/fipskey.h.in
|
||||
*
|
||||
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_FIPSKEY_H
|
||||
# define OPENSSL_FIPSKEY_H
|
||||
# pragma once
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/*
|
||||
* The FIPS validation HMAC key, usable as an array initializer.
|
||||
*/
|
||||
#define FIPS_KEY_ELEMENTS \
|
||||
0xf4, 0x55, 0x66, 0x50, 0xac, 0x31, 0xd3, 0x54, 0x61, 0x61, 0x0b, 0xac, 0x4e, 0xd8, 0x1b, 0x1a, 0x18, 0x1b, 0x2d, 0x8a, 0x43, 0xea, 0x28, 0x54, 0xcb, 0xae, 0x22, 0xca, 0x74, 0x56, 0x08, 0x13
|
||||
|
||||
/*
|
||||
* The FIPS validation key, as a string.
|
||||
*/
|
||||
#define FIPS_KEY_STRING "f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813"
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_KDFERR_H
|
||||
# define HEADER_KDFERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -120,9 +120,8 @@ void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
|
||||
|
||||
# define DEFINE_LHASH_OF(type) \
|
||||
LHASH_OF(type) { union lh_##type##_dummy { void* d1; unsigned long d2; int d3; } dummy; }; \
|
||||
static ossl_inline LHASH_OF(type) * \
|
||||
lh_##type##_new(unsigned long (*hfn)(const type *), \
|
||||
int (*cfn)(const type *, const type *)) \
|
||||
static ossl_unused ossl_inline LHASH_OF(type) *lh_##type##_new(unsigned long (*hfn)(const type *), \
|
||||
int (*cfn)(const type *, const type *)) \
|
||||
{ \
|
||||
return (LHASH_OF(type) *) \
|
||||
OPENSSL_LH_new((OPENSSL_LH_HASHFUNC)hfn, (OPENSSL_LH_COMPFUNC)cfn); \
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* WARNING: do not edit!
|
||||
* Generated by crypto/objects/objects.pl
|
||||
*
|
||||
* Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
@@ -1290,12 +1290,12 @@
|
||||
#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
|
||||
|
||||
#define SN_ms_smartcard_login "msSmartcardLogin"
|
||||
#define LN_ms_smartcard_login "Microsoft Smartcardlogin"
|
||||
#define LN_ms_smartcard_login "Microsoft Smartcard Login"
|
||||
#define NID_ms_smartcard_login 648
|
||||
#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L
|
||||
|
||||
#define SN_ms_upn "msUPN"
|
||||
#define LN_ms_upn "Microsoft Universal Principal Name"
|
||||
#define LN_ms_upn "Microsoft User Principal Name"
|
||||
#define NID_ms_upn 649
|
||||
#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L
|
||||
|
||||
@@ -4280,7 +4280,7 @@
|
||||
|
||||
#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15"
|
||||
#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183
|
||||
#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L
|
||||
#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik,1L
|
||||
|
||||
#define SN_id_tc26_constants "id-tc26-constants"
|
||||
#define NID_id_tc26_constants 994
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_OBJERR_H
|
||||
# define HEADER_OBJERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -123,7 +123,7 @@ typedef struct ocsp_service_locator_st OCSP_SERVICELOC;
|
||||
(char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST, \
|
||||
bp,(char **)(x),cb,NULL)
|
||||
|
||||
# define PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\
|
||||
# define PEM_read_bio_OCSP_RESPONSE(bp,x,cb) (OCSP_RESPONSE *)PEM_ASN1_read_bio(\
|
||||
(char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE, \
|
||||
bp,(char **)(x),cb,NULL)
|
||||
|
||||
@@ -229,8 +229,8 @@ int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
|
||||
int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
|
||||
int *pssl);
|
||||
|
||||
int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
|
||||
int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
|
||||
int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
|
||||
int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
|
||||
|
||||
int OCSP_request_onereq_count(OCSP_REQUEST *req);
|
||||
OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef HEADER_OCSPERR_H
|
||||
# define HEADER_OCSPERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* WARNING: do not edit!
|
||||
* Generated by Makefile from include/openssl/opensslconf.h.in
|
||||
*
|
||||
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -24,9 +24,6 @@ extern "C" {
|
||||
* OpenSSL was configured with the following options:
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
# define OPENSSL_NO_COMP
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_MD2
|
||||
# define OPENSSL_NO_MD2
|
||||
#endif
|
||||
@@ -48,9 +45,6 @@ extern "C" {
|
||||
#ifndef OPENSSL_NO_ASAN
|
||||
# define OPENSSL_NO_ASAN
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_ASM
|
||||
# define OPENSSL_NO_ASM
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CAPIENG
|
||||
# define OPENSSL_NO_CAPIENG
|
||||
#endif
|
||||
@@ -120,9 +114,6 @@ extern "C" {
|
||||
#ifndef OPENSSL_NO_DYNAMIC_ENGINE
|
||||
# define OPENSSL_NO_DYNAMIC_ENGINE
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_AFALGENG
|
||||
# define OPENSSL_NO_AFALGENG
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@@ -144,6 +135,11 @@ extern "C" {
|
||||
# undef DECLARE_DEPRECATED
|
||||
# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated));
|
||||
# endif
|
||||
# elif defined(__SUNPRO_C)
|
||||
# if (__SUNPRO_C >= 0x5130)
|
||||
# undef DECLARE_DEPRECATED
|
||||
# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated));
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user