// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mtpd/device_manager.h"

#include <libudev.h>
#include <sys/stat.h>
#include <sys/time.h>

#include <memory>
#include <set>
#include <utility>

#include <base/bind.h>
#include <base/callback.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/memory/free_deleter.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/stringprintf.h>
#include <base/threading/thread.h>
#include <base/threading/thread_task_runner_handle.h>
#include <chromeos/dbus/service_constants.h>

#include "mtpd/device_event_delegate.h"

namespace mtpd {

namespace {

// For GetObjectHandles PTP operations, this tells GetObjectHandles to only
// list the objects of the root of a store.
// Use this when referring to the root node in the context of ReadDirectory().
// This is an implementation detail that is not exposed to the outside.
const uint32_t kPtpGohRootParent = 0xFFFFFFFF;

// Used to identify a PTP USB device interface.
const char kPtpUsbInterfaceClass[] = "6";
const char kPtpUsbInterfaceSubClass[] = "1";
const char kPtpUsbInterfaceProtocol[] = "1";

// Used to identify a vendor-specific USB device interface.
// Manufacturers sometimes do not report MTP/PTP capable devices using the
// well known PTP interface class. See libgphoto2 and libmtp device databases
// for examples.
const char kVendorSpecificUsbInterfaceClass[] = "255";

const char kUsbPrefix[] = "usb";
const char kUDevEventType[] = "udev";
const char kUDevUsbSubsystem[] = "usb";

std::string RawDeviceToString(const LIBMTP_raw_device_t& device) {
  return base::StringPrintf("%s:%u,%d", kUsbPrefix, device.bus_location,
                            device.devnum);
}

std::string StorageToString(const std::string& usb_bus_str,
                            uint32_t storage_id) {
  return base::StringPrintf("%s:%u", usb_bus_str.c_str(), storage_id);
}

struct LibmtpFileDeleter {
  void operator()(LIBMTP_file_t* file) { LIBMTP_destroy_file_t(file); }
};

using ScopedMtpFile = std::unique_ptr<LIBMTP_file_t, LibmtpFileDeleter>;
ScopedMtpFile CreateScopedMtpFile(LIBMTP_mtpdevice_t* mtp_device,
                                  uint32_t file_id) {
  return ScopedMtpFile((file_id == kRootFileId)
                           ? LIBMTP_new_file_t()
                           : LIBMTP_Get_Filemetadata(mtp_device, file_id));
}

}  // namespace

class DeviceManager::MtpPoller : public base::Thread {
 public:
  using EventCallback =
      base::OnceCallback<void(int ret_code, LIBMTP_event_t event)>;

  explicit MtpPoller(scoped_refptr<base::SingleThreadTaskRunner> task_runner)
      : Thread("MTP poller"), main_thread_task_runner_(task_runner) {}
  ~MtpPoller() override {
    Stop();
  }

  void WaitForEvent(LIBMTP_mtpdevice_t* mtp_device, EventCallback callback) {
    DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

    auto params = std::make_unique<Params>(this, std::move(callback));
    int ret = LIBMTP_Read_Event_Async(mtp_device, &ReadEventFunction,
                                      params.get());
    if (ret) {
      LOG(ERROR) << "LIBMTP_Read_Event_Async error " << ret;
      return;
    }
    // On success, libmtp takes ownership of |params|, and transfers it to the
    // event handler function on an event.
    params.release();

    base::AutoLock al(lock_);
    if (num_pending_ == 0) {
      // NOTE: There's a logical 'race' here where multiple DoEvents() can be
      // posted to the task runner. This happens when an MTP device is rapidly
      // disconnected and reconnected. If a device is removed, then a new device
      // is added between the |num_pending_| decrement in ProcessEvent() and
      // checking the loop condition in DoEvents(), this condition will be hit
      // and a new task is posted while the current one is running. When all
      // devices are eventually removed, the extra task will run and finish
      // immediately since |num_pending_| should be 0.
      task_runner()->PostTask(
          FROM_HERE,
          base::BindOnce(&MtpPoller::DoEvents, base::Unretained(this)));
    }
    num_pending_++;
  }

