OSDN Git Service

Set HWC as DRM master when got exclusive lock of /vendor/hwc.lock.
[android-x86/external-IA-Hardware-Composer.git] / common / core / gpudevice.cpp
index 756d2d7..170559d 100644 (file)
 
 #include <gpudevice.h>
 
+#include <sys/file.h>
+
 #include "mosaicdisplay.h"
 
+#include "hwctrace.h"
+
 namespace hwcomposer {
 
-GpuDevice::GpuDevice() : initialized_(false) {
+GpuDevice::GpuDevice() : HWCThread(-8, "GpuDevice") {
 }
 
 GpuDevice::~GpuDevice() {
@@ -28,34 +32,92 @@ GpuDevice::~GpuDevice() {
 }
 
 bool GpuDevice::Initialize() {
-  if (initialized_)
+  initialization_state_lock_.lock();
+  if (initialization_state_ & kInitialized) {
+    initialization_state_lock_.unlock();
     return true;
+  }
+
+  initialization_state_ |= kInitialized;
+  initialization_state_lock_.unlock();
 
-  initialized_ = true;
-  display_manager_.reset(DisplayManager::CreateDisplayManager());
+  display_manager_.reset(DisplayManager::CreateDisplayManager(this));
 
   bool success = display_manager_->Initialize();
   if (!success) {
     return false;
   }
 
-  std::vector<NativeDisplay *> unordered_displays =
-      display_manager_->GetAllDisplays();
-  size_t size = unordered_displays.size();
+  display_manager_->InitializeDisplayResources();
+  display_manager_->StartHotPlugMonitor();
 
-  // Handle config file reading
-  const char *hwc_dp_cfg_path = std::getenv("HWC_DISPLAY_CONFIG");
-  if (!hwc_dp_cfg_path) {
-    hwc_dp_cfg_path = "/vendor/etc/hwc_display.ini";
+  HandleHWCSettings();
+
+  lock_fd_ = open("/vendor/hwc.lock", O_RDONLY);
+  if (-1 != lock_fd_) {
+    if (!InitWorker()) {
+      ETRACE("Failed to initalize thread for GpuDevice. %s", PRINTERROR());
+    }
+  } else {
+    ITRACE("Failed to open " LOCK_DIR_PREFIX "/hwc.lock file!");
   }
 
+  return true;
+}
+
+uint32_t GpuDevice::GetFD() const {
+  return display_manager_->GetFD();
+}
+
+NativeDisplay *GpuDevice::GetDisplay(uint32_t display_id) {
+  if (total_displays_.size() > display_id)
+    return total_displays_.at(display_id);
+
+  return NULL;
+}
+
+NativeDisplay *GpuDevice::CreateVirtualDisplay(uint32_t display_index) {
+  return display_manager_->CreateVirtualDisplay(display_index);
+}
+
+void GpuDevice::DestroyVirtualDisplay(uint32_t display_index) {
+  display_manager_->DestroyVirtualDisplay(display_index);
+}
+
+void GpuDevice::GetConnectedPhysicalDisplays(
+    std::vector<NativeDisplay *> &displays) {
+  size_t size = total_displays_.size();
+  for (size_t i = 0; i < size; i++) {
+    if (total_displays_.at(i)->IsConnected()) {
+      displays.emplace_back(total_displays_.at(i));
+    }
+  }
+}
+
+const std::vector<NativeDisplay *> &GpuDevice::GetAllDisplays() {
+  return total_displays_;
+}
+
+void GpuDevice::RegisterHotPlugEventCallback(
+    std::shared_ptr<DisplayHotPlugEventCallback> callback) {
+  display_manager_->RegisterHotPlugEventCallback(callback);
+}
+
+void GpuDevice::HandleHWCSettings() {
+  // Handle config file reading
+  const char *hwc_dp_cfg_path = HWC_DISPLAY_INI_PATH;
+  ITRACE("Hwc display config file is %s", hwc_dp_cfg_path);
+
   bool use_logical = false;
   bool use_mosaic = false;
   bool use_cloned = false;
   bool rotate_display = false;
+  bool use_float = false;
   std::vector<uint32_t> logical_displays;
   std::vector<uint32_t> physical_displays;
   std::vector<uint32_t> display_rotation;
+  std::vector<uint32_t> float_display_indices;
+  std::vector<HwcRect<int32_t>> float_displays;
   std::vector<std::vector<uint32_t>> cloned_displays;
   std::vector<std::vector<uint32_t>> mosaic_displays;
   std::ifstream fin(hwc_dp_cfg_path);
@@ -64,11 +126,13 @@ bool GpuDevice::Initialize() {
   std::string key_mosaic("MOSAIC");
   std::string key_clone("CLONE");
   std::string key_rotate("ROTATION");
+  std::string key_float("FLOAT");
   std::string key_logical_display("LOGICAL_DISPLAY");
   std::string key_mosaic_display("MOSAIC_DISPLAY");
   std::string key_physical_display("PHYSICAL_DISPLAY");
   std::string key_physical_display_rotation("PHYSICAL_DISPLAY_ROTATION");
   std::string key_clone_display("CLONE_DISPLAY");
+  std::string key_float_display("FLOAT_DISPLAY");
   std::vector<uint32_t> mosaic_duplicate_check;
   std::vector<uint32_t> clone_duplicate_check;
   std::vector<uint32_t> physical_duplicate_check;
@@ -107,6 +171,11 @@ bool GpuDevice::Initialize() {
           if (!value.compare(enable_str)) {
             rotate_display = true;
           }
+          // Got float switch
+        } else if (!key.compare(key_float)) {
+          if (!value.compare(enable_str)) {
+            use_float = true;
+          }
         } else if (!key.compare(key_logical_display)) {
           std::string physical_index_str;
           std::istringstream i_value(value);
@@ -184,9 +253,7 @@ bool GpuDevice::Initialize() {
               }
             }
             if (!skip_duplicate_display) {
-              if (physical_split_num < size) {
-                physical_displays.emplace_back(physical_split_num);
-              }
+              physical_displays.emplace_back(physical_split_num);
               physical_duplicate_check.emplace_back(physical_split_num);
             }
           }
@@ -254,18 +321,70 @@ bool GpuDevice::Initialize() {
           uint32_t rotation_num = atoi(rotation_str.c_str());
           display_rotation.emplace_back(rotation_num);
           rotation_display_index.emplace_back(physical_index);
+        } else if (!key.compare(key_float_display)) {
+          std::string index_str;
+          std::string float_rect_str;
+          std::vector<int32_t> float_rect;
+          std::istringstream i_value(value);
+
+          // Got display index
+          std::getline(i_value, index_str, ':');
+          if (index_str.empty() ||
+              index_str.find_first_not_of("0123456789") != std::string::npos) {
+            continue;
+          }
+
+          int32_t index = atoi(index_str.c_str());
+
+          // Got rectangle configuration
+          while (std::getline(i_value, float_rect_str, '+')) {
+            if (float_rect_str.empty() ||
+                float_rect_str.find_first_not_of("0123456789") !=
+                    std::string::npos) {
+              continue;
+            }
+            size_t float_rect_val = atoi(float_rect_str.c_str());
+
+            // Save the rectangle - left, top, right & bottom
+            float_rect.emplace_back(float_rect_val);
+          }
+
+          // If entire rect is available, store the parameters
+          // TODO remove hard code
+          if (float_rect.size() == 4) {
+            float_display_indices.emplace_back(index);
+            HwcRect<int32_t> rect =
+                HwcRect<int32_t>(float_rect.at(0), float_rect.at(1),
+                                 float_rect.at(2), float_rect.at(3));
+            float_displays.emplace_back(rect);
+          }
         }
       }
     }
   };
 
   std::vector<NativeDisplay *> displays;
+  std::vector<NativeDisplay *> unordered_displays =
+      display_manager_->GetAllDisplays();
+  size_t size = unordered_displays.size();
+  uint32_t dispmgr_display_size = (uint32_t) size;
+
   if (physical_displays.empty()) {
     displays.swap(unordered_displays);
   } else {
     size = physical_displays.size();
     for (size_t i = 0; i < size; i++) {
-      displays.emplace_back(unordered_displays.at(physical_displays.at(i)));
+      uint32_t pdisp_index = physical_displays.at(i);
+      // Add the physical display only if it has been enumerated from DRM API.
+      // Skip the non-existence display defined in hwc_display.ini file.
+      if (pdisp_index < dispmgr_display_size) {
+        displays.emplace_back(unordered_displays.at(pdisp_index));
+      } else {
+        ETRACE(
+            "Physical display number: %u defined in hwc_display.ini "
+            "doesn't exist in enumerated DRM display list (total: %u).",
+            pdisp_index, dispmgr_display_size);
+      }
     }
 
     if (displays.size() != unordered_displays.size()) {
@@ -287,8 +406,29 @@ bool GpuDevice::Initialize() {
     }
   }
 
+  // Re-order displays based on connection status.
+  std::vector<NativeDisplay *> connected_displays;
+  std::vector<NativeDisplay *> un_connected_displays;
   size = displays.size();
   for (size_t i = 0; i < size; i++) {
+    NativeDisplay *temp = displays.at(i);
+    if (temp->IsConnected()) {
+      connected_displays.emplace_back(temp);
+    } else {
+      un_connected_displays.emplace_back(temp);
+    }
+  }
+
+  displays.swap(connected_displays);
+
+  if (!un_connected_displays.empty()) {
+    size_t temp = un_connected_displays.size();
+    for (size_t i = 0; i < temp; i++) {
+      displays.emplace_back(un_connected_displays.at(i));
+    }
+  }
+
+  for (size_t i = 0; i < size; i++) {
     displays.at(i)->SetDisplayOrder(i);
   }
 
@@ -422,37 +562,132 @@ bool GpuDevice::Initialize() {
     temp_displays.swap(total_displays_);
   }
 
-  return true;
+  // Now set floating display configuration
+  // Get the floating display index and the respective rectangle
+  // TODO Logical display on & mosaic display on scenario
+  if (use_float && !use_logical && !use_mosaic) {
+    bool ret = false;
+    size_t size = float_display_indices.size();
+    size_t num_displays = total_displays_.size();
+
+    // Set custom resolution to desired display instance
+    for (size_t i = 0; i < size; i++) {
+      int index = float_display_indices.at(i);
+
+      // Ignore float index if out of range of connected displays
+      if ((size_t)index < num_displays) {
+        const HwcRect<int32_t> &rect = float_displays.at(i);
+        ret = total_displays_.at(index)->SetCustomResolution(rect);
+      }
+    }
+  }
 }
 
-NativeDisplay *GpuDevice::GetDisplay(uint32_t display_id) {
-  if (total_displays_.size() > display_id)
-    return total_displays_.at(display_id);
+void GpuDevice::EnableHDCPSessionForDisplay(uint32_t display,
+                                            HWCContentType content_type) {
+  if (total_displays_.size() <= display) {
+    ETRACE("Tried to enable HDCP for invalid display %u \n", display);
+    return;
+  }
 
-  return NULL;
+  NativeDisplay *native_display = total_displays_.at(display);
+  native_display->SetHDCPState(HWCContentProtection::kDesired, content_type);
 }
 
-NativeDisplay *GpuDevice::GetVirtualDisplay() {
-  return display_manager_->GetVirtualDisplay();
+void GpuDevice::EnableHDCPSessionForAllDisplays(HWCContentType content_type) {
+  size_t size = total_displays_.size();
+  for (size_t i = 0; i < size; i++) {
+    total_displays_.at(i)
+        ->SetHDCPState(HWCContentProtection::kDesired, content_type);
+  }
 }
 
-void GpuDevice::GetConnectedPhysicalDisplays(
-    std::vector<NativeDisplay *> &displays) {
+void GpuDevice::DisableHDCPSessionForDisplay(uint32_t display) {
+  if (total_displays_.size() <= display) {
+    ETRACE("Tried to enable HDCP for invalid display %u \n", display);
+    return;
+  }
+
+  NativeDisplay *native_display = total_displays_.at(display);
+  native_display->SetHDCPState(HWCContentProtection::kUnDesired,
+                               HWCContentType::kInvalid);
+}
+
+void GpuDevice::DisableHDCPSessionForAllDisplays() {
   size_t size = total_displays_.size();
   for (size_t i = 0; i < size; i++) {
-    if (total_displays_.at(i)->IsConnected()) {
-      displays.emplace_back(total_displays_.at(i));
+    total_displays_.at(i)->SetHDCPState(HWCContentProtection::kUnDesired,
+                                        HWCContentType::kInvalid);
+  }
+}
+
+void GpuDevice::SetPAVPSessionStatus(bool enabled, uint32_t pavp_session_id,
+                                     uint32_t pavp_instance_id) {
+  size_t size = total_displays_.size();
+  for (size_t i = 0; i < size; i++) {
+    total_displays_.at(i)->SetPAVPSessionStatus(enabled, pavp_session_id,
+                                                pavp_instance_id);
+  }
+}
+
+void GpuDevice::SetHDCPSRMForAllDisplays(const int8_t *SRM,
+                                         uint32_t SRMLength) {
+  size_t size = total_displays_.size();
+  for (size_t i = 0; i < size; i++) {
+    total_displays_.at(i)->SetHDCPSRM(SRM, SRMLength);
+  }
+}
+
+void GpuDevice::SetHDCPSRMForDisplay(uint32_t display, const int8_t *SRM,
+                                     uint32_t SRMLength) {
+  if (total_displays_.size() <= display) {
+    ETRACE("Tried to enable HDCP for invalid display %u \n", display);
+    return;
+  }
+
+  NativeDisplay *native_display = total_displays_.at(display);
+  native_display->SetHDCPSRM(SRM, SRMLength);
+}
+
+void GpuDevice::HandleRoutine() {
+  bool update_ignored = false;
+
+  // Iniitialize resources to monitor external events.
+  // These can be two types:
+  // 1) We are showing splash screen and another App
+  //    needs to take the control. In this case splash
+  //    is true.
+  // 2) Another app is having control of display and we
+  //    we need to take control.
+  // TODO: Add splash screen support.
+  if (lock_fd_ != -1) {
+    display_manager_->IgnoreUpdates();
+    update_ignored = true;
+
+    if (flock(lock_fd_, LOCK_EX) != 0) {
+      ETRACE("Failed to wait on the hwc lock.");
+    } else {
+      ITRACE("Successfully grabbed the hwc lock.");
     }
+
+    display_manager_->setDrmMaster();
+
+    close(lock_fd_);
+    lock_fd_ = -1;
   }
+
+  if (update_ignored)
+    display_manager_->ForceRefresh();
 }
 
-std::vector<NativeDisplay *> GpuDevice::GetAllDisplays() {
-  return total_displays_;
+void GpuDevice::HandleWait() {
+  if (lock_fd_ == -1) {
+    HWCThread::HandleWait();
+  }
 }
 
-void GpuDevice::RegisterHotPlugEventCallback(
-    std::shared_ptr<DisplayHotPlugEventCallback> callback) {
-  display_manager_->RegisterHotPlugEventCallback(callback);
+void GpuDevice::DisableWatch() {
+  HWCThread::Exit();
 }
 
 }  // namespace hwcomposer