Camera: Allow dynamic sensor orientation updates

Camera characteristics are usually expected to remain
static. However certain devices such as foldables may need
to be able to update specific values in response to various
events which could include device state changes.
Enable camera clients to query such metadata updates and receive
updated sensor orientation values.

Bug: 201005727
Test: Manual using AOSP Camera2 application,
Camera CTS

Change-Id: I9c191879b690929984a2945f744dd8407290cf99
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 556ddda..9abb972 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -373,6 +373,7 @@
             res = singleRes;
             // continue to do the rest of the providers instead of returning now
         }
+        provider->notifyDeviceInfoStateChangeLocked(mDeviceState);
     }
     return res;
 }
@@ -2039,6 +2040,14 @@
     return OK;
 }
 
+void CameraProviderManager::ProviderInfo::notifyDeviceInfoStateChangeLocked(
+        hardware::hidl_bitfield<provider::V2_5::DeviceState> newDeviceState) {
+    std::lock_guard<std::mutex> lock(mLock);
+    for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
+        (*it)->notifyDeviceStateChange(newDeviceState);
+    }
+}
+
 status_t CameraProviderManager::ProviderInfo::notifyDeviceStateChange(
         hardware::hidl_bitfield<provider::V2_5::DeviceState> newDeviceState) {
     mDeviceState = newDeviceState;
@@ -2293,6 +2302,18 @@
         return;
     }
 
+    if (mCameraCharacteristics.exists(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS)) {
+        const auto &stateMap = mCameraCharacteristics.find(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS);
+        if ((stateMap.count > 0) && ((stateMap.count % 2) == 0)) {
+            for (size_t i = 0; i < stateMap.count; i += 2) {
+                mDeviceStateOrientationMap.emplace(stateMap.data.i64[i], stateMap.data.i64[i+1]);
+            }
+        } else {
+            ALOGW("%s: Invalid ANDROID_INFO_DEVICE_STATE_ORIENTATIONS map size: %zu", __FUNCTION__,
+                    stateMap.count);
+        }
+    }
+
     mSystemCameraKind = getSystemCameraKind();
 
     status_t res = fixupMonochromeTags();
@@ -2421,6 +2442,16 @@
 
 CameraProviderManager::ProviderInfo::DeviceInfo3::~DeviceInfo3() {}
 
+void CameraProviderManager::ProviderInfo::DeviceInfo3::notifyDeviceStateChange(
+        hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> newState) {
+
+    if (!mDeviceStateOrientationMap.empty() &&
+            (mDeviceStateOrientationMap.find(newState) != mDeviceStateOrientationMap.end())) {
+        mCameraCharacteristics.update(ANDROID_SENSOR_ORIENTATION,
+                &mDeviceStateOrientationMap[newState], 1);
+    }
+}
+
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::setTorchMode(bool enabled) {
     return setTorchModeForDevice<InterfaceT>(enabled);
 }
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index d8c1f59..e3763a1 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -40,7 +40,6 @@
 #include <camera/VendorTagDescriptor.h>
 
 namespace android {
-
 /**
  * The vendor tag descriptor class that takes HIDL vendor tag information as
  * input. Not part of VendorTagDescriptor class because that class is used
@@ -440,6 +439,15 @@
         std::vector<std::unordered_set<std::string>> getConcurrentCameraIdCombinations();
 
         /**
+         * Notify 'DeviceInfo' instanced about top-level device physical state changes
+         *
+         * Note that 'mInterfaceMutex' should be held when calling this method.
+         */
+        void notifyDeviceInfoStateChangeLocked(
+               hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
+                   newDeviceState);
+
+        /**
          * Query the camera provider for concurrent stream configuration support
          */
         status_t isConcurrentSessionConfigurationSupported(
@@ -491,6 +499,9 @@
                 return INVALID_OPERATION;
             }
             virtual status_t filterSmallJpegSizes() = 0;
+            virtual void notifyDeviceStateChange(
+                    hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
+                        /*newState*/) {}
 
             template<class InterfaceT>
             sp<InterfaceT> startDeviceInterface();
@@ -551,6 +562,9 @@
                     bool *status /*out*/)
                     override;
             virtual status_t filterSmallJpegSizes() override;
+            virtual void notifyDeviceStateChange(
+                    hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
+                        newState) override;
 
             DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId,
                     const std::string &id, uint16_t minorVersion,
@@ -560,6 +574,8 @@
             virtual ~DeviceInfo3();
         private:
             CameraMetadata mCameraCharacteristics;
+            // Map device states to sensor orientations
+            std::unordered_map<int64_t, int32_t> mDeviceStateOrientationMap;
             // A copy of mCameraCharacteristics without performance class
             // override
             std::unique_ptr<CameraMetadata> mCameraCharNoPCOverride;