 private:
  struct Params {
    Params(MtpPoller* poller, EventCallback callback)
        : poller(poller), callback(std::move(callback)) {}

    MtpPoller* poller;
    EventCallback callback;
  };

  void DoEvents() {
    DCHECK(task_runner()->BelongsToCurrentThread());

    base::AutoLock al(lock_);
    while (num_pending_ > 0) {
      base::AutoUnlock aul(lock_);
      // libmtp requires a non-zero timeout. A day should be reasonable.
      struct timeval tv = {86400, 0};
      int err = LIBMTP_Handle_Events_Timeout_Completed(&tv, nullptr);
      if (err) {
        LOG(ERROR) << "LIBMTP_Handle_Events_Timeout_Completed error " << err;
      }
    }
  }

  static void ReadEventFunction(int ret_code, LIBMTP_event_t event,
                                uint32_t unused_extra, void* user_data) {
    std::unique_ptr<Params> params(static_cast<Params*>(user_data));
    params->poller->ProcessEvent(ret_code, event, std::move(params->callback));
  }

  void ProcessEvent(int ret_code,
                    LIBMTP_event_t event,
                    EventCallback callback) {
    DCHECK(task_runner()->BelongsToCurrentThread());
    {
      base::AutoLock al(lock_);
      num_pending_--;
    }
    main_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), ret_code, event));
  }

  scoped_refptr<base::SingleThreadTaskRunner> const main_thread_task_runner_;

  // Protects |num_pending_|.
  base::Lock lock_;
  // Number of waiters waiting for an event.
  int num_pending_ = 0;

  DISALLOW_COPY_AND_ASSIGN(MtpPoller);
};

DeviceManager::DeviceManager(DeviceEventDelegate* delegate)
    : udev_(udev_new()),
      udev_monitor_(nullptr),
      udev_monitor_fd_(-1),
      delegate_(delegate),
      weak_ptr_factory_(this) {
  // Set up udev monitoring.
  CHECK(delegate_);
  CHECK(udev_);
  udev_monitor_ = udev_monitor_new_from_netlink(udev_, kUDevEventType);
  CHECK(udev_monitor_);
  int ret = udev_monitor_filter_add_match_subsystem_devtype(
      udev_monitor_, kUDevUsbSubsystem, nullptr);
  CHECK_EQ(0, ret);
  ret = udev_monitor_enable_receiving(udev_monitor_);
  CHECK_EQ(0, ret);
  udev_monitor_fd_ = udev_monitor_get_fd(udev_monitor_);
  CHECK_GE(udev_monitor_fd_, 0);

  // Initialize libmtp.
  LIBMTP_Init();

  // Create and start the libmtp poller thread.
  mtp_poller_ = std::make_unique<MtpPoller>(
      base::ThreadTaskRunnerHandle::Get());
  CHECK(mtp_poller_->Start());

  // Trigger a device scan.
  AddDevices();
}

DeviceManager::~DeviceManager() {
  udev_monitor_unref(udev_monitor_);
  udev_unref(udev_);
  RemoveDevices(true /* remove all */);
}

