// 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 <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::Callback<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,
                    const EventCallback& callback) {
    DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

    auto params = std::make_unique<Params>(this, 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::Bind(&MtpPoller::DoEvents, base::Unretained(this)));
    }
    num_pending_++;
  }

 private:
  struct Params {
    Params(MtpPoller* poller, const EventCallback& callback)
        : poller(poller), callback(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, params->callback);
  }

  void ProcessEvent(int ret_code, LIBMTP_event_t event,
                    const EventCallback& callback) {
    DCHECK(task_runner()->BelongsToCurrentThread());
    {
      base::AutoLock al(lock_);
      num_pending_--;
    }
    main_thread_task_runner_->PostTask(FROM_HERE, base::Bind(
        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::ContainsKey(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::ContainsKey(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::MessageLoopForIO::current()->task_runner()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&DeviceManager::AddDevices, weak_ptr_factory_.GetWeakPtr()),
        base::TimeDelta::FromSeconds(1));
    return;
  }
  if (kEventAction == "remove") {
    RemoveDevices(false /* !remove_all */);
    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::ContainsKey(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::ContainsKey(*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::Bind(&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::Bind(&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
