Only provide templates for supported capabilities

Plugs in the StaticProperties class for ease of accessing the
static metadata.

Expands StaticProperties to handle checking template support.

Test: Unit tests pass, test app runs, fixes 2 failing CTS tests on rpi3
BUG: b/32951283
Change-Id: I3077a3507751c3072b88f7d91902bdaa5b53c30e
diff --git a/modules/camera/3_4/camera.cpp b/modules/camera/3_4/camera.cpp
index dc9c825..5a89e3e 100644
--- a/modules/camera/3_4/camera.cpp
+++ b/modules/camera/3_4/camera.cpp
@@ -97,60 +97,50 @@
 
 int Camera::getInfo(struct camera_info *info)
 {
-    android::Mutex::Autolock al(mStaticInfoLock);
-
     info->device_version = mDevice.common.version;
     initDeviceInfo(info);
-    if (mStaticInfo == NULL) {
-        std::unique_ptr<android::CameraMetadata> static_info =
-            std::make_unique<android::CameraMetadata>();
-        if (initStaticInfo(static_info.get())) {
-            return -ENODEV;
+    if (!mStaticInfo) {
+        int res = loadStaticInfo();
+        if (res) {
+            return res;
         }
-        mStaticInfo = std::move(static_info);
     }
-    // The "locking" here only causes non-const methods to fail,
-    // which is not a problem since the CameraMetadata being locked
-    // is already const. Destructing automatically "unlocks".
-    info->static_camera_characteristics = mStaticInfo->getAndLock();
-
-    // Get facing & orientation from the static info.
-    uint8_t facing = 0;
-    int res = v4l2_camera_hal::SingleTagValue(
-        *mStaticInfo, ANDROID_LENS_FACING, &facing);
-    if (res) {
-        ALOGE("%s:%d: Failed to get facing from static metadata.",
-              __func__, mId);
-        return res;
-    }
-    switch (facing) {
-        case (ANDROID_LENS_FACING_FRONT):
-            info->facing = CAMERA_FACING_FRONT;
-            break;
-        case (ANDROID_LENS_FACING_BACK):
-            info->facing = CAMERA_FACING_BACK;
-            break;
-        case (ANDROID_LENS_FACING_EXTERNAL):
-            info->facing = CAMERA_FACING_EXTERNAL;
-            break;
-        default:
-            ALOGE("%s:%d: Invalid facing from metadata: %d.",
-                  __func__, mId, facing);
-            return -ENODEV;
-    }
-    int32_t orientation = 0;
-    res = v4l2_camera_hal::SingleTagValue(
-        *mStaticInfo, ANDROID_SENSOR_ORIENTATION, &orientation);
-    if (res) {
-        ALOGE("%s:%d: Failed to get orientation from static metadata.",
-              __func__, mId);
-        return res;
-    }
-    info->orientation = static_cast<int>(orientation);
+    info->static_camera_characteristics = mStaticInfo->raw_metadata();
+    info->facing = mStaticInfo->facing();
+    info->orientation = mStaticInfo->orientation();
 
     return 0;
 }
 
+int Camera::loadStaticInfo() {
+  // Using a lock here ensures |mStaticInfo| will only ever be set once,
+  // even in concurrent situations.
+  android::Mutex::Autolock al(mStaticInfoLock);
+
+  if (mStaticInfo) {
+    return 0;
+  }
+
+  std::unique_ptr<android::CameraMetadata> static_metadata =
+      std::make_unique<android::CameraMetadata>();
+  int res = initStaticInfo(static_metadata.get());
+  if (res) {
+    ALOGE("%s:%d: Failed to get static info from device.",
+          __func__, mId);
+    return res;
+  }
+
+  mStaticInfo.reset(StaticProperties::NewStaticProperties(
+      std::move(static_metadata)));
+  if (!mStaticInfo) {
+    ALOGE("%s:%d: Failed to initialize static properties from device metadata.",
+          __func__, mId);
+    return -ENODEV;
+  }
+
+  return 0;
+}
+
 int Camera::close()
 {
     ALOGI("%s:%d: Closing camera device", __func__, mId);
@@ -373,6 +363,14 @@
     }
 
     if (!mTemplates[type]) {
+        // Check if the device has the necessary features
+        // for the requested template. If not, don't bother.
+        if (!mStaticInfo->TemplateSupported(type)) {
+            ALOGW("%s:%d: Camera does not support template type %d",
+                  __func__, mId, type);
+            return NULL;
+        }
+
         // Initialize this template if it hasn't been initialized yet.
         std::unique_ptr<android::CameraMetadata> new_template =
             std::make_unique<android::CameraMetadata>();
diff --git a/modules/camera/3_4/camera.h b/modules/camera/3_4/camera.h
index e1f7639..2685fd1 100644
--- a/modules/camera/3_4/camera.h
+++ b/modules/camera/3_4/camera.h
@@ -27,6 +27,7 @@
 #include "capture_request.h"
 #include "metadata/metadata.h"
 #include "request_tracker.h"
+#include "static_properties.h"
 #include "stream.h"
 
 namespace default_camera_hal {
@@ -97,6 +98,8 @@
     private:
         // Camera device handle returned to framework for use
         camera3_device_t mDevice;
+        // Get static info from the device and store it in mStaticInfo.
+        int loadStaticInfo();
         // Reuse a stream already created by this device
         Stream *reuseStream(camera3_stream_t *astream);
         // Destroy all streams in a stream array, and the array itself
@@ -121,7 +124,7 @@
         // Identifier used by framework to distinguish cameras
         const int mId;
         // CameraMetadata containing static characteristics
-        std::unique_ptr<const android::CameraMetadata> mStaticInfo;
+        std::unique_ptr<StaticProperties> mStaticInfo;
         // Flag indicating if settings have been set since
         // the last configure_streams() call.
         bool mSettingsSet;
diff --git a/modules/camera/3_4/metadata/metadata_reader.cpp b/modules/camera/3_4/metadata/metadata_reader.cpp
index 53c9535..fe2ff85 100644
--- a/modules/camera/3_4/metadata/metadata_reader.cpp
+++ b/modules/camera/3_4/metadata/metadata_reader.cpp
@@ -114,6 +114,21 @@
   return 0;
 }
 
+int MetadataReader::RequestCapabilities(std::set<uint8_t>* capabilities) const {
+  std::vector<uint8_t> raw_capabilities;
+  int res = v4l2_camera_hal::VectorTagValue(
+      *metadata_, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &raw_capabilities);
+  if (res) {
+    ALOGE("%s: Failed to get request capabilities from static metadata.",
+          __func__);
+    return res;
+  }
+
+  // Move from vector to set.
+  capabilities->insert(raw_capabilities.begin(), raw_capabilities.end());
+  return 0;
+}
+
 int MetadataReader::StreamConfigurations(
     std::vector<StreamConfiguration>* configs) const {
   std::vector<RawStreamConfiguration> raw_stream_configs;
diff --git a/modules/camera/3_4/metadata/metadata_reader.h b/modules/camera/3_4/metadata/metadata_reader.h
index 828e992..996bf8b 100644
--- a/modules/camera/3_4/metadata/metadata_reader.h
+++ b/modules/camera/3_4/metadata/metadata_reader.h
@@ -19,6 +19,8 @@
 
 #include <map>
 #include <memory>
+#include <set>
+#include <vector>
 
 #include <camera/CameraMetadata.h>
 
@@ -57,6 +59,7 @@
   virtual int MaxOutputStreams(int32_t* max_raw_output_streams,
                                int32_t* max_non_stalling_output_streams,
                                int32_t* max_stalling_output_streams) const;
+  virtual int RequestCapabilities(std::set<uint8_t>* capabilites) const;
   virtual int StreamConfigurations(
       std::vector<StreamConfiguration>* configs) const;
   virtual int StreamStallDurations(
diff --git a/modules/camera/3_4/metadata/metadata_reader_mock.h b/modules/camera/3_4/metadata/metadata_reader_mock.h
index fcd0704..19895a7 100644
--- a/modules/camera/3_4/metadata/metadata_reader_mock.h
+++ b/modules/camera/3_4/metadata/metadata_reader_mock.h
@@ -33,6 +33,7 @@
   MOCK_CONST_METHOD1(Orientation, int(int*));
   MOCK_CONST_METHOD1(MaxInputStreams, int(int32_t*));
   MOCK_CONST_METHOD3(MaxOutputStreams, int(int32_t*, int32_t*, int32_t*));
+  MOCK_CONST_METHOD1(RequestCapabilities, int(std::set<uint8_t>*));
   MOCK_CONST_METHOD1(StreamConfigurations,
                      int(std::vector<StreamConfiguration>*));
   MOCK_CONST_METHOD1(StreamStallDurations,
diff --git a/modules/camera/3_4/metadata/metadata_reader_test.cpp b/modules/camera/3_4/metadata/metadata_reader_test.cpp
index eadf51c..5b9cc63 100644
--- a/modules/camera/3_4/metadata/metadata_reader_test.cpp
+++ b/modules/camera/3_4/metadata/metadata_reader_test.cpp
@@ -363,8 +363,6 @@
 }
 
 TEST_F(MetadataReaderTest, EmptyReprocessFormats) {
-  // 3 indicates that there are 3 output formats for input format 1,
-  // which is not ok since there are only 2 here.
   FillDUT();
   ReprocessFormatMap actual;
   ASSERT_EQ(dut_->ReprocessFormats(&actual), -ENOENT);
diff --git a/modules/camera/3_4/static_properties.cpp b/modules/camera/3_4/static_properties.cpp
index 0584290..b075e6e 100644
--- a/modules/camera/3_4/static_properties.cpp
+++ b/modules/camera/3_4/static_properties.cpp
@@ -19,14 +19,15 @@
 // #define LOG_NDEBUG 0
 #define LOG_TAG "StaticProperties"
 #include <cutils/log.h>
+#include <hardware/camera3.h>
 #include <system/camera.h>
 
 #include "metadata/metadata_reader.h"
 
 namespace default_camera_hal {
 
-// Build and capabilities from configs + stall durations.
-static bool ConstructCapabilities(
+// Build stream capabilities from configs + stall durations.
+static bool ConstructStreamCapabilities(
     const std::vector<StreamConfiguration>& configs,
     const std::vector<StreamStallDuration>& stalls,
     StaticProperties::CapabilitiesMap* capabilities) {
@@ -59,7 +60,7 @@
 
 // Check that each output config has a valid corresponding stall duration
 // (extra durations not matching any output config are ignored).
-static bool ValidateCapabilities(
+static bool ValidateStreamCapabilities(
     StaticProperties::CapabilitiesMap capabilities) {
   for (const auto& spec_capabilities : capabilities) {
     // Only non-negative stall durations are valid. This should only happen
@@ -146,9 +147,10 @@
   int32_t max_raw_output_streams = 0;
   int32_t max_non_stalling_output_streams = 0;
   int32_t max_stalling_output_streams = 0;
+  std::set<uint8_t> request_capabilities;
   std::vector<StreamConfiguration> configs;
   std::vector<StreamStallDuration> stalls;
-  CapabilitiesMap capabilities;
+  CapabilitiesMap stream_capabilities;
   ReprocessFormatMap reprocess_map;
 
   // If reading any data returns an error, something is wrong.
@@ -158,18 +160,19 @@
       metadata_reader->MaxOutputStreams(&max_raw_output_streams,
                                         &max_non_stalling_output_streams,
                                         &max_stalling_output_streams) ||
+      metadata_reader->RequestCapabilities(&request_capabilities) ||
       metadata_reader->StreamConfigurations(&configs) ||
       metadata_reader->StreamStallDurations(&stalls) ||
-      !ConstructCapabilities(configs, stalls, &capabilities) ||
+      !ConstructStreamCapabilities(configs, stalls, &stream_capabilities) ||
       // MetadataReader validates configs and stall seperately,
       // but not that they match.
-      !ValidateCapabilities(capabilities) ||
+      !ValidateStreamCapabilities(stream_capabilities) ||
       // Reprocessing metadata only necessary if input streams are allowed.
       (max_input_streams > 0 &&
        (metadata_reader->ReprocessFormats(&reprocess_map) ||
         // MetadataReader validates configs and the reprocess map seperately,
         // but not that they match.
-        !ValidateReprocessFormats(capabilities, reprocess_map)))) {
+        !ValidateReprocessFormats(stream_capabilities, reprocess_map)))) {
     return nullptr;
   }
 
@@ -180,7 +183,8 @@
                               max_raw_output_streams,
                               max_non_stalling_output_streams,
                               max_stalling_output_streams,
-                              std::move(capabilities),
+                              std::move(request_capabilities),
+                              std::move(stream_capabilities),
                               std::move(reprocess_map));
 }
 
@@ -192,6 +196,7 @@
     int32_t max_raw_output_streams,
     int32_t max_non_stalling_output_streams,
     int32_t max_stalling_output_streams,
+    std::set<uint8_t> request_capabilities,
     CapabilitiesMap stream_capabilities,
     ReprocessFormatMap supported_reprocess_outputs)
     : metadata_reader_(std::move(metadata_reader)),
@@ -201,9 +206,33 @@
       max_raw_output_streams_(max_raw_output_streams),
       max_non_stalling_output_streams_(max_non_stalling_output_streams),
       max_stalling_output_streams_(max_stalling_output_streams),
+      request_capabilities_(std::move(request_capabilities)),
       stream_capabilities_(std::move(stream_capabilities)),
       supported_reprocess_outputs_(std::move(supported_reprocess_outputs)) {}
 
+bool StaticProperties::TemplateSupported(int type) {
+  uint8_t required_capability = 0;
+  switch (type) {
+    case CAMERA3_TEMPLATE_PREVIEW:
+      // Preview is always supported.
+      return true;
+    case CAMERA3_TEMPLATE_MANUAL:
+      required_capability =
+          ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR;
+      break;
+    case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+      required_capability =
+          ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING;
+      break;
+    default:
+      required_capability =
+          ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
+      return true;
+  }
+
+  return request_capabilities_.count(required_capability) > 0;
+}
+
 // Helper functions for checking stream properties when verifying support.
 static bool IsInputType(int stream_type) {
   return stream_type == CAMERA3_STREAM_INPUT ||
diff --git a/modules/camera/3_4/static_properties.h b/modules/camera/3_4/static_properties.h
index a687a80..25c8205 100644
--- a/modules/camera/3_4/static_properties.h
+++ b/modules/camera/3_4/static_properties.h
@@ -51,6 +51,11 @@
   // except that it may return nullptr in case of failure (missing entries).
   static StaticProperties* NewStaticProperties(
       std::unique_ptr<const MetadataReader> metadata_reader);
+  static StaticProperties* NewStaticProperties(
+      std::unique_ptr<android::CameraMetadata> metadata) {
+    return NewStaticProperties(
+        std::make_unique<MetadataReader>(std::move(metadata)));
+  }
   virtual ~StaticProperties(){};
 
   // Simple accessors.
@@ -62,6 +67,8 @@
     return metadata_reader_->raw_metadata();
   };
 
+  // Check if a given template type is supported.
+  bool TemplateSupported(int type);
   // Validators (check that values are consistent with the capabilities
   // this object represents/base requirements of the camera HAL).
   bool StreamConfigurationSupported(
@@ -81,6 +88,7 @@
                    int32_t max_raw_output_streams,
                    int32_t max_non_stalling_output_streams,
                    int32_t max_stalling_output_streams,
+                   std::set<uint8_t> request_capabilities,
                    CapabilitiesMap stream_capabilities,
                    ReprocessFormatMap supported_reprocess_outputs);
 
@@ -101,6 +109,7 @@
   const int32_t max_raw_output_streams_;
   const int32_t max_non_stalling_output_streams_;
   const int32_t max_stalling_output_streams_;
+  const std::set<uint8_t> request_capabilities_;
   const CapabilitiesMap stream_capabilities_;
   const ReprocessFormatMap supported_reprocess_outputs_;
 
diff --git a/modules/camera/3_4/static_properties_test.cpp b/modules/camera/3_4/static_properties_test.cpp
index 4e41ada..e78e343 100644
--- a/modules/camera/3_4/static_properties_test.cpp
+++ b/modules/camera/3_4/static_properties_test.cpp
@@ -66,6 +66,10 @@
                         SetArgPointee<1>(test_max_non_stalling_outputs_),
                         SetArgPointee<2>(test_max_stalling_outputs_),
                         Return(0)));
+    EXPECT_CALL(*mock_reader_, RequestCapabilities(_))
+        .Times(AtMost(1))
+        .WillOnce(
+            DoAll(SetArgPointee<0>(test_request_capabilities_), Return(0)));
     EXPECT_CALL(*mock_reader_, StreamConfigurations(_))
         .Times(AtMost(1))
         .WillOnce(DoAll(SetArgPointee<0>(test_configs_), Return(0)));
@@ -125,6 +129,10 @@
   const int32_t test_max_raw_outputs_ = 1;
   const int32_t test_max_non_stalling_outputs_ = 2;
   const int32_t test_max_stalling_outputs_ = 3;
+  const std::set<uint8_t> test_request_capabilities_ = {
+      ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+      ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
+      ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING};
 
   // Some formats for various purposes (in various combinations,
   // these types should be capable of testing all failure conditions).
@@ -227,6 +235,14 @@
   EXPECT_EQ(dut_, nullptr);
 }
 
+TEST_F(StaticPropertiesTest, FactoryFailedRequestCapabilities) {
+  SetDefaultExpectations();
+  // Override with a failure expectation.
+  EXPECT_CALL(*mock_reader_, RequestCapabilities(_)).WillOnce(Return(99));
+  PrepareDUT();
+  EXPECT_EQ(dut_, nullptr);
+}
+
 TEST_F(StaticPropertiesTest, FactoryFailedStreamConfigs) {
   SetDefaultExpectations();
   // Override with a failure expectation.
@@ -355,6 +371,13 @@
   EXPECT_EQ(dut_, nullptr);
 }
 
+TEST_F(StaticPropertiesTest, TemplatesValid) {
+  PrepareDefaultDUT();
+  for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; ++i) {
+    EXPECT_TRUE(dut_->TemplateSupported(i));
+  }
+}
+
 TEST_F(StaticPropertiesTest, ConfigureSingleOutput) {
   std::vector<camera3_stream_t> streams;
   streams.push_back(MakeStream(output_multisize_non_stalling_));