// static
bool DeviceManager::ParseStorageName(const std::string& storage_name,
                                     std::string* usb_bus_str,
                                     uint32_t* storage_id) {
  std::vector<std::string> split_str = base::SplitString(
      storage_name, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  if (split_str.size() != 3)
    return false;

  if (split_str[0] != kUsbPrefix)
    return false;

  uint32_t id = 0;
  if (!base::StringToUint(split_str[2], &id))
    return false;

  *usb_bus_str = base::StringPrintf("%s:%s", kUsbPrefix, split_str[1].c_str());
  *storage_id = id;
  return true;
}

int DeviceManager::GetDeviceEventDescriptor() const {
  return udev_monitor_fd_;
}

void DeviceManager::ProcessDeviceEvents() {
  udev_device* dev = udev_monitor_receive_device(udev_monitor_);
  if (!dev)
    return;
  HandleDeviceNotification(dev);
  udev_device_unref(dev);
}

std::vector<std::string> DeviceManager::EnumerateStorages() {
  std::vector<std::string> ret;
  for (const auto& device : device_map_) {
    const std::string& usb_bus_str = device.first;
    for (const auto& storage : device.second.storage_map) {
      std::string storage_str = StorageToString(usb_bus_str, storage.first);
      ret.push_back(storage_str);
      LOG(INFO) << "Found storage: " << storage_str;
    }
  }
  return ret;
}

bool DeviceManager::HasStorage(const std::string& storage_name) {
  return GetStorageInfo(storage_name) != nullptr;
}

const StorageInfo* DeviceManager::GetStorageInfo(
    const std::string& storage_name) {
  std::string usb_bus_str;
  uint32_t storage_id = 0;
  if (!ParseStorageName(storage_name, &usb_bus_str, &storage_id))
    return nullptr;

  MtpDeviceMap::const_iterator device_it = device_map_.find(usb_bus_str);
  if (device_it == device_map_.end())
    return nullptr;

  const MtpStorageMap& storage_map = device_it->second.storage_map;
  MtpStorageMap::const_iterator storage_it = storage_map.find(storage_id);
  return storage_it != storage_map.end() ? &storage_it->second : nullptr;
}

const StorageInfo* DeviceManager::GetStorageInfoFromDevice(
    const std::string& storage_name) {
  std::string usb_bus_str;
  uint32_t storage_id = 0;
  if (!ParseStorageName(storage_name, &usb_bus_str, &storage_id))
    return nullptr;

  MtpDeviceMap::iterator device_it = device_map_.find(usb_bus_str);
  if (device_it == device_map_.end())
    return nullptr;

  // Update |storage_map| with the latest storage info.
  MtpStorageMap& storage_map = device_it->second.storage_map;
  LIBMTP_mtpdevice_t* mtp_device = device_it->second.device;
  LIBMTP_Get_Storage(mtp_device, LIBMTP_STORAGE_SORTBY_NOTSORTED);
  for (LIBMTP_devicestorage_t* storage = mtp_device->storage; storage;
       storage = storage->next) {
    MtpStorageMap::iterator storage_it = storage_map.find(storage->id);
    // If |storage->id| does not exist in the map, just ignore here. It should
    // be added at AddOrUpdateDevices.
    if (storage_it == storage_map.end())
      continue;

    storage_it->second.Update(*storage);
  }

  // Returns StorageInfo of |storage_id|.
  MtpStorageMap::const_iterator new_storage_it = storage_map.find(storage_id);
  return new_storage_it != storage_map.end() ? &new_storage_it->second
                                             : nullptr;
}

bool DeviceManager::ReadDirectoryEntryIds(const std::string& storage_name,
                                          uint32_t file_id,
                                          std::vector<uint32_t>* out) {
  LIBMTP_mtpdevice_t* mtp_device = nullptr;
  uint32_t storage_id = 0;
  if (!GetDeviceAndStorageId(storage_name, &mtp_device, &storage_id))
    return false;

  if (file_id == kRootFileId)
    file_id = kPtpGohRootParent;

  uint32_t* children;
  int ret = LIBMTP_Get_Children(mtp_device, storage_id, file_id, &children);
  if (ret < 0)
    return false;

  if (ret > 0) {
    for (int i = 0; i < ret; ++i)
      out->push_back(children[i]);
    free(children);
  }
  return true;
}

bool DeviceManager::GetFileInfo(const std::string& storage_name,
                                const std::vector<uint32_t> file_ids,
                                std::vector<FileEntry>* out) {
  LIBMTP_mtpdevice_t* mtp_device = nullptr;
  uint32_t storage_id = 0;
  if (!GetDeviceAndStorageId(storage_name, &mtp_device, &storage_id))
    return false;

  for (size_t i = 0; i < file_ids.size(); ++i) {
    uint32_t file_id = file_ids[i];
    auto file = CreateScopedMtpFile(mtp_device, file_id);
    if (!file)
      continue;

    // LIBMTP_Get_Filemetadata() does not know how to handle the root node, so
    // fill in relevant fields in the struct manually. The rest of the struct
    // has already been initialized by LIBMTP_new_file_t().
    if (file_id == kRootFileId) {
      file->storage_id = storage_id;
      file->filename = strdup("/");
      file->filetype = LIBMTP_FILETYPE_FOLDER;
    }

    out->push_back(FileEntry(*file));
  }
  return true;
}

bool DeviceManager::ReadFileChunk(const std::string& storage_name,
                                  uint32_t file_id,
                                  uint32_t offset,
                                  uint32_t count,
                                  std::vector<uint8_t>* out) {
  LIBMTP_mtpdevice_t* mtp_device = nullptr;
  uint32_t storage_id = 0;
  if (!GetDeviceAndStorageId(storage_name, &mtp_device, &storage_id))
    return false;
  return ReadFileChunk(mtp_device, file_id, offset, count, out);
}

bool DeviceManager::CopyFileFromLocal(const std::string& storage_name,
                                      const uint32_t file_descriptor,
                                      const uint32_t parent_id,
                                      const std::string& file_name) {
  // Get device.
  LIBMTP_mtpdevice_t* mtp_device = nullptr;
  uint32_t storage_id = 0;
  if (!GetDeviceAndStorageId(storage_name, &mtp_device, &storage_id))
    return false;

  // Get file size.
  struct stat file_stat;
  if (fstat(file_descriptor, &file_stat) != 0)
    return false;

  // Create a new file
  ScopedMtpFile new_file(LIBMTP_new_file_t());
  new_file->filename = strdup(file_name.c_str());
  new_file->filesize = file_stat.st_size;
  new_file->parent_id = parent_id;

  // Transfer a file.
  int transfer_status = LIBMTP_Send_File_From_File_Descriptor(
      mtp_device, file_descriptor, new_file.get(), nullptr, nullptr);
  return transfer_status == 0;
}

bool DeviceManager::DeleteObject(const std::string& storage_name,
                                 const uint32_t object_id) {
  // Get the device.
  LIBMTP_mtpdevice_t* mtp_device = nullptr;
  uint32_t storage_id = 0;
  if (!GetDeviceAndStorageId(storage_name, &mtp_device, &storage_id))
    return false;
  return DeleteObjectInternal(mtp_device, storage_id, object_id);
}

bool DeviceManager::RenameObject(const std::string& storage_name,
                                 const uint32_t object_id,
                                 const std::string& new_name) {
  // Get the device.
  LIBMTP_mtpdevice_t* mtp_device = nullptr;
  uint32_t storage_id = 0;
  if (!GetDeviceAndStorageId(storage_name, &mtp_device, &storage_id))
    return false;

  // The root node cannot be renamed.
  if (object_id == kRootFileId)
    return false;

  // Check the object exists.
  auto file = CreateScopedMtpFile(mtp_device, object_id);
  if (!file)
    return false;

  // Rename the object. While libmtp provides LIBMTP_Set_Folder_Name and other
  // methods for other types, they result in the same call of
  // set_object_filename.
  return LIBMTP_Set_File_Name(mtp_device, file.get(), new_name.c_str()) == 0;
}

bool DeviceManager::CreateDirectory(const std::string& storage_name,
                                    const uint32_t parent_id,
                                    const std::string& directory_name) {
  // Do not allow to create a directory with empty string.
  if (directory_name.empty())
    return false;

  // Get the device.
  LIBMTP_mtpdevice_t* mtp_device = nullptr;
  uint32_t storage_id = 0;
  if (!GetDeviceAndStorageId(storage_name, &mtp_device, &storage_id))
    return false;

  // Creates a directory.
  std::unique_ptr<char, base::FreeDeleter> new_directory_name(
      strdup(directory_name.c_str()));
  int new_directory_object_id = LIBMTP_Create_Folder(
      mtp_device, new_directory_name.get(), parent_id, storage_id);
  if (!strcmp(new_directory_name.get(), directory_name.c_str()))
    return new_directory_object_id > 0;

  // When directory name is changed, handle it as an error.
  if (new_directory_object_id > 0)
    DeleteObjectInternal(mtp_device, storage_id, new_directory_object_id);
  return false;
}

bool DeviceManager::AddStorageForTest(const std::string& storage_name,
                                      const StorageInfo& storage_info) {
  std::string device_location;
  uint32_t storage_id;
  if (!ParseStorageName(storage_name, &device_location, &storage_id))
    return false;

  MtpDeviceMap::iterator it = device_map_.find(device_location);
  if (it == device_map_.end()) {
    // New device case.
    MtpStorageMap new_storage_map;
    new_storage_map.insert(std::make_pair(storage_id, storage_info));
    MtpDevice new_mtp_device(nullptr, new_storage_map);
    device_map_.insert(std::make_pair(device_location, new_mtp_device));
    return true;
  }

  // Existing device case.
  // There should be no real LIBMTP_mtpdevice_t device for this dummy storage.
  MtpDevice& existing_mtp_device = it->second;
  if (existing_mtp_device.device)
    return false;

  // And the storage should not already exist.
  MtpStorageMap& existing_mtp_storage_map = existing_mtp_device.storage_map;
  if (base::Contains(existing_mtp_storage_map, storage_id))
    return false;

  existing_mtp_storage_map.insert(std::make_pair(storage_id, storage_info));
  return true;
}

bool DeviceManager::ReadDirectory(LIBMTP_mtpdevice_t* device,
                                  uint32_t storage_id,
                                  uint32_t file_id,
                                  std::vector<FileEntry>* out) {
  LIBMTP_file_t* file =
      LIBMTP_Get_Files_And_Folders(device, storage_id, file_id);
  while (file) {
    ScopedMtpFile current_file(file);
    file = file->next;
    out->push_back(FileEntry(*current_file));
  }
  return true;
}

bool DeviceManager::ReadFileChunk(LIBMTP_mtpdevice_t* device,
                                  uint32_t file_id,
                                  uint32_t offset,
                                  uint32_t count,
                                  std::vector<uint8_t>* out) {
  // The root node is a virtual node and cannot be read from.
  if (file_id == kRootFileId)
    return false;

  uint8_t* data = nullptr;
  uint32_t bytes_read = 0;
  int transfer_status =
      LIBMTP_Get_File_Chunk(device, file_id, offset, count, &data, &bytes_read);

  // Own |data| in a scoper so it gets freed when this function returns.
  std::unique_ptr<uint8_t, base::FreeDeleter> scoped_data(data);

  if (transfer_status != 0 || bytes_read != count)
    return false;

  for (size_t i = 0; i < count; ++i)
    out->push_back(data[i]);
  return true;
}

bool DeviceManager::DeleteObjectInternal(LIBMTP_mtpdevice_t* mtp_device,
                                         const uint32_t storage_id,
                                         const uint32_t object_id) {
  // The root node cannot be deleted.
  if (object_id == kRootFileId)
    return false;

  // Check the object exists.
  auto file = CreateScopedMtpFile(mtp_device, object_id);
  if (!file)
    return false;

  // If the object is a directory, check it is empty.
  if (file->filetype == LIBMTP_FILETYPE_FOLDER) {
    uint32_t* children;
    int num_of_children =
        LIBMTP_Get_Children(mtp_device, storage_id, object_id, &children);
    if (num_of_children > 0)
      free(children);

    if (num_of_children != 0)
      return false;
  }

  // Delete an object.
  return LIBMTP_Delete_Object(mtp_device, object_id) == 0;
}

bool DeviceManager::GetFileInfoInternal(LIBMTP_mtpdevice_t* device,
                                        uint32_t storage_id,
                                        uint32_t file_id,
                                        FileEntry* out) {
  auto file = CreateScopedMtpFile(device, file_id);
  if (!file)
    return false;

  // LIBMTP_Get_Filemetadata() does not know how to handle the root node, so
  // fill in relevant fields in the struct manually. The rest of the struct has
  // already been initialized by LIBMTP_new_file_t().
  if (file_id == kRootFileId) {
    file->storage_id = storage_id;
    file->filename = strdup("/");
    file->filetype = LIBMTP_FILETYPE_FOLDER;
  }

  *out = FileEntry(*file);
  return true;
}

bool DeviceManager::GetDeviceAndStorageId(const std::string& storage_name,
                                          LIBMTP_mtpdevice_t** mtp_device,
                                          uint32_t* storage_id) {
  std::string usb_bus_str;
  uint32_t id = 0;
  if (!ParseStorageName(storage_name, &usb_bus_str, &id))
    return false;

  MtpDeviceMap::const_iterator device_it = device_map_.find(usb_bus_str);
  if (device_it == device_map_.end())
    return false;

  if (!base::Contains(device_it->second.storage_map, id))
    return false;

  *storage_id = id;
  *mtp_device = device_it->second.device;
  return true;
}

void DeviceManager::HandleDeviceNotification(udev_device* device) {
  const char* action = udev_device_get_property_value(device, "ACTION");
  const char* interface = udev_device_get_property_value(device, "INTERFACE");
  if (!action || !interface)
    return;

  // Check the USB interface. Since this gets called many times by udev for a
  // given physical action, use the udev "INTERFACE" event property as a quick
  // way of getting one unique and interesting udev event for a given physical
  // action. At the same time, do some light filtering and ignore events for
  // uninteresting devices.
  const std::string kEventInterface(interface);
  std::vector<std::string> split_usb_interface = base::SplitString(
      kEventInterface, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  if (split_usb_interface.size() != 3)
    return;

  // Check to see if the device has a vendor-specific interface class.
  // In this case, continue and let libmtp figure it out.
  const std::string& usb_interface_class = split_usb_interface[0];
  const std::string& usb_interface_subclass = split_usb_interface[1];
  const std::string& usb_interface_protocol = split_usb_interface[2];
  bool is_interesting_device =
      (usb_interface_class == kVendorSpecificUsbInterfaceClass);
  if (!is_interesting_device) {
    // Many MTP/PTP devices have this PTP interface.
    is_interesting_device =
        (usb_interface_class == kPtpUsbInterfaceClass &&
         usb_interface_subclass == kPtpUsbInterfaceSubClass &&
         usb_interface_protocol == kPtpUsbInterfaceProtocol);
  }
  if (!is_interesting_device)
    return;

  // Handle the action.
  const std::string kEventAction(action);
  if (kEventAction == "add") {
    // Some devices do not respond well when immediately probed. Thus there is
    // a 1 second wait here to give the device to settle down.
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&DeviceManager::AddDevices,
                       weak_ptr_factory_.GetWeakPtr()),
        base::TimeDelta::FromSeconds(1));
    return;
  }
  if (kEventAction == "remove") {
    // libmtp still detects the mtp device as connected now, so add a 1 second
    // wait to ensure libmtp does not detect the device.
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&DeviceManager::RemoveDevices,
                       weak_ptr_factory_.GetWeakPtr(), false /* !remove_all */),
        base::TimeDelta::FromSeconds(1));
    return;
  }
  // udev notes the existence of other actions like "change" and "move", but
  // they have never been observed with real MTP/PTP devices in testing.
}

