123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- // Copyright 2021 The Chromium 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 "ash/components/phonehub/camera_roll_manager_impl.h"
- #include <memory>
- #include <utility>
- #include "ash/components/phonehub/camera_roll_download_manager.h"
- #include "ash/components/phonehub/camera_roll_item.h"
- #include "ash/components/phonehub/camera_roll_thumbnail_decoder_impl.h"
- #include "ash/components/phonehub/message_receiver.h"
- #include "ash/components/phonehub/message_sender.h"
- #include "ash/components/phonehub/proto/phonehub_api.pb.h"
- #include "ash/components/phonehub/util/histogram_util.h"
- #include "ash/services/secure_channel/public/cpp/client/connection_manager.h"
- #include "ash/services/secure_channel/public/mojom/secure_channel_types.mojom.h"
- #include "base/bind.h"
- #include "base/memory/weak_ptr.h"
- #include "base/metrics/histogram_functions.h"
- #include "base/observer_list.h"
- #include "base/time/time.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- namespace ash {
- namespace phonehub {
- namespace {
- constexpr int kMaxCameraRollItemCount = 4;
- } // namespace
- CameraRollManagerImpl::CameraRollManagerImpl(
- MessageReceiver* message_receiver,
- MessageSender* message_sender,
- multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client,
- secure_channel::ConnectionManager* connection_manager,
- std::unique_ptr<CameraRollDownloadManager> camera_roll_download_manager)
- : message_receiver_(message_receiver),
- message_sender_(message_sender),
- multidevice_setup_client_(multidevice_setup_client),
- connection_manager_(connection_manager),
- camera_roll_download_manager_(std::move(camera_roll_download_manager)),
- thumbnail_decoder_(std::make_unique<CameraRollThumbnailDecoderImpl>()) {
- message_receiver->AddObserver(this);
- multidevice_setup_client_->AddObserver(this);
- connection_manager_->AddObserver(this);
- }
- CameraRollManagerImpl::~CameraRollManagerImpl() {
- message_receiver_->RemoveObserver(this);
- multidevice_setup_client_->RemoveObserver(this);
- connection_manager_->RemoveObserver(this);
- }
- void CameraRollManagerImpl::DownloadItem(
- const proto::CameraRollItemMetadata& item_metadata) {
- proto::FetchCameraRollItemDataRequest request;
- *request.mutable_metadata() = item_metadata;
- message_sender_->SendFetchCameraRollItemDataRequest(request);
- }
- void CameraRollManagerImpl::OnFetchCameraRollItemDataResponseReceived(
- const proto::FetchCameraRollItemDataResponse& response) {
- if (response.file_availability() !=
- proto::FetchCameraRollItemDataResponse::AVAILABLE) {
- util::LogCameraRollDownloadResult(
- util::CameraRollDownloadResult::kFileNotAvailable);
- NotifyCameraRollDownloadError(
- CameraRollManager::Observer::DownloadErrorType::kGenericError,
- response.metadata());
- return;
- }
- camera_roll_download_manager_->CreatePayloadFiles(
- response.payload_id(), response.metadata(),
- base::BindOnce(&CameraRollManagerImpl::OnPayloadFilesCreated,
- weak_ptr_factory_.GetWeakPtr(), response));
- }
- void CameraRollManagerImpl::OnPayloadFilesCreated(
- const proto::FetchCameraRollItemDataResponse& response,
- CameraRollDownloadManager::CreatePayloadFilesResult result,
- absl::optional<secure_channel::mojom::PayloadFilesPtr> payload_files) {
- switch (result) {
- case CameraRollDownloadManager::CreatePayloadFilesResult::kSuccess:
- connection_manager_->RegisterPayloadFile(
- response.payload_id(), std::move(payload_files.value()),
- base::BindRepeating(&CameraRollManagerImpl::OnFileTransferUpdate,
- weak_ptr_factory_.GetWeakPtr(),
- response.metadata()),
- base::BindOnce(&CameraRollManagerImpl::OnPayloadFileRegistered,
- weak_ptr_factory_.GetWeakPtr(), response.metadata(),
- response.payload_id()));
- break;
- case CameraRollDownloadManager::CreatePayloadFilesResult::
- kInsufficientDiskSpace:
- util::LogCameraRollDownloadResult(
- util::CameraRollDownloadResult::kInsufficientDiskSpace);
- NotifyCameraRollDownloadError(
- CameraRollManager::Observer::DownloadErrorType::kInsufficientStorage,
- response.metadata());
- break;
- case CameraRollDownloadManager::CreatePayloadFilesResult::kInvalidFileName:
- util::LogCameraRollDownloadResult(
- util::CameraRollDownloadResult::kInvalidFileName);
- NotifyCameraRollDownloadError(
- CameraRollManager::Observer::DownloadErrorType::kGenericError,
- response.metadata());
- break;
- case CameraRollDownloadManager::CreatePayloadFilesResult::
- kPayloadAlreadyExists:
- util::LogCameraRollDownloadResult(
- util::CameraRollDownloadResult::kPayloadAlreadyExists);
- NotifyCameraRollDownloadError(
- CameraRollManager::Observer::DownloadErrorType::kGenericError,
- response.metadata());
- break;
- case CameraRollDownloadManager::CreatePayloadFilesResult::
- kNotUniqueFilePath:
- util::LogCameraRollDownloadResult(
- util::CameraRollDownloadResult::kNotUniqueFilePath);
- NotifyCameraRollDownloadError(
- CameraRollManager::Observer::DownloadErrorType::kGenericError,
- response.metadata());
- break;
- }
- }
- void CameraRollManagerImpl::OnPayloadFileRegistered(
- const proto::CameraRollItemMetadata& metadata,
- int64_t payload_id,
- bool success) {
- if (!success) {
- camera_roll_download_manager_->DeleteFile(payload_id);
- util::LogCameraRollDownloadResult(
- util::CameraRollDownloadResult::kTargetFileNotAccessible);
- NotifyCameraRollDownloadError(
- CameraRollManager::Observer::DownloadErrorType::kGenericError,
- metadata);
- return;
- }
- proto::InitiateCameraRollItemTransferRequest request;
- *request.mutable_metadata() = metadata;
- request.set_payload_id(payload_id);
- message_sender_->SendInitiateCameraRollItemTransferRequest(request);
- }
- void CameraRollManagerImpl::OnFileTransferUpdate(
- const proto::CameraRollItemMetadata& metadata,
- secure_channel::mojom::FileTransferUpdatePtr update) {
- switch (update->status) {
- case secure_channel::mojom::FileTransferStatus::kInProgress:
- break;
- case secure_channel::mojom::FileTransferStatus::kSuccess:
- util::LogCameraRollDownloadResult(
- util::CameraRollDownloadResult::kSuccess);
- break;
- case secure_channel::mojom::FileTransferStatus::kFailure:
- util::LogCameraRollDownloadResult(
- util::CameraRollDownloadResult::kTransferFailed);
- NotifyCameraRollDownloadError(
- CameraRollManager::Observer::DownloadErrorType::kNetworkConnection,
- metadata);
- break;
- case secure_channel::mojom::FileTransferStatus::kCanceled:
- util::LogCameraRollDownloadResult(
- util::CameraRollDownloadResult::kTransferCanceled);
- NotifyCameraRollDownloadError(
- CameraRollManager::Observer::DownloadErrorType::kNetworkConnection,
- metadata);
- break;
- }
- camera_roll_download_manager_->UpdateDownloadProgress(std::move(update));
- }
- void CameraRollManagerImpl::OnPhoneStatusSnapshotReceived(
- proto::PhoneStatusSnapshot phone_status_snapshot) {
- UpdateCameraRollAccessStateAndNotifyIfNeeded(
- phone_status_snapshot.properties().camera_roll_access_state());
- if (!is_android_storage_granted_ || !IsCameraRollSettingEnabled()) {
- ClearCurrentItems();
- CancelPendingThumbnailRequests();
- return;
- }
- SendFetchCameraRollItemsRequest();
- }
- void CameraRollManagerImpl::OnPhoneStatusUpdateReceived(
- proto::PhoneStatusUpdate phone_status_update) {
- UpdateCameraRollAccessStateAndNotifyIfNeeded(
- phone_status_update.properties().camera_roll_access_state());
- if (!is_android_storage_granted_ || !IsCameraRollSettingEnabled()) {
- ClearCurrentItems();
- CancelPendingThumbnailRequests();
- return;
- }
- if (phone_status_update.has_camera_roll_updates()) {
- SendFetchCameraRollItemsRequest();
- }
- }
- void CameraRollManagerImpl::OnFetchCameraRollItemsResponseReceived(
- const proto::FetchCameraRollItemsResponse& response) {
- thumbnail_decoder_->BatchDecode(
- response, current_items(),
- base::BindOnce(&CameraRollManagerImpl::OnItemThumbnailsDecoded,
- thumbnail_decoder_weak_ptr_factory_.GetWeakPtr()));
- }
- void CameraRollManagerImpl::SendFetchCameraRollItemsRequest() {
- // Clears pending thumbnail decode requests to avoid changing the current item
- // set after sending it with the |FetchCameraRollItemsRequest|. These pending
- // thumbnails will be invalidated anyway when the new response is received.
- CancelPendingThumbnailRequests();
- // Do not update the timestamp if it is already set. It means that there's an
- // in-progress request. We want to measure the time it takes from the first
- // time we request an update to when the UI is updated. This is the time the
- // user spends waiting.
- if (!fetch_items_request_start_timestamp_) {
- fetch_items_request_start_timestamp_ = base::TimeTicks::Now();
- }
- proto::FetchCameraRollItemsRequest request;
- request.set_max_item_count(kMaxCameraRollItemCount);
- for (const CameraRollItem& current_item : current_items()) {
- *request.add_current_item_metadata() = current_item.metadata();
- }
- message_sender_->SendFetchCameraRollItemsRequest(request);
- }
- void CameraRollManagerImpl::OnItemThumbnailsDecoded(
- CameraRollThumbnailDecoder::BatchDecodeResult result,
- const std::vector<CameraRollItem>& items) {
- if (result == CameraRollThumbnailDecoder::BatchDecodeResult::kCompleted) {
- if (fetch_items_request_start_timestamp_) {
- base::UmaHistogramMediumTimes(
- "PhoneHub.CameraRoll.Latency.RefreshItems",
- base::TimeTicks::Now() - *fetch_items_request_start_timestamp_);
- fetch_items_request_start_timestamp_.reset();
- }
- SetCurrentItems(items);
- }
- }
- void CameraRollManagerImpl::CancelPendingThumbnailRequests() {
- thumbnail_decoder_weak_ptr_factory_.InvalidateWeakPtrs();
- }
- bool CameraRollManagerImpl::IsCameraRollSettingEnabled() {
- multidevice_setup::mojom::FeatureState camera_roll_feature_state =
- multidevice_setup_client_->GetFeatureState(
- multidevice_setup::mojom::Feature::kPhoneHubCameraRoll);
- return camera_roll_feature_state ==
- multidevice_setup::mojom::FeatureState::kEnabledByUser;
- }
- void CameraRollManagerImpl::OnFeatureStatesChanged(
- const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
- feature_states_map) {
- if (!IsCameraRollSettingEnabled()) {
- // ClearCurrentItems() would also call ComputeAndUpdateUiState()
- ClearCurrentItems();
- CancelPendingThumbnailRequests();
- } else {
- ComputeAndUpdateUiState();
- }
- }
- void CameraRollManagerImpl::OnConnectionStatusChanged() {
- if (connection_manager_->GetStatus() ==
- secure_channel::ConnectionManager::Status::kDisconnected) {
- ClearCurrentItems();
- CancelPendingThumbnailRequests();
- }
- }
- void CameraRollManagerImpl::UpdateCameraRollAccessStateAndNotifyIfNeeded(
- const proto::CameraRollAccessState& access_state) {
- bool updated_storage_granted = access_state.storage_permission_granted();
- if (is_android_storage_granted_ != updated_storage_granted) {
- is_android_storage_granted_ = updated_storage_granted;
- util::LogCameraRollAndroidHasStorageAccessPermission(
- is_android_storage_granted_);
- ComputeAndUpdateUiState();
- }
- }
- void CameraRollManagerImpl::ComputeAndUpdateUiState() {
- if (!is_android_storage_granted_) {
- ui_state_ = CameraRollUiState::NO_STORAGE_PERMISSION;
- NotifyCameraRollViewUiStateUpdated();
- return;
- }
- multidevice_setup::mojom::FeatureState feature_state =
- multidevice_setup_client_->GetFeatureState(
- multidevice_setup::mojom::Feature::kPhoneHubCameraRoll);
- switch (feature_state) {
- case multidevice_setup::mojom::FeatureState::kDisabledByUser:
- ui_state_ = CameraRollUiState::SHOULD_HIDE;
- ;
- break;
- case multidevice_setup::mojom::FeatureState::kEnabledByUser:
- if (current_items().empty()) {
- ui_state_ = CameraRollUiState::SHOULD_HIDE;
- } else {
- ui_state_ = CameraRollUiState::ITEMS_VISIBLE;
- }
- break;
- default:
- ui_state_ = CameraRollUiState::SHOULD_HIDE;
- break;
- }
- NotifyCameraRollViewUiStateUpdated();
- }
- } // namespace phonehub
- } // namespace ash
|