diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index e4f12c8460094241abec61e66809c0d077e6345d..0000000000000000000000000000000000000000
--- a/Android.bp
+++ /dev/null
@@ -1,7 +0,0 @@
-subdirs = [
- "camera",
- "drm/*",
- "media/*",
- "services/*",
- "soundtrigger",
-]
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 793cbf48f69300dfbc2178f521a4cff0f227a540..e584ffb5306fe8e64416bc46170e1483348dff66 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -81,6 +81,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libmediacodecservice.so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libstagefright_xmlparser@1.0.so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libstagefright_soft_*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk/libstagefright_soft_*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libaudiopolicyengineconfig*)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/apex/Android.bp b/apex/Android.bp
index 575603f5a85b701ee2721a95bd91bd5560476629..42a620bc0085d7104b4a6d7006319db96b34a209 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -12,25 +12,90 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+apex_defaults {
+ name: "com.android.media-defaults",
+ java_libs: ["updatable-media"],
+ multilib: {
+ first: {
+ // Extractor process runs only with the primary ABI.
+ native_shared_libs: [
+ // Extractor plugins
+ "libaacextractor",
+ "libamrextractor",
+ "libflacextractor",
+ "libmidiextractor",
+ "libmkvextractor",
+ "libmp3extractor",
+ "libmp4extractor",
+ "libmpeg2extractor",
+ "liboggextractor",
+ "libwavextractor",
+ ],
+ },
+ },
+ prebuilts: [
+ "mediaextractor.policy",
+ ],
+ key: "com.android.media.key",
+ certificate: ":com.android.media.certificate",
+
+ // Use a custom AndroidManifest.xml used for API targeting.
+ androidManifest: ":com.android.media-androidManifest",
+}
+
apex {
name: "com.android.media",
manifest: "manifest.json",
- native_shared_libs: [
- // Extractor plugins
- "libaacextractor",
- "libamrextractor",
- "libflacextractor",
- "libmidiextractor",
- "libmkvextractor",
- "libmp3extractor",
- "libmp4extractor",
- "libmpeg2extractor",
- "liboggextractor",
- "libwavextractor",
- // MediaPlayer2
- "libmedia2_jni",
+ defaults: ["com.android.media-defaults"],
+}
+
+filegroup {
+ name: "com.android.media-androidManifest",
+ srcs: ["AndroidManifest-media.xml"],
+}
+
+filegroup {
+ name: "com.android.media.swcodec-androidManifest",
+ srcs: ["AndroidManifest-swcodec.xml"],
+}
+
+apex_defaults {
+ name: "com.android.media.swcodec-defaults",
+ binaries: [
+ "mediaswcodec",
],
- key: "com.android.media.key",
+ prebuilts: [
+ "com.android.media.swcodec-mediaswcodec.rc",
+ "com.android.media.swcodec-ld.config.txt",
+ "mediaswcodec.policy",
+ "mediaswcodec.xml",
+ ],
+ use_vendor: true,
+ key: "com.android.media.swcodec.key",
+ certificate: ":com.android.media.swcodec.certificate",
+
+ // Use a custom AndroidManifest.xml used for API targeting.
+ androidManifest: ":com.android.media.swcodec-androidManifest",
+}
+
+prebuilt_etc {
+ name: "com.android.media.swcodec-mediaswcodec.rc",
+ src: "mediaswcodec.rc",
+ filename: "init.rc",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "com.android.media.swcodec-ld.config.txt",
+ src: "ld.config.txt",
+ filename: "ld.config.txt",
+ installable: false,
+}
+
+apex {
+ name: "com.android.media.swcodec",
+ manifest: "manifest_codec.json",
+ defaults: ["com.android.media.swcodec-defaults"],
}
apex_key {
@@ -38,3 +103,19 @@ apex_key {
public_key: "com.android.media.avbpubkey",
private_key: "com.android.media.pem",
}
+
+apex_key {
+ name: "com.android.media.swcodec.key",
+ public_key: "com.android.media.swcodec.avbpubkey",
+ private_key: "com.android.media.swcodec.pem",
+}
+
+android_app_certificate {
+ name: "com.android.media.certificate",
+ certificate: "com.android.media",
+}
+
+android_app_certificate {
+ name: "com.android.media.swcodec.certificate",
+ certificate: "com.android.media.swcodec",
+}
diff --git a/apex/AndroidManifest-media.xml b/apex/AndroidManifest-media.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1af458617768e0a13202c4b560d9e8ae7a4a4735
--- /dev/null
+++ b/apex/AndroidManifest-media.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/apex/AndroidManifest-swcodec.xml b/apex/AndroidManifest-swcodec.xml
new file mode 100644
index 0000000000000000000000000000000000000000..de50864aaa7d1739df8e600f2bc05cc0ad160e0b
--- /dev/null
+++ b/apex/AndroidManifest-swcodec.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/apex/TEST_MAPPING b/apex/TEST_MAPPING
new file mode 100644
index 0000000000000000000000000000000000000000..a2e98cc4bc0fd8fd49549720b92db74a92cffe0e
--- /dev/null
+++ b/apex/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "system/apex/tests"
+ }
+ ]
+}
diff --git a/apex/com.android.media.pk8 b/apex/com.android.media.pk8
new file mode 100644
index 0000000000000000000000000000000000000000..6df741e917e2d26397402d812bd9fe64bcdc8b1f
Binary files /dev/null and b/apex/com.android.media.pk8 differ
diff --git a/apex/com.android.media.swcodec.avbpubkey b/apex/com.android.media.swcodec.avbpubkey
new file mode 100644
index 0000000000000000000000000000000000000000..045972306d1ec3e68eecf09c41e577cf10ed9420
Binary files /dev/null and b/apex/com.android.media.swcodec.avbpubkey differ
diff --git a/apex/com.android.media.swcodec.pem b/apex/com.android.media.swcodec.pem
new file mode 100644
index 0000000000000000000000000000000000000000..e379cd3a8766462d1b66faefb6507b883f7b3b5a
--- /dev/null
+++ b/apex/com.android.media.swcodec.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEAvB6lOEEOR58KMcFlayEZjsXuPgcfHi/OPxcvfpiGLCpOcK3l
+OPChWUvDRcIHMB7BO+Csfxs0HgsHvvZfNyoNIm99WcjFbboiO7WrBBArIszPr14X
+cfY2NxzT9LBj+EqAnbdL+4OQW1/npLHNE0qtDcxL71ipbjSuKNb58E9qGL0KwvkS
+fwwueWj++bg/iz7dq0mz7iKpnxYscNm4RhJjqcG2Usmg4Ejhr8h5UmOUmTJbObC/
+vzClXQqeeuzS8NTtGVgQ/CI9gC2WN9upq2p/2T7P4U3o3CWvBytUoLKR0UyC83ey
+S8XJgOa42uWR3T/eJOI1ZS4H6Srg1o2XC8Yb8EprFI/NM6/+/5DX/FgDimsslAP6
+Qq4+pSte9v/FjWGqy7QBQaefFRGRuS63xHcSZhXC9J2CFdnxo8+65QT8r4yfQEei
+Ax/0Q94yB7VIL1pIJxHEonKjtd3iKdFEKQzADJ3edsmtHybERdJKCxcm9QIrDCsC
+4YVT9nX0OoC9RD5d5EVD7W5I6eEnRu6igrKIKgUVppeYFQNZD+o+eiNJa4yoggRl
+h8sT0/xLKjMRxAQ7fafi1j+LB2O7UgJmIDDAnidq8Aoz7h3pNi139rNWrjNfwhus
+nMcZvL9dTVv26JWeESHP/zAfAX7j1rfkDwR02ocRLquwEUs1+UHA27Wi1bMCAwEA
+AQKCAgAO3PT83tb7/arWh4s1zaWxTB4otHNW9Tv8bB6KiA6Bys3rxTGJMCnvXjcN
+eekLekKWMoguer3BaemwwtJ/D0l+YQSsZVqD8uLliNL8PTLLSxdVqb98d5GNBTAR
+8yXS5kAHNgZA1wI+1fL9ZjbnwUyu/Gc7f+vTE0J3Y5TX0c52KemBwiAd/Z5mZU9P
+96i9nbfx4p7ev8pbEWttdyZCEw3gybdYDyowzlFWjCZZxhhlij7+7eIYfwVxtncT
+C0cXVBtvly+wXBwz1mY5/5cGPiHfzkCqcndlfWy4ykmjcLhoqvzls51Ys0Xac2BD
+m0PNEVDB5UWGuv5RA9xD12gJvBtU3D7ggMw6C5RcXJT+jSYmSFtD2klWi+It8A/N
+Hv42soKskt6JqYAWE1cvJ3PEqH9ASEJNq2R0Z/PmuM000UJyzU9KId3SNwjXA1Xc
+Kn9hRga4uf9elHTjkTDt79/8+Xv7hjer9sF/S/np7g04rUjIWkuFkC/7NK2tQSh1
+mljV1sD9SF4DPfVK75LwJJaQUlI7TtGd5KJ7FzZwvb+w8ODrpW3hkt6FcI6KwE/a
+QT1T2Z9DknXJSYNdWGrj6vMHsYMiyz8IdAHSCrOB6eXCQxpitbn6W71Raw7f9UaZ
+VDK5AhTU493hkGj1no4cJwecXInMigg/c4ywk2Ibh6IV8O0nkQKCAQEA2+dQQ0IF
+vvVgmQ2WxHBD7M2mbOyf43YBY6Ka6oPBNGPVpZE8X8LoTavQLV+SgCkH8T6gY7XS
+5L4Ze0JFxfua0o1rm6+L2XrOx5F/A2Y40YcPclEik5h1woSwH/J1iHGiEhY8Nqeu
+9GCvjQojkgXx/Rn3Nz+lpvZ329O3H85RWWGF0l60RwLOkig0ZwUb619t8affmGIl
+sxdDv2nfy7OtJX8iGDua7Kf64dvVWQKKtACWkARrlkcWX3uoESxkpSDxue+z7ndH
+o7uHLfM8Tx+Rn+QvYWuRW5TPLbEDMbIYrX65ISt2r/T7v/04XdAC8YpCQRytlqPI
+fpDm15htyHBizQKCAQEA2v+5otRoY56JduISaVGlsJ/IbvKzDAIyWmM14EpRCR5E
+lu+MpTcRAiFQAbHGXr1tMlTFdVFD090WAzIKaKtADFVLXobIHeGspnRCq5OpVp9W
+RvLtVwLxflHAc2yN9/LNtnBqHUgt+S01LBPElybdGHQRTtqAKXhkp31sM21O34Go
+Pri/IxgupWxykMaW44Kig1Cr5DKvc8cwUsGuyDdJm8oBQeNPTMWqSnXtqoTWSaYg
+2kxiMTFokrkSXgufb8wng6OXt/QelywrhG3hAsldPO3GdKidDSxhWZSgpUXXFdAX
+y4GO0IcRJBF/WJtYTYtR+l84nQA2/1Ye4ujFlT0afwKCAQEAmXrXpSm2cvI2CnzW
+hqJIdkWOa6W3bn1VOOIrt5Rfy54GZnl4pumVU2igcpqq2HJKzdDFBvLHj8kyZbn6
+ktUp2NzFhzK9q/uvyNA+0vOMoojeeg4w0MzvG+WaO6Hw8FtHH9KPEiJ01LGKtSin
+bOpjXCC8T75HcsHBJBefTz6jvnt3eD2LG6jU3mPbNy/0rZG8XZaqU2PlJhsNuNI/
+VaBBL9OMy1cGqTgQvYS+YlKI1ls2uqurH4bcEaZvxhSy5iGZNQodDkoIITnofmSu
+6haBgBQ2EYuPN1kkRKKwNQY1fRneQk1gmCynbPdiWO+urkCuP12xtlr3u4aM51rG
+/Meb3QKCAQEA12SxZm9XhLOHLIBJ74A4YLGm50iZxXPbpn7xnHo7naZBe9p8EHtK
+pTeygxggrUnOPrSVyT92YMiQP/BVwIC+a+LwUDZsWMd/ke/DKxH+eY4Zw4pm2S+x
+6bXqfRwFvhr3LTr/g3FcljlalNGUh73Xs5dk9pN9fkxFY16+rw4Rh0709Uur4o6E
+QnuZar+H5Ji10kXj6nvXiR4ebybEC3QlV66k8fLqKe44AShf61jfkmxs34hFA3E/
+EyAn6ouv8rtvGdArBuh5teHho0yXBLCcnbKXgGHepfhCf2LpZeR9GZ0j6iqxFnPh
+7gGvqKyReyNOK9y/x9tQPG6tzit3OcNxbQKCAQEAuDheDOSkXPopXMvLAKOHBIdZ
+rbQ7oFTDHt59gbucM7U8/l2YtaxuKOQFBLnzQa/amIkkrtklYwOsz8E24d7Nm39w
+ykLHwX0XrmjAm6M4XKmDv66a+kSnSV6LEbKZdjvXP02DV+tGeZ5VsnNvJDquxMsD
+fvRTspB8j8CpU96szekxl/tCRhqbdw/4kVTSj5BF++OaRRcJrAyj1B2qf1ynAZE1
+gUvVPkEYa914zcrxg9XIXT4M7yqB7i8KJegOtOtcWjJ7uTiP+638AvygJLMJnSrV
++HjFZWG6P9btZmLHSEBRvwGOAilp0qejXo866l0fmnlGy7ehKz8u3PzvnlPYjQ==
+-----END RSA PRIVATE KEY-----
diff --git a/apex/com.android.media.swcodec.pk8 b/apex/com.android.media.swcodec.pk8
new file mode 100644
index 0000000000000000000000000000000000000000..05a4216fef4d286d4bc3e7197be4a8c28c4a3640
Binary files /dev/null and b/apex/com.android.media.swcodec.pk8 differ
diff --git a/apex/com.android.media.swcodec.x509.pem b/apex/com.android.media.swcodec.x509.pem
new file mode 100644
index 0000000000000000000000000000000000000000..67b9b4feb5e07f0e67992ebc919007f8a937b165
--- /dev/null
+++ b/apex/com.android.media.swcodec.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIJAIM72JpD4v6XMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEiMCAGA1UE
+AwwZY29tLmFuZHJvaWQubWVkaWEuc3djb2RlYzAgFw0xOTAyMTEwMjExMTFaGA80
+NzU3MDEwNzAyMTExMVowgYIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y
+bmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAw
+DgYDVQQLDAdBbmRyb2lkMSIwIAYDVQQDDBljb20uYW5kcm9pZC5tZWRpYS5zd2Nv
+ZGVjMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsqXE0AIWpLW9Tgq2
+nQGph7KZ6L2Q9oxviqCVHxIaPqfhM2SwTbycADIQeqrrlRxhddVkjLuMUkJa7mev
+fERmgpiOfnPIlGK6PTs2gljCkskZhF3bgfeyuHt0tsYO+UaN8MVoZD7/QdiE46w2
+OMDClG1UqgiqOBhLTEN/cHXObnUiiVXUYqN8aYZf6L6Fs3yQi2ZZgfbxTVFewqdv
+aLLOqCYnVYXZH+ZxbXESA0M+WXKgRKsYTj2GYs3eko1rFi4Y6uHVLx45yaoT5u/i
+SxPEkocyMCKvGJWu4XlSOd3EjSOMaqCOYVyGLxdlnQWQU7PZDqBSJ0SysWgpFHpB
+I15c2jhRdXOCfQ9ZtDfPZkE0a2A8kJDAoF1mzTp6IvBAWUsl5nHPw5CWkFpNad/h
+tqqGCScWbiKZuvrQ4/RQNm3f1K+mxX9TrjFigpqNO6d4pGAo1fa6sHR3xWPw/myq
+h5ZJjVnXU5Yq64S4xWOssfjpOg7RfNuvzuk3ok3MYs1mbx3vhZOj5km1f3qrgX9c
+mXjYnyXD0jJBm4uAJWXLdK9PlZvlXbztMCzYj832Io4pFLCtSxkzX75t1em36Nv0
+mNp6NtSSy6SFSq8l7IsXV2FNyUiyHWxS/UQm8pYg5Q5dWHvEEF78P6lV0wRa6FQl
+BBSgpqTAI092KIjDDtB7GQCgV5ECAwEAAaNTMFEwHQYDVR0OBBYEFAFIdFTDEDft
+ewSSAS7Fa3OZ5TXzMB8GA1UdIwQYMBaAFAFIdFTDEDftewSSAS7Fa3OZ5TXzMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAC5e3zXythJCGmz1FmAV
+8Y/UI+Glg6G0x/k04WaRG0DPLLjlJ1F0LM1/IReBSgXcYAL0CAgPycf/rGPOgMFm
+tQxYyjBUxKdjpIqU5DJoV1feanGveIRpto1YRKNgHuzG9rZGR4AgPnt6X4Yxlq04
+lI7QpWadXe1myARJhj3niSNY9+2wEInkx4ZuCO1LtIGqnbdc8jQ8YoVqIE5N4kuM
+ccyPYgsdABtopbjN92rueu8sfF8R6ROy+tNgb6OjpAAevtnBfZ2LXqfObKirHCK+
+k6w4WSB1UUoZ3Xgz8sJtXgokvYeInkN8tHuTagHYU2VQTcA0rdBGMN/1OljJpWlN
+0UUq4fAYU6cN4lHxr2LM9If4WvAzdLAWvaIZrDqaU4i/zYT9l6rR4lC2KW3EHWov
+nPXfgEJJ8AP1iRGibvew3i3SB6XTWFQYTUIBeJfDz/KDXQabP+yzXWISdZCUMUpx
+f+Raqsb5MoKaJdVgnSL0mBunjCyJDzzg34J7oGx6/BnwoiOrwLN4Qaz5U8jbrPSx
+p9LfleCcO7ZdeE8GKqx0X1T4d7tradtmxOS8Iwr4niskkHGRkzozvVvuyGKmoN2k
+162Vfjq+ddj7qEpSh3BS6hHU+vlMbC9L0trGxPxFEAHDrwu0KwGNduTkiu/3jvfB
+JTgH8P9mD1loYxRdo+vet8eQ
+-----END CERTIFICATE-----
diff --git a/apex/com.android.media.x509.pem b/apex/com.android.media.x509.pem
new file mode 100644
index 0000000000000000000000000000000000000000..e7908fa69a0064d1fd5222494a253f5632f05cf5
--- /dev/null
+++ b/apex/com.android.media.x509.pem
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFzDCCA7SgAwIBAgIJAO05DBBusaaLMA0GCSqGSIb3DQEBCwUAMHoxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
+aWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMRowGAYDVQQD
+DBFjb20uYW5kcm9pZC5tZWRpYTAgFw0xOTAxMjUxNzE3MTdaGA80NzU2MTIyMTE3
+MTcxN1owejELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
+BAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsMB0Fu
+ZHJvaWQxGjAYBgNVBAMMEWNvbS5hbmRyb2lkLm1lZGlhMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAmNkVxUbp/bLbeGbvKqYXzwBycSDpmOhh///lNGYQ
+/AMUD0q6EaZzU2bd4aL0rOGqfoYlhKd0kMVmMUmfdE9ODAfKxleEeEaRl2GJS8a9
+ABi770l3GHbB2xMI2sEWeOD9xsPFF6+ByPZmoUuNhMr4pUbXsDpE3h8ljrgXHtIg
+bh7ofbvddruwBV0lS1k9OZ9jPVGhEKkJnhgQa67cwgdjizAMbI0Dcz9gtMMawsDj
+Z2aQd1r+vxgh1/XkI/NMmXCnG2ERytXcJeC5S4gEtHfTTPoP0FuVgSB6y6dalMuZ
+F0NBZw8Mvgdy3QJip0uNa36J63CMZKTJWbTdlFpPL2hk0PgaYvje8C5Xtk5282wT
+dMocc8n2zIXbzbnSXGvjcNZib3Pfu55YUnX6eTqZ1BxlJ0FHZAsC4quFFWXxYBYD
+LCRoNNFEtIDQpuvuHF2DuHNDULpAQjy2y6+7eot0KEsVoDmZ4H8BpuAVVu2SxYNb
+gYflR9SmM0tmYeAcRT48q3xrocGyEHMqvgQRUpPfvct/8l8xVcDzOI/sJVDqmYzM
+u0Cj3fkSypGDJOMF/esFSmVvoI01tS7kaNS5vvtKYib//xqKRC9f0dCsGfFLnuUK
+o4KYbYWYwMyJqEd/5/ZvXyKIPAEeJL174L9+wTkc3cQpoBwJN4t+2E5MnhOEq6do
+5L0CAwEAAaNTMFEwHQYDVR0OBBYEFHjNK/GZko1RdZp+8iavWXL5xz9wMB8GA1Ud
+IwQYMBaAFHjNK/GZko1RdZp+8iavWXL5xz9wMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+KoZIhvcNAQELBQADggIBACmPQMksuLrNV1vbI44S1f70I0FHdBxchFGB39zuLbcn
+SsYom/LPtYJiD0Dl4bB4eb+ZnxkQP2XeP6pycmUH2j1EWexFwvdUvlfe8Qz+wAec
+ap4AxiX4Z2Ke2ivYotIZFUHdZOLkX20js8Wex1mzY43MLQn5APl9gK1VZTxDggeR
+EObH1S+JVjGwQqYZj2e6gNZH34Q25NQ698RL85GDkYtSISAifJtaJsU/B3vKm82I
+k9xMiCooCH6bRdGHG1jze4SRpidjxEm8cxkiaQagfcuXeCLziXJr3qAMKYiEY6bp
+0+bAqCt3S8OrrN3RQZfQrnlwitsM1jJJ/+C+WoDg4eY5AFrXDLvNeKh1qO/f8xv+
+fCXkQPcVVphLfRH9oxNrSgOWBP5/qIDH4s1YUL9luGT6H+08dlue3RkbzDbBqsQu
+7fQ/BbrIG/GuVKgyEM+a7C9gv7zc86YlueVYJEyxKidnn7RxOqyDBqyyfXA3zvme
+Rro7xIrMHPL7Nu3AWjwjXzbp/w0z+tEFPsfVB+OOHKsWPcUG0HUTJGkyeO/uHRjN
+qPEkkf7BHHUO4V2gjOIdCsELxKwHf7vsZTOk40EV751fZ7FDHMr1eddQkgH4eqAb
+DB79uP+SLfUo+42n4q6eMmoqw8d76bBXRoUhIo/Ms4sebhV0sRtAS67OQioc9UUg
+-----END CERTIFICATE-----
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a5937fd9d8fc6799572ff7b3fa548c33cc9414d0
--- /dev/null
+++ b/apex/ld.config.txt
@@ -0,0 +1,131 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Bionic loader config file for the media swcodec APEX.
+#
+# There are no versioned APEX paths here - this APEX module does not support
+# having several versions mounted.
+
+dir.swcodec = /apex/com.android.media.swcodec/bin/
+
+[swcodec]
+additional.namespaces = platform,sphal
+
+###############################################################################
+# "default" namespace
+#
+# This namespace is for the binaries and libraries on the swcodec APEX.
+###############################################################################
+
+namespace.default.isolated = true
+namespace.default.visible = true
+
+namespace.default.search.paths = /apex/com.android.media.swcodec/${LIB}
+namespace.default.asan.search.paths = /apex/com.android.media.swcodec/${LIB}
+
+namespace.default.links = platform
+
+# TODO: replace the following when apex has a way to auto-generate this list
+# namespace.default.link.platform.shared_libs = %LLNDK_LIBRARIES%
+# namespace.default.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so
+
+###############################################################################
+# "platform" namespace
+#
+# This namespace is for linking to LLNDK and ASAN libraries on the system.
+###############################################################################
+
+namespace.platform.isolated = true
+
+namespace.platform.search.paths = /system/${LIB}
+namespace.platform.asan.search.paths = /data/asan/system/${LIB}
+namespace.platform.asan.search.paths += /system/${LIB}
+
+# /system/lib/libc.so, etc are symlinks to /apex/com.android.lib/lib/bionic/libc.so, etc.
+# Add /apex/... pat to the permitted paths because linker uses realpath(3)
+# to check the accessibility of the lib. We could add this to search.paths
+# instead but that makes the resolution of bionic libs be dependent on
+# the order of /system/lib and /apex/... in search.paths. If /apex/...
+# is after /system/lib, then /apex/... is never tried because libc.so
+# is always found in /system/lib but fails to pass the accessibility test
+# because of its realpath. It's better to not depend on the ordering if
+# possible.
+namespace.platform.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
+namespace.platform.asan.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
+
+###############################################################################
+# "sphal" namespace
+#
+###############################################################################
+namespace.sphal.isolated = true
+namespace.sphal.visible = true
+
+# Keep the below in sync with "sphal" namespace in system's /etc/ld.config.txt
+# Codec2 has dependencies on some SP-hals (eg. android.hardware.graphics.mapper@2.0)
+# These are dlopen'ed by libvndksupport.so.
+namespace.sphal.search.paths = /odm/${LIB}
+namespace.sphal.search.paths += /vendor/${LIB}
+
+namespace.sphal.permitted.paths = /odm/${LIB}
+namespace.sphal.permitted.paths += /vendor/${LIB}
+namespace.sphal.permitted.paths += /vendor/${LIB}/hw
+namespace.sphal.permitted.paths += /system/vendor/${LIB}
+
+namespace.sphal.asan.search.paths = /data/asan/odm/${LIB}
+namespace.sphal.asan.search.paths += /odm/${LIB}
+namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}
+namespace.sphal.asan.search.paths += /vendor/${LIB}
+
+namespace.sphal.asan.permitted.paths = /data/asan/odm/${LIB}
+namespace.sphal.asan.permitted.paths += /odm/${LIB}
+namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}
+namespace.sphal.asan.permitted.paths += /vendor/${LIB}
+
+# Keep the below in sync with "vndk" namespace in system's /etc/ld.config.txt
+# System's sphal namespace links to vndk namespace for %VNDK_SAMEPROCESS_LIBRARIES%,
+# since we don't have a good way to auto-expand %VNDK_SAMEPROCESS_LIBRARIES%,
+# we'll add the vndk paths below.
+
+namespace.sphal.search.paths += /odm/${LIB}/vndk-sp
+namespace.sphal.search.paths += /vendor/${LIB}/vndk-sp
+namespace.sphal.search.paths += /system/${LIB}/vndk-sp${VNDK_VER}
+
+namespace.sphal.permitted.paths += /odm/${LIB}/hw
+namespace.sphal.permitted.paths += /odm/${LIB}/egl
+namespace.sphal.permitted.paths += /vendor/${LIB}/hw
+namespace.sphal.permitted.paths += /vendor/${LIB}/egl
+namespace.sphal.permitted.paths += /system/vendor/${LIB}/hw
+namespace.sphal.permitted.paths += /system/vendor/${LIB}/egl
+# This is exceptionally required since android.hidl.memory@1.0-impl.so is here
+namespace.sphal.permitted.paths += /system/${LIB}/vndk-sp${VNDK_VER}/hw
+
+namespace.sphal.asan.search.paths += /data/asan/odm/${LIB}/vndk-sp
+namespace.sphal.asan.search.paths += /odm/${LIB}/vndk-sp
+namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
+namespace.sphal.asan.search.paths += /vendor/${LIB}/vndk-sp
+namespace.sphal.asan.search.paths += /data/asan/system/${LIB}/vndk-sp${VNDK_VER}
+namespace.sphal.asan.search.paths += /system/${LIB}/vndk-sp${VNDK_VER}
+
+namespace.sphal.asan.permitted.paths += /data/asan/odm/${LIB}/hw
+namespace.sphal.asan.permitted.paths += /odm/${LIB}/hw
+namespace.sphal.asan.permitted.paths += /data/asan/odm/${LIB}/egl
+namespace.sphal.asan.permitted.paths += /odm/${LIB}/egl
+namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}/hw
+namespace.sphal.asan.permitted.paths += /vendor/${LIB}/hw
+namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}/egl
+namespace.sphal.asan.permitted.paths += /vendor/${LIB}/egl
+
+namespace.sphal.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp${VNDK_VER}/hw
+namespace.sphal.asan.permitted.paths += /system/${LIB}/vndk-sp${VNDK_VER}/hw
+
+# Once in this namespace, access to libraries in /system/lib is restricted. Only
+# libs listed here can be used.
+namespace.sphal.links = platform
+
+# TODO: replace the following when apex has a way to auto-generate this list
+# namespace.sphal.link.platform.shared_libs = %LLNDK_LIBRARIES%
+# namespace.sphal.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so
+
+# Add a link for libz.so which is llndk on devices where VNDK is not enforced.
+namespace.sphal.link.platform.shared_libs += libz.so
diff --git a/apex/manifest.json b/apex/manifest.json
index e2df3a3b2fadc8cae15efea3f9d849bbcb009203..3011ee832e8cc0a3c6c2ec24fd5fa66e7868097f 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,4 @@
{
"name": "com.android.media",
- "version": 1
+ "version": 290000000
}
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
new file mode 100644
index 0000000000000000000000000000000000000000..83a517859bd4138254421be49a0e975699c8c2dc
--- /dev/null
+++ b/apex/manifest_codec.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.media.swcodec",
+ "version": 290000000
+}
diff --git a/apex/mediaswcodec.rc b/apex/mediaswcodec.rc
new file mode 100644
index 0000000000000000000000000000000000000000..d17481bf98ac5ae732422eaf86e623674834f564
--- /dev/null
+++ b/apex/mediaswcodec.rc
@@ -0,0 +1,7 @@
+service media.swcodec /apex/com.android.media.swcodec/bin/mediaswcodec
+ class main
+ user mediacodec
+ group camera drmrpc mediadrm
+ override
+ ioprio rt 4
+ writepid /dev/cpuset/foreground/tasks
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
new file mode 100644
index 0000000000000000000000000000000000000000..701ced732eceb4f01684aa6916d54f23f60cb534
--- /dev/null
+++ b/apex/testing/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+apex {
+ name: "test_com.android.media",
+ manifest: "test_manifest.json",
+ file_contexts: "com.android.media",
+ defaults: ["com.android.media-defaults"],
+ installable: false,
+}
+
+apex {
+ name: "test_com.android.media.swcodec",
+ manifest: "test_manifest_codec.json",
+ file_contexts: "com.android.media.swcodec",
+ defaults: ["com.android.media.swcodec-defaults"],
+ installable: false,
+}
diff --git a/apex/testing/test_manifest.json b/apex/testing/test_manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..ddd642ed3c13c536733155ca5a6b9f9c51d87caf
--- /dev/null
+++ b/apex/testing/test_manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.media",
+ "version": 300000000
+}
diff --git a/apex/testing/test_manifest_codec.json b/apex/testing/test_manifest_codec.json
new file mode 100644
index 0000000000000000000000000000000000000000..2320fd76f6c276b3e9cbe3a43ae3e5f34d32b9b4
--- /dev/null
+++ b/apex/testing/test_manifest_codec.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.media.swcodec",
+ "version": 300000000
+}
diff --git a/camera/Android.bp b/camera/Android.bp
index e2c123caccbf9729ccfd650dc4879ebfc028abcf..b288bcfce0357f2d267cbf4b451fe35c7380305b 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-subdirs = ["ndk"]
-
cc_library_shared {
name: "libcamera_client",
@@ -43,6 +41,7 @@ cc_library_shared {
"ICameraRecordingProxyListener.cpp",
"camera2/CaptureRequest.cpp",
"camera2/OutputConfiguration.cpp",
+ "camera2/SessionConfiguration.cpp",
"camera2/SubmitInfo.cpp",
"CameraBase.cpp",
"CameraUtils.cpp",
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index e143e052b98e51b18ec8d6987350b61f4ca10204..92fe84b6d37e70b03b6603594cc31bf2901298c4 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -22,7 +22,6 @@
#include
#include
-#include
namespace android {
@@ -409,6 +408,79 @@ status_t CameraMetadata::erase(uint32_t tag) {
return res;
}
+status_t CameraMetadata::removePermissionEntries(metadata_vendor_id_t vendorId,
+ std::vector *tagsRemoved) {
+ uint32_t tagCount = 0;
+ std::vector tagsToRemove;
+
+ if (tagsRemoved == nullptr) {
+ return BAD_VALUE;
+ }
+
+ sp vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
+ if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
+ sp cache =
+ VendorTagDescriptorCache::getGlobalVendorTagCache();
+ if (cache.get()) {
+ cache->getVendorTagDescriptor(vendorId, &vTags);
+ }
+ }
+
+ if ((nullptr != vTags.get()) && (vTags->getTagCount() > 0)) {
+ tagCount = vTags->getTagCount();
+ uint32_t *vendorTags = new uint32_t[tagCount];
+ if (nullptr == vendorTags) {
+ return NO_MEMORY;
+ }
+ vTags->getTagArray(vendorTags);
+
+ tagsToRemove.reserve(tagCount);
+ tagsToRemove.insert(tagsToRemove.begin(), vendorTags, vendorTags + tagCount);
+
+ delete [] vendorTags;
+ tagCount = 0;
+ }
+
+ auto tagsNeedingPermission = get_camera_metadata_permission_needed(&tagCount);
+ if (tagCount > 0) {
+ tagsToRemove.reserve(tagsToRemove.capacity() + tagCount);
+ tagsToRemove.insert(tagsToRemove.end(), tagsNeedingPermission,
+ tagsNeedingPermission + tagCount);
+ }
+
+ tagsRemoved->reserve(tagsToRemove.size());
+ for (const auto &it : tagsToRemove) {
+ if (exists(it)) {
+ auto rc = erase(it);
+ if (NO_ERROR != rc) {
+ ALOGE("%s: Failed to erase tag: %x", __func__, it);
+ return rc;
+ }
+ tagsRemoved->push_back(it);
+ }
+ }
+
+ // Update the available characterstics accordingly
+ if (exists(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS)) {
+ std::vector currentKeys;
+
+ std::sort(tagsRemoved->begin(), tagsRemoved->end());
+ auto keys = find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
+ currentKeys.reserve(keys.count);
+ currentKeys.insert(currentKeys.end(), keys.data.i32, keys.data.i32 + keys.count);
+ std::sort(currentKeys.begin(), currentKeys.end());
+
+ std::vector newKeys(keys.count);
+ auto end = std::set_difference(currentKeys.begin(), currentKeys.end(), tagsRemoved->begin(),
+ tagsRemoved->end(), newKeys.begin());
+ newKeys.resize(end - newKeys.begin());
+
+ update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, newKeys.data(), newKeys.size());
+ }
+
+ return NO_ERROR;
+}
+
void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
}
diff --git a/camera/CaptureResult.cpp b/camera/CaptureResult.cpp
index 928a6bca0ac72b2795990adab30690406c902c30..1d8e8c42d034984630764157861fb5ecda1dfc25 100644
--- a/camera/CaptureResult.cpp
+++ b/camera/CaptureResult.cpp
@@ -39,6 +39,16 @@ status_t CaptureResultExtras::readFromParcel(const android::Parcel *parcel) {
parcel->readInt64(&frameNumber);
parcel->readInt32(&partialResultCount);
parcel->readInt32(&errorStreamId);
+ auto physicalCameraIdPresent = parcel->readBool();
+ if (physicalCameraIdPresent) {
+ String16 cameraId;
+ status_t res = OK;
+ if ((res = parcel->readString16(&cameraId)) != OK) {
+ ALOGE("%s: Failed to read camera id: %d", __FUNCTION__, res);
+ return res;
+ }
+ errorPhysicalCameraId = cameraId;
+ }
return OK;
}
@@ -56,6 +66,16 @@ status_t CaptureResultExtras::writeToParcel(android::Parcel *parcel) const {
parcel->writeInt64(frameNumber);
parcel->writeInt32(partialResultCount);
parcel->writeInt32(errorStreamId);
+ if (errorPhysicalCameraId.size() > 0) {
+ parcel->writeBool(true);
+ status_t res = OK;
+ if ((res = parcel->writeString16(errorPhysicalCameraId)) != OK) {
+ ALOGE("%s: Failed to write physical camera ID to parcel: %d", __FUNCTION__, res);
+ return res;
+ }
+ } else {
+ parcel->writeBool(false);
+ }
return OK;
}
diff --git a/camera/OWNERS b/camera/OWNERS
index 18acfee14555ac44b0fb66f42f150160ea75add1..d6b95da768fce05e610e9c172ced8f8b6d9a8813 100644
--- a/camera/OWNERS
+++ b/camera/OWNERS
@@ -1,6 +1,8 @@
-cychen@google.com
epeev@google.com
etalvala@google.com
+jchowdhary@google.com
shuzhenwang@google.com
yinchiayeh@google.com
+# backup owner
+cychen@google.com
zhijunhe@google.com
diff --git a/camera/VendorTagDescriptor.cpp b/camera/VendorTagDescriptor.cpp
index a86cc87da99b3c5e3ea3e6954ec37235d07ab066..d713d2dd86ad3744a7734abc13151fa169dfdaac 100644
--- a/camera/VendorTagDescriptor.cpp
+++ b/camera/VendorTagDescriptor.cpp
@@ -315,6 +315,10 @@ status_t VendorTagDescriptor::lookupTag(const String8& name, const String8& sect
return OK;
}
+ssize_t VendorTagDescriptor::getSectionIndex(uint32_t tag) const {
+ return mTagToSectionMap.valueFor(tag);
+}
+
void VendorTagDescriptor::dump(int fd, int verbosity, int indentation) const {
size_t size = mTagToNameMap.size();
@@ -407,6 +411,11 @@ status_t VendorTagDescriptorCache::readFromParcel(const Parcel* parcel) {
return res;
}
+const std::unordered_map> &
+ VendorTagDescriptorCache::getVendorIdsAndTagDescriptors() {
+ return mVendorMap;
+}
+
int VendorTagDescriptorCache::getTagCount(metadata_vendor_id_t id) const {
int ret = 0;
auto desc = mVendorMap.find(id);
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 9c0f28bfa98e8a163222eccd9b8d5ee6da10d052..3e8992aaafc0950ff14b41431c24530aa92dc98f 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -108,7 +108,7 @@ interface ICameraService
*
* Also returns the set of currently-known camera IDs and state of each device.
* Adding a listener will trigger the torch status listener to fire for all
- * devices that have a flash unit
+ * devices that have a flash unit.
*/
CameraStatus[] addListener(ICameraServiceListener listener);
@@ -149,8 +149,10 @@ interface ICameraService
const int API_VERSION_1 = 1;
const int API_VERSION_2 = 2;
- // Determines if a particular API version is supported directly
+ // Determines if a particular API version is supported directly for a cameraId.
boolean supportsCameraApi(String cameraId, int apiVersion);
+ // Determines if a cameraId is a hidden physical camera of a logical multi-camera.
+ boolean isHiddenPhysicalCamera(String cameraId);
void setTorchMode(String cameraId, boolean enabled, IBinder clientBinder);
@@ -160,6 +162,28 @@ interface ICameraService
* Callers require the android.permission.CAMERA_SEND_SYSTEM_EVENTS permission.
*/
const int EVENT_NONE = 0;
- const int EVENT_USER_SWITCHED = 1;
+ const int EVENT_USER_SWITCHED = 1; // The argument is the set of new foreground user IDs.
oneway void notifySystemEvent(int eventId, in int[] args);
+
+ /**
+ * Notify the camera service of a device physical status change. May only be called from
+ * a privileged process.
+ *
+ * newState is a bitfield consisting of DEVICE_STATE_* values combined together. Valid state
+ * combinations are device-specific. At device startup, the camera service will assume the device
+ * state is NORMAL until otherwise notified.
+ *
+ * Callers require the android.permission.CAMERA_SEND_SYSTEM_EVENTS permission.
+ */
+ oneway void notifyDeviceStateChange(long newState);
+
+ // Bitfield constants for notifyDeviceStateChange
+ // All bits >= 32 are for custom vendor states
+ // Written as ints since AIDL does not support long constants.
+ const int DEVICE_STATE_NORMAL = 0;
+ const int DEVICE_STATE_BACK_COVERED = 1;
+ const int DEVICE_STATE_FRONT_COVERED = 2;
+ const int DEVICE_STATE_FOLDED = 4;
+ const int DEVICE_STATE_LAST_FRAMEWORK_BIT = 0x80000000; // 1 << 31;
+
}
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
index f871ce41c9b4d20de1c4be31804653477eac8f50..e9dcbdb6f6b33821ab454292249bfe8bfae8a47c 100644
--- a/camera/aidl/android/hardware/ICameraServiceListener.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -76,4 +76,11 @@ interface ICameraServiceListener
const int TORCH_STATUS_UNKNOWN = -1;
oneway void onTorchStatusChanged(int status, String cameraId);
+
+ /**
+ * Notify registered clients about camera access priority changes.
+ * Clients which were previously unable to open a certain camera device
+ * can retry after receiving this callback.
+ */
+ oneway void onCameraAccessPrioritiesChanged();
}
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 4ced08c229800c9a7a0bb3a29658d150df01d5c8..49dfde8ac5ddfa44c487f252d7839d4180e04eba 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -19,6 +19,7 @@ package android.hardware.camera2;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.params.OutputConfiguration;
+import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.utils.SubmitInfo;
import android.view.Surface;
@@ -83,6 +84,16 @@ interface ICameraDeviceUser
*/
void endConfigure(int operatingMode, in CameraMetadataNative sessionParams);
+ /**
+ * Check whether a particular session configuration has camera device
+ * support.
+ *
+ * @param sessionConfiguration Specific session configuration to be verified.
+ * @return true - in case the stream combination is supported.
+ * false - in case there is no device support.
+ */
+ boolean isSessionConfigurationSupported(in SessionConfiguration sessionConfiguration);
+
void deleteStream(int streamId);
/**
diff --git a/camera/aidl/android/hardware/camera2/params/SessionConfiguration.aidl b/camera/aidl/android/hardware/camera2/params/SessionConfiguration.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..abf15567f4072f748d8f422da36b71c562879dea
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/params/SessionConfiguration.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.params;
+
+/** @hide */
+parcelable SessionConfiguration cpp_header "camera/camera2/SessionConfiguration.h";
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index feb04c24ed85d6f3563589abd2e71d11891e9985..4e9b27d50dff44b38635b4625240e72514edf716 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -167,14 +167,24 @@ status_t OutputConfiguration::readFromParcel(const android::Parcel* parcel) {
}
OutputConfiguration::OutputConfiguration(sp& gbp, int rotation,
+ const String16& physicalId,
int surfaceSetID, bool isShared) {
mGbps.push_back(gbp);
mRotation = rotation;
mSurfaceSetID = surfaceSetID;
mIsDeferred = false;
mIsShared = isShared;
+ mPhysicalCameraId = physicalId;
}
+OutputConfiguration::OutputConfiguration(
+ const std::vector>& gbps,
+ int rotation, const String16& physicalCameraId, int surfaceSetID, int surfaceType,
+ int width, int height, bool isShared)
+ : mGbps(gbps), mRotation(rotation), mSurfaceSetID(surfaceSetID), mSurfaceType(surfaceType),
+ mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared),
+ mPhysicalCameraId(physicalCameraId) { }
+
status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
if (parcel == nullptr) return BAD_VALUE;
diff --git a/camera/camera2/SessionConfiguration.cpp b/camera/camera2/SessionConfiguration.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a431a33525cfb22eeaa38eb0c26156ddb4cc5044
--- /dev/null
+++ b/camera/camera2/SessionConfiguration.cpp
@@ -0,0 +1,133 @@
+/*
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "SessionConfiguration"
+//#define LOG_NDEBUG 0
+
+#include
+
+#include
+#include
+#include
+
+namespace android {
+
+status_t SessionConfiguration::readFromParcel(const android::Parcel* parcel) {
+ status_t err = OK;
+ int operatingMode = 0;
+
+ if (parcel == nullptr) return BAD_VALUE;
+
+ if ((err = parcel->readInt32(&operatingMode)) != OK) {
+ ALOGE("%s: Failed to read operating mode from parcel", __FUNCTION__);
+ return err;
+ }
+
+ int inputWidth = 0;
+ if ((err = parcel->readInt32(&inputWidth)) != OK) {
+ ALOGE("%s: Failed to read input width from parcel", __FUNCTION__);
+ return err;
+ }
+
+ int inputHeight = 0;
+ if ((err = parcel->readInt32(&inputHeight)) != OK) {
+ ALOGE("%s: Failed to read input height from parcel", __FUNCTION__);
+ return err;
+ }
+
+ int inputFormat = -1;
+ if ((err = parcel->readInt32(&inputFormat)) != OK) {
+ ALOGE("%s: Failed to read input format from parcel", __FUNCTION__);
+ return err;
+ }
+
+ std::vector outputStreams;
+ if ((err = parcel->readParcelableVector(&outputStreams)) != OK) {
+ ALOGE("%s: Failed to read output configurations from parcel", __FUNCTION__);
+ return err;
+ }
+
+ mOperatingMode = operatingMode;
+ mInputWidth = inputWidth;
+ mInputHeight = inputHeight;
+ mInputFormat = inputFormat;
+ for (auto& stream : outputStreams) {
+ mOutputStreams.push_back(stream);
+ }
+
+
+ return err;
+}
+
+status_t SessionConfiguration::writeToParcel(android::Parcel* parcel) const {
+
+ if (parcel == nullptr) return BAD_VALUE;
+ status_t err = OK;
+
+ err = parcel->writeInt32(mOperatingMode);
+ if (err != OK) return err;
+
+ err = parcel->writeInt32(mInputWidth);
+ if (err != OK) return err;
+
+ err = parcel->writeInt32(mInputHeight);
+ if (err != OK) return err;
+
+ err = parcel->writeInt32(mInputFormat);
+ if (err != OK) return err;
+
+ err = parcel->writeParcelableVector(mOutputStreams);
+ if (err != OK) return err;
+
+ return OK;
+}
+
+bool SessionConfiguration::outputsEqual(const SessionConfiguration& other) const {
+ const std::vector& otherOutputStreams =
+ other.getOutputConfigurations();
+
+ if (mOutputStreams.size() != otherOutputStreams.size()) {
+ return false;
+ }
+
+ for (size_t i = 0; i < mOutputStreams.size(); i++) {
+ if (mOutputStreams[i] != otherOutputStreams[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool SessionConfiguration::outputsLessThan(const SessionConfiguration& other) const {
+ const std::vector& otherOutputStreams =
+ other.getOutputConfigurations();
+
+ if (mOutputStreams.size() != otherOutputStreams.size()) {
+ return mOutputStreams.size() < otherOutputStreams.size();
+ }
+
+ for (size_t i = 0; i < mOutputStreams.size(); i++) {
+ if (mOutputStreams[i] != otherOutputStreams[i]) {
+ return mOutputStreams[i] < otherOutputStreams[i];
+ }
+ }
+
+ return false;
+}
+
+}; // namespace android
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
new file mode 100644
index 0000000000000000000000000000000000000000..ecaba3ac11109a77625dfabd5e62b79bb6dbe212
--- /dev/null
+++ b/camera/cameraserver/Android.bp
@@ -0,0 +1,49 @@
+// Copyright 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+ name: "cameraserver",
+
+ srcs: ["main_cameraserver.cpp"],
+
+ shared_libs: [
+ "libcameraservice",
+ "liblog",
+ "libutils",
+ "libui",
+ "libgui",
+ "libbinder",
+ "libhidlbase",
+ "libhidltransport",
+ "android.hardware.camera.common@1.0",
+ "android.hardware.camera.provider@2.4",
+ "android.hardware.camera.provider@2.5",
+ "android.hardware.camera.device@1.0",
+ "android.hardware.camera.device@3.2",
+ "android.hardware.camera.device@3.4",
+ ],
+ compile_multilib: "32",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wno-unused-parameter",
+ ],
+
+ init_rc: ["cameraserver.rc"],
+
+ vintf_fragments: [
+ "manifest_android.frameworks.cameraservice.service@2.0.xml",
+ ],
+}
diff --git a/camera/cameraserver/Android.mk b/camera/cameraserver/Android.mk
deleted file mode 100644
index b8c94e64e34e3d37d80cd4ad554fb2688185c2a4..0000000000000000000000000000000000000000
--- a/camera/cameraserver/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- main_cameraserver.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcameraservice \
- liblog \
- libutils \
- libui \
- libgui \
- libbinder \
- libhidltransport \
- android.hardware.camera.common@1.0 \
- android.hardware.camera.provider@2.4 \
- android.hardware.camera.device@1.0 \
- android.hardware.camera.device@3.2
-
-LOCAL_MODULE:= cameraserver
-LOCAL_32_BIT_ONLY := true
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter
-
-LOCAL_INIT_RC := cameraserver.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/camera/cameraserver/main_cameraserver.cpp b/camera/cameraserver/main_cameraserver.cpp
index 3972436a76a98735eafd5135232cf0e455e188d4..53b3d848940ccc628efa53b5060ad22ff6d67adc 100644
--- a/camera/cameraserver/main_cameraserver.cpp
+++ b/camera/cameraserver/main_cameraserver.cpp
@@ -26,8 +26,9 @@ int main(int argc __unused, char** argv __unused)
{
signal(SIGPIPE, SIG_IGN);
- // Set 3 threads for HIDL calls
- hardware::configureRpcThreadpool(3, /*willjoin*/ false);
+ // Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls in
+ // addition to consuming them from the Camera HAL as well.
+ hardware::configureRpcThreadpool(5, /*willjoin*/ false);
sp proc(ProcessState::self());
sp sm = defaultServiceManager();
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml
new file mode 100644
index 0000000000000000000000000000000000000000..601c7171b0dbead43b125e5599ba4f0d6a830a62
--- /dev/null
+++ b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml
@@ -0,0 +1,11 @@
+
+
+ android.frameworks.cameraservice.service
+ hwbinder
+ 2.0
+
+ ICameraService
+ default
+
+
+
diff --git a/camera/include/camera/CameraMetadata.h b/camera/include/camera/CameraMetadata.h
index d28447784f4c4161987667a387c0d15f59a153c9..844bb80302218bb9666001e290e3fcb388956584 100644
--- a/camera/include/camera/CameraMetadata.h
+++ b/camera/include/camera/CameraMetadata.h
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
namespace android {
@@ -169,6 +170,12 @@ class CameraMetadata: public Parcelable {
*/
status_t erase(uint32_t tag);
+ /**
+ * Remove metadata entries that need additional permissions.
+ */
+ status_t removePermissionEntries(metadata_vendor_id_t vendorId,
+ std::vector *tagsRemoved /*out*/);
+
/**
* Swap the underlying camera metadata between this and the other
* metadata object.
diff --git a/camera/include/camera/CaptureResult.h b/camera/include/camera/CaptureResult.h
index 56fa17886f4f4bd276a6edae7a158287d3fae6ef..ef830b50b7f8c8de4a7966a1756c05d37911eba8 100644
--- a/camera/include/camera/CaptureResult.h
+++ b/camera/include/camera/CaptureResult.h
@@ -69,6 +69,13 @@ struct CaptureResultExtras : public android::Parcelable {
*/
int32_t errorStreamId;
+ /**
+ * For capture result errors, the physical camera ID in case the respective request contains
+ * a reference to physical camera device.
+ * Empty otherwise.
+ */
+ String16 errorPhysicalCameraId;
+
/**
* Constructor initializes object as invalid by setting requestId to be -1.
*/
@@ -79,7 +86,8 @@ struct CaptureResultExtras : public android::Parcelable {
precaptureTriggerId(0),
frameNumber(0),
partialResultCount(0),
- errorStreamId(-1) {
+ errorStreamId(-1),
+ errorPhysicalCameraId() {
}
/**
diff --git a/camera/include/camera/VendorTagDescriptor.h b/camera/include/camera/VendorTagDescriptor.h
index 904fba2919a68dd5e379ed20aced79472947fde2..6f55890149af50aca6e12add56dd237b648d8b8e 100644
--- a/camera/include/camera/VendorTagDescriptor.h
+++ b/camera/include/camera/VendorTagDescriptor.h
@@ -98,6 +98,11 @@ class VendorTagDescriptor : public Parcelable {
*/
void dump(int fd, int verbosity, int indentation) const;
+ /**
+ * Get Section for corresponding tag.
+ */
+ ssize_t getSectionIndex(uint32_t tag) const;
+
/**
* Read values VendorTagDescriptor object from the given parcel.
*
@@ -206,6 +211,9 @@ class VendorTagDescriptorCache : public Parcelable {
*/
void dump(int fd, int verbosity, int indentation) const;
+ const std::unordered_map> &
+ getVendorIdsAndTagDescriptors();
+
protected:
std::unordered_map> mVendorMap;
struct vendor_tag_cache_ops mVendorCacheOps;
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index a80f44b1f4c03793ab56eebcb76494534b37b5a3..95c4f39d91869dd658344dcac45644f9bd28bef5 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -65,8 +65,15 @@ public:
OutputConfiguration(const android::Parcel& parcel);
OutputConfiguration(sp& gbp, int rotation,
+ const String16& physicalCameraId,
int surfaceSetID = INVALID_SET_ID, bool isShared = false);
+ OutputConfiguration(const std::vector>& gbps,
+ int rotation, const String16& physicalCameraId,
+ int surfaceSetID = INVALID_SET_ID,
+ int surfaceType = OutputConfiguration::SURFACE_TYPE_UNKNOWN, int width = 0,
+ int height = 0, bool isShared = false);
+
bool operator == (const OutputConfiguration& other) const {
return ( mRotation == other.mRotation &&
mSurfaceSetID == other.mSurfaceSetID &&
diff --git a/camera/include/camera/camera2/SessionConfiguration.h b/camera/include/camera/camera2/SessionConfiguration.h
new file mode 100644
index 0000000000000000000000000000000000000000..64288ed1bba627e27d6bead3c8a3f20173afacfc
--- /dev/null
+++ b/camera/include/camera/camera2/SessionConfiguration.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA2_SESSIONCONFIGURATION_H
+#define ANDROID_HARDWARE_CAMERA2_SESSIONCONFIGURATION_H
+
+#include
+
+namespace android {
+
+namespace hardware {
+namespace camera2 {
+namespace params {
+
+class OutputConfiguration;
+
+class SessionConfiguration : public android::Parcelable {
+public:
+
+ const std::vector& getOutputConfigurations() const {
+ return mOutputStreams;
+ }
+
+ int getInputWidth() const { return mInputWidth; }
+ int getInputHeight() const { return mInputHeight; }
+ int getInputFormat() const { return mInputFormat; }
+ int getOperatingMode() const { return mOperatingMode; }
+
+ virtual status_t writeToParcel(android::Parcel* parcel) const override;
+ virtual status_t readFromParcel(const android::Parcel* parcel) override;
+
+ SessionConfiguration() :
+ mInputWidth(0),
+ mInputHeight(0),
+ mInputFormat(-1),
+ mOperatingMode(-1) {}
+
+ SessionConfiguration(const android::Parcel& parcel) {
+ readFromParcel(&parcel);
+ }
+
+ SessionConfiguration(int inputWidth, int inputHeight, int inputFormat, int operatingMode) :
+ mInputWidth(inputWidth), mInputHeight(inputHeight), mInputFormat(inputFormat),
+ mOperatingMode(operatingMode) {}
+
+ bool operator == (const SessionConfiguration& other) const {
+ return (outputsEqual(other) &&
+ mInputWidth == other.mInputWidth &&
+ mInputHeight == other.mInputHeight &&
+ mInputFormat == other.mInputFormat &&
+ mOperatingMode == other.mOperatingMode);
+ }
+
+ bool operator != (const SessionConfiguration& other) const {
+ return !(*this == other);
+ }
+
+ bool operator < (const SessionConfiguration& other) const {
+ if (*this == other) return false;
+
+ if (mInputWidth != other.mInputWidth) {
+ return mInputWidth < other.mInputWidth;
+ }
+
+ if (mInputHeight != other.mInputHeight) {
+ return mInputHeight < other.mInputHeight;
+ }
+
+ if (mInputFormat != other.mInputFormat) {
+ return mInputFormat < other.mInputFormat;
+ }
+
+ if (mOperatingMode != other.mOperatingMode) {
+ return mOperatingMode < other.mOperatingMode;
+ }
+
+ return outputsLessThan(other);
+ }
+
+ bool operator > (const SessionConfiguration& other) const {
+ return (*this != other && !(*this < other));
+ }
+
+ bool outputsEqual(const SessionConfiguration& other) const;
+ bool outputsLessThan(const SessionConfiguration& other) const;
+ void addOutputConfiguration(const OutputConfiguration &config) {
+ mOutputStreams.push_back(config);
+ }
+
+private:
+
+ std::vector mOutputStreams;
+ int mInputWidth, mInputHeight, mInputFormat, mOperatingMode;
+};
+} // namespace params
+} // namespace camera2
+} // namespace hardware
+
+using hardware::camera2::params::SessionConfiguration;
+
+}; // namespace android
+
+#endif
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 75075f17e00e0bd8fe0dd3ad34dc1b1b7f53f5b8..a2ee65dc98676a0b13b669f925ed6b486b6a6bd1 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -55,6 +55,7 @@ cc_library_shared {
"libcutils",
"libcamera_metadata",
"libmediandk",
+ "libnativewindow",
],
cflags: [
"-fvisibility=hidden",
@@ -63,11 +64,99 @@ cc_library_shared {
"-Wextra",
"-Werror",
],
+ // TODO: jchowdhary@, use header_libs instead b/131165718
+ include_dirs: [
+ "system/media/private/camera/include",
+ ],
+ export_include_dirs: ["include"],
+ export_shared_lib_headers: [
+ "libnativewindow",
+ ],
+ version_script: "libcamera2ndk.map.txt",
+}
+
+cc_library_shared {
+ name: "libcamera2ndk_vendor",
+ vendor: true,
+ srcs: [
+ "ndk_vendor/impl/ACameraDevice.cpp",
+ "ndk_vendor/impl/ACameraManager.cpp",
+ "ndk_vendor/impl/utils.cpp",
+ "impl/ACameraMetadata.cpp",
+ "impl/ACameraCaptureSession.cpp",
+ "NdkCameraMetadata.cpp",
+ "NdkCameraCaptureSession.cpp",
+ "NdkCameraManager.cpp",
+ "NdkCameraDevice.cpp",
+ "NdkCaptureRequest.cpp",
+ ],
+
export_include_dirs: ["include"],
+ export_shared_lib_headers: [
+ "libcutils",
+ ],
+ local_include_dirs: [
+ ".",
+ "include",
+ "impl",
+ ],
+ cflags: [
+ "-fvisibility=hidden",
+ "-DEXPORT=__attribute__((visibility(\"default\")))",
+ "-D__ANDROID_VNDK__",
+ ],
+
+ shared_libs: [
+ "libhwbinder",
+ "libfmq",
+ "libhidlbase",
+ "libhardware",
+ "libnativewindow",
+ "liblog",
+ "libutils",
+ "libstagefright_foundation",
+ "libcutils",
+ "libcamera_metadata",
+ "libmediandk",
+ "android.frameworks.cameraservice.device@2.0",
+ "android.frameworks.cameraservice.common@2.0",
+ "android.frameworks.cameraservice.service@2.0",
+ ],
+
+ static_libs: [
+ "android.hardware.camera.common@1.0-helper",
+ "libarect",
+ ],
+ // TODO: jchowdhary@, use header_libs instead b/131165718
+ include_dirs: [
+ "system/media/private/camera/include",
+ ],
product_variables: {
pdk: {
enabled: false,
},
},
- version_script: "libcamera2ndk.map.txt",
+}
+
+cc_test {
+ name: "AImageReaderVendorTest",
+ vendor: true,
+ srcs: ["ndk_vendor/tests/AImageReaderVendorTest.cpp"],
+ shared_libs: [
+ "libhwbinder",
+ "libcamera2ndk_vendor",
+ "libcamera_metadata",
+ "libmediandk",
+ "libnativewindow",
+ "libutils",
+ "libui",
+ "libcutils",
+ "liblog",
+ ],
+ static_libs: [
+ "android.hardware.camera.common@1.0-helper",
+ ],
+ cflags: [
+ "-D__ANDROID_VNDK__",
+ ],
}
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index fd95296161bb149a58e43d9faa353886f578c0aa..1ac8482ac41c3599f4afeea36717b7f07611517e 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -28,6 +28,8 @@
#include
#include "impl/ACameraCaptureSession.h"
+#include "impl/ACameraCaptureSession.inc"
+
using namespace android;
EXPORT
@@ -78,11 +80,39 @@ camera_status_t ACameraCaptureSession_capture(
if (session->isClosed()) {
ALOGE("%s: session %p is already closed", __FUNCTION__, session);
- *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ if (captureSequenceId != nullptr) {
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ }
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->capture(
+ cbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_capture(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ if (captureSequenceId) {
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ }
return ACAMERA_ERROR_SESSION_CLOSED;
}
- return session->capture(cbs, numRequests, requests, captureSequenceId);
+ return session->capture(
+ lcbs, numRequests, requests, captureSequenceId);
}
EXPORT
@@ -99,13 +129,39 @@ camera_status_t ACameraCaptureSession_setRepeatingRequest(
if (session->isClosed()) {
ALOGE("%s: session %p is already closed", __FUNCTION__, session);
- *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ if (captureSequenceId) {
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ }
return ACAMERA_ERROR_SESSION_CLOSED;
}
return session->setRepeatingRequest(cbs, numRequests, requests, captureSequenceId);
}
+EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ if (captureSequenceId) {
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ }
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->setRepeatingRequest(lcbs, numRequests, requests, captureSequenceId);
+}
+
EXPORT
camera_status_t ACameraCaptureSession_stopRepeating(ACameraCaptureSession* session) {
ATRACE_CALL();
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index 812a312c54483745429f846540127d0cf424ba73..691996bdbf6c3922e0d9551846f5633e634e8f37 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -24,7 +24,15 @@
#include
#include "impl/ACameraCaptureSession.h"
-using namespace android;
+using namespace android::acam;
+
+bool areWindowTypesEqual(ACameraWindowType *a, ACameraWindowType *b) {
+#ifdef __ANDROID_VNDK__
+ return utils::isWindowNativeHandleEqual(a, b);
+#else
+ return a == b;
+#endif
+}
EXPORT
camera_status_t ACameraDevice_close(ACameraDevice* device) {
@@ -70,7 +78,34 @@ camera_status_t ACameraDevice_createCaptureRequest(
ALOGE("%s: unknown template ID %d", __FUNCTION__, templateId);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- return device->createCaptureRequest(templateId, request);
+ return device->createCaptureRequest(templateId, nullptr /*physicalIdList*/, request);
+}
+
+EXPORT
+camera_status_t ACameraDevice_createCaptureRequest_withPhysicalIds(
+ const ACameraDevice* device,
+ ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalCameraIdList,
+ ACaptureRequest** request) {
+ ATRACE_CALL();
+ if (device == nullptr || request == nullptr || physicalCameraIdList == nullptr) {
+ ALOGE("%s: invalid argument! device %p request %p, physicalCameraIdList %p",
+ __FUNCTION__, device, request, physicalCameraIdList);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ switch (templateId) {
+ case TEMPLATE_PREVIEW:
+ case TEMPLATE_STILL_CAPTURE:
+ case TEMPLATE_RECORD:
+ case TEMPLATE_VIDEO_SNAPSHOT:
+ case TEMPLATE_ZERO_SHUTTER_LAG:
+ case TEMPLATE_MANUAL:
+ break;
+ default:
+ ALOGE("%s: unknown template ID %d", __FUNCTION__, templateId);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return device->createCaptureRequest(templateId, physicalCameraIdList, request);
}
EXPORT
@@ -96,7 +131,7 @@ void ACaptureSessionOutputContainer_free(ACaptureSessionOutputContainer* contain
EXPORT
camera_status_t ACaptureSessionOutput_create(
- ANativeWindow* window, /*out*/ACaptureSessionOutput** out) {
+ ACameraWindowType* window, /*out*/ACaptureSessionOutput** out) {
ATRACE_CALL();
if (window == nullptr || out == nullptr) {
ALOGE("%s: Error: bad argument. window %p, out %p",
@@ -109,7 +144,7 @@ camera_status_t ACaptureSessionOutput_create(
EXPORT
camera_status_t ACaptureSessionSharedOutput_create(
- ANativeWindow* window, /*out*/ACaptureSessionOutput** out) {
+ ACameraWindowType* window, /*out*/ACaptureSessionOutput** out) {
ATRACE_CALL();
if (window == nullptr || out == nullptr) {
ALOGE("%s: Error: bad argument. window %p, out %p",
@@ -120,9 +155,23 @@ camera_status_t ACaptureSessionSharedOutput_create(
return ACAMERA_OK;
}
+EXPORT
+camera_status_t ACaptureSessionPhysicalOutput_create(
+ ACameraWindowType* window, const char* physicalId,
+ /*out*/ACaptureSessionOutput** out) {
+ ATRACE_CALL();
+ if (window == nullptr || physicalId == nullptr || out == nullptr) {
+ ALOGE("%s: Error: bad argument. window %p, physicalId %p, out %p",
+ __FUNCTION__, window, physicalId, out);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ *out = new ACaptureSessionOutput(window, false, physicalId);
+ return ACAMERA_OK;
+}
+
EXPORT
camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *out,
- ANativeWindow* window) {
+ ACameraWindowType* window) {
ATRACE_CALL();
if ((window == nullptr) || (out == nullptr)) {
ALOGE("%s: Error: bad argument. window %p, out %p",
@@ -134,7 +183,7 @@ camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *out,
__FUNCTION__);
return ACAMERA_ERROR_INVALID_OPERATION;
}
- if (out->mWindow == window) {
+ if (areWindowTypesEqual(out->mWindow, window)) {
ALOGE("%s: Error trying to add the same window associated with the output configuration",
__FUNCTION__);
return ACAMERA_ERROR_INVALID_PARAMETER;
@@ -147,7 +196,7 @@ camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *out,
EXPORT
camera_status_t ACaptureSessionSharedOutput_remove(ACaptureSessionOutput *out,
- ANativeWindow* window) {
+ ACameraWindowType* window) {
ATRACE_CALL();
if ((window == nullptr) || (out == nullptr)) {
ALOGE("%s: Error: bad argument. window %p, out %p",
@@ -159,7 +208,7 @@ camera_status_t ACaptureSessionSharedOutput_remove(ACaptureSessionOutput *out,
__FUNCTION__);
return ACAMERA_ERROR_INVALID_OPERATION;
}
- if (out->mWindow == window) {
+ if (areWindowTypesEqual(out->mWindow, window)) {
ALOGE("%s: Error trying to remove the same window associated with the output configuration",
__FUNCTION__);
return ACAMERA_ERROR_INVALID_PARAMETER;
@@ -238,3 +287,16 @@ camera_status_t ACameraDevice_createCaptureSessionWithSessionParameters(
}
return device->createCaptureSession(outputs, sessionParameters, callbacks, session);
}
+
+EXPORT
+camera_status_t ACameraDevice_isSessionConfigurationSupported(
+ const ACameraDevice* device,
+ const ACaptureSessionOutputContainer* sessionOutputContainer) {
+ ATRACE_CALL();
+ if (device == nullptr || sessionOutputContainer == nullptr) {
+ ALOGE("%s: Error: invalid input: device %p, sessionOutputContainer %p",
+ __FUNCTION__, device, sessionOutputContainer);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return device->isSessionConfigurationSupported(sessionOutputContainer);
+}
diff --git a/camera/ndk/NdkCameraManager.cpp b/camera/ndk/NdkCameraManager.cpp
index 60b4763d85f59d31cbc125bce56c34678b68b392..3d231a810761f15a6862e2d7f0c23b43d0278771 100644
--- a/camera/ndk/NdkCameraManager.cpp
+++ b/camera/ndk/NdkCameraManager.cpp
@@ -22,9 +22,15 @@
#include
#include
+
+#ifdef __ANDROID_VNDK__
+#include "ndk_vendor/impl/ACameraManager.h"
+#else
#include "impl/ACameraManager.h"
+#endif
+#include "impl/ACameraMetadata.h"
-using namespace android;
+using namespace android::acam;
EXPORT
ACameraManager* ACameraManager_create() {
@@ -98,6 +104,60 @@ camera_status_t ACameraManager_unregisterAvailabilityCallback(
return ACAMERA_OK;
}
+EXPORT
+camera_status_t ACameraManager_registerExtendedAvailabilityCallback(
+ ACameraManager* /*manager*/, const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
+ ATRACE_CALL();
+ if (callback == nullptr) {
+ ALOGE("%s: invalid argument! callback is null!", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ if ((callback->availabilityCallbacks.onCameraAvailable == nullptr) ||
+ (callback->availabilityCallbacks.onCameraUnavailable == nullptr) ||
+ (callback->onCameraAccessPrioritiesChanged == nullptr)) {
+ ALOGE("%s: invalid argument! callback %p, "
+ "onCameraAvailable %p, onCameraUnavailable %p onCameraAccessPrioritiesChanged %p",
+ __FUNCTION__, callback,
+ callback->availabilityCallbacks.onCameraAvailable,
+ callback->availabilityCallbacks.onCameraUnavailable,
+ callback->onCameraAccessPrioritiesChanged);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ auto reservedEntriesCount = sizeof(callback->reserved) / sizeof(callback->reserved[0]);
+ for (size_t i = 0; i < reservedEntriesCount; i++) {
+ if (callback->reserved[i] != nullptr) {
+ ALOGE("%s: invalid argument! callback reserved entries must be set to NULL",
+ __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ }
+ CameraManagerGlobal::getInstance().registerExtendedAvailabilityCallback(callback);
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraManager_unregisterExtendedAvailabilityCallback(
+ ACameraManager* /*manager*/, const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
+ ATRACE_CALL();
+ if (callback == nullptr) {
+ ALOGE("%s: invalid argument! callback is null!", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ if ((callback->availabilityCallbacks.onCameraAvailable == nullptr) ||
+ (callback->availabilityCallbacks.onCameraUnavailable == nullptr) ||
+ (callback->onCameraAccessPrioritiesChanged == nullptr)) {
+ ALOGE("%s: invalid argument! callback %p, "
+ "onCameraAvailable %p, onCameraUnavailable %p onCameraAccessPrioritiesChanged %p",
+ __FUNCTION__, callback,
+ callback->availabilityCallbacks.onCameraAvailable,
+ callback->availabilityCallbacks.onCameraUnavailable,
+ callback->onCameraAccessPrioritiesChanged);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ CameraManagerGlobal::getInstance().unregisterExtendedAvailabilityCallback(callback);
+ return ACAMERA_OK;
+}
+
EXPORT
camera_status_t ACameraManager_getCameraCharacteristics(
ACameraManager* mgr, const char* cameraId, ACameraMetadata** chars){
@@ -107,7 +167,14 @@ camera_status_t ACameraManager_getCameraCharacteristics(
__FUNCTION__, mgr, cameraId, chars);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- return mgr->getCameraCharacteristics(cameraId, chars);
+ sp spChars;
+ camera_status_t status = mgr->getCameraCharacteristics(cameraId, &spChars);
+ if (status != ACAMERA_OK) {
+ return status;
+ }
+ spChars->incStrong((void*) ACameraManager_getCameraCharacteristics);
+ *chars = spChars.get();
+ return ACAMERA_OK;
}
EXPORT
@@ -123,3 +190,17 @@ camera_status_t ACameraManager_openCamera(
}
return mgr->openCamera(cameraId, callback, device);
}
+
+#ifdef __ANDROID_VNDK__
+EXPORT
+camera_status_t ACameraManager_getTagFromName(ACameraManager *mgr, const char* cameraId,
+ const char *name, /*out*/uint32_t *tag) {
+ ATRACE_CALL();
+ if (mgr == nullptr || cameraId == nullptr || name == nullptr) {
+ ALOGE("%s: invalid argument! mgr %p cameraId %p name %p",
+ __FUNCTION__, mgr, cameraId, name);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return mgr->getTagFromName(cameraId, name, tag);
+}
+#endif
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
index 65de81ff81f50c553d230819ded36ed1c9e8e987..9a39ed872f00ecee5ea832d04969674977e3dd0c 100644
--- a/camera/ndk/NdkCameraMetadata.cpp
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -57,13 +57,32 @@ ACameraMetadata* ACameraMetadata_copy(const ACameraMetadata* src) {
ALOGE("%s: src is null!", __FUNCTION__);
return nullptr;
}
- return new ACameraMetadata(*src);
+ ACameraMetadata* copy = new ACameraMetadata(*src);
+ copy->incStrong((void*) ACameraMetadata_copy);
+ return copy;
}
EXPORT
void ACameraMetadata_free(ACameraMetadata* metadata) {
ATRACE_CALL();
if (metadata != nullptr) {
- delete metadata;
+ metadata->decStrong((void*) ACameraMetadata_free);
}
}
+
+EXPORT
+bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,
+ /*out*/size_t* numPhysicalCameras, /*out*/const char*const** physicalCameraIds) {
+ ATRACE_CALL();
+ if (numPhysicalCameras == nullptr || physicalCameraIds == nullptr) {
+ ALOGE("%s: Invalid input: numPhysicalCameras %p, physicalCameraIds %p",
+ __FUNCTION__, numPhysicalCameras, physicalCameraIds);
+ return false;
+ }
+ if (staticMetadata == nullptr) {
+ ALOGE("%s: Invalid input: staticMetadata is null.", __FUNCTION__);
+ return false;
+ }
+
+ return staticMetadata->isLogicalMultiCamera(numPhysicalCameras, physicalCameraIds);
+}
diff --git a/camera/ndk/NdkCaptureRequest.cpp b/camera/ndk/NdkCaptureRequest.cpp
index ac1856b6f17faa58c811c8c0c760daba68859403..87de4a9ba39ae5d8f71aa54475f2567488ff1ccd 100644
--- a/camera/ndk/NdkCaptureRequest.cpp
+++ b/camera/ndk/NdkCaptureRequest.cpp
@@ -27,7 +27,7 @@
EXPORT
camera_status_t ACameraOutputTarget_create(
- ANativeWindow* window, ACameraOutputTarget** out) {
+ ACameraWindowType* window, ACameraOutputTarget** out) {
ATRACE_CALL();
if (window == nullptr) {
ALOGE("%s: Error: input window is null", __FUNCTION__);
@@ -97,6 +97,27 @@ camera_status_t ACaptureRequest_getConstEntry(
return req->settings->getConstEntry(tag, entry);
}
+EXPORT
+camera_status_t ACaptureRequest_getConstEntry_physicalCamera(
+ const ACaptureRequest* req, const char* physicalId,
+ uint32_t tag, ACameraMetadata_const_entry* entry) {
+ ATRACE_CALL();
+ if (req == nullptr || entry == nullptr || physicalId == nullptr) {
+ ALOGE("%s: invalid argument! req %p, tag 0x%x, entry %p, physicalId %p",
+ __FUNCTION__, req, tag, entry, physicalId);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ const auto& physicalSettings = req->physicalSettings.find(physicalId);
+ if (physicalSettings == req->physicalSettings.end()) {
+ ALOGE("%s: Failed to find metadata for physical camera id %s",
+ __FUNCTION__, physicalId);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ return physicalSettings->second->getConstEntry(tag, entry);
+}
+
EXPORT
camera_status_t ACaptureRequest_getAllTags(
const ACaptureRequest* req, /*out*/int32_t* numTags, /*out*/const uint32_t** tags) {
@@ -131,13 +152,42 @@ SET_ENTRY(rational,ACameraMetadata_rational)
#undef SET_ENTRY
+#define SET_PHYSICAL_ENTRY(NAME,NDK_TYPE) \
+EXPORT \
+camera_status_t ACaptureRequest_setEntry_physicalCamera_##NAME( \
+ ACaptureRequest* req, const char* physicalId, uint32_t tag, \
+ uint32_t count, const NDK_TYPE* data) { \
+ ATRACE_CALL(); \
+ if (req == nullptr || (count > 0 && data == nullptr) || physicalId == nullptr) { \
+ ALOGE("%s: invalid argument! req %p, tag 0x%x, count %d, data 0x%p, physicalId %p", \
+ __FUNCTION__, req, tag, count, data, physicalId); \
+ return ACAMERA_ERROR_INVALID_PARAMETER; \
+ } \
+ if (req->physicalSettings.find(physicalId) == req->physicalSettings.end()) { \
+ ALOGE("%s: Failed to find metadata for physical camera id %s", \
+ __FUNCTION__, physicalId); \
+ return ACAMERA_ERROR_INVALID_PARAMETER; \
+ } \
+ return req->physicalSettings[physicalId]->update(tag, count, data); \
+}
+
+SET_PHYSICAL_ENTRY(u8,uint8_t)
+SET_PHYSICAL_ENTRY(i32,int32_t)
+SET_PHYSICAL_ENTRY(float,float)
+SET_PHYSICAL_ENTRY(double,double)
+SET_PHYSICAL_ENTRY(i64,int64_t)
+SET_PHYSICAL_ENTRY(rational,ACameraMetadata_rational)
+
+#undef SET_PHYSICAL_ENTRY
+
EXPORT
void ACaptureRequest_free(ACaptureRequest* request) {
ATRACE_CALL();
if (request == nullptr) {
return;
}
- delete request->settings;
+ request->settings.clear();
+ request->physicalSettings.clear();
delete request->targets;
delete request;
return;
@@ -174,6 +224,9 @@ ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src) {
ACaptureRequest* pRequest = new ACaptureRequest();
pRequest->settings = new ACameraMetadata(*(src->settings));
+ for (const auto& entry : src->physicalSettings) {
+ pRequest->physicalSettings[entry.first] = new ACameraMetadata(*(entry.second));
+ }
pRequest->targets = new ACameraOutputTargets();
*(pRequest->targets) = *(src->targets);
pRequest->context = src->context;
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index f60e5fd9cdb9150b1d78f1d10129f9bdf42cbd58..d6f14122eab44687a2b7db67159c831d2b329cdf 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -23,7 +23,7 @@ using namespace android;
ACameraCaptureSession::~ACameraCaptureSession() {
ALOGV("~ACameraCaptureSession: %p notify device end of life", this);
- sp dev = getDeviceSp();
+ sp dev = getDeviceSp();
if (dev != nullptr && !dev->isClosed()) {
dev->lockDeviceForSessionOps();
{
@@ -48,7 +48,7 @@ ACameraCaptureSession::closeByApp() {
mClosedByApp = true;
}
- sp dev = getDeviceSp();
+ sp dev = getDeviceSp();
if (dev != nullptr) {
dev->lockDeviceForSessionOps();
}
@@ -73,7 +73,7 @@ ACameraCaptureSession::closeByApp() {
camera_status_t
ACameraCaptureSession::stopRepeating() {
- sp dev = getDeviceSp();
+ sp dev = getDeviceSp();
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return ACAMERA_ERROR_SESSION_CLOSED;
@@ -91,7 +91,7 @@ ACameraCaptureSession::stopRepeating() {
camera_status_t
ACameraCaptureSession::abortCaptures() {
- sp dev = getDeviceSp();
+ sp dev = getDeviceSp();
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return ACAMERA_ERROR_SESSION_CLOSED;
@@ -107,49 +107,8 @@ ACameraCaptureSession::abortCaptures() {
return ret;
}
-camera_status_t
-ACameraCaptureSession::setRepeatingRequest(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- sp dev = getDeviceSp();
- if (dev == nullptr) {
- ALOGE("Error: Device associated with session %p has been closed!", this);
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
-
- camera_status_t ret;
- dev->lockDeviceForSessionOps();
- {
- Mutex::Autolock _l(mSessionLock);
- ret = dev->setRepeatingRequestsLocked(
- this, cbs, numRequests, requests, captureSequenceId);
- }
- dev->unlockDevice();
- return ret;
-}
-
-camera_status_t ACameraCaptureSession::capture(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- sp dev = getDeviceSp();
- if (dev == nullptr) {
- ALOGE("Error: Device associated with session %p has been closed!", this);
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
- camera_status_t ret;
- dev->lockDeviceForSessionOps();
- {
- Mutex::Autolock _l(mSessionLock);
- ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
- }
- dev->unlockDevice();
- return ret;
-}
-
camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSessionOutput *output) {
- sp dev = getDeviceSp();
+ sp dev = getDeviceSp();
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return ACAMERA_ERROR_SESSION_CLOSED;
@@ -168,7 +127,7 @@ camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSession
ACameraDevice*
ACameraCaptureSession::getDevice() {
Mutex::Autolock _l(mSessionLock);
- sp dev = getDeviceSp();
+ sp dev = getDeviceSp();
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return nullptr;
@@ -182,9 +141,9 @@ ACameraCaptureSession::closeByDevice() {
mIsClosed = true;
}
-sp
+sp
ACameraCaptureSession::getDeviceSp() {
- sp device = mDevice.promote();
+ sp device = mDevice.promote();
if (device == nullptr || device->isClosed()) {
ALOGW("Device is closed but session %d is not notified", mId);
return nullptr;
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index a2068e71b102652ed4e87286416289a26aa1f47a..08a922634d5d91c5582cacb6bfac8e3708299fa6 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -17,15 +17,22 @@
#define _ACAMERA_CAPTURE_SESSION_H
#include
+#include
#include
#include
+
+#ifdef __ANDROID_VNDK__
+#include "ndk_vendor/impl/ACameraDevice.h"
+#include "ndk_vendor/impl/ACameraCaptureSessionVendor.h"
+#else
#include "ACameraDevice.h"
using namespace android;
struct ACaptureSessionOutput {
- explicit ACaptureSessionOutput(ANativeWindow* window, bool isShared = false) :
- mWindow(window), mIsShared(isShared) {};
+ explicit ACaptureSessionOutput(ACameraWindowType* window, bool isShared = false,
+ const char* physicalCameraId = "") :
+ mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {};
bool operator == (const ACaptureSessionOutput& other) const {
return mWindow == other.mWindow;
@@ -40,11 +47,13 @@ struct ACaptureSessionOutput {
return mWindow > other.mWindow;
}
- ANativeWindow* mWindow;
- std::set mSharedWindows;
+ ACameraWindowType* mWindow;
+ std::set mSharedWindows;
bool mIsShared;
int mRotation = CAMERA3_STREAM_ROTATION_0;
+ std::string mPhysicalCameraId;
};
+#endif
struct ACaptureSessionOutputContainer {
std::set mOutputs;
@@ -60,7 +69,7 @@ struct ACameraCaptureSession : public RefBase {
int id,
const ACaptureSessionOutputContainer* outputs,
const ACameraCaptureSession_stateCallbacks* cb,
- CameraDevice* device) :
+ android::acam::CameraDevice* device) :
mId(id), mOutput(*outputs), mUserSessionCallback(*cb),
mDevice(device) {}
@@ -82,13 +91,15 @@ struct ACameraCaptureSession : public RefBase {
camera_status_t abortCaptures();
+ template
camera_status_t setRepeatingRequest(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template
camera_status_t capture(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
@@ -97,18 +108,18 @@ struct ACameraCaptureSession : public RefBase {
ACameraDevice* getDevice();
private:
- friend class CameraDevice;
+ friend class android::acam::CameraDevice;
// Close session because app close camera device, camera device got ERROR_DISCONNECTED,
// or a new session is replacing this session.
void closeByDevice();
- sp getDeviceSp();
+ sp getDeviceSp();
const int mId;
const ACaptureSessionOutputContainer mOutput;
const ACameraCaptureSession_stateCallbacks mUserSessionCallback;
- const wp mDevice;
+ const wp mDevice;
bool mIsClosed = false;
bool mClosedByApp = false;
Mutex mSessionLock;
diff --git a/camera/ndk/impl/ACameraCaptureSession.inc b/camera/ndk/impl/ACameraCaptureSession.inc
new file mode 100644
index 0000000000000000000000000000000000000000..86bf8a5d255e8ce1e39bde94900f88828a3264c3
--- /dev/null
+++ b/camera/ndk/impl/ACameraCaptureSession.inc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ACameraCaptureSession.h"
+
+#ifdef __ANDROID_VNDK__
+#include "ndk_vendor/impl/ACameraDeviceVendor.inc"
+#else
+#include "ACameraDevice.inc"
+#endif
+
+using namespace android;
+
+template
+camera_status_t
+ACameraCaptureSession::setRepeatingRequest(
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ sp dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->setRepeatingRequestsLocked(
+ this, cbs, numRequests, requests, captureSequenceId);
+ }
+ dev->unlockDevice();
+ return ret;
+}
+
+template
+camera_status_t ACameraCaptureSession::capture(
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ sp dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
+ }
+ dev->unlockDevice();
+ return ret;
+}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index ffabf7b27c862d37008b568083122205f96ecaa6..d24cb814a32ade3fe4e6de223d15e8341b18fe0a 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -20,16 +20,21 @@
#include
#include
#include
-#include
#include
#include "ACameraDevice.h"
#include "ACameraMetadata.h"
#include "ACaptureRequest.h"
#include "ACameraCaptureSession.h"
-using namespace android;
+#include "ACameraCaptureSession.inc"
+
+ACameraDevice::~ACameraDevice() {
+ mDevice->stopLooper();
+}
namespace android {
+namespace acam {
+
// Static member definitions
const char* CameraDevice::kContextKey = "Context";
const char* CameraDevice::kDeviceKey = "Device";
@@ -39,10 +44,12 @@ const char* CameraDevice::kSessionSpKey = "SessionSp";
const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
const char* CameraDevice::kTimeStampKey = "TimeStamp";
const char* CameraDevice::kCaptureResultKey = "CaptureResult";
+const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult";
const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
const char* CameraDevice::kSequenceIdKey = "SequenceId";
const char* CameraDevice::kFrameNumberKey = "FrameNumber";
const char* CameraDevice::kAnwKey = "Anw";
+const char* CameraDevice::kFailingPhysicalCameraId= "FailingPhysicalCameraId";
/**
* CameraDevice Implementation
@@ -50,11 +57,11 @@ const char* CameraDevice::kAnwKey = "Anw";
CameraDevice::CameraDevice(
const char* id,
ACameraDevice_StateCallbacks* cb,
- std::unique_ptr chars,
+ sp chars,
ACameraDevice* wrapper) :
mCameraId(id),
mAppCallbacks(*cb),
- mChars(std::move(chars)),
+ mChars(chars),
mServiceCallback(new ServiceCallback(this)),
mWrapper(wrapper),
mInError(false),
@@ -74,7 +81,7 @@ CameraDevice::CameraDevice(
__FUNCTION__, strerror(-err), err);
setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
}
- mHandler = new CallbackHandler();
+ mHandler = new CallbackHandler(id);
mCbLooper->registerHandler(mHandler);
const CameraMetadata& metadata = mChars->getInternalData();
@@ -95,6 +102,14 @@ CameraDevice::CameraDevice(
mShadingMapSize[0] = entry.data.i32[0];
mShadingMapSize[1] = entry.data.i32[1];
}
+
+ size_t physicalIdCnt = 0;
+ const char*const* physicalCameraIds;
+ if (mChars->isLogicalMultiCamera(&physicalIdCnt, &physicalCameraIds)) {
+ for (size_t i = 0; i < physicalIdCnt; i++) {
+ mPhysicalIds.push_back(physicalCameraIds[i]);
+ }
+ }
}
// Device close implementaiton
@@ -105,14 +120,10 @@ CameraDevice::~CameraDevice() {
if (!isClosed()) {
disconnectLocked(session);
}
+ LOG_ALWAYS_FATAL_IF(mCbLooper != nullptr,
+ "CameraDevice looper should've been stopped before ~CameraDevice");
mCurrentSession = nullptr;
- if (mCbLooper != nullptr) {
- mCbLooper->unregisterHandler(mHandler->id());
- mCbLooper->stop();
- }
}
- mCbLooper.clear();
- mHandler.clear();
}
void
@@ -127,8 +138,29 @@ CameraDevice::postSessionMsgAndCleanup(sp& msg) {
camera_status_t
CameraDevice::createCaptureRequest(
ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalIdList,
ACaptureRequest** request) const {
Mutex::Autolock _l(mDeviceLock);
+
+ if (physicalIdList != nullptr) {
+ if (physicalIdList->numCameras > static_cast(mPhysicalIds.size())) {
+ ALOGE("%s: physicalIdList size %d exceeds number of available physical cameras %zu",
+ __FUNCTION__, physicalIdList->numCameras, mPhysicalIds.size());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ for (auto i = 0; i < physicalIdList->numCameras; i++) {
+ if (physicalIdList->cameraIds[i] == nullptr) {
+ ALOGE("%s: physicalId is null!", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ if (mPhysicalIds.end() == std::find(
+ mPhysicalIds.begin(), mPhysicalIds.end(), physicalIdList->cameraIds[i])) {
+ ALOGE("%s: Invalid physicalId %s!", __FUNCTION__, physicalIdList->cameraIds[i]);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ }
+ }
+
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
return ret;
@@ -149,6 +181,12 @@ CameraDevice::createCaptureRequest(
}
ACaptureRequest* outReq = new ACaptureRequest();
outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
+ if (physicalIdList != nullptr) {
+ for (auto i = 0; i < physicalIdList->numCameras; i++) {
+ outReq->physicalSettings.emplace(physicalIdList->cameraIds[i],
+ new ACameraMetadata(*(outReq->settings)));
+ }
+ }
outReq->targets = new ACameraOutputTargets();
*request = outReq;
return ACAMERA_OK;
@@ -190,104 +228,53 @@ CameraDevice::createCaptureSession(
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::captureLocked(
- sp session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
-}
-
-camera_status_t
-CameraDevice::setRepeatingRequestsLocked(
- sp session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
-}
-
-camera_status_t
-CameraDevice::submitRequestsLocked(
- sp session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId,
- bool isRepeating) {
+camera_status_t CameraDevice::isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const {
+ Mutex::Autolock _l(mDeviceLock);
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
- ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
return ret;
}
- // Form two vectors of capture request, one for internal tracking
- std::vector requestList;
- Vector > requestsV;
- requestsV.setCapacity(numRequests);
- for (int i = 0; i < numRequests; i++) {
- sp req;
- ret = allocateCaptureRequest(requests[i], req);
- if (ret != ACAMERA_OK) {
- ALOGE("Convert capture request to internal format failure! ret %d", ret);
- return ret;
- }
- if (req->mSurfaceList.empty()) {
- ALOGE("Capture request without output target cannot be submitted!");
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
- requestList.push_back(*(req.get()));
- requestsV.push_back(req);
- }
-
- if (isRepeating) {
- ret = stopRepeatingLocked();
+ SessionConfiguration sessionConfiguration(0 /*inputWidth*/, 0 /*inputHeight*/,
+ -1 /*inputFormat*/, CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
+ for (const auto& output : sessionOutputContainer->mOutputs) {
+ sp iGBP(nullptr);
+ ret = getIGBPfromAnw(output.mWindow, iGBP);
if (ret != ACAMERA_OK) {
- ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+ ALOGE("Camera device %s failed to extract graphic producer from native window",
+ getId());
return ret;
}
- }
-
- binder::Status remoteRet;
- hardware::camera2::utils::SubmitInfo info;
- remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
- int sequenceId = info.mRequestId;
- int64_t lastFrameNumber = info.mLastFrameNumber;
- if (sequenceId < 0) {
- ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
- return ACAMERA_ERROR_UNKNOWN;
- }
- CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
- mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+ String16 physicalId16(output.mPhysicalCameraId.c_str());
+ OutputConfiguration outConfig(iGBP, output.mRotation, physicalId16,
+ OutputConfiguration::INVALID_SET_ID, true);
- if (isRepeating) {
- // stopRepeating above should have cleanup repeating sequence id
- if (mRepeatingSequenceId != REQUEST_ID_NONE) {
- setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
- return ACAMERA_ERROR_CAMERA_DEVICE;
+ for (auto& anw : output.mSharedWindows) {
+ ret = getIGBPfromAnw(anw, iGBP);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s failed to extract graphic producer from native window",
+ getId());
+ return ret;
+ }
+ outConfig.addGraphicProducer(iGBP);
}
- mRepeatingSequenceId = sequenceId;
- } else {
- mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
- }
- if (mIdle) {
- sp msg = new AMessage(kWhatSessionStateCb, mHandler);
- msg->setPointer(kContextKey, session->mUserSessionCallback.context);
- msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
- postSessionMsgAndCleanup(msg);
+ sessionConfiguration.addOutputConfiguration(outConfig);
}
- mIdle = false;
- mBusySession = session;
- if (captureSequenceId) {
- *captureSequenceId = sequenceId;
+ bool supported = false;
+ binder::Status remoteRet = mRemote->isSessionConfigurationSupported(
+ sessionConfiguration, &supported);
+ if (remoteRet.serviceSpecificErrorCode() ==
+ hardware::ICameraService::ERROR_INVALID_OPERATION) {
+ return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+ } else if (!remoteRet.isOk()) {
+ return ACAMERA_ERROR_UNKNOWN;
+ } else {
+ return supported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
}
- return ACAMERA_OK;
}
camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
@@ -325,8 +312,9 @@ camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOut
return ret;
}
- OutputConfiguration outConfig(iGBP, output->mRotation, OutputConfiguration::INVALID_SET_ID,
- true);
+ String16 physicalId16(output->mPhysicalCameraId.c_str());
+ OutputConfiguration outConfig(iGBP, output->mRotation, physicalId16,
+ OutputConfiguration::INVALID_SET_ID, true);
for (auto& anw : output->mSharedWindows) {
ret = getIGBPfromAnw(anw, iGBP);
@@ -372,8 +360,12 @@ CameraDevice::allocateCaptureRequest(
const ACaptureRequest* request, /*out*/sp& outReq) {
camera_status_t ret;
sp req(new CaptureRequest());
- req->mPhysicalCameraSettings.push_back({std::string(mCameraId.string()),
+ req->mPhysicalCameraSettings.push_back({getId(),
request->settings->getInternalData()});
+ for (auto& entry : request->physicalSettings) {
+ req->mPhysicalCameraSettings.push_back({entry.first,
+ entry.second->getInternalData()});
+ }
req->mIsReprocess = false; // NDK does not support reprocessing yet
req->mContext = request->context;
req->mSurfaceConverted = true; // set to true, and fill in stream/surface idx to speed up IPC
@@ -417,10 +409,17 @@ CameraDevice::allocateCaptureRequest(
}
ACaptureRequest*
-CameraDevice::allocateACaptureRequest(sp& req) {
+CameraDevice::allocateACaptureRequest(sp& req, const std::string& deviceId) {
ACaptureRequest* pRequest = new ACaptureRequest();
- CameraMetadata clone = req->mPhysicalCameraSettings.begin()->settings;
- pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
+ for (auto& entry : req->mPhysicalCameraSettings) {
+ CameraMetadata clone = entry.settings;
+ if (entry.id == deviceId) {
+ pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
+ } else {
+ pRequest->physicalSettings.emplace(entry.id,
+ new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST));
+ }
+ }
pRequest->targets = new ACameraOutputTargets();
for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
ANativeWindow* anw = static_cast(req->mSurfaceList[i].get());
@@ -436,7 +435,8 @@ CameraDevice::freeACaptureRequest(ACaptureRequest* req) {
if (req == nullptr) {
return;
}
- delete req->settings;
+ req->settings.clear();
+ req->physicalSettings.clear();
delete req->targets;
delete req;
}
@@ -640,8 +640,9 @@ CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outpu
if (ret != ACAMERA_OK) {
return ret;
}
+ String16 physicalId16(outConfig.mPhysicalCameraId.c_str());
outputSet.insert(std::make_pair(
- anw, OutputConfiguration(iGBP, outConfig.mRotation,
+ anw, OutputConfiguration(iGBP, outConfig.mRotation, physicalId16,
OutputConfiguration::INVALID_SET_ID, outConfig.mIsShared)));
}
auto addSet = outputSet;
@@ -829,7 +830,7 @@ CameraDevice::onCaptureErrorLocked(
if (errorCode == hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER) {
int32_t streamId = resultExtras.errorStreamId;
ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
- cbh.mCallbacks.onCaptureBufferLost;
+ cbh.mOnCaptureBufferLost;
auto outputPairIt = mConfiguredOutputs.find(streamId);
if (outputPairIt == mConfiguredOutputs.end()) {
ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
@@ -846,7 +847,7 @@ CameraDevice::onCaptureErrorLocked(
getId(), anw, frameNumber);
sp msg = new AMessage(kWhatCaptureBufferLost, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
msg->setObject(kCaptureRequestKey, request);
@@ -858,7 +859,7 @@ CameraDevice::onCaptureErrorLocked(
}
} else { // Handle other capture failures
// Fire capture failure callback if there is one registered
- ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
+ ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed;
sp failure(new CameraCaptureFailure());
failure->frameNumber = frameNumber;
// TODO: refine this when implementing flush
@@ -867,10 +868,19 @@ CameraDevice::onCaptureErrorLocked(
failure->wasImageCaptured = (errorCode ==
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT);
- sp msg = new AMessage(kWhatCaptureFail, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ sp msg = new AMessage(cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureFail :
+ kWhatCaptureFail, mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) onError);
+ if (cbh.mIsLogicalCameraCallback) {
+ if (resultExtras.errorPhysicalCameraId.size() > 0) {
+ String8 cameraId(resultExtras.errorPhysicalCameraId);
+ msg->setString(kFailingPhysicalCameraId, cameraId.string(), cameraId.size());
+ }
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnLogicalCameraCaptureFailed);
+ } else {
+ msg->setPointer(kCallbackFpKey, (void*) onError);
+ }
msg->setObject(kCaptureRequestKey, request);
msg->setObject(kCaptureFailureKey, failure);
postSessionMsgAndCleanup(msg);
@@ -882,6 +892,19 @@ CameraDevice::onCaptureErrorLocked(
return;
}
+void CameraDevice::stopLooper() {
+ Mutex::Autolock _l(mDeviceLock);
+ if (mCbLooper != nullptr) {
+ mCbLooper->unregisterHandler(mHandler->id());
+ mCbLooper->stop();
+ }
+ mCbLooper.clear();
+ mHandler.clear();
+}
+
+CameraDevice::CallbackHandler::CallbackHandler(const char* id) : mId(id) {
+}
+
void CameraDevice::CallbackHandler::onMessageReceived(
const sp &msg) {
switch (msg->what()) {
@@ -890,7 +913,9 @@ void CameraDevice::CallbackHandler::onMessageReceived(
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
+ case kWhatLogicalCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
case kWhatCaptureBufferLost:
@@ -960,7 +985,9 @@ void CameraDevice::CallbackHandler::onMessageReceived(
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
+ case kWhatLogicalCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
case kWhatCaptureBufferLost:
@@ -977,7 +1004,9 @@ void CameraDevice::CallbackHandler::onMessageReceived(
switch (msg->what()) {
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
+ case kWhatLogicalCaptureFail:
case kWhatCaptureBufferLost:
found = msg->findObject(kCaptureRequestKey, &obj);
if (!found) {
@@ -1020,7 +1049,7 @@ void CameraDevice::CallbackHandler::onMessageReceived(
ALOGE("%s: Cannot find timestamp!", __FUNCTION__);
return;
}
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onStart)(context, session.get(), request, timestamp);
freeACaptureRequest(request);
break;
@@ -1043,11 +1072,69 @@ void CameraDevice::CallbackHandler::onMessageReceived(
return;
}
sp result(static_cast(obj.get()));
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onResult)(context, session.get(), request, result.get());
freeACaptureRequest(request);
break;
}
+ case kWhatLogicalCaptureResult:
+ {
+ ACameraCaptureSession_logicalCamera_captureCallback_result onResult;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+ if (!found) {
+ ALOGE("%s: Cannot find logicalCamera capture result callback!",
+ __FUNCTION__);
+ return;
+ }
+ if (onResult == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+ return;
+ }
+ sp result(static_cast(obj.get()));
+
+ found = msg->findObject(kPhysicalCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find physical capture result!", __FUNCTION__);
+ return;
+ }
+ sp physicalResult(
+ static_cast(obj.get()));
+ std::vector& physicalResultInfo =
+ physicalResult->mPhysicalResultInfo;
+
+ std::vector physicalCameraIds;
+ std::vector> physicalMetadataCopy;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ String8 physicalId8(physicalResultInfo[i].mPhysicalCameraId);
+ physicalCameraIds.push_back(physicalId8.c_str());
+
+ CameraMetadata clone = physicalResultInfo[i].mPhysicalCameraMetadata;
+ clone.update(ANDROID_SYNC_FRAME_NUMBER,
+ &physicalResult->mFrameNumber, /*data_count*/1);
+ sp metadata =
+ new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+ physicalMetadataCopy.push_back(metadata);
+ }
+
+ std::vector physicalCameraIdPtrs;
+ std::vector physicalMetadataCopyPtrs;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str());
+ physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
+ (*onResult)(context, session.get(), request, result.get(),
+ physicalResultInfo.size(), physicalCameraIdPtrs.data(),
+ physicalMetadataCopyPtrs.data());
+ freeACaptureRequest(request);
+ break;
+ }
case kWhatCaptureFail:
{
ACameraCaptureSession_captureCallback_failed onFail;
@@ -1069,11 +1156,44 @@ void CameraDevice::CallbackHandler::onMessageReceived(
static_cast(obj.get()));
ACameraCaptureFailure* failure =
static_cast(failureSp.get());
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onFail)(context, session.get(), request, failure);
freeACaptureRequest(request);
break;
}
+ case kWhatLogicalCaptureFail:
+ {
+ ACameraCaptureSession_logicalCamera_captureCallback_failed onFail;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onFail);
+ if (!found) {
+ ALOGE("%s: Cannot find capture fail callback!", __FUNCTION__);
+ return;
+ }
+ if (onFail == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureFailureKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture failure!", __FUNCTION__);
+ return;
+ }
+ sp failureSp(
+ static_cast(obj.get()));
+ ALogicalCameraCaptureFailure failure;
+ AString physicalCameraId;
+ found = msg->findString(kFailingPhysicalCameraId, &physicalCameraId);
+ if (found && !physicalCameraId.empty()) {
+ failure.physicalCameraId = physicalCameraId.c_str();
+ } else {
+ failure.physicalCameraId = nullptr;
+ }
+ failure.captureFailure = *failureSp;
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
+ (*onFail)(context, session.get(), request, &failure);
+ freeACaptureRequest(request);
+ break;
+ }
case kWhatCaptureSeqEnd:
{
ACameraCaptureSession_captureCallback_sequenceEnd onSeqEnd;
@@ -1146,7 +1266,7 @@ void CameraDevice::CallbackHandler::onMessageReceived(
return;
}
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onBufferLost)(context, session.get(), request, anw, frameNumber);
freeACaptureRequest(request);
break;
@@ -1158,12 +1278,36 @@ void CameraDevice::CallbackHandler::onMessageReceived(
}
CameraDevice::CallbackHolder::CallbackHolder(
- sp session,
- const Vector >& requests,
- bool isRepeating,
- ACameraCaptureSession_captureCallbacks* cbs) :
- mSession(session), mRequests(requests),
- mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {}
+ sp session,
+ const Vector >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacks* cbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(false) {
+ initCaptureCallbacks(cbs);
+
+ if (cbs != nullptr) {
+ mOnCaptureCompleted = cbs->onCaptureCompleted;
+ mOnCaptureFailed = cbs->onCaptureFailed;
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp session,
+ const Vector >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(true) {
+ initCaptureCallbacks(lcbs);
+
+ if (lcbs != nullptr) {
+ mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+ mOnLogicalCameraCaptureFailed = lcbs->onLogicalCameraCaptureFailed;
+ }
+}
void
CameraDevice::checkRepeatingSequenceCompleteLocked(
@@ -1180,9 +1324,9 @@ CameraDevice::checkRepeatingSequenceCompleteLocked(
mSequenceCallbackMap.erase(cbIt);
// send seq aborted callback
sp msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted);
msg->setInt32(kSequenceIdKey, sequenceId);
postSessionMsgAndCleanup(msg);
} else {
@@ -1230,9 +1374,9 @@ CameraDevice::checkAndFireSequenceCompleteLocked() {
mSequenceCallbackMap.erase(cbIt);
// send seq complete callback
sp msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
msg->setInt32(kSequenceIdKey, sequenceId);
msg->setInt64(kFrameNumberKey, lastFrameNumber);
@@ -1389,7 +1533,7 @@ CameraDevice::ServiceCallback::onCaptureStarted(
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted;
+ ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
sp session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1398,7 +1542,7 @@ CameraDevice::ServiceCallback::onCaptureStarted(
}
sp request = cbh.mRequests[burstId];
sp msg = new AMessage(kWhatCaptureStart, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onStart);
msg->setObject(kCaptureRequestKey, request);
@@ -1413,7 +1557,6 @@ CameraDevice::ServiceCallback::onResultReceived(
const CameraMetadata& metadata,
const CaptureResultExtras& resultExtras,
const std::vector& physicalResultInfos) {
- (void) physicalResultInfos;
binder::Status ret = binder::Status::ok();
sp dev = mDevice.promote();
@@ -1449,9 +1592,6 @@ CameraDevice::ServiceCallback::onResultReceived(
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_result onResult = isPartialResult ?
- cbh.mCallbacks.onCaptureProgressed :
- cbh.mCallbacks.onCaptureCompleted;
sp session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1461,13 +1601,27 @@ CameraDevice::ServiceCallback::onResultReceived(
sp request = cbh.mRequests[burstId];
sp result(new ACameraMetadata(
metadataCopy.release(), ACameraMetadata::ACM_RESULT));
+ sp physicalResult(
+ new ACameraPhysicalCaptureResultInfo(physicalResultInfos, frameNumber));
- sp msg = new AMessage(kWhatCaptureResult, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ sp msg = new AMessage(
+ cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult,
+ dev->mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) onResult);
msg->setObject(kCaptureRequestKey, request);
msg->setObject(kCaptureResultKey, result);
+ if (isPartialResult) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureProgressed);
+ } else if (cbh.mIsLogicalCameraCallback) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnLogicalCameraCaptureCompleted);
+ msg->setObject(kPhysicalCaptureResultKey, physicalResult);
+ } else {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureCompleted);
+ }
dev->postSessionMsgAndCleanup(msg);
}
@@ -1513,5 +1667,5 @@ CameraDevice::ServiceCallback::onRepeatingRequestError(
return ret;
}
-
+} // namespace acam
} // namespace android
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 136914823adef6745323a803c2a17bf677df6aca..7a35bf0e81f6f53b9153fee75b2132ea4a9b4d1b 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -34,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
@@ -41,14 +43,25 @@
#include "ACameraMetadata.h"
namespace android {
+namespace acam {
// Wrap ACameraCaptureFailure so it can be ref-counted
struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure {};
+// Wrap PhysicalCaptureResultInfo so that it can be ref-counted
+struct ACameraPhysicalCaptureResultInfo: public RefBase {
+ ACameraPhysicalCaptureResultInfo(const std::vector& info,
+ int64_t frameNumber) :
+ mPhysicalResultInfo(info), mFrameNumber(frameNumber) {}
+
+ std::vector mPhysicalResultInfo;
+ int64_t mFrameNumber;
+};
+
class CameraDevice final : public RefBase {
public:
CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
- std::unique_ptr chars,
+ sp chars,
ACameraDevice* wrapper);
~CameraDevice();
@@ -56,6 +69,7 @@ class CameraDevice final : public RefBase {
camera_status_t createCaptureRequest(
ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalIdList,
ACaptureRequest** request) const;
camera_status_t createCaptureSession(
@@ -64,6 +78,9 @@ class CameraDevice final : public RefBase {
const ACameraCaptureSession_stateCallbacks* callbacks,
/*out*/ACameraCaptureSession** session);
+ camera_status_t isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const;
+
// Callbacks from camera service
class ServiceCallback : public hardware::camera2::BnCameraDeviceCallbacks {
public:
@@ -92,6 +109,9 @@ class CameraDevice final : public RefBase {
inline ACameraDevice* getWrapper() const { return mWrapper; };
+ // Stop the looper thread and unregister the handler
+ void stopLooper();
+
private:
friend ACameraCaptureSession;
camera_status_t checkCameraClosedOrErrorLocked() const;
@@ -108,19 +128,22 @@ class CameraDevice final : public RefBase {
camera_status_t waitUntilIdleLocked();
+ template
camera_status_t captureLocked(sp session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template
camera_status_t setRepeatingRequestsLocked(sp session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template
camera_status_t submitRequestsLocked(
sp session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*out*/int* captureSequenceId,
bool isRepeating);
@@ -130,7 +153,8 @@ class CameraDevice final : public RefBase {
camera_status_t allocateCaptureRequest(
const ACaptureRequest* request, sp& outReq);
- static ACaptureRequest* allocateACaptureRequest(sp& req);
+ static ACaptureRequest* allocateACaptureRequest(sp& req,
+ const std::string& deviceId);
static void freeACaptureRequest(ACaptureRequest*);
// only For session to hold device lock
@@ -156,7 +180,7 @@ class CameraDevice final : public RefBase {
mutable Mutex mDeviceLock;
const String8 mCameraId; // Camera ID
const ACameraDevice_StateCallbacks mAppCallbacks; // Callback to app
- const std::unique_ptr mChars; // Camera characteristics
+ const sp mChars; // Camera characteristics
const sp mServiceCallback;
ACameraDevice* mWrapper;
@@ -191,7 +215,9 @@ class CameraDevice final : public RefBase {
// Capture callbacks
kWhatCaptureStart, // onCaptureStarted
kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
+ kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted
kWhatCaptureFail, // onCaptureFailed
+ kWhatLogicalCaptureFail, // onLogicalCameraCaptureFailed
kWhatCaptureSeqEnd, // onCaptureSequenceCompleted
kWhatCaptureSeqAbort, // onCaptureSequenceAborted
kWhatCaptureBufferLost,// onCaptureBufferLost
@@ -206,16 +232,20 @@ class CameraDevice final : public RefBase {
static const char* kCaptureRequestKey;
static const char* kTimeStampKey;
static const char* kCaptureResultKey;
+ static const char* kPhysicalCaptureResultKey;
static const char* kCaptureFailureKey;
static const char* kSequenceIdKey;
static const char* kFrameNumberKey;
static const char* kAnwKey;
+ static const char* kFailingPhysicalCameraId;
class CallbackHandler : public AHandler {
public:
+ explicit CallbackHandler(const char* id);
void onMessageReceived(const sp &msg) override;
private:
+ std::string mId;
// This handler will cache all capture session sp until kWhatCleanUpSessions
// is processed. This is used to guarantee the last session reference is always
// being removed in callback thread without holding camera device lock
@@ -244,19 +274,47 @@ class CameraDevice final : public RefBase {
const Vector >& requests,
bool isRepeating,
ACameraCaptureSession_captureCallbacks* cbs);
-
- static ACameraCaptureSession_captureCallbacks fillCb(
- ACameraCaptureSession_captureCallbacks* cbs) {
+ CallbackHolder(sp session,
+ const Vector >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
+
+ template
+ void initCaptureCallbacks(T* cbs) {
+ mContext = nullptr;
+ mOnCaptureStarted = nullptr;
+ mOnCaptureProgressed = nullptr;
+ mOnCaptureCompleted = nullptr;
+ mOnLogicalCameraCaptureCompleted = nullptr;
+ mOnLogicalCameraCaptureFailed = nullptr;
+ mOnCaptureFailed = nullptr;
+ mOnCaptureSequenceCompleted = nullptr;
+ mOnCaptureSequenceAborted = nullptr;
+ mOnCaptureBufferLost = nullptr;
if (cbs != nullptr) {
- return *cbs;
+ mContext = cbs->context;
+ mOnCaptureStarted = cbs->onCaptureStarted;
+ mOnCaptureProgressed = cbs->onCaptureProgressed;
+ mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted;
+ mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted;
+ mOnCaptureBufferLost = cbs->onCaptureBufferLost;
}
- return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
}
-
sp mSession;
Vector > mRequests;
const bool mIsRepeating;
- ACameraCaptureSession_captureCallbacks mCallbacks;
+ const bool mIsLogicalCameraCallback;
+
+ void* mContext;
+ ACameraCaptureSession_captureCallback_start mOnCaptureStarted;
+ ACameraCaptureSession_captureCallback_result mOnCaptureProgressed;
+ ACameraCaptureSession_captureCallback_result mOnCaptureCompleted;
+ ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted;
+ ACameraCaptureSession_logicalCamera_captureCallback_failed mOnLogicalCameraCaptureFailed;
+ ACameraCaptureSession_captureCallback_failed mOnCaptureFailed;
+ ACameraCaptureSession_captureCallback_sequenceEnd mOnCaptureSequenceCompleted;
+ ACameraCaptureSession_captureCallback_sequenceAbort mOnCaptureSequenceAborted;
+ ACameraCaptureSession_captureCallback_bufferLost mOnCaptureBufferLost;
};
// sequence id -> callbacks map
std::map mSequenceCallbackMap;
@@ -283,9 +341,11 @@ class CameraDevice final : public RefBase {
// Misc variables
int32_t mShadingMapSize[2]; // const after constructor
int32_t mPartialResultCount; // const after constructor
+ std::vector mPhysicalIds; // const after constructor
};
+} // namespace acam;
} // namespace android;
/**
@@ -294,10 +354,10 @@ class CameraDevice final : public RefBase {
*/
struct ACameraDevice {
ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
- std::unique_ptr chars) :
- mDevice(new CameraDevice(id, cb, std::move(chars), this)) {}
+ sp chars) :
+ mDevice(new android::acam::CameraDevice(id, cb, chars, this)) {}
- ~ACameraDevice() {};
+ ~ACameraDevice();
/*******************
* NDK public APIs *
@@ -306,8 +366,9 @@ struct ACameraDevice {
camera_status_t createCaptureRequest(
ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalCameraIdList,
ACaptureRequest** request) const {
- return mDevice->createCaptureRequest(templateId, request);
+ return mDevice->createCaptureRequest(templateId, physicalCameraIdList, request);
}
camera_status_t createCaptureSession(
@@ -318,6 +379,11 @@ struct ACameraDevice {
return mDevice->createCaptureSession(outputs, sessionParameters, callbacks, session);
}
+ camera_status_t isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const {
+ return mDevice->isSessionConfigurationSupported(sessionOutputContainer);
+ }
+
/***********************
* Device interal APIs *
***********************/
@@ -331,7 +397,7 @@ struct ACameraDevice {
}
private:
- android::sp mDevice;
+ android::sp mDevice;
};
#endif // _ACAMERA_DEVICE_H
diff --git a/camera/ndk/impl/ACameraDevice.inc b/camera/ndk/impl/ACameraDevice.inc
new file mode 100644
index 0000000000000000000000000000000000000000..1fc5352e85912323feba7ee790f66dacf74305f8
--- /dev/null
+++ b/camera/ndk/impl/ACameraDevice.inc
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include "ACameraDevice.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "ACameraCaptureSession.h"
+
+namespace android {
+namespace acam {
+
+template
+camera_status_t
+CameraDevice::captureLocked(
+ sp session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
+}
+
+template
+camera_status_t
+CameraDevice::setRepeatingRequestsLocked(
+ sp session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
+}
+
+template
+camera_status_t CameraDevice::submitRequestsLocked(
+ sp session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId,
+ bool isRepeating) {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
+ return ret;
+ }
+
+ // Form two vectors of capture request, one for internal tracking
+ std::vector requestList;
+ Vector > requestsV;
+ requestsV.setCapacity(numRequests);
+ for (int i = 0; i < numRequests; i++) {
+ sp req;
+ ret = allocateCaptureRequest(requests[i], req);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Convert capture request to internal format failure! ret %d", ret);
+ return ret;
+ }
+ if (req->mSurfaceList.empty()) {
+ ALOGE("Capture request without output target cannot be submitted!");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ requestList.push_back(*(req.get()));
+ requestsV.push_back(req);
+ }
+
+ if (isRepeating) {
+ ret = stopRepeatingLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+ return ret;
+ }
+ }
+
+ binder::Status remoteRet;
+ hardware::camera2::utils::SubmitInfo info;
+ remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
+ int sequenceId = info.mRequestId;
+ int64_t lastFrameNumber = info.mLastFrameNumber;
+ if (sequenceId < 0) {
+ ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
+ mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+
+ if (isRepeating) {
+ // stopRepeating above should have cleanup repeating sequence id
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return ACAMERA_ERROR_CAMERA_DEVICE;
+ }
+ mRepeatingSequenceId = sequenceId;
+ } else {
+ mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+ }
+
+ if (mIdle) {
+ sp msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+ postSessionMsgAndCleanup(msg);
+ }
+ mIdle = false;
+ mBusySession = session;
+
+ if (captureSequenceId) {
+ *captureSequenceId = sequenceId;
+ }
+ return ACAMERA_OK;
+}
+
+} // namespace acam
+} // namespace android
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index c59d0e7cf6f353b71a6d806ab3b53f255ebdedef..9d40fd71440f73e09f86b8c2237e45825193ab62 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -26,9 +26,10 @@
#include
#include
-using namespace android;
+using namespace android::acam;
namespace android {
+namespace acam {
// Static member definitions
const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
@@ -192,6 +193,20 @@ void CameraManagerGlobal::DeathNotifier::binderDied(const wp&)
}
}
+void CameraManagerGlobal::registerExtendedAvailabilityCallback(
+ const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
+ Mutex::Autolock _l(mLock);
+ Callback cb(callback);
+ mCallbacks.insert(cb);
+}
+
+void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
+ const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
+ Mutex::Autolock _l(mLock);
+ Callback cb(callback);
+ mCallbacks.erase(cb);
+}
+
void CameraManagerGlobal::registerAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
@@ -288,12 +303,40 @@ void CameraManagerGlobal::CallbackHandler::onMessageReceived(
(*cb)(context, cameraId.c_str());
break;
}
+ case kWhatSendSingleAccessCallback:
+ {
+ ACameraManager_AccessPrioritiesChangedCallback cb;
+ void* context;
+ AString cameraId;
+ bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
+ if (!found) {
+ ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
+ return;
+ }
+ found = msg->findPointer(kContextKey, &context);
+ if (!found) {
+ ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+ return;
+ }
+ (*cb)(context);
+ break;
+ }
default:
ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
break;
}
}
+binder::Status CameraManagerGlobal::CameraServiceListener::onCameraAccessPrioritiesChanged() {
+ sp cm = mCameraManager.promote();
+ if (cm != nullptr) {
+ cm->onCameraAccessPrioritiesChanged();
+ } else {
+ ALOGE("Cannot deliver camera access priority callback. Global camera manager died");
+ }
+ return binder::Status::ok();
+}
+
binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
int32_t status, const String16& cameraId) {
sp cm = mCameraManager.promote();
@@ -305,6 +348,19 @@ binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
return binder::Status::ok();
}
+void CameraManagerGlobal::onCameraAccessPrioritiesChanged() {
+ Mutex::Autolock _l(mLock);
+ for (auto cb : mCallbacks) {
+ sp msg = new AMessage(kWhatSendSingleAccessCallback, mHandler);
+ ACameraManager_AccessPrioritiesChangedCallback cbFp = cb.mAccessPriorityChanged;
+ if (cbFp != nullptr) {
+ msg->setPointer(kCallbackFpKey, (void *) cbFp);
+ msg->setPointer(kContextKey, cb.mContext);
+ msg->post();
+ }
+ }
+}
+
void CameraManagerGlobal::onStatusChanged(
int32_t status, const String8& cameraId) {
Mutex::Autolock _l(mLock);
@@ -345,6 +401,7 @@ void CameraManagerGlobal::onStatusChangedLocked(
}
}
+} // namespace acam
} // namespace android
/**
@@ -402,7 +459,7 @@ ACameraManager::deleteCameraIdList(ACameraIdList* cameraIdList) {
}
camera_status_t ACameraManager::getCameraCharacteristics(
- const char *cameraIdStr, ACameraMetadata **characteristics) {
+ const char* cameraIdStr, sp* characteristics) {
Mutex::Autolock _l(mLock);
sp cs = CameraManagerGlobal::getInstance().getCameraService();
@@ -437,18 +494,16 @@ ACameraManager::openCamera(
const char* cameraId,
ACameraDevice_StateCallbacks* callback,
/*out*/ACameraDevice** outDevice) {
- ACameraMetadata* rawChars;
- camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
+ sp chars;
+ camera_status_t ret = getCameraCharacteristics(cameraId, &chars);
Mutex::Autolock _l(mLock);
if (ret != ACAMERA_OK) {
ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
__FUNCTION__, cameraId, ret);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- std::unique_ptr chars(rawChars);
- rawChars = nullptr;
- ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(chars));
+ ACameraDevice* device = new ACameraDevice(cameraId, callback, chars);
sp cs = CameraManagerGlobal::getInstance().getCameraService();
if (cs == nullptr) {
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index cc42f77c2c365c72820dafc59fce7344423ef11e..8c1da364185f87e33a39ae2db9e24da190cd5288 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -35,6 +35,7 @@
#include
*
+ * This tag is also used for HEIC image capture.
*/
ACAMERA_JPEG_GPS_COORDINATES = // double[3]
ACAMERA_JPEG_START,
@@ -1927,6 +1932,7 @@ typedef enum acamera_metadata_tag {
* ACaptureRequest
*
*
+ * This tag is also used for HEIC image capture.
*/
ACAMERA_JPEG_GPS_PROCESSING_METHOD = // byte
ACAMERA_JPEG_START + 1,
@@ -1942,6 +1948,7 @@ typedef enum acamera_metadata_tag {
* ACaptureRequest
*
*
+ * This tag is also used for HEIC image capture.
*/
ACAMERA_JPEG_GPS_TIMESTAMP = // int64
ACAMERA_JPEG_START + 2,
@@ -1986,6 +1993,10 @@ typedef enum acamera_metadata_tag {
*
* For EXTERNAL cameras the sensor orientation will always be set to 0 and the facing will
* also be set to EXTERNAL. The above code is not relevant in such case.
+ * This tag is also used to describe the orientation of the HEIC image capture, in which
+ * case the rotation is reflected by
+ * EXIF orientation flag, and not by
+ * rotating the image data itself.
*
* @see ACAMERA_SENSOR_ORIENTATION
*/
@@ -2003,7 +2014,8 @@ typedef enum acamera_metadata_tag {
* ACaptureRequest
*
*
- * 85-95 is typical usage range.
+ * 85-95 is typical usage range. This tag is also used to describe the quality
+ * of the HEIC image capture.
*/
ACAMERA_JPEG_QUALITY = // byte
ACAMERA_JPEG_START + 4,
@@ -2019,6 +2031,7 @@ typedef enum acamera_metadata_tag {
* ACaptureRequest
*
*
+ * This tag is also used to describe the quality of the HEIC image capture.
*/
ACAMERA_JPEG_THUMBNAIL_QUALITY = // byte
ACAMERA_JPEG_START + 5,
@@ -2055,6 +2068,10 @@ typedef enum acamera_metadata_tag {
* orientation is requested. LEGACY device will always report unrotated thumbnail
* size.
*
+ * The tag is also used as thumbnail size for HEIC image format capture, in which case the
+ * the thumbnail rotation is reflected by
+ * EXIF orientation flag, and not by
+ * rotating the thumbnail data itself.
*
* @see ACAMERA_JPEG_ORIENTATION
*/
@@ -2088,6 +2105,7 @@ typedef enum acamera_metadata_tag {
* and vice versa.
* All non-(0, 0)
sizes will have non-zero widths and heights.
*
+ * This list is also used as supported thumbnail sizes for HEIC image format capture.
*
* @see ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
*/
@@ -2783,7 +2801,7 @@ typedef enum acamera_metadata_tag {
* {@link AIMAGE_FORMAT_RAW12 RAW12}.
* Processed (but not-stalling): any non-RAW format without a stall duration. Typically
* {@link AIMAGE_FORMAT_YUV_420_888 YUV_420_888},
- * NV21, or YV12.
+ * NV21, YV12, or {@link AIMAGE_FORMAT_Y8 Y8} .
*
*
* @see ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
@@ -3028,6 +3046,28 @@ typedef enum acamera_metadata_tag {
*/
ACAMERA_REQUEST_AVAILABLE_SESSION_KEYS = // int32[n]
ACAMERA_REQUEST_START + 16,
+ /**
+ * A subset of the available request keys that can be overridden for
+ * physical devices backing a logical multi-camera.
+ *
+ * Type: int32[n]
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * This is a subset of ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS which contains a list
+ * of keys that can be overridden using Builder#setPhysicalCameraKey.
+ * The respective value of such request key can be obtained by calling
+ * Builder#getPhysicalCameraKey. Capture requests that contain
+ * individual physical device requests must be built via
+ * Set).
+ *
+ * @see ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS
+ */
+ ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS = // int32[n]
+ ACAMERA_REQUEST_START + 17,
ACAMERA_REQUEST_END,
/**
@@ -3257,6 +3297,7 @@ typedef enum acamera_metadata_tag {
* {@link AIMAGE_FORMAT_YUV_420_888 }
* {@link AIMAGE_FORMAT_RAW10 }
* {@link AIMAGE_FORMAT_RAW12 }
+ * {@link AIMAGE_FORMAT_Y8 }
*
* All other formats may or may not have an allowed stall duration on
* a per-capability basis; refer to ACAMERA_REQUEST_AVAILABLE_CAPABILITIES
@@ -3294,6 +3335,81 @@ typedef enum acamera_metadata_tag {
*/
ACAMERA_SCALER_CROPPING_TYPE = // byte (acamera_metadata_enum_android_scaler_cropping_type_t)
ACAMERA_SCALER_START + 13,
+ /**
+ *
Recommended stream configurations for common client use cases.
+ *
+ * Type: int32[n*5] (acamera_metadata_enum_android_scaler_available_recommended_stream_configurations_t)
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * Optional subset of the ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS that contains
+ * similar tuples listed as
+ * (i.e. width, height, format, output/input stream, usecase bit field).
+ * Camera devices will be able to suggest particular stream configurations which are
+ * power and performance efficient for specific use cases. For more information about
+ * retrieving the suggestions see
+ * CameraCharacteristics#getRecommendedStreamConfigurationMap.
+ * The data representation is int[5], which maps to
+ * (width, height, format, output/input stream, usecase bit field). The array can be
+ * parsed using the following pseudo code:
+ * struct StreamConfiguration {
+ * int32_t format;
+ * int32_t width;
+ * int32_t height;
+ * int32_t isInput; };
+ * void getPreferredStreamConfigurations(
+ * int32_t *array, size_t count, int32_t usecaseId,
+ * Vector < StreamConfiguration > * scs) {
+ * const size_t STREAM_CONFIGURATION_SIZE = 5;
+ * const size_t STREAM_WIDTH_OFFSET = 0;
+ * const size_t STREAM_HEIGHT_OFFSET = 1;
+ * const size_t STREAM_FORMAT_OFFSET = 2;
+ * const size_t STREAM_IS_INPUT_OFFSET = 3;
+ * const size_t STREAM_USECASE_BITMAP_OFFSET = 4;
+ * for (size_t i = 0; i < count; i+= STREAM_CONFIGURATION_SIZE) {
+ * int32_t width = array[i + STREAM_WIDTH_OFFSET];
+ * int32_t height = array[i + STREAM_HEIGHT_OFFSET];
+ * int32_t format = array[i + STREAM_FORMAT_OFFSET];
+ * int32_t isInput = array[i + STREAM_IS_INPUT_OFFSET];
+ * int32_t supportedUsecases = array[i + STREAM_USECASE_BITMAP_OFFSET];
+ * if (supportedUsecases & (1 << usecaseId)) {
+ * StreamConfiguration sc = {format, width, height, isInput};
+ * scs->add(sc);
+ * }
+ * }
+ *
+ * }
+ *
+ * @see ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS =
+ // int32[n*5] (acamera_metadata_enum_android_scaler_available_recommended_stream_configurations_t)
+ ACAMERA_SCALER_START + 14,
+ /**
+ * Recommended mappings of image formats that are supported by this
+ * camera device for input streams, to their corresponding output formats.
+ *
+ * Type: int32
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * This is a recommended subset of the complete list of mappings found in
+ * android.scaler.availableInputOutputFormatsMap. The same requirements apply here as well.
+ * The list however doesn't need to contain all available and supported mappings. Instead of
+ * this developers must list only recommended and efficient entries.
+ * If set, the information will be available in the ZERO_SHUTTER_LAG recommended stream
+ * configuration see
+ * CameraCharacteristics#getRecommendedStreamConfigurationMap.
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_INPUT_OUTPUT_FORMATS_MAP =
+ // int32
+ ACAMERA_SCALER_START + 15,
ACAMERA_SCALER_END,
/**
@@ -3454,6 +3570,8 @@ typedef enum acamera_metadata_tag {
* Some devices may choose to provide a second set of calibration
* information for improved quality, including
* ACAMERA_SENSOR_REFERENCE_ILLUMINANT2 and its corresponding matrices.
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*
* @see ACAMERA_SENSOR_CALIBRATION_TRANSFORM1
* @see ACAMERA_SENSOR_COLOR_TRANSFORM1
@@ -3483,6 +3601,8 @@ typedef enum acamera_metadata_tag {
* If this key is present, then ACAMERA_SENSOR_COLOR_TRANSFORM2,
* ACAMERA_SENSOR_CALIBRATION_TRANSFORM2, and
* ACAMERA_SENSOR_FORWARD_MATRIX2 will also be present.
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*
* @see ACAMERA_SENSOR_CALIBRATION_TRANSFORM2
* @see ACAMERA_SENSOR_COLOR_TRANSFORM2
@@ -3510,6 +3630,8 @@ typedef enum acamera_metadata_tag {
* colorspace) into this camera device's native sensor color
* space under the first reference illuminant
* (ACAMERA_SENSOR_REFERENCE_ILLUMINANT1).
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*
* @see ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
*/
@@ -3537,6 +3659,8 @@ typedef enum acamera_metadata_tag {
* (ACAMERA_SENSOR_REFERENCE_ILLUMINANT2).
* This matrix will only be present if the second reference
* illuminant is present.
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*
* @see ACAMERA_SENSOR_REFERENCE_ILLUMINANT2
*/
@@ -3565,6 +3689,8 @@ typedef enum acamera_metadata_tag {
* and the CIE XYZ colorspace when calculating this transform will
* match the standard white point for the first reference illuminant
* (i.e. no chromatic adaptation will be applied by this transform).
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*
* @see ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
*/
@@ -3595,6 +3721,8 @@ typedef enum acamera_metadata_tag {
* (i.e. no chromatic adaptation will be applied by this transform).
* This matrix will only be present if the second reference
* illuminant is present.
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*
* @see ACAMERA_SENSOR_REFERENCE_ILLUMINANT2
*/
@@ -3621,6 +3749,8 @@ typedef enum acamera_metadata_tag {
* this matrix is chosen so that the standard white point for this reference
* illuminant in the reference sensor colorspace is mapped to D50 in the
* CIE XYZ colorspace.
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*
* @see ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
*/
@@ -3649,6 +3779,8 @@ typedef enum acamera_metadata_tag {
* CIE XYZ colorspace.
* This matrix will only be present if the second reference
* illuminant is present.
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*
* @see ACAMERA_SENSOR_REFERENCE_ILLUMINANT2
*/
@@ -3681,6 +3813,7 @@ typedef enum acamera_metadata_tag {
* level values. For raw capture in particular, it is recommended to use
* pixels from ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS to calculate black
* level values for each frame.
+ * For a MONOCHROME camera device, all of the 2x2 channels must have the same values.
*
* @see ACAMERA_SENSOR_DYNAMIC_BLACK_LEVEL
* @see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
@@ -3775,6 +3908,8 @@ typedef enum acamera_metadata_tag {
* used to interpolate between the provided color transforms when
* processing raw sensor data.
* The order of the values is R, G, B; where R is in the lowest index.
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*/
ACAMERA_SENSOR_NEUTRAL_COLOR_POINT = // rational[3]
ACAMERA_SENSOR_START + 18,
@@ -3805,6 +3940,8 @@ typedef enum acamera_metadata_tag {
* that channel.
* A more detailed description of the noise model can be found in the
* Adobe DNG specification for the NoiseProfile tag.
+ * For a MONOCHROME camera, there is only one color channel. So the noise model coefficients
+ * will only contain one S and one O.
*
* @see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
*/
@@ -3850,6 +3987,8 @@ typedef enum acamera_metadata_tag {
* R > 1.20 will require strong software correction to produce
* a usuable image (>20% divergence).
*
+ * Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.
*/
ACAMERA_SENSOR_GREEN_SPLIT = // float
ACAMERA_SENSOR_START + 22,
@@ -4002,6 +4141,7 @@ typedef enum acamera_metadata_tag {
* layout key (see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT), i.e. the
* nth value given corresponds to the black level offset for the nth
* color channel listed in the CFA.
+ * For a MONOCHROME camera, all of the 2x2 channels must have the same values.
* This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is available or the
* camera device advertises this key via {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS }.
*
@@ -4104,7 +4244,8 @@ typedef enum acamera_metadata_tag {
/**
* The arrangement of color filters on sensor;
* represents the colors in the top-left 2x2 section of
- * the sensor, in reading order.
+ * the sensor, in reading order, for a Bayer camera, or the
+ * light spectrum it captures for MONOCHROME camera.
*
* Type: byte (acamera_metadata_enum_android_sensor_info_color_filter_arrangement_t)
*
@@ -4573,13 +4714,13 @@ typedef enum acamera_metadata_tag {
* (x,y) ϵ (0 ... N-1, 0 ... M-1) is the value of the shading map at
* pixel ( ((W-1)/(N-1)) * x, ((H-1)/(M-1)) * y) for the four color channels.
* The map is assumed to be bilinearly interpolated between the sample points.
- * The channel order is [R, Geven, Godd, B], where Geven is the green
- * channel for the even rows of a Bayer pattern, and Godd is the odd rows.
+ *
For a Bayer camera, the channel order is [R, Geven, Godd, B], where Geven is
+ * the green channel for the even rows of a Bayer pattern, and Godd is the odd rows.
* The shading map is stored in a fully interleaved format, and its size
* is provided in the camera static metadata by ACAMERA_LENS_INFO_SHADING_MAP_SIZE.
* The shading map will generally have on the order of 30-40 rows and columns,
* and will be smaller than 64x64.
- * As an example, given a very small map defined as:
+ * As an example, given a very small map for a Bayer camera defined as:
* ACAMERA_LENS_INFO_SHADING_MAP_SIZE = [ 4, 3 ]
* ACAMERA_STATISTICS_LENS_SHADING_MAP =
* [ 1.3, 1.2, 1.15, 1.2, 1.2, 1.2, 1.15, 1.2,
@@ -4599,6 +4740,17 @@ typedef enum acamera_metadata_tag {
* image of a gray wall (using bicubic interpolation for visual quality)
* as captured by the sensor gives:
*
+ * For a MONOCHROME camera, all of the 2x2 channels must have the same values. An example
+ * shading map for such a camera is defined as:
+ * ACAMERA_LENS_INFO_SHADING_MAP_SIZE = [ 4, 3 ]
+ * ACAMERA_STATISTICS_LENS_SHADING_MAP =
+ * [ 1.3, 1.3, 1.3, 1.3, 1.2, 1.2, 1.2, 1.2,
+ * 1.1, 1.1, 1.1, 1.1, 1.3, 1.3, 1.3, 1.3,
+ * 1.2, 1.2, 1.2, 1.2, 1.1, 1.1, 1.1, 1.1,
+ * 1.0, 1.0, 1.0, 1.0, 1.2, 1.2, 1.2, 1.2,
+ * 1.3, 1.3, 1.3, 1.3, 1.2, 1.2, 1.2, 1.2,
+ * 1.2, 1.2, 1.2, 1.2, 1.3, 1.3, 1.3, 1.3 ]
+ *
* Note that the RAW image data might be subject to lens shading
* correction not reported on this map. Query
* ACAMERA_SENSOR_INFO_LENS_SHADING_APPLIED to see if RAW image data has subject
@@ -4942,8 +5094,8 @@ typedef enum acamera_metadata_tag {
* of points can be less than max (that is, the request doesn't have to
* always provide a curve with number of points equivalent to
* ACAMERA_TONEMAP_MAX_CURVE_POINTS).
- * For devices with MONOCHROME capability, only red channel is used. Green and blue channels
- * are ignored.
+ * For devices with MONOCHROME capability, all three channels must have the same set of
+ * control points.
* A few examples, and their corresponding graphical mappings; these
* only specify the red channel and the precision is limited to 4
* digits, for conciseness.
@@ -5417,8 +5569,120 @@ typedef enum acamera_metadata_tag {
*/
ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE = // byte (acamera_metadata_enum_android_depth_depth_is_exclusive_t)
ACAMERA_DEPTH_START + 4,
+ /**
+ * Recommended depth stream configurations for common client use cases.
+ *
+ * Type: int32[n*5]
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * Optional subset of the ACAMERA_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS that
+ * contains similar tuples listed as
+ * (i.e. width, height, format, output/input stream, usecase bit field).
+ * Camera devices will be able to suggest particular depth stream configurations which are
+ * power and performance efficient for specific use cases. For more information about
+ * retrieving the suggestions see
+ * CameraCharacteristics#getRecommendedStreamConfigurationMap.
+ * For data representation please refer to
+ * ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS
+ *
+ * @see ACAMERA_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS
+ * @see ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS
+ */
+ ACAMERA_DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS =
+ // int32[n*5]
+ ACAMERA_DEPTH_START + 5,
+ /**
+ * The available dynamic depth dataspace stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream).
+ *
+ * Type: int32[n*4] (acamera_metadata_enum_android_depth_available_dynamic_depth_stream_configurations_t)
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * These are output stream configurations for use with
+ * dataSpace DYNAMIC_DEPTH. The configurations are
+ * listed as (format, width, height, input?)
tuples.
+ * Only devices that support depth output for at least
+ * the HAL_PIXEL_FORMAT_Y16 dense depth map along with
+ * HAL_PIXEL_FORMAT_BLOB with the same size or size with
+ * the same aspect ratio can have dynamic depth dataspace
+ * stream configuration. ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE also
+ * needs to be set to FALSE.
+ *
+ * @see ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE
+ */
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS =
+ // int32[n*4] (acamera_metadata_enum_android_depth_available_dynamic_depth_stream_configurations_t)
+ ACAMERA_DEPTH_START + 6,
+ /**
+ * This lists the minimum frame duration for each
+ * format/size combination for dynamic depth output streams.
+ *
+ * Type: int64[4*n]
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * This should correspond to the frame duration when only that
+ * stream is active, with all processing (typically in android.*.mode)
+ * set to either OFF or FAST.
+ * When multiple streams are used in a request, the minimum frame
+ * duration will be max(individual stream min durations).
+ * The minimum frame duration of a stream (of a particular format, size)
+ * is the same regardless of whether the stream is input or output.
+ */
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS = // int64[4*n]
+ ACAMERA_DEPTH_START + 7,
+ /**
+ * This lists the maximum stall duration for each
+ * output format/size combination for dynamic depth streams.
+ *
+ * Type: int64[4*n]
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * A stall duration is how much extra time would get added
+ * to the normal minimum frame duration for a repeating request
+ * that has streams with non-zero stall.
+ * All dynamic depth output streams may have a nonzero stall
+ * duration.
+ */
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS = // int64[4*n]
+ ACAMERA_DEPTH_START + 8,
ACAMERA_DEPTH_END,
+ /**
+ * String containing the ids of the underlying physical cameras.
+ *
+ * Type: byte[n]
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * For a logical camera, this is concatenation of all underlying physical camera IDs.
+ * The null terminator for physical camera ID must be preserved so that the whole string
+ * can be tokenized using '\0' to generate list of physical camera IDs.
+ * For example, if the physical camera IDs of the logical camera are "2" and "3", the
+ * value of this tag will be ['2', '\0', '3', '\0'].
+ * The number of physical camera IDs must be no less than 2.
+ */
+ ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS = // byte[n]
+ ACAMERA_LOGICAL_MULTI_CAMERA_START,
/**
* The accuracy of frame timestamp synchronization between physical cameras
*
@@ -5437,9 +5701,37 @@ typedef enum acamera_metadata_tag {
* In both cases, all images generated for a particular capture request still carry the same
* timestamps, so that they can be used to look up the matching frame number and
* onCaptureStarted callback.
+ * This tag is only applicable if the logical camera device supports concurrent physical
+ * streams from different physical cameras.
*/
ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE = // byte (acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t)
ACAMERA_LOGICAL_MULTI_CAMERA_START + 1,
+ /**
+ * String containing the ID of the underlying active physical camera.
+ *
+ * Type: byte
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks
+ *
+ *
+ * The ID of the active physical camera that's backing the logical camera. All camera
+ * streams and metadata that are not physical camera specific will be originating from this
+ * physical camera.
+ * For a logical camera made up of physical cameras where each camera's lenses have
+ * different characteristics, the camera device may choose to switch between the physical
+ * cameras when application changes FOCAL_LENGTH or SCALER_CROP_REGION.
+ * At the time of lens switch, this result metadata reflects the new active physical camera
+ * ID.
+ * This key will be available if the camera device advertises this key via {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS }.
+ * When available, this must be one of valid physical IDs backing this logical multi-camera.
+ * If this key is not available for a logical multi-camera, the camera device implementation
+ * may still switch between different active physical cameras based on use case, but the
+ * current active physical camera information won't be available to the application.
+ */
+ ACAMERA_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID = // byte
+ ACAMERA_LOGICAL_MULTI_CAMERA_START + 2,
ACAMERA_LOGICAL_MULTI_CAMERA_END,
/**
@@ -5463,8 +5755,8 @@ typedef enum acamera_metadata_tag {
* will not slow down capture rate when applying correction. FAST may be the same as OFF if
* any correction at all would slow down capture rate. Every output stream will have a
* similar amount of enhancement applied.
- * The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
- * applied to any RAW output.
+ * The correction only applies to processed outputs such as YUV, Y8, JPEG, or DEPTH16; it is
+ * not applied to any RAW output.
* This control will be on by default on devices that support this control. Applications
* disabling distortion correction need to pay extra attention with the coordinate system of
* metering regions, crop region, and face rectangles. When distortion correction is OFF,
@@ -5517,6 +5809,80 @@ typedef enum acamera_metadata_tag {
ACAMERA_DISTORTION_CORRECTION_START + 1,
ACAMERA_DISTORTION_CORRECTION_END,
+ /**
+ *
The available HEIC (ISO/IEC 23008-12) stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream).
+ *
+ * Type: int32[n*4] (acamera_metadata_enum_android_heic_available_heic_stream_configurations_t)
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * The configurations are listed as (format, width, height, input?)
tuples.
+ * If the camera device supports HEIC image format, it will support identical set of stream
+ * combinations involving HEIC image format, compared to the combinations involving JPEG
+ * image format as required by the device's hardware level and capabilities.
+ * All the static, control, and dynamic metadata tags related to JPEG apply to HEIC formats.
+ * Configuring JPEG and HEIC streams at the same time is not supported.
+ * All the configuration tuples (format, width, height, input?)
will contain
+ * AIMAGE_FORMAT_HEIC format as OUTPUT only.
+ */
+ ACAMERA_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS = // int32[n*4] (acamera_metadata_enum_android_heic_available_heic_stream_configurations_t)
+ ACAMERA_HEIC_START,
+ /**
+ * This lists the minimum frame duration for each
+ * format/size combination for HEIC output formats.
+ *
+ * Type: int64[4*n]
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * This should correspond to the frame duration when only that
+ * stream is active, with all processing (typically in android.*.mode)
+ * set to either OFF or FAST.
+ * When multiple streams are used in a request, the minimum frame
+ * duration will be max(individual stream min durations).
+ * See ACAMERA_SENSOR_FRAME_DURATION and
+ * ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS for more details about
+ * calculating the max frame rate.
+ *
+ * @see ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS
+ * @see ACAMERA_SENSOR_FRAME_DURATION
+ */
+ ACAMERA_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS = // int64[4*n]
+ ACAMERA_HEIC_START + 1,
+ /**
+ * This lists the maximum stall duration for each
+ * output format/size combination for HEIC streams.
+ *
+ * Type: int64[4*n]
+ *
+ * This tag may appear in:
+ *
+ * - ACameraMetadata from ACameraManager_getCameraCharacteristics
+ *
+ *
+ * A stall duration is how much extra time would get added
+ * to the normal minimum frame duration for a repeating request
+ * that has streams with non-zero stall.
+ * This functions similarly to
+ * ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS for HEIC
+ * streams.
+ * All HEIC output stream formats may have a nonzero stall
+ * duration.
+ *
+ * @see ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS
+ */
+ ACAMERA_HEIC_AVAILABLE_HEIC_STALL_DURATIONS = // int64[4*n]
+ ACAMERA_HEIC_START + 2,
+ ACAMERA_HEIC_END,
+
} acamera_metadata_tag_t;
/**
@@ -7011,6 +7377,10 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities {
* If this is supported, android.scaler.streamConfigurationMap will
* additionally return a min frame duration that is greater than
* zero for each supported size-format combination.
+ * For camera devices with LOGICAL_MULTI_CAMERA capability, when the underlying active
+ * physical camera switches, exposureTime, sensitivity, and lens properties may change
+ * even if AE/AF is locked. However, the overall auto exposure and auto focus experience
+ * for users will be consistent. Refer to LOGICAL_MULTI_CAMERA capability for details.
*
* @see ACAMERA_BLACK_LEVEL_LOCK
* @see ACAMERA_CONTROL_AE_LOCK
@@ -7066,6 +7436,10 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities {
* will accurately report the values applied by AWB in the result.
* A given camera device may also support additional post-processing
* controls, but this capability only covers the above list of controls.
+ * For camera devices with LOGICAL_MULTI_CAMERA capability, when underlying active
+ * physical camera switches, tonemap, white balance, and shading map may change even if
+ * awb is locked. However, the overall post-processing experience for users will be
+ * consistent. Refer to LOGICAL_MULTI_CAMERA capability for details.
*
* @see ACAMERA_COLOR_CORRECTION_ABERRATION_MODE
* @see ACAMERA_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES
@@ -7137,19 +7511,20 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities {
/**
* The camera device supports capturing high-resolution images at >= 20 frames per
- * second, in at least the uncompressed YUV format, when post-processing settings are set
- * to FAST. Additionally, maximum-resolution images can be captured at >= 10 frames
- * per second. Here, 'high resolution' means at least 8 megapixels, or the maximum
- * resolution of the device, whichever is smaller.
+ * second, in at least the uncompressed YUV format, when post-processing settings are
+ * set to FAST. Additionally, all image resolutions less than 24 megapixels can be
+ * captured at >= 10 frames per second. Here, 'high resolution' means at least 8
+ * megapixels, or the maximum resolution of the device, whichever is smaller.
* More specifically, this means that at least one output {@link AIMAGE_FORMAT_YUV_420_888 } size listed in
* {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS }
* is larger or equal to the 'high resolution' defined above, and can be captured at at
* least 20 fps. For the largest {@link AIMAGE_FORMAT_YUV_420_888 } size listed in
* {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS },
- * camera device can capture this size for at least 10 frames per second. Also the
- * ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES entry lists at least one FPS range where
- * the minimum FPS is >= 1 / minimumFrameDuration for the largest YUV_420_888 size.
- * If the device supports the {@link AIMAGE_FORMAT_RAW10 }, {@link AIMAGE_FORMAT_RAW12 }, then those can also be
+ * camera device can capture this size for at least 10 frames per second if the size is
+ * less than 24 megapixels. Also the ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES entry
+ * lists at least one FPS range where the minimum FPS is >= 1 / minimumFrameDuration
+ * for the largest YUV_420_888 size.
+ * If the device supports the {@link AIMAGE_FORMAT_RAW10 }, {@link AIMAGE_FORMAT_RAW12 }, {@link AIMAGE_FORMAT_Y8 }, then those can also be
* captured at the same rate as the maximum-size YUV_420_888 resolution is.
* In addition, the ACAMERA_SYNC_MAX_LATENCY field is guaranted to have a value between 0
* and 4, inclusive. ACAMERA_CONTROL_AE_LOCK_AVAILABLE and ACAMERA_CONTROL_AWB_LOCK_AVAILABLE
@@ -7183,8 +7558,8 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities {
*
The ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE entry is listed by this device.
* As of Android P, the ACAMERA_LENS_POSE_REFERENCE entry is listed by this device.
* A LIMITED camera with only the DEPTH_OUTPUT capability does not have to support
- * normal YUV_420_888, JPEG, and PRIV-format outputs. It only has to support the DEPTH16
- * format.
+ * normal YUV_420_888, Y8, JPEG, and PRIV-format outputs. It only has to support the
+ * DEPTH16 format.
*
* Generally, depth output operates at a slower frame rate than standard color capture,
* so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that
@@ -7215,8 +7590,23 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities {
ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING = 10,
/**
- *
The camera device is a logical camera backed by two or more physical cameras that are
- * also exposed to the application.
+ * The camera device is a logical camera backed by two or more physical cameras.
+ * In API level 28, the physical cameras must also be exposed to the application via
+ * CameraManager#getCameraIdList.
+ * Starting from API level 29, some or all physical cameras may not be independently
+ * exposed to the application, in which case the physical camera IDs will not be
+ * available in CameraManager#getCameraIdList. But the
+ * application can still query the physical cameras' characteristics by calling
+ * CameraManager#getCameraCharacteristics. Additionally,
+ * if a physical camera is hidden from camera ID list, the mandatory stream combinations
+ * for that physical camera must be supported through the logical camera using physical
+ * streams.
+ * Combinations of logical and physical streams, or physical streams from different
+ * physical cameras are not guaranteed. However, if the camera device supports
+ * {@link ACameraDevice_isSessionConfigurationSupported },
+ * application must be able to query whether a stream combination involving physical
+ * streams is supported by calling
+ * {@link ACameraDevice_isSessionConfigurationSupported }.
* Camera application shouldn't assume that there are at most 1 rear camera and 1 front
* camera in the system. For an application that switches between front and back cameras,
* the recommendation is to switch between the first rear camera and the first front
@@ -7239,42 +7629,128 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities {
*
*
The SENSOR_INFO_TIMESTAMP_SOURCE of the logical device and physical devices must be
* the same.
- * The logical camera device must be LIMITED or higher device.
+ * The logical camera must be LIMITED or higher device.
*
- * Both the logical camera device and its underlying physical devices support the
- * mandatory stream combinations required for their device levels.
- * Additionally, for each guaranteed stream combination, the logical camera supports:
- *
- * - For each guaranteed stream combination, the logical camera supports replacing one
- * logical {@link AIMAGE_FORMAT_YUV_420_888 YUV_420_888}
- * or raw stream with two physical streams of the same size and format, each from a
- * separate physical camera, given that the size and format are supported by both
- * physical cameras.
- * - If the logical camera doesn't advertise RAW capability, but the underlying physical
- * cameras do, the logical camera will support guaranteed stream combinations for RAW
- * capability, except that the RAW streams will be physical streams, each from a separate
- * physical camera. This is usually the case when the physical cameras have different
- * sensor sizes.
+ * A logical camera device's dynamic metadata may contain
+ * ACAMERA_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID to notify the application of the current
+ * active physical camera Id. An active physical camera is the physical camera from which
+ * the logical camera's main image data outputs (YUV or RAW) and metadata come from.
+ * In addition, this serves as an indication which physical camera is used to output to
+ * a RAW stream, or in case only physical cameras support RAW, which physical RAW stream
+ * the application should request.
+ * Logical camera's static metadata tags below describe the default active physical
+ * camera. An active physical camera is default if it's used when application directly
+ * uses requests built from a template. All templates will default to the same active
+ * physical camera.
+ *
+ * - ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE
+ * - ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+ * - ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE
+ * - ACAMERA_SENSOR_INFO_MAX_FRAME_DURATION
+ * - ACAMERA_SENSOR_INFO_PHYSICAL_SIZE
+ * - ACAMERA_SENSOR_INFO_WHITE_LEVEL
+ * - ACAMERA_SENSOR_INFO_LENS_SHADING_APPLIED
+ * - ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
+ * - ACAMERA_SENSOR_REFERENCE_ILLUMINANT2
+ * - ACAMERA_SENSOR_CALIBRATION_TRANSFORM1
+ * - ACAMERA_SENSOR_CALIBRATION_TRANSFORM2
+ * - ACAMERA_SENSOR_COLOR_TRANSFORM1
+ * - ACAMERA_SENSOR_COLOR_TRANSFORM2
+ * - ACAMERA_SENSOR_FORWARD_MATRIX1
+ * - ACAMERA_SENSOR_FORWARD_MATRIX2
+ * - ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
+ * - ACAMERA_SENSOR_MAX_ANALOG_SENSITIVITY
+ * - ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS
+ * - ACAMERA_SENSOR_AVAILABLE_TEST_PATTERN_MODES
+ * - ACAMERA_LENS_INFO_HYPERFOCAL_DISTANCE
+ * - ACAMERA_LENS_INFO_MINIMUM_FOCUS_DISTANCE
+ * - ACAMERA_LENS_INFO_FOCUS_DISTANCE_CALIBRATION
+ * - ACAMERA_LENS_POSE_ROTATION
+ * - ACAMERA_LENS_POSE_TRANSLATION
+ * - ACAMERA_LENS_INTRINSIC_CALIBRATION
+ * - ACAMERA_LENS_POSE_REFERENCE
+ * - ACAMERA_LENS_DISTORTION
*
- * Using physical streams in place of a logical stream of the same size and format will
- * not slow down the frame rate of the capture, as long as the minimum frame duration
- * of the physical and logical streams are the same.
+ * The field of view of all non-RAW physical streams must be the same or as close as
+ * possible to that of non-RAW logical streams. If the requested FOV is outside of the
+ * range supported by the physical camera, the physical stream for that physical camera
+ * will use either the maximum or minimum scaler crop region, depending on which one is
+ * closer to the requested FOV. For example, for a logical camera with wide-tele lens
+ * configuration where the wide lens is the default, if the logical camera's crop region
+ * is set to maximum, the physical stream for the tele lens will be configured to its
+ * maximum crop region. On the other hand, if the logical camera has a normal-wide lens
+ * configuration where the normal lens is the default, when the logical camera's crop
+ * region is set to maximum, the FOV of the logical streams will be that of the normal
+ * lens. The FOV of the physical streams for the wide lens will be the same as the
+ * logical stream, by making the crop region smaller than its active array size to
+ * compensate for the smaller focal length.
+ * Even if the underlying physical cameras have different RAW characteristics (such as
+ * size or CFA pattern), a logical camera can still advertise RAW capability. In this
+ * case, when the application configures a RAW stream, the camera device will make sure
+ * the active physical camera will remain active to ensure consistent RAW output
+ * behavior, and not switch to other physical cameras.
+ * The capture request and result metadata tags required for backward compatible camera
+ * functionalities will be solely based on the logical camera capabiltity. On the other
+ * hand, the use of manual capture controls (sensor or post-processing) with a
+ * logical camera may result in unexpected behavior when the HAL decides to switch
+ * between physical cameras with different characteristics under the hood. For example,
+ * when the application manually sets exposure time and sensitivity while zooming in,
+ * the brightness of the camera images may suddenly change because HAL switches from one
+ * physical camera to the other.
*
* @see ACAMERA_LENS_DISTORTION
+ * @see ACAMERA_LENS_INFO_FOCUS_DISTANCE_CALIBRATION
+ * @see ACAMERA_LENS_INFO_HYPERFOCAL_DISTANCE
+ * @see ACAMERA_LENS_INFO_MINIMUM_FOCUS_DISTANCE
* @see ACAMERA_LENS_INTRINSIC_CALIBRATION
* @see ACAMERA_LENS_POSE_REFERENCE
* @see ACAMERA_LENS_POSE_ROTATION
* @see ACAMERA_LENS_POSE_TRANSLATION
+ * @see ACAMERA_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID
* @see ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
+ * @see ACAMERA_SENSOR_AVAILABLE_TEST_PATTERN_MODES
+ * @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
+ * @see ACAMERA_SENSOR_CALIBRATION_TRANSFORM1
+ * @see ACAMERA_SENSOR_CALIBRATION_TRANSFORM2
+ * @see ACAMERA_SENSOR_COLOR_TRANSFORM1
+ * @see ACAMERA_SENSOR_COLOR_TRANSFORM2
+ * @see ACAMERA_SENSOR_FORWARD_MATRIX1
+ * @see ACAMERA_SENSOR_FORWARD_MATRIX2
+ * @see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+ * @see ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE
+ * @see ACAMERA_SENSOR_INFO_LENS_SHADING_APPLIED
+ * @see ACAMERA_SENSOR_INFO_MAX_FRAME_DURATION
+ * @see ACAMERA_SENSOR_INFO_PHYSICAL_SIZE
+ * @see ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE
+ * @see ACAMERA_SENSOR_INFO_WHITE_LEVEL
+ * @see ACAMERA_SENSOR_MAX_ANALOG_SENSITIVITY
+ * @see ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS
+ * @see ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
+ * @see ACAMERA_SENSOR_REFERENCE_ILLUMINANT2
*/
ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA = 11,
/**
* The camera device is a monochrome camera that doesn't contain a color filter array,
- * and the pixel values on U and V planes are all 128.
+ * and for YUV_420_888 stream, the pixel values on U and V planes are all 128.
+ * A MONOCHROME camera must support the guaranteed stream combinations required for
+ * its device level and capabilities. Additionally, if the monochrome camera device
+ * supports Y8 format, all mandatory stream combination requirements related to {@link AIMAGE_FORMAT_YUV_420_888 YUV_420_888} apply
+ * to {@link AIMAGE_FORMAT_Y8 Y8} as well. There are no
+ * mandatory stream combination requirements with regard to
+ * {@link AIMAGE_FORMAT_Y8 Y8} for Bayer camera devices.
+ * Starting from Android Q, the SENSOR_INFO_COLOR_FILTER_ARRANGEMENT of a MONOCHROME
+ * camera will be either MONO or NIR.
*/
ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME = 12,
+ /**
+ * The camera device is capable of writing image data into a region of memory
+ * inaccessible to Android userspace or the Android kernel, and only accessible to
+ * trusted execution environments (TEE).
+ */
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA = 13,
+
} acamera_metadata_enum_android_request_available_capabilities_t;
@@ -7300,6 +7776,81 @@ typedef enum acamera_metadata_enum_acamera_scaler_cropping_type {
} acamera_metadata_enum_android_scaler_cropping_type_t;
+// ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS
+typedef enum acamera_metadata_enum_acamera_scaler_available_recommended_stream_configurations {
+ /**
+ * Preview must only include non-stalling processed stream configurations with
+ * output formats like
+ * {@link AIMAGE_FORMAT_YUV_420_888 },
+ * {@link AIMAGE_FORMAT_PRIVATE }, etc.
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW
+ = 0x0,
+
+ /**
+ * Video record must include stream configurations that match the advertised
+ * supported media profiles CamcorderProfile with
+ * IMPLEMENTATION_DEFINED format.
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD
+ = 0x1,
+
+ /**
+ * Video snapshot must include stream configurations at least as big as
+ * the maximum RECORD resolutions and only with
+ * {@link AIMAGE_FORMAT_JPEG JPEG output format}.
+ * Additionally the configurations shouldn't cause preview glitches and also be able to
+ * run at 30 fps.
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VIDEO_SNAPSHOT
+ = 0x2,
+
+ /**
+ * Recommended snapshot stream configurations must include at least one with
+ * size close to ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE and
+ * {@link AIMAGE_FORMAT_JPEG JPEG output format}.
+ * Taking into account restrictions on aspect ratio, alignment etc. the area of the
+ * maximum suggested size shouldn’t be less than 97% of the sensor array size area.
+ *
+ * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT
+ = 0x3,
+
+ /**
+ * If supported, recommended input stream configurations must only be advertised with
+ * ZSL along with other processed and/or stalling output formats.
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_ZSL = 0x4,
+
+ /**
+ * If supported, recommended raw stream configurations must only include RAW based
+ * output formats.
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RAW = 0x5,
+
+ /**
+ * If supported, the recommended low latency stream configurations must have
+ * end-to-end latency that does not exceed 200 ms. under standard operating conditions
+ * (reasonable light levels, not loaded system) and using template
+ * TEMPLATE_STILL_CAPTURE. This is primarily for listing configurations for the
+ * {@link AIMAGE_FORMAT_JPEG JPEG output format}
+ * however other supported output formats can be added as well.
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_LOW_LATENCY_SNAPSHOT
+ = 0x6,
+
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END
+ = 0x7,
+
+ /**
+ * Vendor defined use cases. These depend on the vendor implementation.
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VENDOR_START
+ = 0x18,
+
+} acamera_metadata_enum_android_scaler_available_recommended_stream_configurations_t;
+
// ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
typedef enum acamera_metadata_enum_acamera_sensor_reference_illuminant1 {
@@ -7476,6 +8027,21 @@ typedef enum acamera_metadata_enum_acamera_sensor_info_color_filter_arrangement
*/
ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4,
+ /**
+ * Sensor doesn't have any Bayer color filter.
+ * Such sensor captures visible light in monochrome. The exact weighting and
+ * wavelengths captured is not specified, but generally only includes the visible
+ * frequencies. This value implies a MONOCHROME camera.
+ */
+ ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO = 5,
+
+ /**
+ * Sensor has a near infrared filter capturing light with wavelength between
+ * roughly 750nm and 1400nm, and the same filter covers the whole sensor array. This
+ * value implies a MONOCHROME camera.
+ */
+ ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR = 6,
+
} acamera_metadata_enum_android_sensor_info_color_filter_arrangement_t;
// ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE
@@ -7764,6 +8330,7 @@ typedef enum acamera_metadata_enum_acamera_info_supported_hardware_level {
* fire the flash for flash power metering during precapture, and then fire the flash
* for the final capture, if a flash is available on the device and the AE mode is set to
* enable the flash.
+ * Devices that initially shipped with Android version Q or newer will not include any LEGACY-level devices.
*
* @see ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER
* @see ACAMERA_REQUEST_AVAILABLE_CAPABILITIES
@@ -7904,6 +8471,16 @@ typedef enum acamera_metadata_enum_acamera_depth_depth_is_exclusive {
} acamera_metadata_enum_android_depth_depth_is_exclusive_t;
+// ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS
+typedef enum acamera_metadata_enum_acamera_depth_available_dynamic_depth_stream_configurations {
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_OUTPUT
+ = 0,
+
+ ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_INPUT
+ = 1,
+
+} acamera_metadata_enum_android_depth_available_dynamic_depth_stream_configurations_t;
+
// ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
typedef enum acamera_metadata_enum_acamera_logical_multi_camera_sensor_sync_type {
@@ -7947,6 +8524,16 @@ typedef enum acamera_metadata_enum_acamera_distortion_correction_mode {
} acamera_metadata_enum_android_distortion_correction_mode_t;
+// ACAMERA_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS
+typedef enum acamera_metadata_enum_acamera_heic_available_heic_stream_configurations {
+ ACAMERA_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_OUTPUT = 0,
+
+ ACAMERA_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_INPUT = 1,
+
+} acamera_metadata_enum_android_heic_available_heic_stream_configurations_t;
+
+
+
#endif /* __ANDROID_API__ >= 24 */
__END_DECLS
diff --git a/camera/ndk/include/camera/NdkCameraWindowType.h b/camera/ndk/include/camera/NdkCameraWindowType.h
new file mode 100644
index 0000000000000000000000000000000000000000..99f67e9a5a59d185da40e9db29cac55009f64752
--- /dev/null
+++ b/camera/ndk/include/camera/NdkCameraWindowType.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _NDK_CAMERA_WINDOW_TYPE_H
+#define _NDK_CAMERA_WINDOW_TYPE_H
+
+/**
+ * @addtogroup Camera
+ * @{
+ */
+
+/**
+ * @file NdkCameraWindowType.h
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+/**
+ * This file defines the window type used by NDK and the VNDK variants of the
+ * camera2 NDK. This enables us to share the api definition headers and avoid
+ * code duplication (since the VNDK variant doesn't use ANativeWindow unlike the
+ * NDK variant).
+ */
+#ifdef __ANDROID_VNDK__
+#include
+typedef native_handle_t ACameraWindowType;
+#else
+#include
+typedef ANativeWindow ACameraWindowType;
+#endif
+
+#endif //_NDK_CAMERA_WINDOW_TYPE_H
diff --git a/camera/ndk/include/camera/NdkCaptureRequest.h b/camera/ndk/include/camera/NdkCaptureRequest.h
index 5340e7604441c0e4ef2feb027e93a2aef014686a..d3f8826002dedeb95aac6b02d35c8b5be41f9d88 100644
--- a/camera/ndk/include/camera/NdkCaptureRequest.h
+++ b/camera/ndk/include/camera/NdkCaptureRequest.h
@@ -35,9 +35,9 @@
#include
-#include
#include "NdkCameraError.h"
#include "NdkCameraMetadata.h"
+#include "NdkCameraWindowType.h"
#ifndef _NDK_CAPTURE_REQUEST_H
#define _NDK_CAPTURE_REQUEST_H
@@ -101,7 +101,7 @@ typedef struct ACaptureRequest ACaptureRequest;
*
* @see ACaptureRequest_addTarget
*/
-camera_status_t ACameraOutputTarget_create(ANativeWindow* window,
+camera_status_t ACameraOutputTarget_create(ACameraWindowType* window,
ACameraOutputTarget** output) __INTRODUCED_IN(24);
/**
@@ -358,6 +358,219 @@ ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src) __INTRODUCED_I
#endif /* __ANDROID_API__ >= 28 */
+#if __ANDROID_API__ >= 29
+
+/**
+ * Get a metadata entry from input {@link ACaptureRequest} for
+ * a physical camera backing a logical multi-camera device.
+ *
+ * Same as ACaptureRequest_getConstEntry, except that if the key is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * returns the entry set by ACaptureRequest_setEntry_physicalCamera_* class of
+ * functions on the particular physical camera.
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag the capture request metadata tag in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}
+ * that is set by ACaptureRequest_setEntry_physicalCamera_* class of functions.
+ *
+ * @return
+ * - {@link ACAMERA_OK} if the method call succeeds.
+ * - {@link ACAMERA_ERROR_INVALID_PARAMETER} if metadata, physicalId, or entry is NULL,
+ * physicalId is not one of the Ids used in creating the request, or if the capture
+ * request is a regular request with no physical Ids at all.
+ * - {@link ACAMERA_ERROR_METADATA_NOT_FOUND} if the capture request does not contain an
+ * entry of input tag value.
+ */
+camera_status_t ACaptureRequest_getConstEntry_physicalCamera(
+ const ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ ACameraMetadata_const_entry* entry) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with unsigned 8 bits data type for
+ * a physical camera backing a logical multi-camera device.
+ *
+ * Same as ACaptureRequest_setEntry_u8, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return
+ * - {@link ACAMERA_OK} if the method call succeeds.
+ * - {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not unsigned 8 bits,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_u8(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const uint8_t* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with signed 32 bits data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * Same as ACaptureRequest_setEntry_i32, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return
+ * - {@link ACAMERA_OK} if the method call succeeds.
+ * - {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not signed 32 bits,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_i32(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const int32_t* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with float data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * Same as ACaptureRequest_setEntry_float, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return
+ * - {@link ACAMERA_OK} if the method call succeeds.
+ * - {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not float,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_float(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const float* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with signed 64 bits data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * Same as ACaptureRequest_setEntry_i64, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return
+ * - {@link ACAMERA_OK} if the method call succeeds.
+ * - {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not signed 64 bits,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_i64(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const int64_t* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with double data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * Same as ACaptureRequest_setEntry_double, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return
+ * - {@link ACAMERA_OK} if the method call succeeds.
+ * - {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not double,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_double(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const double* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with rational data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * Same as ACaptureRequest_setEntry_rational, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return
+ * - {@link ACAMERA_OK} if the method call succeeds.
+ * - {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not rational,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_rational(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const ACameraMetadata_rational* data) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
__END_DECLS
#endif /* _NDK_CAPTURE_REQUEST_H */
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index a29e96df3451bd1745c06e317f4bbc2a42c1953a..b6f1553ee3f7250dacbf8d2024a96a38380aa02c 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -2,15 +2,19 @@ LIBCAMERA2NDK {
global:
ACameraCaptureSession_abortCaptures;
ACameraCaptureSession_capture;
+ ACameraCaptureSession_logicalCamera_capture; # introduced=29
ACameraCaptureSession_close;
ACameraCaptureSession_getDevice;
ACameraCaptureSession_setRepeatingRequest;
+ ACameraCaptureSession_logicalCamera_setRepeatingRequest; # introduced=29
ACameraCaptureSession_stopRepeating;
ACameraCaptureSession_updateSharedOutput; # introduced=28
ACameraDevice_close;
ACameraDevice_createCaptureRequest;
+ ACameraDevice_createCaptureRequest_withPhysicalIds; # introduced=29
ACameraDevice_createCaptureSession;
ACameraDevice_createCaptureSessionWithSessionParameters; # introduced=28
+ ACameraDevice_isSessionConfigurationSupported; # introduced=29
ACameraDevice_getId;
ACameraManager_create;
ACameraManager_delete;
@@ -20,10 +24,13 @@ LIBCAMERA2NDK {
ACameraManager_openCamera;
ACameraManager_registerAvailabilityCallback;
ACameraManager_unregisterAvailabilityCallback;
+ ACameraManager_registerExtendedAvailabilityCallback; # introduced=29
+ ACameraManager_unregisterExtendedAvailabilityCallback; # introduced=29
ACameraMetadata_copy;
ACameraMetadata_free;
ACameraMetadata_getAllTags;
ACameraMetadata_getConstEntry;
+ ACameraMetadata_isLogicalMultiCamera; # introduced=29
ACameraOutputTarget_create;
ACameraOutputTarget_free;
ACaptureRequest_addTarget;
@@ -31,14 +38,21 @@ LIBCAMERA2NDK {
ACaptureRequest_free;
ACaptureRequest_getAllTags;
ACaptureRequest_getConstEntry;
+ ACaptureRequest_getConstEntry_physicalCamera; # introduced=29
ACaptureRequest_getUserContext; # introduced=28
ACaptureRequest_removeTarget;
ACaptureRequest_setEntry_double;
+ ACaptureRequest_setEntry_physicalCamera_double; # introduced=29
ACaptureRequest_setEntry_float;
+ ACaptureRequest_setEntry_physicalCamera_float; # introduced=29
ACaptureRequest_setEntry_i32;
+ ACaptureRequest_setEntry_physicalCamera_i32; # introduced=29
ACaptureRequest_setEntry_i64;
+ ACaptureRequest_setEntry_physicalCamera_i64; # introduced=29
ACaptureRequest_setEntry_rational;
+ ACaptureRequest_setEntry_physicalCamera_rational; # introduced=29
ACaptureRequest_setEntry_u8;
+ ACaptureRequest_setEntry_physicalCamera_u8; # introduced=29
ACaptureRequest_setUserContext; # introduced=28
ACaptureSessionOutputContainer_add;
ACaptureSessionOutputContainer_create;
@@ -48,6 +62,7 @@ LIBCAMERA2NDK {
ACaptureSessionSharedOutput_create; # introduced=28
ACaptureSessionSharedOutput_add; # introduced=28
ACaptureSessionSharedOutput_remove; # introduced=28
+ ACaptureSessionPhysicalOutput_create; # introduced=29
ACaptureSessionOutput_free;
local:
*;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1af8c142168c38c4137a6793d1d27e66cd6239a
--- /dev/null
+++ b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include "utils.h"
+
+struct ACaptureSessionOutput {
+ explicit ACaptureSessionOutput(native_handle_t* window, bool isShared = false,
+ const char* physicalCameraId = "") :
+ mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {};
+
+ bool operator == (const ACaptureSessionOutput& other) const {
+ return (mWindow == other.mWindow);
+ }
+
+ bool operator != (const ACaptureSessionOutput& other) const {
+ return mWindow != other.mWindow;
+ }
+
+ bool operator < (const ACaptureSessionOutput& other) const {
+ return mWindow < other.mWindow;
+ }
+
+ bool operator > (const ACaptureSessionOutput& other) const {
+ return mWindow > other.mWindow;
+ }
+
+ android::acam::utils::native_handle_ptr_wrapper mWindow;
+ std::set mSharedWindows;
+ bool mIsShared;
+ int mRotation = CAMERA3_STREAM_ROTATION_0;
+ std::string mPhysicalCameraId;
+};
+
+
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..35c83551c2df93cb60a1836d408add9fa48c85a2
--- /dev/null
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -0,0 +1,1719 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACameraDeviceVendor"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "ndk_vendor/impl/ACameraDevice.h"
+#include "ACameraCaptureSession.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "utils.h"
+
+#include "ACameraCaptureSession.inc"
+
+#define CHECK_TRANSACTION_AND_RET(remoteRet, status, callName) \
+ if (!remoteRet.isOk()) { \
+ ALOGE("%s: Transaction error during %s call %s", __FUNCTION__, callName, \
+ remoteRet.description().c_str()); \
+ return ACAMERA_ERROR_UNKNOWN; \
+ } \
+ if (status != Status::NO_ERROR) { \
+ ALOGE("%s: %s call failed", __FUNCTION__, callName); \
+ return utils::convertFromHidl(status); \
+ }
+
+using namespace android;
+
+ACameraDevice::~ACameraDevice() {
+ mDevice->stopLooper();
+}
+
+namespace android {
+namespace acam {
+
+using HCameraMetadata = frameworks::cameraservice::device::V2_0::CameraMetadata;
+using OutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration;
+using SessionConfiguration = frameworks::cameraservice::device::V2_0::SessionConfiguration;
+using hardware::Void;
+
+// Static member definitions
+const char* CameraDevice::kContextKey = "Context";
+const char* CameraDevice::kDeviceKey = "Device";
+const char* CameraDevice::kErrorCodeKey = "ErrorCode";
+const char* CameraDevice::kCallbackFpKey = "Callback";
+const char* CameraDevice::kSessionSpKey = "SessionSp";
+const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
+const char* CameraDevice::kTimeStampKey = "TimeStamp";
+const char* CameraDevice::kCaptureResultKey = "CaptureResult";
+const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult";
+const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
+const char* CameraDevice::kSequenceIdKey = "SequenceId";
+const char* CameraDevice::kFrameNumberKey = "FrameNumber";
+const char* CameraDevice::kAnwKey = "Anw";
+const char* CameraDevice::kFailingPhysicalCameraId= "FailingPhysicalCameraId";
+
+/**
+ * CameraDevice Implementation
+ */
+CameraDevice::CameraDevice(
+ const char* id,
+ ACameraDevice_StateCallbacks* cb,
+ sp chars,
+ ACameraDevice* wrapper) :
+ mCameraId(id),
+ mAppCallbacks(*cb),
+ mChars(std::move(chars)),
+ mServiceCallback(new ServiceCallback(this)),
+ mWrapper(wrapper),
+ mInError(false),
+ mError(ACAMERA_OK),
+ mIdle(true),
+ mCurrentSession(nullptr) {
+ mClosing = false;
+ // Setup looper thread to perfrom device callbacks to app
+ mCbLooper = new ALooper;
+ mCbLooper->setName("C2N-dev-looper");
+ status_t err = mCbLooper->start(
+ /*runOnCallingThread*/false,
+ /*canCallJava*/ true,
+ PRIORITY_DEFAULT);
+ if (err != OK) {
+ ALOGE("%s: Unable to start camera device callback looper: %s (%d)",
+ __FUNCTION__, strerror(-err), err);
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ }
+ mHandler = new CallbackHandler(id);
+ mCbLooper->registerHandler(mHandler);
+
+ const CameraMetadata& metadata = mChars->getInternalData();
+ camera_metadata_ro_entry entry = metadata.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
+ if (entry.count != 1) {
+ ALOGW("%s: bad count %zu for partial result count", __FUNCTION__, entry.count);
+ mPartialResultCount = 1;
+ } else {
+ mPartialResultCount = entry.data.i32[0];
+ }
+
+ entry = metadata.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
+ if (entry.count != 2) {
+ ALOGW("%s: bad count %zu for shading map size", __FUNCTION__, entry.count);
+ mShadingMapSize[0] = 0;
+ mShadingMapSize[1] = 0;
+ } else {
+ mShadingMapSize[0] = entry.data.i32[0];
+ mShadingMapSize[1] = entry.data.i32[1];
+ }
+}
+
+// Device close implementaiton
+CameraDevice::~CameraDevice() {
+ sp session = mCurrentSession.promote();
+ {
+ Mutex::Autolock _l(mDeviceLock);
+ if (!isClosed()) {
+ disconnectLocked(session);
+ }
+ mCurrentSession = nullptr;
+ LOG_ALWAYS_FATAL_IF(mCbLooper != nullptr,
+ "CameraDevice looper should've been stopped before ~CameraDevice");
+ }
+}
+
+void
+CameraDevice::postSessionMsgAndCleanup(sp& msg) {
+ msg->post();
+ msg.clear();
+ sp cleanupMsg = new AMessage(kWhatCleanUpSessions, mHandler);
+ cleanupMsg->post();
+}
+
+// TODO: cached created request?
+camera_status_t
+CameraDevice::createCaptureRequest(
+ ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalCameraIdList,
+ ACaptureRequest** request) const {
+ Mutex::Autolock _l(mDeviceLock);
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+ if (mRemote == nullptr) {
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ }
+ CameraMetadata rawRequest;
+ Status status = Status::UNKNOWN_ERROR;
+ auto remoteRet = mRemote->createDefaultRequest(
+ utils::convertToHidl(templateId),
+ [&status, &rawRequest](auto s, const hidl_vec &metadata) {
+ status = s;
+ if (status == Status::NO_ERROR && utils::convertFromHidlCloned(metadata, &rawRequest)) {
+ } else {
+ ALOGE("%s: Couldn't create default request", __FUNCTION__);
+ }
+ });
+ CHECK_TRANSACTION_AND_RET(remoteRet, status, "createDefaultRequest()")
+ ACaptureRequest* outReq = new ACaptureRequest();
+ outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
+ if (physicalCameraIdList != nullptr) {
+ for (auto i = 0; i < physicalCameraIdList->numCameras; i++) {
+ outReq->physicalSettings.emplace(physicalCameraIdList->cameraIds[i],
+ new ACameraMetadata(*(outReq->settings)));
+ }
+ }
+ outReq->targets = new ACameraOutputTargets();
+ *request = outReq;
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::createCaptureSession(
+ const ACaptureSessionOutputContainer* outputs,
+ const ACaptureRequest* sessionParameters,
+ const ACameraCaptureSession_stateCallbacks* callbacks,
+ /*out*/ACameraCaptureSession** session) {
+ sp currentSession = mCurrentSession.promote();
+ Mutex::Autolock _l(mDeviceLock);
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ if (currentSession != nullptr) {
+ currentSession->closeByDevice();
+ stopRepeatingLocked();
+ }
+
+ // Create new session
+ ret = configureStreamsLocked(outputs, sessionParameters);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Fail to create new session. cannot configure streams");
+ return ret;
+ }
+
+ ACameraCaptureSession* newSession = new ACameraCaptureSession(
+ mNextSessionId++, outputs, callbacks, this);
+
+ // set new session as current session
+ newSession->incStrong((void *) ACameraDevice_createCaptureSession);
+ mCurrentSession = newSession;
+ mFlushing = false;
+ *session = newSession;
+ return ACAMERA_OK;
+}
+
+camera_status_t CameraDevice::isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const {
+ Mutex::Autolock _l(mDeviceLock);
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ SessionConfiguration sessionConfig;
+ sessionConfig.inputWidth = 0;
+ sessionConfig.inputHeight = 0;
+ sessionConfig.inputFormat = -1;
+ sessionConfig.operationMode = StreamConfigurationMode::NORMAL_MODE;
+ sessionConfig.outputStreams.resize(sessionOutputContainer->mOutputs.size());
+ size_t index = 0;
+ for (const auto& output : sessionOutputContainer->mOutputs) {
+ sessionConfig.outputStreams[index].rotation = utils::convertToHidl(output.mRotation);
+ sessionConfig.outputStreams[index].windowGroupId = -1;
+ sessionConfig.outputStreams[index].windowHandles.resize(output.mSharedWindows.size() + 1);
+ sessionConfig.outputStreams[index].windowHandles[0] = output.mWindow;
+ sessionConfig.outputStreams[index].physicalCameraId = output.mPhysicalCameraId;
+ index++;
+ }
+
+ bool configSupported = false;
+ Status status = Status::UNKNOWN_ERROR;
+ auto remoteRet = mRemote->isSessionConfigurationSupported(sessionConfig,
+ [&status, &configSupported](auto s, auto supported) {
+ status = s;
+ configSupported = supported;
+ });
+
+ CHECK_TRANSACTION_AND_RET(remoteRet, status, "isSessionConfigurationSupported()");
+ return configSupported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
+}
+
+static void addMetadataToPhysicalCameraSettings(const CameraMetadata *metadata,
+ const std::string &cameraId, PhysicalCameraSettings *physicalCameraSettings) {
+ CameraMetadata metadataCopy = *metadata;
+ camera_metadata_t *camera_metadata = metadataCopy.release();
+ HCameraMetadata hCameraMetadata;
+ utils::convertToHidl(camera_metadata, &hCameraMetadata, /*shouldOwn*/ true);
+ physicalCameraSettings->settings.metadata(std::move(hCameraMetadata));
+ physicalCameraSettings->id = cameraId;
+}
+
+void CameraDevice::addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
+ sp &req) {
+ req->mPhysicalCameraSettings.resize(1 + aCaptureRequest->physicalSettings.size());
+ addMetadataToPhysicalCameraSettings(&(aCaptureRequest->settings->getInternalData()), getId(),
+ &(req->mPhysicalCameraSettings[0]));
+ size_t i = 1;
+ for (auto &physicalSetting : aCaptureRequest->physicalSettings) {
+ addMetadataToPhysicalCameraSettings(&(physicalSetting.second->getInternalData()),
+ physicalSetting.first, &(req->mPhysicalCameraSettings[i]));
+ i++;
+ }
+}
+
+camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ if (output == nullptr) {
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!output->mIsShared) {
+ ALOGE("Error output configuration is not shared");
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ }
+
+ int32_t streamId = -1;
+ for (auto& kvPair : mConfiguredOutputs) {
+ if (utils::isWindowNativeHandleEqual(kvPair.second.first, output->mWindow)) {
+ streamId = kvPair.first;
+ break;
+ }
+ }
+ if (streamId < 0) {
+ ALOGE("Error: Invalid output configuration");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ OutputConfigurationWrapper outConfigW;
+ OutputConfiguration &outConfig = outConfigW.mOutputConfiguration;
+ outConfig.rotation = utils::convertToHidl(output->mRotation);
+ outConfig.windowHandles.resize(output->mSharedWindows.size() + 1);
+ outConfig.windowHandles[0] = output->mWindow;
+ outConfig.physicalCameraId = output->mPhysicalCameraId;
+ int i = 1;
+ for (auto& anw : output->mSharedWindows) {
+ outConfig.windowHandles[i++] = anw;
+ }
+
+ auto remoteRet = mRemote->updateOutputConfiguration(streamId, outConfig);
+ if (!remoteRet.isOk()) {
+ ALOGE("%s: Transaction error in updating OutputConfiguration: %s", __FUNCTION__,
+ remoteRet.description().c_str());
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ switch (remoteRet) {
+ case Status::NO_ERROR:
+ break;
+ case Status::INVALID_OPERATION:
+ ALOGE("Camera device %s invalid operation", getId());
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ case Status::ALREADY_EXISTS:
+ ALOGE("Camera device %s output surface already exists", getId());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ case Status::ILLEGAL_ARGUMENT:
+ ALOGE("Camera device %s invalid input argument", getId());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ default:
+ ALOGE("Camera device %s failed to add shared output", getId());
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ mConfiguredOutputs[streamId] = std::make_pair(output->mWindow, outConfigW);
+
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::allocateCaptureRequestLocked(
+ const ACaptureRequest* request, /*out*/sp &outReq) {
+ sp req(new CaptureRequest());
+ req->mCaptureRequest.physicalCameraSettings.resize(1 + request->physicalSettings.size());
+
+ size_t index = 0;
+ allocateOneCaptureRequestMetadata(
+ req->mCaptureRequest.physicalCameraSettings[index++], mCameraId, request->settings);
+
+ for (auto& physicalEntry : request->physicalSettings) {
+ allocateOneCaptureRequestMetadata(
+ req->mCaptureRequest.physicalCameraSettings[index++],
+ physicalEntry.first, physicalEntry.second);
+ }
+
+ std::vector requestStreamIdxList;
+ std::vector requestSurfaceIdxList;
+ for (auto outputTarget : request->targets->mOutputs) {
+ native_handle_t* anw = outputTarget.mWindow;
+ bool found = false;
+ req->mSurfaceList.push_back(anw);
+ // lookup stream/surface ID
+ for (const auto& kvPair : mConfiguredOutputs) {
+ int streamId = kvPair.first;
+ const OutputConfigurationWrapper& outConfig = kvPair.second.second;
+ const auto& windowHandles = outConfig.mOutputConfiguration.windowHandles;
+ for (int surfaceId = 0; surfaceId < (int) windowHandles.size(); surfaceId++) {
+ // If two native handles are equivalent, so are their surfaces.
+ if (utils::isWindowNativeHandleEqual(windowHandles[surfaceId].getNativeHandle(),
+ anw)) {
+ found = true;
+ requestStreamIdxList.push_back(streamId);
+ requestSurfaceIdxList.push_back(surfaceId);
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+ }
+ if (!found) {
+ ALOGE("Unconfigured output target %p in capture request!", anw);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ }
+ req->mCaptureRequest.streamAndWindowIds.resize(requestStreamIdxList.size());
+ for (int i = 0; i < requestStreamIdxList.size(); i++) {
+ req->mCaptureRequest.streamAndWindowIds[i].streamId = requestStreamIdxList[i];
+ req->mCaptureRequest.streamAndWindowIds[i].windowId = requestSurfaceIdxList[i];
+ }
+ outReq = req;
+ return ACAMERA_OK;
+}
+
+void CameraDevice::allocateOneCaptureRequestMetadata(
+ PhysicalCameraSettings& cameraSettings,
+ const std::string& id, const sp& metadata) {
+ cameraSettings.id = id;
+ // TODO: Do we really need to copy the metadata here ?
+ CameraMetadata metadataCopy = metadata->getInternalData();
+ camera_metadata_t *cameraMetadata = metadataCopy.release();
+ HCameraMetadata hCameraMetadata;
+ utils::convertToHidl(cameraMetadata, &hCameraMetadata, true);
+ if (metadata != nullptr) {
+ if (hCameraMetadata.data() != nullptr &&
+ mCaptureRequestMetadataQueue != nullptr &&
+ mCaptureRequestMetadataQueue->write(
+ reinterpret_cast(hCameraMetadata.data()),
+ hCameraMetadata.size())) {
+ // The metadata field of the union would've been destructued, so no need
+ // to re-size it.
+ cameraSettings.settings.fmqMetadataSize(hCameraMetadata.size());
+ } else {
+ ALOGE("Fmq write capture result failed, falling back to hwbinder");
+ cameraSettings.settings.metadata(std::move(hCameraMetadata));
+ }
+ }
+}
+
+
+ACaptureRequest*
+CameraDevice::allocateACaptureRequest(sp& req, const char* deviceId) {
+ ACaptureRequest* pRequest = new ACaptureRequest();
+ for (size_t i = 0; i < req->mPhysicalCameraSettings.size(); i++) {
+ const std::string& id = req->mPhysicalCameraSettings[i].id;
+ CameraMetadata clone;
+ utils::convertFromHidlCloned(req->mPhysicalCameraSettings[i].settings.metadata(), &clone);
+ camera_metadata_t *clonep = clone.release();
+ if (id == deviceId) {
+ pRequest->settings = new ACameraMetadata(clonep, ACameraMetadata::ACM_REQUEST);
+ } else {
+ pRequest->physicalSettings[req->mPhysicalCameraSettings[i].id] =
+ new ACameraMetadata(clonep, ACameraMetadata::ACM_REQUEST);
+ }
+ }
+ pRequest->targets = new ACameraOutputTargets();
+ for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
+ native_handle_t* anw = req->mSurfaceList[i];
+ ACameraOutputTarget outputTarget(anw);
+ pRequest->targets->mOutputs.insert(outputTarget);
+ }
+ return pRequest;
+}
+
+void
+CameraDevice::freeACaptureRequest(ACaptureRequest* req) {
+ if (req == nullptr) {
+ return;
+ }
+ req->settings.clear();
+ delete req->targets;
+ delete req;
+}
+
+void
+CameraDevice::notifySessionEndOfLifeLocked(ACameraCaptureSession* session) {
+ if (isClosed()) {
+ // Device is closing already. do nothing
+ return;
+ }
+
+ if (mCurrentSession != session) {
+ // Session has been replaced by other seesion or device is closed
+ return;
+ }
+ mCurrentSession = nullptr;
+
+ // Should not happen
+ if (!session->mIsClosed) {
+ ALOGE("Error: unclosed session %p reaches end of life!", session);
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return;
+ }
+
+ // No new session, unconfigure now
+ camera_status_t ret = configureStreamsLocked(nullptr, nullptr);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Unconfigure stream failed. Device might still be configured! ret %d", ret);
+ }
+}
+
+void
+CameraDevice::disconnectLocked(sp& session) {
+ if (mClosing.exchange(true)) {
+ // Already closing, just return
+ ALOGW("Camera device %s is already closing.", getId());
+ return;
+ }
+
+ if (mRemote != nullptr) {
+ auto ret = mRemote->disconnect();
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error while disconnecting device %s", __FUNCTION__,
+ ret.description().c_str());
+ }
+ }
+ mRemote = nullptr;
+
+ if (session != nullptr) {
+ session->closeByDevice();
+ }
+}
+
+camera_status_t
+CameraDevice::stopRepeatingLocked() {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+ return ret;
+ }
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ int repeatingSequenceId = mRepeatingSequenceId;
+ mRepeatingSequenceId = REQUEST_ID_NONE;
+
+ int64_t lastFrameNumber;
+ Status status = Status::UNKNOWN_ERROR;
+ auto remoteRet = mRemote->cancelRepeatingRequest(
+ [&status, &lastFrameNumber](Status s, auto frameNumber) {
+ status = s;
+ lastFrameNumber = frameNumber;
+ });
+ CHECK_TRANSACTION_AND_RET(remoteRet, status, "cancelRepeatingRequest()");
+ checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
+ }
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::flushLocked(ACameraCaptureSession* session) {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s abort captures failed! ret %d", getId(), ret);
+ return ret;
+ }
+
+ // This should never happen because creating a new session will close
+ // previous one and thus reject any API call from previous session.
+ // But still good to check here in case something unexpected happen.
+ if (mCurrentSession != session) {
+ ALOGE("Camera %s session %p is not current active session!", getId(), session);
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ }
+
+ if (mFlushing) {
+ ALOGW("Camera %s is already aborting captures", getId());
+ return ACAMERA_OK;
+ }
+
+ mFlushing = true;
+
+ // Send onActive callback to guarantee there is always active->ready transition
+ sp msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+ postSessionMsgAndCleanup(msg);
+
+ // If device is already idling, send callback and exit early
+ if (mIdle) {
+ sp msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onReady);
+ postSessionMsgAndCleanup(msg);
+ mFlushing = false;
+ return ACAMERA_OK;
+ }
+
+ int64_t lastFrameNumber;
+ Status status = Status::UNKNOWN_ERROR;
+ auto remoteRet = mRemote->flush([&status, &lastFrameNumber](auto s, auto frameNumber) {
+ status = s;
+ lastFrameNumber = frameNumber;
+ });
+ CHECK_TRANSACTION_AND_RET(remoteRet, status, "flush()")
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ checkRepeatingSequenceCompleteLocked(mRepeatingSequenceId, lastFrameNumber);
+ }
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::waitUntilIdleLocked() {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Wait until camera %s idle failed! ret %d", getId(), ret);
+ return ret;
+ }
+
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ ALOGE("Camera device %s won't go to idle when there is repeating request!", getId());
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ }
+
+ auto remoteRet = mRemote->waitUntilIdle();
+ CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "waitUntilIdle()")
+ return ACAMERA_OK;
+}
+
+camera_status_t
+CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outputs,
+ const ACaptureRequest* sessionParameters) {
+ ACaptureSessionOutputContainer emptyOutput;
+ if (outputs == nullptr) {
+ outputs = &emptyOutput;
+ }
+
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ std::set> outputSet;
+ for (auto outConfig : outputs->mOutputs) {
+ native_handle_t* anw = outConfig.mWindow;
+ OutputConfigurationWrapper outConfigInsertW;
+ OutputConfiguration &outConfigInsert = outConfigInsertW.mOutputConfiguration;
+ outConfigInsert.rotation = utils::convertToHidl(outConfig.mRotation);
+ outConfigInsert.windowGroupId = -1;
+ outConfigInsert.windowHandles.resize(outConfig.mSharedWindows.size() + 1);
+ outConfigInsert.windowHandles[0] = anw;
+ outConfigInsert.physicalCameraId = outConfig.mPhysicalCameraId;
+ native_handle_ptr_wrapper wrap(anw);
+ outputSet.insert(std::make_pair(anw, outConfigInsertW));
+ }
+ std::set> addSet = outputSet;
+ std::vector deleteList;
+
+ // Determine which streams need to be created, which to be deleted
+ for (auto& kvPair : mConfiguredOutputs) {
+ int32_t streamId = kvPair.first;
+ auto& outputPair = kvPair.second;
+ if (outputSet.count(outputPair)) {
+ deleteList.push_back(streamId); // Need to delete a no longer needed stream
+ } else {
+ addSet.erase(outputPair); // No need to add already existing stream
+ }
+ }
+
+ ret = stopRepeatingLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s stop repeating failed, ret %d", getId(), ret);
+ return ret;
+ }
+
+ ret = waitUntilIdleLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s wait until idle failed, ret %d", getId(), ret);
+ return ret;
+ }
+
+ // Send onReady to previous session
+ // CurrentSession will be updated after configureStreamLocked, so here
+ // mCurrentSession is the session to be replaced by a new session
+ if (!mIdle && mCurrentSession != nullptr) {
+ if (mBusySession != mCurrentSession) {
+ ALOGE("Current session != busy session");
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return ACAMERA_ERROR_CAMERA_DEVICE;
+ }
+ sp msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, mBusySession->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, mBusySession);
+ msg->setPointer(kCallbackFpKey, (void*) mBusySession->mUserSessionCallback.onReady);
+ mBusySession.clear();
+ postSessionMsgAndCleanup(msg);
+ }
+ mIdle = true;
+
+ auto remoteRet = mRemote->beginConfigure();
+ CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "beginConfigure()")
+
+ // delete to-be-deleted streams
+ for (auto streamId : deleteList) {
+ remoteRet = mRemote->deleteStream(streamId);
+ CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "deleteStream()")
+ mConfiguredOutputs.erase(streamId);
+ }
+
+ // add new streams
+ for (auto outputPair : addSet) {
+ int streamId;
+ Status status = Status::UNKNOWN_ERROR;
+ auto ret = mRemote->createStream(outputPair.second,
+ [&status, &streamId](Status s, auto stream_id) {
+ status = s;
+ streamId = stream_id;
+ });
+ CHECK_TRANSACTION_AND_RET(ret, status, "createStream()")
+ mConfiguredOutputs.insert(std::make_pair(streamId, outputPair));
+ }
+
+ CameraMetadata params;
+ HCameraMetadata hidlParams;
+ if ((sessionParameters != nullptr) && (sessionParameters->settings != nullptr)) {
+ params.append(sessionParameters->settings->getInternalData());
+ const camera_metadata_t *params_metadata = params.getAndLock();
+ utils::convertToHidl(params_metadata, &hidlParams);
+ params.unlock(params_metadata);
+ }
+ remoteRet = mRemote->endConfigure(StreamConfigurationMode::NORMAL_MODE, hidlParams);
+ CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "endConfigure()")
+ return ACAMERA_OK;
+}
+
+void
+CameraDevice::setRemoteDevice(sp remote) {
+ Mutex::Autolock _l(mDeviceLock);
+ mRemote = remote;
+}
+
+bool
+CameraDevice::setDeviceMetadataQueues() {
+ if (mRemote == nullptr) {
+ ALOGE("mRemote must not be null while trying to fetch metadata queues");
+ return false;
+ }
+ std::shared_ptr &reqQueue = mCaptureRequestMetadataQueue;
+ auto ret =
+ mRemote->getCaptureRequestMetadataQueue(
+ [&reqQueue](const auto &mqDescriptor) {
+ reqQueue = std::make_shared(mqDescriptor);
+ if (!reqQueue->isValid() || reqQueue->availableToWrite() <=0) {
+ ALOGE("Empty fmq from cameraserver");
+ reqQueue = nullptr;
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("Transaction error trying to get capture request metadata queue");
+ return false;
+ }
+ std::shared_ptr &resQueue = mCaptureResultMetadataQueue;
+ ret =
+ mRemote->getCaptureResultMetadataQueue(
+ [&resQueue](const auto &mqDescriptor) {
+ resQueue = std::make_shared(mqDescriptor);
+ if (!resQueue->isValid() || resQueue->availableToWrite() <=0) {
+ ALOGE("Empty fmq from cameraserver");
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("Transaction error trying to get capture result metadata queue");
+ return false;
+ }
+ return true;
+}
+
+camera_status_t
+CameraDevice::checkCameraClosedOrErrorLocked() const {
+ if (mRemote == nullptr) {
+ ALOGE("%s: camera device already closed", __FUNCTION__);
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ }
+ if (mInError) {// triggered by onDeviceError
+ ALOGE("%s: camera device has encountered a serious error", __FUNCTION__);
+ return mError;
+ }
+ return ACAMERA_OK;
+}
+
+void
+CameraDevice::setCameraDeviceErrorLocked(camera_status_t error) {
+ mInError = true;
+ mError = error;
+ return;
+}
+
+void
+CameraDevice::FrameNumberTracker::updateTracker(int64_t frameNumber, bool isError) {
+ ALOGV("updateTracker frame %" PRId64 " isError %d", frameNumber, isError);
+ if (isError) {
+ mFutureErrorSet.insert(frameNumber);
+ } else if (frameNumber <= mCompletedFrameNumber) {
+ ALOGE("Frame number %" PRId64 " decreased! current fn %" PRId64,
+ frameNumber, mCompletedFrameNumber);
+ return;
+ } else {
+ if (frameNumber != mCompletedFrameNumber + 1) {
+ ALOGE("Frame number out of order. Expect %" PRId64 " but get %" PRId64,
+ mCompletedFrameNumber + 1, frameNumber);
+ // Do not assert as in java implementation
+ }
+ mCompletedFrameNumber = frameNumber;
+ }
+ update();
+}
+
+void
+CameraDevice::FrameNumberTracker::update() {
+ for (auto it = mFutureErrorSet.begin(); it != mFutureErrorSet.end();) {
+ int64_t errorFrameNumber = *it;
+ if (errorFrameNumber == mCompletedFrameNumber + 1) {
+ mCompletedFrameNumber++;
+ it = mFutureErrorSet.erase(it);
+ } else if (errorFrameNumber <= mCompletedFrameNumber) {
+ // This should not happen, but deal with it anyway
+ ALOGE("Completd frame number passed through current frame number!");
+ // erase the old error since it's no longer useful
+ it = mFutureErrorSet.erase(it);
+ } else {
+ // Normal requests hasn't catched up error frames, just break
+ break;
+ }
+ }
+ ALOGV("Update complete frame %" PRId64, mCompletedFrameNumber);
+}
+
+void
+CameraDevice::onCaptureErrorLocked(
+ ErrorCode errorCode,
+ const CaptureResultExtras& resultExtras) {
+ int sequenceId = resultExtras.requestId;
+ int64_t frameNumber = resultExtras.frameNumber;
+ int32_t burstId = resultExtras.burstId;
+ auto it = mSequenceCallbackMap.find(sequenceId);
+ if (it == mSequenceCallbackMap.end()) {
+ ALOGE("%s: Error: capture sequence index %d not found!",
+ __FUNCTION__, sequenceId);
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ return;
+ }
+
+ CallbackHolder cbh = (*it).second;
+ sp session = cbh.mSession;
+ if ((size_t) burstId >= cbh.mRequests.size()) {
+ ALOGE("%s: Error: request index %d out of bound (size %zu)",
+ __FUNCTION__, burstId, cbh.mRequests.size());
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ return;
+ }
+ sp request = cbh.mRequests[burstId];
+
+ // Handle buffer error
+ if (errorCode == ErrorCode::CAMERA_BUFFER) {
+ int32_t streamId = resultExtras.errorStreamId;
+ ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
+ cbh.mOnCaptureBufferLost;
+ auto outputPairIt = mConfiguredOutputs.find(streamId);
+ if (outputPairIt == mConfiguredOutputs.end()) {
+ ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ return;
+ }
+
+ const auto& windowHandles = outputPairIt->second.second.mOutputConfiguration.windowHandles;
+ for (const auto& outHandle : windowHandles) {
+ for (auto streamAndWindowId : request->mCaptureRequest.streamAndWindowIds) {
+ int32_t windowId = streamAndWindowId.windowId;
+ if (utils::isWindowNativeHandleEqual(windowHandles[windowId],outHandle)) {
+ native_handle_t* anw =
+ const_cast(windowHandles[windowId].getNativeHandle());
+ ALOGV("Camera %s Lost output buffer for ANW %p frame %" PRId64,
+ getId(), anw, frameNumber);
+
+ sp msg = new AMessage(kWhatCaptureBufferLost, mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
+ msg->setObject(kCaptureRequestKey, request);
+ msg->setPointer(kAnwKey, (void*) anw);
+ msg->setInt64(kFrameNumberKey, frameNumber);
+ postSessionMsgAndCleanup(msg);
+ }
+ }
+ }
+ } else { // Handle other capture failures
+ // Fire capture failure callback if there is one registered
+ ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed;
+ sp failure(new CameraCaptureFailure());
+ failure->frameNumber = frameNumber;
+ // TODO: refine this when implementing flush
+ failure->reason = CAPTURE_FAILURE_REASON_ERROR;
+ failure->sequenceId = sequenceId;
+ failure->wasImageCaptured = (errorCode == ErrorCode::CAMERA_RESULT);
+
+ sp msg = new AMessage(cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureFail :
+ kWhatCaptureFail, mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
+ msg->setObject(kSessionSpKey, session);
+ if (cbh.mIsLogicalCameraCallback) {
+ if (resultExtras.errorPhysicalCameraId.size() > 0) {
+ msg->setString(kFailingPhysicalCameraId, resultExtras.errorPhysicalCameraId.c_str(),
+ resultExtras.errorPhysicalCameraId.size());
+ }
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnLogicalCameraCaptureFailed);
+ } else {
+ msg->setPointer(kCallbackFpKey, (void*) onError);
+ }
+ msg->setObject(kCaptureRequestKey, request);
+ msg->setObject(kCaptureFailureKey, failure);
+ postSessionMsgAndCleanup(msg);
+
+ // Update tracker
+ mFrameNumberTracker.updateTracker(frameNumber, /*isError*/true);
+ checkAndFireSequenceCompleteLocked();
+ }
+ return;
+}
+
+CameraDevice::CallbackHandler::CallbackHandler(const char *id) : mId(id) { }
+
+void CameraDevice::CallbackHandler::onMessageReceived(
+ const sp &msg) {
+ switch (msg->what()) {
+ case kWhatOnDisconnected:
+ case kWhatOnError:
+ case kWhatSessionStateCb:
+ case kWhatCaptureStart:
+ case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
+ case kWhatCaptureFail:
+ case kWhatLogicalCaptureFail:
+ case kWhatCaptureSeqEnd:
+ case kWhatCaptureSeqAbort:
+ case kWhatCaptureBufferLost:
+ ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
+ break;
+ case kWhatCleanUpSessions:
+ mCachedSessions.clear();
+ return;
+ default:
+ ALOGE("%s:Error: unknown device callback %d", __FUNCTION__, msg->what());
+ return;
+ }
+ // Check the common part of all message
+ void* context;
+ bool found = msg->findPointer(kContextKey, &context);
+ if (!found) {
+ ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+ return;
+ }
+ switch (msg->what()) {
+ case kWhatOnDisconnected:
+ {
+ ACameraDevice* dev;
+ found = msg->findPointer(kDeviceKey, (void**) &dev);
+ if (!found || dev == nullptr) {
+ ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+ return;
+ }
+ ACameraDevice_StateCallback onDisconnected;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onDisconnected);
+ if (!found) {
+ ALOGE("%s: Cannot find onDisconnected!", __FUNCTION__);
+ return;
+ }
+ if (onDisconnected == nullptr) {
+ return;
+ }
+ (*onDisconnected)(context, dev);
+ break;
+ }
+ case kWhatOnError:
+ {
+ ACameraDevice* dev;
+ found = msg->findPointer(kDeviceKey, (void**) &dev);
+ if (!found || dev == nullptr) {
+ ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+ return;
+ }
+ ACameraDevice_ErrorStateCallback onError;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onError);
+ if (!found) {
+ ALOGE("%s: Cannot find onError!", __FUNCTION__);
+ return;
+ }
+ int errorCode;
+ found = msg->findInt32(kErrorCodeKey, &errorCode);
+ if (!found) {
+ ALOGE("%s: Cannot find error code!", __FUNCTION__);
+ return;
+ }
+ if (onError == nullptr) {
+ return;
+ }
+ (*onError)(context, dev, errorCode);
+ break;
+ }
+ case kWhatSessionStateCb:
+ case kWhatCaptureStart:
+ case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
+ case kWhatCaptureFail:
+ case kWhatLogicalCaptureFail:
+ case kWhatCaptureSeqEnd:
+ case kWhatCaptureSeqAbort:
+ case kWhatCaptureBufferLost:
+ {
+ sp obj;
+ found = msg->findObject(kSessionSpKey, &obj);
+ if (!found || obj == nullptr) {
+ ALOGE("%s: Cannot find session pointer!", __FUNCTION__);
+ return;
+ }
+ sp session(static_cast(obj.get()));
+ mCachedSessions.push(session);
+ sp requestSp = nullptr;
+ const char *id_cstr = mId.c_str();
+ switch (msg->what()) {
+ case kWhatCaptureStart:
+ case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
+ case kWhatCaptureFail:
+ case kWhatLogicalCaptureFail:
+ case kWhatCaptureBufferLost:
+ found = msg->findObject(kCaptureRequestKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture request!", __FUNCTION__);
+ return;
+ }
+ requestSp = static_cast(obj.get());
+ break;
+ }
+
+ switch (msg->what()) {
+ case kWhatSessionStateCb:
+ {
+ ACameraCaptureSession_stateCallback onState;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onState);
+ if (!found) {
+ ALOGE("%s: Cannot find state callback!", __FUNCTION__);
+ return;
+ }
+ if (onState == nullptr) {
+ return;
+ }
+ (*onState)(context, session.get());
+ break;
+ }
+ case kWhatCaptureStart:
+ {
+ ACameraCaptureSession_captureCallback_start onStart;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onStart);
+ if (!found) {
+ ALOGE("%s: Cannot find capture start callback!", __FUNCTION__);
+ return;
+ }
+ if (onStart == nullptr) {
+ return;
+ }
+ int64_t timestamp;
+ found = msg->findInt64(kTimeStampKey, ×tamp);
+ if (!found) {
+ ALOGE("%s: Cannot find timestamp!", __FUNCTION__);
+ return;
+ }
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, id_cstr);
+ (*onStart)(context, session.get(), request, timestamp);
+ freeACaptureRequest(request);
+ break;
+ }
+ case kWhatCaptureResult:
+ {
+ ACameraCaptureSession_captureCallback_result onResult;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result callback!", __FUNCTION__);
+ return;
+ }
+ if (onResult == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+ return;
+ }
+ sp result(static_cast(obj.get()));
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, id_cstr);
+ (*onResult)(context, session.get(), request, result.get());
+ freeACaptureRequest(request);
+ break;
+ }
+ case kWhatLogicalCaptureResult:
+ {
+ ACameraCaptureSession_logicalCamera_captureCallback_result onResult;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result callback!", __FUNCTION__);
+ return;
+ }
+ if (onResult == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+ return;
+ }
+ sp result(static_cast(obj.get()));
+
+ found = msg->findObject(kPhysicalCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find physical capture result!", __FUNCTION__);
+ return;
+ }
+ sp physicalResult(
+ static_cast(obj.get()));
+ std::vector& physicalResultInfo =
+ physicalResult->mPhysicalResultInfo;
+
+ std::vector physicalCameraIds;
+ std::vector> physicalMetadataCopy;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ physicalCameraIds.push_back(physicalResultInfo[i].physicalCameraId);
+
+ CameraMetadata clone = physicalResultInfo[i].physicalMetadata;
+ clone.update(ANDROID_SYNC_FRAME_NUMBER,
+ &physicalResult->mFrameNumber, /*data_count*/1);
+ sp metadata =
+ new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+ physicalMetadataCopy.push_back(metadata);
+ }
+ std::vector physicalCameraIdPtrs;
+ std::vector physicalMetadataCopyPtrs;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str());
+ physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, id_cstr);
+ (*onResult)(context, session.get(), request, result.get(),
+ physicalResultInfo.size(), physicalCameraIdPtrs.data(),
+ physicalMetadataCopyPtrs.data());
+ freeACaptureRequest(request);
+ break;
+ }
+
+ case kWhatCaptureFail:
+ {
+ ACameraCaptureSession_captureCallback_failed onFail;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onFail);
+ if (!found) {
+ ALOGE("%s: Cannot find capture fail callback!", __FUNCTION__);
+ return;
+ }
+ if (onFail == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureFailureKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture failure!", __FUNCTION__);
+ return;
+ }
+ sp failureSp(
+ static_cast(obj.get()));
+ ACameraCaptureFailure* failure =
+ static_cast(failureSp.get());
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, id_cstr);
+ (*onFail)(context, session.get(), request, failure);
+ freeACaptureRequest(request);
+ break;
+ }
+ case kWhatLogicalCaptureFail:
+ {
+ ACameraCaptureSession_logicalCamera_captureCallback_failed onFail;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onFail);
+ if (!found) {
+ ALOGE("%s: Cannot find capture fail callback!", __FUNCTION__);
+ return;
+ }
+ if (onFail == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureFailureKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture failure!", __FUNCTION__);
+ return;
+ }
+ sp failureSp(
+ static_cast(obj.get()));
+ ALogicalCameraCaptureFailure failure;
+ AString physicalCameraId;
+ found = msg->findString(kFailingPhysicalCameraId, &physicalCameraId);
+ if (found && !physicalCameraId.empty()) {
+ failure.physicalCameraId = physicalCameraId.c_str();
+ } else {
+ failure.physicalCameraId = nullptr;
+ }
+ failure.captureFailure = *failureSp;
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, id_cstr);
+ (*onFail)(context, session.get(), request, &failure);
+ freeACaptureRequest(request);
+ break;
+ }
+ case kWhatCaptureSeqEnd:
+ {
+ ACameraCaptureSession_captureCallback_sequenceEnd onSeqEnd;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onSeqEnd);
+ if (!found) {
+ ALOGE("%s: Cannot find sequence end callback!", __FUNCTION__);
+ return;
+ }
+ if (onSeqEnd == nullptr) {
+ return;
+ }
+ int seqId;
+ found = msg->findInt32(kSequenceIdKey, &seqId);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+ int64_t frameNumber;
+ found = msg->findInt64(kFrameNumberKey, &frameNumber);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+ (*onSeqEnd)(context, session.get(), seqId, frameNumber);
+ break;
+ }
+ case kWhatCaptureSeqAbort:
+ {
+ ACameraCaptureSession_captureCallback_sequenceAbort onSeqAbort;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onSeqAbort);
+ if (!found) {
+ ALOGE("%s: Cannot find sequence end callback!", __FUNCTION__);
+ return;
+ }
+ if (onSeqAbort == nullptr) {
+ return;
+ }
+ int seqId;
+ found = msg->findInt32(kSequenceIdKey, &seqId);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+ (*onSeqAbort)(context, session.get(), seqId);
+ break;
+ }
+ case kWhatCaptureBufferLost:
+ {
+ ACameraCaptureSession_captureCallback_bufferLost onBufferLost;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onBufferLost);
+ if (!found) {
+ ALOGE("%s: Cannot find buffer lost callback!", __FUNCTION__);
+ return;
+ }
+ if (onBufferLost == nullptr) {
+ return;
+ }
+
+ native_handle_t* anw;
+ found = msg->findPointer(kAnwKey, (void**) &anw);
+ if (!found) {
+ ALOGE("%s: Cannot find native_handle_t!", __FUNCTION__);
+ return;
+ }
+
+ int64_t frameNumber;
+ found = msg->findInt64(kFrameNumberKey, &frameNumber);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, id_cstr);
+ (*onBufferLost)(context, session.get(), request, anw, frameNumber);
+ freeACaptureRequest(request);
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp session,
+ const Vector >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacks* cbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(false) {
+ initCaptureCallbacks(cbs);
+
+ if (cbs != nullptr) {
+ mOnCaptureCompleted = cbs->onCaptureCompleted;
+ mOnCaptureFailed = cbs->onCaptureFailed;
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp session,
+ const Vector >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(true) {
+ initCaptureCallbacks(lcbs);
+
+ if (lcbs != nullptr) {
+ mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+ mOnLogicalCameraCaptureFailed = lcbs->onLogicalCameraCaptureFailed;
+ }
+}
+
+void
+CameraDevice::checkRepeatingSequenceCompleteLocked(
+ const int sequenceId, const int64_t lastFrameNumber) {
+ ALOGV("Repeating seqId %d lastFrameNumer %" PRId64, sequenceId, lastFrameNumber);
+ if (lastFrameNumber == NO_FRAMES_CAPTURED) {
+ if (mSequenceCallbackMap.count(sequenceId) == 0) {
+ ALOGW("No callback found for sequenceId %d", sequenceId);
+ return;
+ }
+ // remove callback holder from callback map
+ auto cbIt = mSequenceCallbackMap.find(sequenceId);
+ CallbackHolder cbh = cbIt->second;
+ mSequenceCallbackMap.erase(cbIt);
+ // send seq aborted callback
+ sp msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
+ msg->setObject(kSessionSpKey, cbh.mSession);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted);
+ msg->setInt32(kSequenceIdKey, sequenceId);
+ postSessionMsgAndCleanup(msg);
+ } else {
+ // Use mSequenceLastFrameNumberMap to track
+ mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+
+ // Last frame might have arrived. Check now
+ checkAndFireSequenceCompleteLocked();
+ }
+}
+
+void
+CameraDevice::checkAndFireSequenceCompleteLocked() {
+ int64_t completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
+ auto it = mSequenceLastFrameNumberMap.begin();
+ while (it != mSequenceLastFrameNumberMap.end()) {
+ int sequenceId = it->first;
+ int64_t lastFrameNumber = it->second;
+ bool seqCompleted = false;
+ bool hasCallback = true;
+
+ if (mRemote == nullptr) {
+ ALOGW("Camera %s closed while checking sequence complete", getId());
+ return;
+ }
+
+ // Check if there is callback for this sequence
+ // This should not happen because we always register callback (with nullptr inside)
+ if (mSequenceCallbackMap.count(sequenceId) == 0) {
+ ALOGW("No callback found for sequenceId %d", sequenceId);
+ hasCallback = false;
+ }
+
+ if (lastFrameNumber <= completedFrameNumber) {
+ ALOGV("seq %d reached last frame %" PRId64 ", completed %" PRId64,
+ sequenceId, lastFrameNumber, completedFrameNumber);
+ seqCompleted = true;
+ }
+
+ if (seqCompleted && hasCallback) {
+ // remove callback holder from callback map
+ auto cbIt = mSequenceCallbackMap.find(sequenceId);
+ CallbackHolder cbh = cbIt->second;
+ mSequenceCallbackMap.erase(cbIt);
+ // send seq complete callback
+ sp msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
+ msg->setObject(kSessionSpKey, cbh.mSession);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
+ msg->setInt32(kSequenceIdKey, sequenceId);
+ msg->setInt64(kFrameNumberKey, lastFrameNumber);
+
+ // Clear the session sp before we send out the message
+ // This will guarantee the rare case where the message is processed
+ // before cbh goes out of scope and causing we call the session
+ // destructor while holding device lock
+ cbh.mSession.clear();
+ postSessionMsgAndCleanup(msg);
+ }
+
+ // No need to track sequence complete if there is no callback registered
+ if (seqCompleted || !hasCallback) {
+ it = mSequenceLastFrameNumberMap.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+void CameraDevice::stopLooper() {
+ Mutex::Autolock _l(mDeviceLock);
+ if (mCbLooper != nullptr) {
+ mCbLooper->unregisterHandler(mHandler->id());
+ mCbLooper->stop();
+ }
+ mCbLooper.clear();
+ mHandler.clear();
+}
+
+/**
+ * Camera service callback implementation
+ */
+android::hardware::Return
+CameraDevice::ServiceCallback::onDeviceError(
+ ErrorCode errorCode,
+ const CaptureResultExtras& resultExtras) {
+ ALOGD("Device error received, code %d, frame number %" PRId64 ", request ID %d, subseq ID %d"
+ " physical camera ID %s", errorCode, resultExtras.frameNumber, resultExtras.requestId,
+ resultExtras.burstId, resultExtras.errorPhysicalCameraId.c_str());
+ auto ret = Void();
+ sp dev = mDevice.promote();
+ if (dev == nullptr) {
+ return ret; // device has been closed
+ }
+
+ sp session = dev->mCurrentSession.promote();
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->mRemote == nullptr) {
+ return ret; // device has been closed
+ }
+ switch (errorCode) {
+ case ErrorCode::CAMERA_DISCONNECTED:
+ {
+ // Camera is disconnected, close the session and expect no more callbacks
+ if (session != nullptr) {
+ session->closeByDevice();
+ }
+ dev->mCurrentSession = nullptr;
+ sp msg = new AMessage(kWhatOnDisconnected, dev->mHandler);
+ msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+ msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+ msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onDisconnected);
+ msg->post();
+ break;
+ }
+ default:
+ ALOGE("Unknown error from camera device: %d", errorCode);
+ [[fallthrough]];
+ case ErrorCode::CAMERA_DEVICE:
+ case ErrorCode::CAMERA_SERVICE:
+ {
+ int32_t errorVal = ::ERROR_CAMERA_DEVICE;
+ // We keep this switch since this block might be encountered with
+ // more than just 2 states. The default fallthrough could have us
+ // handling more unmatched error cases.
+ switch (errorCode) {
+ case ErrorCode::CAMERA_DEVICE:
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ break;
+ case ErrorCode::CAMERA_SERVICE:
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ errorVal = ::ERROR_CAMERA_SERVICE;
+ break;
+ default:
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_UNKNOWN);
+ break;
+ }
+ sp msg = new AMessage(kWhatOnError, dev->mHandler);
+ msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+ msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+ msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onError);
+ msg->setInt32(kErrorCodeKey, errorVal);
+ msg->post();
+ break;
+ }
+ case ErrorCode::CAMERA_REQUEST:
+ case ErrorCode::CAMERA_RESULT:
+ case ErrorCode::CAMERA_BUFFER:
+ dev->onCaptureErrorLocked(errorCode, resultExtras);
+ break;
+ }
+ return ret;
+}
+
+android::hardware::Return
+CameraDevice::ServiceCallback::onDeviceIdle() {
+ ALOGV("Camera is now idle");
+ auto ret = Void();
+ sp dev = mDevice.promote();
+ if (dev == nullptr) {
+ return ret; // device has been closed
+ }
+
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->isClosed() || dev->mRemote == nullptr) {
+ return ret;
+ }
+
+ if (dev->mIdle) {
+ // Already in idle state. Possibly other thread did waitUntilIdle
+ return ret;
+ }
+
+ if (dev->mCurrentSession != nullptr) {
+ ALOGE("onDeviceIdle sending state cb");
+ if (dev->mBusySession != dev->mCurrentSession) {
+ ALOGE("Current session != busy session");
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return ret;
+ }
+
+ sp msg = new AMessage(kWhatSessionStateCb, dev->mHandler);
+ msg->setPointer(kContextKey, dev->mBusySession->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, dev->mBusySession);
+ msg->setPointer(kCallbackFpKey, (void*) dev->mBusySession->mUserSessionCallback.onReady);
+ // Make sure we clear the sp first so the session destructor can
+ // only happen on handler thread (where we don't hold device/session lock)
+ dev->mBusySession.clear();
+ dev->postSessionMsgAndCleanup(msg);
+ }
+ dev->mIdle = true;
+ dev->mFlushing = false;
+ return ret;
+}
+
+android::hardware::Return
+CameraDevice::ServiceCallback::onCaptureStarted(
+ const CaptureResultExtras& resultExtras,
+ uint64_t timestamp) {
+ auto ret = Void();
+
+ sp dev = mDevice.promote();
+ if (dev == nullptr) {
+ return ret; // device has been closed
+ }
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->isClosed() || dev->mRemote == nullptr) {
+ return ret;
+ }
+
+ int32_t sequenceId = resultExtras.requestId;
+ int32_t burstId = resultExtras.burstId;
+
+ auto it = dev->mSequenceCallbackMap.find(sequenceId);
+ if (it != dev->mSequenceCallbackMap.end()) {
+ CallbackHolder cbh = (*it).second;
+ ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
+ sp session = cbh.mSession;
+ if ((size_t) burstId >= cbh.mRequests.size()) {
+ ALOGE("%s: Error: request index %d out of bound (size %zu)",
+ __FUNCTION__, burstId, cbh.mRequests.size());
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ }
+ sp request = cbh.mRequests[burstId];
+ sp msg = new AMessage(kWhatCaptureStart, dev->mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) onStart);
+ msg->setObject(kCaptureRequestKey, request);
+ msg->setInt64(kTimeStampKey, timestamp);
+ dev->postSessionMsgAndCleanup(msg);
+ }
+ return ret;
+}
+
+android::hardware::Return
+CameraDevice::ServiceCallback::onResultReceived(
+ const FmqSizeOrMetadata& resultMetadata,
+ const CaptureResultExtras& resultExtras,
+ const hidl_vec& physicalResultInfos) {
+ auto ret = Void();
+
+ sp dev = mDevice.promote();
+ if (dev == nullptr) {
+ return ret; // device has been closed
+ }
+ int32_t sequenceId = resultExtras.requestId;
+ int64_t frameNumber = resultExtras.frameNumber;
+ int32_t burstId = resultExtras.burstId;
+ bool isPartialResult = (resultExtras.partialResultCount < dev->mPartialResultCount);
+
+ if (!isPartialResult) {
+ ALOGV("SeqId %d frame %" PRId64 " result arrive.", sequenceId, frameNumber);
+ }
+
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->mRemote == nullptr) {
+ return ret; // device has been disconnected
+ }
+
+ if (dev->isClosed()) {
+ if (!isPartialResult) {
+ dev->mFrameNumberTracker.updateTracker(frameNumber, /*isError*/false);
+ }
+ // early return to avoid callback sent to closed devices
+ return ret;
+ }
+
+ CameraMetadata metadataCopy;
+ camera_status_t status = readOneResultMetadata(resultMetadata,
+ dev->mCaptureResultMetadataQueue.get(), &metadataCopy);
+ if (status != ACAMERA_OK) {
+ ALOGE("%s: result metadata couldn't be converted", __FUNCTION__);
+ return ret;
+ }
+
+ metadataCopy.update(ANDROID_LENS_INFO_SHADING_MAP_SIZE, dev->mShadingMapSize, /*data_count*/2);
+ metadataCopy.update(ANDROID_SYNC_FRAME_NUMBER, &frameNumber, /*data_count*/1);
+
+ auto it = dev->mSequenceCallbackMap.find(sequenceId);
+ if (it != dev->mSequenceCallbackMap.end()) {
+ CallbackHolder cbh = (*it).second;
+ sp session = cbh.mSession;
+ if ((size_t) burstId >= cbh.mRequests.size()) {
+ ALOGE("%s: Error: request index %d out of bound (size %zu)",
+ __FUNCTION__, burstId, cbh.mRequests.size());
+ dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ }
+ sp request = cbh.mRequests[burstId];
+ sp result(new ACameraMetadata(
+ metadataCopy.release(), ACameraMetadata::ACM_RESULT));
+
+ std::vector localPhysicalResult;
+ localPhysicalResult.resize(physicalResultInfos.size());
+ for (size_t i = 0; i < physicalResultInfos.size(); i++) {
+ localPhysicalResult[i].physicalCameraId = physicalResultInfos[i].physicalCameraId;
+ status = readOneResultMetadata(physicalResultInfos[i].physicalCameraMetadata,
+ dev->mCaptureResultMetadataQueue.get(),
+ &localPhysicalResult[i].physicalMetadata);
+ if (status != ACAMERA_OK) {
+ ALOGE("%s: physical camera result metadata couldn't be converted", __FUNCTION__);
+ return ret;
+ }
+ }
+ sp physicalResult(
+ new ACameraPhysicalCaptureResultInfo(localPhysicalResult, frameNumber));
+
+ sp msg = new AMessage(
+ cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult,
+ dev->mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
+ msg->setObject(kSessionSpKey, session);
+ msg->setObject(kCaptureRequestKey, request);
+ msg->setObject(kCaptureResultKey, result);
+ if (isPartialResult) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureProgressed);
+ } else if (cbh.mIsLogicalCameraCallback) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnLogicalCameraCaptureCompleted);
+ msg->setObject(kPhysicalCaptureResultKey, physicalResult);
+ } else {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureCompleted);
+ }
+ dev->postSessionMsgAndCleanup(msg);
+ }
+
+ if (!isPartialResult) {
+ dev->mFrameNumberTracker.updateTracker(frameNumber, /*isError*/false);
+ dev->checkAndFireSequenceCompleteLocked();
+ }
+
+ return ret;
+}
+
+android::hardware::Return
+CameraDevice::ServiceCallback::onRepeatingRequestError(
+ uint64_t lastFrameNumber, int32_t stoppedSequenceId) {
+ auto ret = Void();
+
+ sp dev = mDevice.promote();
+ if (dev == nullptr) {
+ return ret; // device has been closed
+ }
+
+ Mutex::Autolock _l(dev->mDeviceLock);
+
+ int repeatingSequenceId = dev->mRepeatingSequenceId;
+ if (stoppedSequenceId == repeatingSequenceId) {
+ dev->mRepeatingSequenceId = REQUEST_ID_NONE;
+ }
+
+ dev->checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
+
+ return ret;
+}
+
+camera_status_t CameraDevice::ServiceCallback::readOneResultMetadata(
+ const FmqSizeOrMetadata& fmqSizeOrMetadata, ResultMetadataQueue* metadataQueue,
+ CameraMetadata* metadata) {
+ if (metadataQueue == nullptr || metadata == nullptr) {
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ bool converted;
+ HCameraMetadata hCameraMetadata;
+ if (fmqSizeOrMetadata.getDiscriminator() ==
+ FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
+ hCameraMetadata.resize(fmqSizeOrMetadata.fmqMetadataSize());
+ bool read = metadataQueue->read(
+ hCameraMetadata.data(), fmqSizeOrMetadata.fmqMetadataSize());
+ if (!read) {
+ ALOGE("%s capture request settings could't be read from fmq", __FUNCTION__);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ // TODO: Do we actually need to clone here ?
+ converted = utils::convertFromHidlCloned(hCameraMetadata, metadata);
+ } else {
+ converted = utils::convertFromHidlCloned(fmqSizeOrMetadata.metadata(), metadata);
+ }
+
+ return converted ? ACAMERA_OK : ACAMERA_ERROR_UNKNOWN;
+}
+
+} // namespace acam
+} // namespace android
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
new file mode 100644
index 0000000000000000000000000000000000000000..3328a8568695d630491e2e9e3938e6d35d944a8d
--- /dev/null
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _ACAMERA_DEVICE_H
+#define _ACAMERA_DEVICE_H
+
+#include
+#include