void DeviceManager::AddDevices() {
  AddOrUpdateDevices(true /* add */, "");
}

void DeviceManager::UpdateDevice(const std::string& usb_bus_name) {
  AddOrUpdateDevices(false /* update */, usb_bus_name);
}

void DeviceManager::AddOrUpdateDevices(
    bool add_update,
    const std::string& changed_usb_device_name) {
  // Get raw devices.
  LIBMTP_raw_device_t* raw_devices = nullptr;
  int raw_devices_count = 0;
  LIBMTP_error_number_t err =
      LIBMTP_Detect_Raw_Devices(&raw_devices, &raw_devices_count);
  if (err == LIBMTP_ERROR_NO_DEVICE_ATTACHED) {
    LOG(INFO) << "LIBMTP_Detect_Raw_Devices failed with NO_DEVICE_ATTACHED";
    return;
  }
  if (err != LIBMTP_ERROR_NONE) {
    LOG(ERROR) << "LIBMTP_Detect_Raw_Devices failed with " << err;
    return;
  }
  std::unique_ptr<LIBMTP_raw_device_t, base::FreeDeleter> scoped_raw_devices(
      raw_devices);
  // Iterate through raw devices. Look for target device, if updating.
  for (int i = 0; i < raw_devices_count; ++i) {
    const std::string usb_bus_str = RawDeviceToString(raw_devices[i]);

    if (add_update) {
      // Skip devices that have already been opened.
      if (base::Contains(device_map_, usb_bus_str))
        continue;
    } else {
      // Skip non-target device.
      if (usb_bus_str != changed_usb_device_name)
        continue;
    }

    LIBMTP_mtpdevice_t* mtp_device = nullptr;
    if (add_update) {
      // Open the mtp device.
      mtp_device = LIBMTP_Open_Raw_Device_Uncached(&raw_devices[i]);
      if (!mtp_device) {
        LOG(ERROR) << "LIBMTP_Open_Raw_Device_Uncached failed for "
                   << usb_bus_str;
        continue;
      }
    } else {
      mtp_device = device_map_[usb_bus_str].device;

      // For existing devices, update the storage lists.
      if (LIBMTP_Get_Storage(mtp_device, LIBMTP_STORAGE_SORTBY_NOTSORTED) < 0) {
        LOG(ERROR) << "LIBMTP_Get_Storage failed for " << usb_bus_str;
        return;
      }
    }

    // Fetch fallback vendor / product info.
    std::unique_ptr<char, base::FreeDeleter> duplicated_string;
    duplicated_string.reset(LIBMTP_Get_Manufacturername(mtp_device));
    std::string fallback_vendor;
    if (duplicated_string.get())
      fallback_vendor = duplicated_string.get();

    duplicated_string.reset(LIBMTP_Get_Modelname(mtp_device));
    std::string fallback_product;
    if (duplicated_string.get())
      fallback_product = duplicated_string.get();

    MtpStorageMap new_storage_map;
    MtpStorageMap* storage_map_ptr;
    if (add_update)
      storage_map_ptr = &new_storage_map;
    else
      storage_map_ptr = &device_map_[usb_bus_str].storage_map;

    // Compute the set of storage ids that are contained in the mtpd's
    // storage_map but not in the latest device info. They are removed storages.
    std::set<uint32_t> removed_storage_ids;
    for (const auto& it : *storage_map_ptr)
      removed_storage_ids.insert(it.first);

    for (LIBMTP_devicestorage_t* storage = mtp_device->storage; storage;
         storage = storage->next) {
      removed_storage_ids.erase(storage->id);
    }
    // Iterate through storages on the device and remove storages that are no
    // longer on the device.
    for (const auto& storage_id : removed_storage_ids) {
      storage_map_ptr->erase(storage_id);
      delegate_->StorageDetached(StorageToString(usb_bus_str, storage_id));
    }

    // Iterate through storages on the device and add any that are missing.
    for (LIBMTP_devicestorage_t* storage = mtp_device->storage; storage;
         storage = storage->next) {
      if (base::Contains(*storage_map_ptr, storage->id))
        continue;
      const std::string storage_name =
          StorageToString(usb_bus_str, storage->id);
      StorageInfo info(storage_name, raw_devices[i].device_entry, *storage,
                       fallback_vendor, fallback_product);
      bool storage_added =
          storage_map_ptr->insert(std::make_pair(storage->id, info)).second;
      CHECK(storage_added);
      delegate_->StorageAttached(storage_name);
      LOG(INFO) << "Added storage " << storage_name;
    }
    if (!add_update) {
      LOG(INFO) << "Updated device " << usb_bus_str << " with "
                << storage_map_ptr->size() << " storages";
      return;
    }
    if (storage_map_ptr->empty()) {
      // Devices such as the Pixel 2 may expose a fake PTP interface in "No data
      // transfer" mode (b/135955589) with 0 storage. In this case mtpd
      // shouldn't keep the handle open ideally.
      device_map_.erase(usb_bus_str);
      LIBMTP_Release_Device(mtp_device);
      LOG(INFO) << "Ignoring device with 0 storage " << usb_bus_str;
      return;
    }
    mtp_poller_->WaitForEvent(
        mtp_device,
        base::BindOnce(&DeviceManager::HandleMtpEvent,
                       weak_ptr_factory_.GetWeakPtr(), usb_bus_str));
    bool device_added =
        device_map_
            .insert(std::make_pair(
                usb_bus_str,
                MtpDevice(mtp_device, *storage_map_ptr)))
            .second;
    CHECK(device_added);
    LOG(INFO) << "Added device " << usb_bus_str << " with "
              << storage_map_ptr->size() << " storages";
  }
}

