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 namespace android { +namespace acam { /** * Per-process singleton instance of CameraManger. Shared by all ACameraManager @@ -53,6 +54,11 @@ class CameraManagerGlobal final : public RefBase { void unregisterAvailabilityCallback( const ACameraManager_AvailabilityCallbacks *callback); + void registerExtendedAvailabilityCallback( + const ACameraManager_ExtendedAvailabilityCallbacks* callback); + void unregisterExtendedAvailabilityCallback( + const ACameraManager_ExtendedAvailabilityCallbacks* callback); + /** * Return camera IDs that support camera2 */ @@ -85,6 +91,8 @@ class CameraManagerGlobal final : public RefBase { return binder::Status::ok(); } + virtual binder::Status onCameraAccessPrioritiesChanged(); + private: const wp mCameraManager; }; @@ -95,11 +103,19 @@ class CameraManagerGlobal final : public RefBase { explicit Callback(const ACameraManager_AvailabilityCallbacks *callback) : mAvailable(callback->onCameraAvailable), mUnavailable(callback->onCameraUnavailable), + mAccessPriorityChanged(nullptr), mContext(callback->context) {} + explicit Callback(const ACameraManager_ExtendedAvailabilityCallbacks *callback) : + mAvailable(callback->availabilityCallbacks.onCameraAvailable), + mUnavailable(callback->availabilityCallbacks.onCameraUnavailable), + mAccessPriorityChanged(callback->onCameraAccessPrioritiesChanged), + mContext(callback->availabilityCallbacks.context) {} + bool operator == (const Callback& other) const { return (mAvailable == other.mAvailable && mUnavailable == other.mUnavailable && + mAccessPriorityChanged == other.mAccessPriorityChanged && mContext == other.mContext); } bool operator != (const Callback& other) const { @@ -108,6 +124,9 @@ class CameraManagerGlobal final : public RefBase { bool operator < (const Callback& other) const { if (*this == other) return false; if (mContext != other.mContext) return mContext < other.mContext; + if (mAccessPriorityChanged != other.mAccessPriorityChanged) { + return mAccessPriorityChanged < other.mAccessPriorityChanged; + } if (mAvailable != other.mAvailable) return mAvailable < other.mAvailable; return mUnavailable < other.mUnavailable; } @@ -116,13 +135,15 @@ class CameraManagerGlobal final : public RefBase { } ACameraManager_AvailabilityCallback mAvailable; ACameraManager_AvailabilityCallback mUnavailable; + ACameraManager_AccessPrioritiesChangedCallback mAccessPriorityChanged; void* mContext; }; std::set mCallbacks; // definition of handler and message enum { - kWhatSendSingleCallback + kWhatSendSingleCallback, + kWhatSendSingleAccessCallback, }; static const char* kCameraIdKey; static const char* kCallbackFpKey; @@ -135,6 +156,7 @@ class CameraManagerGlobal final : public RefBase { sp mHandler; sp mCbLooper; // Looper thread where callbacks actually happen on + void onCameraAccessPrioritiesChanged(); void onStatusChanged(int32_t status, const String8& cameraId); void onStatusChangedLocked(int32_t status, const String8& cameraId); // Utils for status @@ -172,6 +194,7 @@ class CameraManagerGlobal final : public RefBase { ~CameraManagerGlobal(); }; +} // namespace acam; } // namespace android; /** @@ -180,13 +203,13 @@ class CameraManagerGlobal final : public RefBase { */ struct ACameraManager { ACameraManager() : - mGlobalManager(&(android::CameraManagerGlobal::getInstance())) {} + mGlobalManager(&(android::acam::CameraManagerGlobal::getInstance())) {} ~ACameraManager(); camera_status_t getCameraIdList(ACameraIdList** cameraIdList); static void deleteCameraIdList(ACameraIdList* cameraIdList); camera_status_t getCameraCharacteristics( - const char *cameraId, ACameraMetadata **characteristics); + const char* cameraId, android::sp* characteristics); camera_status_t openCamera(const char* cameraId, ACameraDevice_StateCallbacks* callback, /*out*/ACameraDevice** device); @@ -196,7 +219,7 @@ struct ACameraManager { kCameraIdListNotInit = -1 }; android::Mutex mLock; - android::sp mGlobalManager; + android::sp mGlobalManager; }; #endif //_ACAMERA_MANAGER_H diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp index 9d341aeaf300d022adb987294b1469b79f004d4e..77dcd488d96dd0b0f1ec57481aaf278bdcb10d5d 100644 --- a/camera/ndk/impl/ACameraMetadata.cpp +++ b/camera/ndk/impl/ACameraMetadata.cpp @@ -36,6 +36,10 @@ ACameraMetadata::ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYP filterDurations(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS); filterDurations(ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS); filterDurations(ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS); + filterDurations(ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS); + filterDurations(ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS); + filterDurations(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS); + filterDurations(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS); } // TODO: filter request/result keys } @@ -43,23 +47,14 @@ ACameraMetadata::ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYP bool ACameraMetadata::isNdkSupportedCapability(int32_t capability) { switch (capability) { - case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE: - case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR: - case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING: - case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW: - case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS: - case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE: - case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT: - return true; case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING: case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING: case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO: return false; default: - // Newly defined capabilities will be unsupported by default (blacklist) - // TODO: Should we do whitelist or blacklist here? - ALOGE("%s: Unknonwn capability %d", __FUNCTION__, capability); - return false; + // Assuming every capability passed to this function is actually a + // valid capability. + return true; } } @@ -79,11 +74,42 @@ ACameraMetadata::filterUnsupportedFeatures() { uint8_t capability = entry.data.u8[i]; if (isNdkSupportedCapability(capability)) { capabilities.push(capability); + + if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) { + derivePhysicalCameraIds(); + } } } mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities); } +void +ACameraMetadata::derivePhysicalCameraIds() { + ACameraMetadata_const_entry entry; + auto ret = getConstEntry(ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS, &entry); + if (ret != ACAMERA_OK) { + ALOGE("%s: Get ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS key failed. ret %d", + __FUNCTION__, ret); + return; + } + + const uint8_t* ids = entry.data.u8; + size_t start = 0; + for (size_t i = 0; i < entry.count; ++i) { + if (ids[i] == '\0') { + if (start != i) { + mStaticPhysicalCameraIdValues.push_back(String8((const char *)ids+start)); + mStaticPhysicalCameraIds.push_back(mStaticPhysicalCameraIdValues.back().string()); + } + start = i+1; + } + } + + if (mStaticPhysicalCameraIds.size() < 2) { + ALOGW("%s: Logical multi-camera device only has %zu physical cameras", + __FUNCTION__, mStaticPhysicalCameraIds.size()); + } +} void ACameraMetadata::filterDurations(uint32_t tag) { @@ -142,6 +168,26 @@ ACameraMetadata::filterDurations(uint32_t tag) { filteredDurations.push_back(duration); } break; + case ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS: + case ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS: + if (format == HAL_PIXEL_FORMAT_BLOB) { + format = AIMAGE_FORMAT_HEIC; + filteredDurations.push_back(format); + filteredDurations.push_back(width); + filteredDurations.push_back(height); + filteredDurations.push_back(duration); + } + break; + case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS: + case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS: + if (format == HAL_PIXEL_FORMAT_BLOB) { + format = AIMAGE_FORMAT_DEPTH_JPEG; + filteredDurations.push_back(format); + filteredDurations.push_back(width); + filteredDurations.push_back(height); + filteredDurations.push_back(duration); + } + break; default: // Should not reach here ALOGE("%s: Unkown tag 0x%x", __FUNCTION__, tag); @@ -228,6 +274,56 @@ ACameraMetadata::filterStreamConfigurations() { filteredDepthStreamConfigs); } + entry = mData.find(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS); + Vector filteredHeicStreamConfigs; + filteredHeicStreamConfigs.setCapacity(entry.count); + + for (size_t i=0; i < entry.count; i += STREAM_CONFIGURATION_SIZE) { + int32_t format = entry.data.i32[i + STREAM_FORMAT_OFFSET]; + int32_t width = entry.data.i32[i + STREAM_WIDTH_OFFSET]; + int32_t height = entry.data.i32[i + STREAM_HEIGHT_OFFSET]; + int32_t isInput = entry.data.i32[i + STREAM_IS_INPUT_OFFSET]; + if (isInput == ACAMERA_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_INPUT) { + // Hide input streams + continue; + } + // Translate HAL formats to NDK format + if (format == HAL_PIXEL_FORMAT_BLOB) { + format = AIMAGE_FORMAT_HEIC; + } + + filteredHeicStreamConfigs.push_back(format); + filteredHeicStreamConfigs.push_back(width); + filteredHeicStreamConfigs.push_back(height); + filteredHeicStreamConfigs.push_back(isInput); + } + mData.update(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, filteredHeicStreamConfigs); + + entry = mData.find(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS); + Vector filteredDynamicDepthStreamConfigs; + filteredDynamicDepthStreamConfigs.setCapacity(entry.count); + + for (size_t i = 0; i < entry.count; i += STREAM_CONFIGURATION_SIZE) { + int32_t format = entry.data.i32[i + STREAM_FORMAT_OFFSET]; + int32_t width = entry.data.i32[i + STREAM_WIDTH_OFFSET]; + int32_t height = entry.data.i32[i + STREAM_HEIGHT_OFFSET]; + int32_t isInput = entry.data.i32[i + STREAM_IS_INPUT_OFFSET]; + if (isInput == ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_INPUT) { + // Hide input streams + continue; + } + // Translate HAL formats to NDK format + if (format == HAL_PIXEL_FORMAT_BLOB) { + format = AIMAGE_FORMAT_DEPTH_JPEG; + } + + filteredDynamicDepthStreamConfigs.push_back(format); + filteredDynamicDepthStreamConfigs.push_back(width); + filteredDynamicDepthStreamConfigs.push_back(height); + filteredDynamicDepthStreamConfigs.push_back(isInput); + } + mData.update(ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, + filteredDynamicDepthStreamConfigs); } bool @@ -322,6 +418,27 @@ ACameraMetadata::getInternalData() const { return mData; } +bool +ACameraMetadata::isLogicalMultiCamera(size_t* count, const char*const** physicalCameraIds) const { + if (mType != ACM_CHARACTERISTICS) { + ALOGE("%s must be called for a static metadata!", __FUNCTION__); + return false; + } + if (count == nullptr || physicalCameraIds == nullptr) { + ALOGE("%s: Invalid input count: %p, physicalCameraIds: %p", __FUNCTION__, + count, physicalCameraIds); + return false; + } + + if (mStaticPhysicalCameraIds.size() >= 2) { + *count = mStaticPhysicalCameraIds.size(); + *physicalCameraIds = mStaticPhysicalCameraIds.data(); + return true; + } + + return false; +} + // TODO: some of key below should be hidden from user // ex: ACAMERA_REQUEST_ID and ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ @@ -443,7 +560,10 @@ std::unordered_set ACameraMetadata::sSystemTags ({ ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT, ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE, ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE, + ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, ANDROID_DEPTH_MAX_DEPTH_SAMPLES, + ANDROID_HEIC_INFO_SUPPORTED, + ANDROID_HEIC_INFO_MAX_JPEG_APP_SEGMENTS_COUNT, }); /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h index e76b80cef700449f62d60ee9a5c6e4543efb279d..97f7f48c1ca4cc01ebd137f80877c0cfb20262c7 100644 --- a/camera/ndk/impl/ACameraMetadata.h +++ b/camera/ndk/impl/ACameraMetadata.h @@ -17,12 +17,19 @@ #define _ACAMERA_METADATA_H #include +#include #include #include #include #include + +#ifdef __ANDROID_VNDK__ +#include +using CameraMetadata = android::hardware::camera::common::V1_0::helper::CameraMetadata; +#else #include +#endif #include @@ -59,15 +66,19 @@ struct ACameraMetadata : public RefBase { /*out*/const uint32_t** tags) const; const CameraMetadata& getInternalData() const; + bool isLogicalMultiCamera(size_t* count, const char* const** physicalCameraIds) const; private: + // This function does not check whether the capability passed to it is valid. + // The caller must make sure that it is. bool isNdkSupportedCapability(const int32_t capability); static inline bool isVendorTag(const uint32_t tag); static bool isCaptureRequestTag(const uint32_t tag); void filterUnsupportedFeatures(); // Hide features not yet supported by NDK void filterStreamConfigurations(); // Hide input streams, translate hal format to NDK formats void filterDurations(uint32_t tag); // translate hal format to NDK formats + void derivePhysicalCameraIds(); // Derive array of physical ids. template camera_status_t updateImpl(uint32_t tag, uint32_t count, const NDK_T* data) { @@ -106,6 +117,9 @@ struct ACameraMetadata : public RefBase { const ACAMERA_METADATA_TYPE mType; static std::unordered_set sSystemTags; + + std::vector mStaticPhysicalCameraIds; + std::vector mStaticPhysicalCameraIdValues; }; #endif // _ACAMERA_METADATA_H diff --git a/camera/ndk/impl/ACaptureRequest.h b/camera/ndk/impl/ACaptureRequest.h index 06b2cc3c2727e48ca911b6b613390af3842a12ee..2ffcafecb227c720a910f758b6f5b99cb9761abd 100644 --- a/camera/ndk/impl/ACaptureRequest.h +++ b/camera/ndk/impl/ACaptureRequest.h @@ -18,11 +18,15 @@ #include #include +#include using namespace android; +#ifdef __ANDROID_VNDK__ +#include "ndk_vendor/impl/ACaptureRequestVendor.h" +#else struct ACameraOutputTarget { - explicit ACameraOutputTarget(ANativeWindow* window) : mWindow(window) {}; + explicit ACameraOutputTarget(ACameraWindowType* window) : mWindow(window) {}; bool operator == (const ACameraOutputTarget& other) const { return mWindow == other.mWindow; @@ -37,8 +41,9 @@ struct ACameraOutputTarget { return mWindow > other.mWindow; } - ANativeWindow* mWindow; + ACameraWindowType* mWindow; }; +#endif struct ACameraOutputTargets { std::set mOutputs; @@ -55,7 +60,8 @@ struct ACaptureRequest { return ACAMERA_OK; } - ACameraMetadata* settings; + sp settings; + std::unordered_map> physicalSettings; ACameraOutputTargets* targets; void* context; }; diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h index 5e0db60c17fb824e89f4075f310329107fcfa93c..07176cf7f9a38147153c4956245a59f3450ac749 100644 --- a/camera/ndk/include/camera/NdkCameraCaptureSession.h +++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h @@ -35,10 +35,10 @@ #include #include -#include #include "NdkCameraError.h" #include "NdkCameraMetadata.h" #include "NdkCaptureRequest.h" +#include "NdkCameraWindowType.h" #ifndef _NDK_CAMERA_CAPTURE_SESSION_H #define _NDK_CAMERA_CAPTURE_SESSION_H @@ -246,7 +246,7 @@ typedef void (*ACameraCaptureSession_captureCallback_sequenceAbort)( */ typedef void (*ACameraCaptureSession_captureCallback_bufferLost)( void* context, ACameraCaptureSession* session, - ACaptureRequest* request, ANativeWindow* window, int64_t frameNumber); + ACaptureRequest* request, ACameraWindowType* window, int64_t frameNumber); typedef struct ACameraCaptureSession_captureCallbacks { /// optional application context. @@ -643,6 +643,153 @@ camera_status_t ACameraCaptureSession_updateSharedOutput(ACameraCaptureSession* ACaptureSessionOutput* output) __INTRODUCED_IN(28); #endif /* __ANDROID_API__ >= 28 */ +#if __ANDROID_API__ >= 29 +/** + * The definition of final capture result callback with logical multi-camera support. + * + * This has the same functionality as final ACameraCaptureSession_captureCallback_result, with + * added ability to return physical camera result metadata within a logical multi-camera. + * + * For a logical multi-camera, this function will be called with the Id and result metadata + * of the underlying physical cameras, which the corresponding capture request contains targets for. + * If the capture request doesn't contain targets specific to any physical camera, or the current + * camera device isn't a logical multi-camera, physicalResultCount will be 0. + * + * @param context The optional application context provided by user in + * {@link ACameraCaptureSession_captureCallbacks}. + * @param session The camera capture session of interest. + * @param request The capture request of interest. Note that this pointer points to a copy of + * capture request sent by application, so the address is different to what + * application sent but the content will match. This request will be freed by + * framework immediately after this callback returns. + * @param result The capture result metadata reported by camera device. The memory is managed by + * camera framework. Do not access this pointer after this callback returns. + * @param physicalResultCount The number of physical camera result metadata + * @param physicalCameraIds The array of physical camera IDs on which the + * physical result metadata are reported. + * @param physicalResults The array of capture result metadata reported by the + * physical camera devices. + */ +typedef void (*ACameraCaptureSession_logicalCamera_captureCallback_result)( + void* context, ACameraCaptureSession* session, + ACaptureRequest* request, const ACameraMetadata* result, + size_t physicalResultCount, const char** physicalCameraIds, + const ACameraMetadata** physicalResults); + +/// Struct to describe a logical camera capture failure +typedef struct ALogicalCameraCaptureFailure { + /** + * The {@link ACameraCaptureFailure} contains information about regular logical device capture + * failure. + */ + struct ACameraCaptureFailure captureFailure; + + /** + * The physical camera device ID in case the capture failure comes from a capture request + * with configured physical camera streams for a logical camera. physicalCameraId will be set + * to NULL in case the capture request has no associated physical camera device. + * + */ + const char* physicalCameraId; +} ALogicalCameraCaptureFailure; + +/** + * The definition of logical camera capture failure callback. + * + * @param context The optional application context provided by user in + * {@link ACameraCaptureSession_captureCallbacks}. + * @param session The camera capture session of interest. + * @param request The capture request of interest. Note that this pointer points to a copy of + * capture request sent by application, so the address is different to what + * application sent but the content will match. This request will be freed by + * framework immediately after this callback returns. + * @param failure The {@link ALogicalCameraCaptureFailure} desribes the capture failure. The memory + * is managed by camera framework. Do not access this pointer after this callback + * returns. + */ +typedef void (*ACameraCaptureSession_logicalCamera_captureCallback_failed)( + void* context, ACameraCaptureSession* session, + ACaptureRequest* request, ALogicalCameraCaptureFailure* failure); + +/** + * This has the same functionality as ACameraCaptureSession_captureCallbacks, + * with the exception that an onLogicalCameraCaptureCompleted callback is + * used, instead of onCaptureCompleted, to support logical multi-camera. + */ +typedef struct ACameraCaptureSession_logicalCamera_captureCallbacks { + /** + * Same as ACameraCaptureSession_captureCallbacks + */ + void* context; + ACameraCaptureSession_captureCallback_start onCaptureStarted; + ACameraCaptureSession_captureCallback_result onCaptureProgressed; + + /** + * This callback is called when an image capture has fully completed and all the + * result metadata is available. For a logical multi-camera, this callback + * also returns the result metadata for all physical cameras being + * explicitly requested on. + * + *

This callback will always fire after the last {@link onCaptureProgressed}; + * in other words, no more partial results will be delivered once the completed result + * is available.

+ * + *

For performance-intensive use-cases where latency is a factor, consider + * using {@link onCaptureProgressed} instead.

+ * + *

Note that the ACaptureRequest pointer in the callback will not match what application has + * submitted, but the contents the ACaptureRequest will match what application submitted.

+ */ + ACameraCaptureSession_logicalCamera_captureCallback_result onLogicalCameraCaptureCompleted; + + /** + * This callback is called instead of {@link onLogicalCameraCaptureCompleted} when the + * camera device failed to produce a capture result for the + * request. + * + *

Other requests are unaffected, and some or all image buffers from + * the capture may have been pushed to their respective output + * streams.

+ * + *

Note that the ACaptureRequest pointer in the callback will not match what application has + * submitted, but the contents the ACaptureRequest will match what application submitted.

+ * + * @see ALogicalCameraCaptureFailure + */ + ACameraCaptureSession_logicalCamera_captureCallback_failed onLogicalCameraCaptureFailed; + + /** + * Same as ACameraCaptureSession_captureCallbacks + */ + ACameraCaptureSession_captureCallback_sequenceEnd onCaptureSequenceCompleted; + ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted; + ACameraCaptureSession_captureCallback_bufferLost onCaptureBufferLost; +} ACameraCaptureSession_logicalCamera_captureCallbacks; + +/** + * This has the same functionality as ACameraCaptureSession_capture, with added + * support for logical multi-camera where the capture callbacks supports result metadata for + * physical cameras. + */ +camera_status_t ACameraCaptureSession_logicalCamera_capture( + ACameraCaptureSession* session, + /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) __INTRODUCED_IN(29); + +/** + * This has the same functionality as ACameraCaptureSession_setRepeatingRequest, with added + * support for logical multi-camera where the capture callbacks supports result metadata for + * physical cameras. + */ +camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest( + ACameraCaptureSession* session, + /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) __INTRODUCED_IN(29); + +#endif /* __ANDROID_API__ >= 29 */ + __END_DECLS #endif /* _NDK_CAMERA_CAPTURE_SESSION_H */ diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h index 7793fb8a4d3567b4ab45908d3c8dbc7cf068628c..1537bdef156ffb02692fb0de23f671dab3c59168 100644 --- a/camera/ndk/include/camera/NdkCameraDevice.h +++ b/camera/ndk/include/camera/NdkCameraDevice.h @@ -34,10 +34,10 @@ */ #include -#include #include "NdkCameraError.h" #include "NdkCaptureRequest.h" #include "NdkCameraCaptureSession.h" +#include "NdkCameraWindowType.h" #ifndef _NDK_CAMERA_DEVICE_H #define _NDK_CAMERA_DEVICE_H @@ -53,6 +53,17 @@ __BEGIN_DECLS */ typedef struct ACameraDevice ACameraDevice; +/** + * Struct to hold list of camera device Ids. This can refer to either the Ids + * of connected camera devices returned from {@link ACameraManager_getCameraIdList}, + * or the physical camera Ids passed into + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + */ +typedef struct ACameraIdList { + int numCameras; ///< Number of camera device Ids + const char** cameraIds; ///< list of camera device Ids +} ACameraIdList; + /// Enum for ACameraDevice_ErrorStateCallback error code enum { /** @@ -345,7 +356,7 @@ void ACaptureSessionOutputContainer_free(ACaptureSessionOutputContain * @see ACaptureSessionOutputContainer_add */ camera_status_t ACaptureSessionOutput_create( - ANativeWindow* anw, /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(24); + ACameraWindowType* anw, /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(24); /** * Free a ACaptureSessionOutput object. @@ -702,7 +713,7 @@ camera_status_t ACameraDevice_createCaptureSession( * @see ACaptureSessionOutputContainer_add */ camera_status_t ACaptureSessionSharedOutput_create( - ANativeWindow* anw, /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(28); + ACameraWindowType* anw, /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(28); /** * Add a native window to shared ACaptureSessionOutput. @@ -720,7 +731,7 @@ camera_status_t ACaptureSessionSharedOutput_create( * ACaptureSessionOutput. */ camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *output, - ANativeWindow *anw) __INTRODUCED_IN(28); + ACameraWindowType *anw) __INTRODUCED_IN(28); /** * Remove a native window from shared ACaptureSessionOutput. @@ -736,7 +747,7 @@ camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *output, * ACaptureSessionOutput. */ camera_status_t ACaptureSessionSharedOutput_remove(ACaptureSessionOutput *output, - ANativeWindow* anw) __INTRODUCED_IN(28); + ACameraWindowType* anw) __INTRODUCED_IN(28); /** * Create a new camera capture session similar to {@link ACameraDevice_createCaptureSession}. This @@ -773,6 +784,114 @@ camera_status_t ACameraDevice_createCaptureSessionWithSessionParameters( #endif /* __ANDROID_API__ >= 28 */ +#if __ANDROID_API__ >= 29 + +/** + * Create a ACaptureSessionOutput object used for streaming from a physical + * camera as part of a logical camera device. + * + *

The ACaptureSessionOutput is used in {@link ACaptureSessionOutputContainer_add} method to add + * an output {@link ANativeWindow} to ACaptureSessionOutputContainer. Use + * {@link ACaptureSessionOutput_free} to free the object and its memory after application no longer + * needs the {@link ACaptureSessionOutput}.

+ * + * @param anw the {@link ANativeWindow} to be associated with the {@link ACaptureSessionOutput} + * @param physicalId the Id of the physical camera this output is associated + * with. + * @param output the output {@link ACaptureSessionOutput} will be stored here if the + * method call succeeds. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds. The created container will be + * filled in the output argument.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if anw, physicalId or output is NULL.
+ * + * @see ACaptureSessionOutputContainer_add + */ +camera_status_t ACaptureSessionPhysicalOutput_create( + ACameraWindowType* anw, const char* physicalId, + /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(29); + +/** + * Create a logical multi-camera ACaptureRequest for capturing images, initialized with template + * for a target use case, with the ability to specify physical camera settings. + * + *

The settings are chosen to be the best options for this camera device, + * so it is not recommended to reuse the same request for a different camera device.

+ * + *

Note that for all keys in physical camera settings, only the keys + * advertised in ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS are + * applicable. All other keys are ignored by the camera device.

+ * + * @param device the camera device of interest + * @param templateId the type of capture request to be created. + * See {@link ACameraDevice_request_template}. + * @param physicalIdList The list of physical camera Ids that can be used to + * customize the request for a specific physical camera. + * @param request the output request will be stored here if the method call succeeds. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds. The created capture request will be + * filled in request argument.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if device, physicalIdList, or request is + * NULL, templateId is undefined or camera device does not support + * requested template, or if some Ids in physicalIdList isn't a + * valid physical camera backing the current camera device.
  • + *
  • {@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed.
  • + *
  • {@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error.
  • + *
  • {@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error.
  • + *
  • {@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.
+ * + * @see TEMPLATE_PREVIEW + * @see TEMPLATE_RECORD + * @see TEMPLATE_STILL_CAPTURE + * @see TEMPLATE_VIDEO_SNAPSHOT + * @see TEMPLATE_MANUAL + */ +camera_status_t ACameraDevice_createCaptureRequest_withPhysicalIds( + const ACameraDevice* device, ACameraDevice_request_template templateId, + const ACameraIdList* physicalIdList, + /*out*/ACaptureRequest** request) __INTRODUCED_IN(29); + +/** + * Check whether a particular {@ACaptureSessionOutputContainer} is supported by + * the camera device. + * + *

This method performs a runtime check of a given {@link + * ACaptureSessionOutputContainer}. The result confirms whether or not the + * passed CaptureSession outputs can be successfully used to create a camera + * capture session using {@link ACameraDevice_createCaptureSession}.

+ * + *

This method can be called at any point before, during and after active + * capture session. It must not impact normal camera behavior in any way and + * must complete significantly faster than creating a capture session.

+ * + *

Although this method is faster than creating a new capture session, it is not intended + * to be used for exploring the entire space of supported stream combinations.

+ * + * @param device the camera device of interest + * @param sessionOutputContainer the {@link ACaptureSessionOutputContainer} of + * interest. + * + * @return
    + *
  • {@link ACAMERA_OK} if the given {@link ACaptureSessionOutputContainer} + * is supported by the camera device.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if device, or sessionOutputContainer + * is NULL.
  • + *
  • {@link ACAMERA_ERROR_STREAM_CONFIGURE_FAIL} if the given + * {@link ACaptureSessionOutputContainer} + * is not supported by + * the camera + * device.
  • + *
  • {@link ACAMERA_ERROR_UNSUPPORTED_OPERATION} if the query operation is not + * supported by the camera device.
  • + */ +camera_status_t ACameraDevice_isSessionConfigurationSupported( + const ACameraDevice* device, + const ACaptureSessionOutputContainer* sessionOutputContainer) __INTRODUCED_IN(29); + +#endif /* __ANDROID_API__ >= 29 */ + __END_DECLS #endif /* _NDK_CAMERA_DEVICE_H */ diff --git a/camera/ndk/include/camera/NdkCameraError.h b/camera/ndk/include/camera/NdkCameraError.h index 6b5815502b11df56637755d7d833c868898c9aee..fc618eee50a322484bab97262a82e25e6db2a890 100644 --- a/camera/ndk/include/camera/NdkCameraError.h +++ b/camera/ndk/include/camera/NdkCameraError.h @@ -106,7 +106,8 @@ typedef enum { /** * Camera device does not support the stream configuration provided by application in - * {@link ACameraDevice_createCaptureSession}. + * {@link ACameraDevice_createCaptureSession} or {@link + * ACameraDevice_isSessionConfigurationSupported}. */ ACAMERA_ERROR_STREAM_CONFIGURE_FAIL = ACAMERA_ERROR_BASE - 9, @@ -130,6 +131,11 @@ typedef enum { * The application does not have permission to open camera. */ ACAMERA_ERROR_PERMISSION_DENIED = ACAMERA_ERROR_BASE - 13, + + /** + * The operation is not supported by the camera device. + */ + ACAMERA_ERROR_UNSUPPORTED_OPERATION = ACAMERA_ERROR_BASE - 14, } camera_status_t; #endif /* __ANDROID_API__ >= 24 */ diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h index ea767388069035c6eee57b4a48a0a4df3d1d06a4..2cc8a9743b4d28724131e841aa8ea1ff81809727 100644 --- a/camera/ndk/include/camera/NdkCameraManager.h +++ b/camera/ndk/include/camera/NdkCameraManager.h @@ -74,12 +74,6 @@ ACameraManager* ACameraManager_create() __INTRODUCED_IN(24); */ void ACameraManager_delete(ACameraManager* manager) __INTRODUCED_IN(24); -/// Struct to hold list of camera devices -typedef struct ACameraIdList { - int numCameras; ///< Number of connected camera devices - const char** cameraIds; ///< list of identifier of connected camera devices -} ACameraIdList; - /** * Create a list of currently connected camera devices, including * cameras that may be in use by other camera API clients. @@ -91,6 +85,11 @@ typedef struct ACameraIdList { *

    ACameraManager_getCameraIdList will allocate and return an {@link ACameraIdList}. * The caller must call {@link ACameraManager_deleteCameraIdList} to free the memory

    * + *

    Note: the returned camera list might be a subset to the output of + * SDK CameraManager#getCameraIdList API as the NDK API does not support some legacy camera + * hardware.

    + * * @param manager the {@link ACameraManager} of interest * @param cameraIdList the output {@link ACameraIdList} will be filled in here if the method call * succeeds. @@ -278,6 +277,122 @@ camera_status_t ACameraManager_openCamera( #endif /* __ANDROID_API__ >= 24 */ +#if __ANDROID_API__ >= 29 + +/** + * Definition of camera access permission change callback. + * + *

    Notification that camera access priorities have changed and the camera may + * now be openable. An application that was previously denied camera access due to + * a higher-priority user already using the camera, or that was disconnected from an + * active camera session due to a higher-priority user trying to open the camera, + * should try to open the camera again if it still wants to use it. Note that + * multiple applications may receive this callback at the same time, and only one of + * them will succeed in opening the camera in practice, depending on exact access + * priority levels and timing. This method is useful in cases where multiple + * applications may be in the resumed state at the same time, and the user switches + * focus between them, or if the current camera-using application moves between + * full-screen and Picture-in-Picture (PiP) states. In such cases, the camera + * available/unavailable callbacks will not be invoked, but another application may + * now have higher priority for camera access than the current camera-using + * application.

    + + * @param context The optional application context provided by user in + * {@link ACameraManager_AvailabilityListener}. + */ +typedef void (*ACameraManager_AccessPrioritiesChangedCallback)(void* context); + +/** + * A listener for camera devices becoming available/unavailable to open or when + * the camera access permissions change. + * + *

    Cameras become available when they are no longer in use, or when a new + * removable camera is connected. They become unavailable when some + * application or service starts using a camera, or when a removable camera + * is disconnected.

    + * + * @see ACameraManager_registerExtendedAvailabilityCallback + */ +typedef struct ACameraManager_ExtendedAvailabilityListener { + /// + ACameraManager_AvailabilityCallbacks availabilityCallbacks; + + /// Called when there is camera access permission change + ACameraManager_AccessPrioritiesChangedCallback onCameraAccessPrioritiesChanged; + + /// Reserved for future use, please ensure that all entries are set to NULL + void *reserved[6]; +} ACameraManager_ExtendedAvailabilityCallbacks; + +/** + * Register camera extended availability callbacks. + * + *

    onCameraUnavailable will be called whenever a camera device is opened by any camera API + * client. Other camera API clients may still be able to open such a camera device, evicting the + * existing client if they have higher priority than the existing client of a camera device. + * See {@link ACameraManager_openCamera} for more details.

    + * + *

    The callbacks will be called on a dedicated thread shared among all ACameraManager + * instances.

    + * + *

    Since this callback will be registered with the camera service, remember to unregister it + * once it is no longer needed; otherwise the callback will continue to receive events + * indefinitely and it may prevent other resources from being released. Specifically, the + * callbacks will be invoked independently of the general activity lifecycle and independently + * of the state of individual ACameraManager instances.

    + * + * @param manager the {@link ACameraManager} of interest. + * @param callback the {@link ACameraManager_ExtendedAvailabilityCallbacks} to be registered. + * + * @return
      + *
    • {@link ACAMERA_OK} if the method call succeeds.
    • + *
    • {@link ACAMERA_ERROR_INVALID_PARAMETER} if manager or callback is NULL, or + * {ACameraManager_ExtendedAvailabilityCallbacks#onCameraAccessPrioritiesChanged} + * or {ACameraManager_AvailabilityCallbacks#onCameraAvailable} or + * {ACameraManager_AvailabilityCallbacks#onCameraUnavailable} is NULL.
    + */ +camera_status_t ACameraManager_registerExtendedAvailabilityCallback( + ACameraManager* manager, + const ACameraManager_ExtendedAvailabilityCallbacks* callback) __INTRODUCED_IN(29); + +/** + * Unregister camera extended availability callbacks. + * + *

    Removing a callback that isn't registered has no effect.

    + * + * @param manager the {@link ACameraManager} of interest. + * @param callback the {@link ACameraManager_ExtendedAvailabilityCallbacks} to be unregistered. + * + * @return
      + *
    • {@link ACAMERA_OK} if the method call succeeds.
    • + *
    • {@link ACAMERA_ERROR_INVALID_PARAMETER} if callback, + * {ACameraManager_ExtendedAvailabilityCallbacks#onCameraAccessPrioritiesChanged} + * or {ACameraManager_AvailabilityCallbacks#onCameraAvailable} or + * {ACameraManager_AvailabilityCallbacks#onCameraUnavailable} is NULL.
    + */ +camera_status_t ACameraManager_unregisterExtendedAvailabilityCallback( + ACameraManager* manager, + const ACameraManager_ExtendedAvailabilityCallbacks* callback) __INTRODUCED_IN(29); + +#ifdef __ANDROID_VNDK__ +/** + * Retrieve the tag value, given the tag name and camera id. + * This method is device specific since some metadata might be defined by device manufacturers + * and might only be accessible for specific cameras. + * @param manager The {@link ACameraManager} of interest. + * @param cameraId The cameraId, which is used to query camera characteristics. + * @param name The name of the tag being queried. + * @param tag The output tag assigned by this method. + * + * @return ACAMERA_OK only if the function call was successful. + */ +camera_status_t ACameraManager_getTagFromName(ACameraManager *manager, const char* cameraId, + const char *name, /*out*/uint32_t *tag) + __INTRODUCED_IN(29); +#endif + +#endif /* __ANDROID_API__ >= 29 */ + __END_DECLS #endif /* _NDK_CAMERA_MANAGER_H */ diff --git a/camera/ndk/include/camera/NdkCameraMetadata.h b/camera/ndk/include/camera/NdkCameraMetadata.h index 611e270e56570ad3e8b0ab1d1e9f69ea48081186..9bbfb83fc8ea92ffe980ccc7d7367e7a997c87a8 100644 --- a/camera/ndk/include/camera/NdkCameraMetadata.h +++ b/camera/ndk/include/camera/NdkCameraMetadata.h @@ -233,6 +233,28 @@ void ACameraMetadata_free(ACameraMetadata* metadata) __INTRODUCED_IN(24); #endif /* __ANDROID_API__ >= 24 */ +#if __ANDROID_API__ >= 29 + +/** + * Helper function to check if a camera is logical multi-camera. + * + *

    Check whether a camera device is a logical multi-camera based on its + * static metadata. If it is, also returns its physical sub camera Ids.

    + * + * @param staticMetadata the static metadata of the camera being checked. + * @param numPhysicalCameras returns the number of physical cameras. + * @param physicalCameraIds returns the array of physical camera Ids backing this logical + * camera device. Note that this pointer is only valid + * during the lifetime of the staticMetadata object. + * + * @return true if this is a logical multi-camera, false otherwise. + */ +bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata, + /*out*/size_t* numPhysicalCameras, /*out*/const char* const** physicalCameraIds) + __INTRODUCED_IN(29); + +#endif /* __ANDROID_API__ >= 29 */ + __END_DECLS #endif /* _NDK_CAMERA_METADATA_H */ diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index ef1cbad35f3f2fef6021c9b4caf07a4ea32f8558..8dd6e00e497f5070a12c4175de9ea6befc0af3ad 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -71,6 +71,8 @@ typedef enum acamera_metadata_section { ACAMERA_DEPTH, ACAMERA_LOGICAL_MULTI_CAMERA, ACAMERA_DISTORTION_CORRECTION, + ACAMERA_HEIC, + ACAMERA_HEIC_INFO, ACAMERA_SECTION_COUNT, ACAMERA_VENDOR = 0x8000 @@ -112,6 +114,8 @@ typedef enum acamera_metadata_section_start { ACAMERA_DISTORTION_CORRECTION_START = ACAMERA_DISTORTION_CORRECTION << 16, + ACAMERA_HEIC_START = ACAMERA_HEIC << 16, + ACAMERA_HEIC_INFO_START = ACAMERA_HEIC_INFO << 16, ACAMERA_VENDOR_START = ACAMERA_VENDOR << 16 } acamera_metadata_section_start_t; @@ -1912,6 +1916,7 @@ typedef enum acamera_metadata_tag { *
  • ACaptureRequest
  • *

* + *

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:

    *

    Image of a uniform white wall (inverse shading map)

    + *

    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:

    - *