void DeviceManager::HandleMtpEvent(const std::string& usb_bus_name,
                                   int ret_code,
                                   LIBMTP_event_t event) {
  LOG(INFO) << "HandleMtpEvent " << usb_bus_name << " ret_code " << ret_code;
  if (ret_code != LIBMTP_HANDLER_RETURN_OK) {
    return;
  }

  if (event == LIBMTP_EVENT_STORE_ADDED ||
      event == LIBMTP_EVENT_STORE_REMOVED) {
    UpdateDevice(usb_bus_name);
  }

  auto it = device_map_.find(usb_bus_name);
  if (it == device_map_.end()) {
    return;
  }

  mtp_poller_->WaitForEvent(
      it->second.device,
      base::BindOnce(&DeviceManager::HandleMtpEvent,
                     weak_ptr_factory_.GetWeakPtr(), usb_bus_name));
}

void DeviceManager::RemoveDevices(bool remove_all) {
  LIBMTP_raw_device_t* raw_devices = nullptr;
  int raw_devices_count = 0;

  if (!remove_all) {
    LIBMTP_error_number_t err =
        LIBMTP_Detect_Raw_Devices(&raw_devices, &raw_devices_count);
    if (!(err == LIBMTP_ERROR_NONE || err == LIBMTP_ERROR_NO_DEVICE_ATTACHED)) {
      LOG(ERROR) << "LIBMTP_Detect_Raw_Devices failed with " << err;
      return;
    }
  }
  std::unique_ptr<LIBMTP_raw_device_t, base::FreeDeleter> scoped_raw_devices(
      raw_devices);

  // Populate |devices_set| with all known attached devices.
  std::set<std::string> devices_set;
  for (const auto& device : device_map_)
    devices_set.insert(device.first);

  // And remove the ones that are still attached.
  for (int i = 0; i < raw_devices_count; ++i)
    devices_set.erase(RawDeviceToString(raw_devices[i]));

  // The ones left in the set are the detached devices.
  for (const auto& device : devices_set) {
    LOG(INFO) << "Removed " << device;
    MtpDeviceMap::iterator device_it = device_map_.find(device);
    if (device_it == device_map_.end()) {
      NOTREACHED();
      continue;
    }

    // Remove all the storages on that device.
    const std::string& usb_bus_str = device_it->first;
    const MtpStorageMap& storage_map = device_it->second.storage_map;
    for (const auto& storage : storage_map) {
      delegate_->StorageDetached(StorageToString(usb_bus_str, storage.first));
    }

    // Delete the device's map entry and cleanup.
    LIBMTP_mtpdevice_t* mtp_device = device_it->second.device;
    device_map_.erase(device_it);

    // |mtp_device| can be NULL in testing.
    if (!mtp_device)
      continue;

    // When |remove_all| is false, the device has already been detached
    // and this runs after the fact. As such, this call will very
    // likely fail and spew a bunch of error messages. Call it anyway to
    // let libmtp do any cleanup it can.
    LIBMTP_Release_Device(mtp_device);
  }
}

}  // namespace mtpd
